texture_cache: Corrections, documentation and asserts
This commit is contained in:
parent
c0abc7124d
commit
88bc39374f
|
@ -60,10 +60,10 @@ public:
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
/***
|
||||
* `Guard` guarantees that rendertargets don't unregister themselves if the
|
||||
* collide. Protection is currently only done on 3D slices.
|
||||
**/
|
||||
***/
|
||||
void GuardRenderTargets(bool new_guard) {
|
||||
guard_render_targets = new_guard;
|
||||
}
|
||||
|
@ -191,20 +191,22 @@ public:
|
|||
}
|
||||
|
||||
void SetEmptyDepthBuffer() {
|
||||
if (depth_buffer.target != nullptr) {
|
||||
if (depth_buffer.target == nullptr) {
|
||||
return;
|
||||
}
|
||||
depth_buffer.target->MarkAsRenderTarget(false);
|
||||
depth_buffer.target = nullptr;
|
||||
depth_buffer.view = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
void SetEmptyColorBuffer(std::size_t index) {
|
||||
if (render_targets[index].target != nullptr) {
|
||||
if (render_targets[index].target == nullptr) {
|
||||
return;
|
||||
}
|
||||
render_targets[index].target->MarkAsRenderTarget(false);
|
||||
render_targets[index].target = nullptr;
|
||||
render_targets[index].view = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
void DoFermiCopy(const Tegra::Engines::Fermi2D::Regs::Surface& src_config,
|
||||
const Tegra::Engines::Fermi2D::Regs::Surface& dst_config,
|
||||
|
@ -283,8 +285,8 @@ protected:
|
|||
gpu_addr);
|
||||
return;
|
||||
}
|
||||
bool continuouty = system.GPU().MemoryManager().IsBlockContinuous(gpu_addr, size);
|
||||
surface->MarkAsContinuous(continuouty);
|
||||
const bool continuous = system.GPU().MemoryManager().IsBlockContinuous(gpu_addr, size);
|
||||
surface->MarkAsContinuous(continuous);
|
||||
surface->SetCacheAddr(cache_ptr);
|
||||
surface->SetCpuAddr(*cpu_addr);
|
||||
RegisterInnerCache(surface);
|
||||
|
@ -381,8 +383,8 @@ private:
|
|||
const SurfaceParams& params, const GPUVAddr gpu_addr,
|
||||
const bool preserve_contents,
|
||||
const MatchTopologyResult untopological) {
|
||||
const bool do_load = Settings::values.use_accurate_gpu_emulation && preserve_contents;
|
||||
for (auto surface : overlaps) {
|
||||
const bool do_load = preserve_contents && Settings::values.use_accurate_gpu_emulation;
|
||||
for (auto& surface : overlaps) {
|
||||
Unregister(surface);
|
||||
}
|
||||
switch (PickStrategy(overlaps, params, gpu_addr, untopological)) {
|
||||
|
@ -394,7 +396,7 @@ private:
|
|||
[](const TSurface& a, const TSurface& b) -> bool {
|
||||
return a->GetModificationTick() < b->GetModificationTick();
|
||||
});
|
||||
for (auto surface : overlaps) {
|
||||
for (auto& surface : overlaps) {
|
||||
FlushSurface(surface);
|
||||
}
|
||||
return InitializeSurface(gpu_addr, params, preserve_contents);
|
||||
|
@ -460,20 +462,20 @@ private:
|
|||
const SurfaceParams& params, bool is_render) {
|
||||
const bool is_mirage = !current_surface->MatchFormat(params.pixel_format);
|
||||
const bool matches_target = current_surface->MatchTarget(params.target);
|
||||
auto match_check = ([&]() -> std::pair<TSurface, TView> {
|
||||
const auto match_check = ([&]() -> std::pair<TSurface, TView> {
|
||||
if (matches_target) {
|
||||
return {current_surface, current_surface->GetMainView()};
|
||||
}
|
||||
return {current_surface, current_surface->EmplaceOverview(params)};
|
||||
});
|
||||
if (is_mirage) {
|
||||
if (!is_mirage) {
|
||||
return match_check();
|
||||
}
|
||||
if (!is_render && siblings_table[current_surface->GetFormat()] == params.pixel_format) {
|
||||
return match_check();
|
||||
}
|
||||
return RebuildSurface(current_surface, params, is_render);
|
||||
}
|
||||
return match_check();
|
||||
}
|
||||
|
||||
/**
|
||||
* `TryReconstructSurface` unlike `RebuildSurface` where we know the registered surface
|
||||
|
@ -493,7 +495,7 @@ private:
|
|||
bool modified = false;
|
||||
TSurface new_surface = GetUncachedSurface(gpu_addr, params);
|
||||
u32 passed_tests = 0;
|
||||
for (auto surface : overlaps) {
|
||||
for (auto& surface : overlaps) {
|
||||
const SurfaceParams& src_params = surface->GetSurfaceParams();
|
||||
if (src_params.is_layered || src_params.num_levels > 1) {
|
||||
// We send this cases to recycle as they are more complex to handle
|
||||
|
@ -504,8 +506,7 @@ private:
|
|||
if (!mipmap_layer) {
|
||||
continue;
|
||||
}
|
||||
const u32 layer{mipmap_layer->first};
|
||||
const u32 mipmap{mipmap_layer->second};
|
||||
const auto [layer, mipmap] = *mipmap_layer;
|
||||
if (new_surface->GetMipmapSize(mipmap) != candidate_size) {
|
||||
continue;
|
||||
}
|
||||
|
@ -519,7 +520,7 @@ private:
|
|||
}
|
||||
if (passed_tests == 0) {
|
||||
return {};
|
||||
// In Accurate GPU all test should pass, else we recycle
|
||||
// In Accurate GPU all tests should pass, else we recycle
|
||||
} else if (Settings::values.use_accurate_gpu_emulation && passed_tests != overlaps.size()) {
|
||||
return {};
|
||||
}
|
||||
|
@ -548,7 +549,6 @@ private:
|
|||
**/
|
||||
std::pair<TSurface, TView> GetSurface(const GPUVAddr gpu_addr, const SurfaceParams& params,
|
||||
bool preserve_contents, bool is_render) {
|
||||
|
||||
const auto host_ptr{system.GPU().MemoryManager().GetPointer(gpu_addr)};
|
||||
const auto cache_addr{ToCacheAddr(host_ptr)};
|
||||
|
||||
|
@ -570,17 +570,17 @@ private:
|
|||
auto iter = l1_cache.find(cache_addr);
|
||||
if (iter != l1_cache.end()) {
|
||||
TSurface& current_surface = iter->second;
|
||||
auto topological_result = current_surface->MatchesTopology(params);
|
||||
const auto topological_result = current_surface->MatchesTopology(params);
|
||||
if (topological_result != MatchTopologyResult::FullMatch) {
|
||||
std::vector<TSurface> overlaps{current_surface};
|
||||
return RecycleSurface(overlaps, params, gpu_addr, preserve_contents,
|
||||
topological_result);
|
||||
}
|
||||
MatchStructureResult s_result = current_surface->MatchesStructure(params);
|
||||
if (s_result != MatchStructureResult::None &&
|
||||
const auto struct_result = current_surface->MatchesStructure(params);
|
||||
if (struct_result != MatchStructureResult::None &&
|
||||
(params.target != SurfaceTarget::Texture3D ||
|
||||
current_surface->MatchTarget(params.target))) {
|
||||
if (s_result == MatchStructureResult::FullMatch) {
|
||||
if (struct_result == MatchStructureResult::FullMatch) {
|
||||
return ManageStructuralMatch(current_surface, params, is_render);
|
||||
} else {
|
||||
return RebuildSurface(current_surface, params, is_render);
|
||||
|
@ -602,8 +602,8 @@ private:
|
|||
// Now we need to figure the relationship between the texture and its overlaps
|
||||
// we do a topological test to ensure we can find some relationship. If it fails
|
||||
// inmediatly recycle the texture
|
||||
for (auto surface : overlaps) {
|
||||
auto topological_result = surface->MatchesTopology(params);
|
||||
for (const auto& surface : overlaps) {
|
||||
const auto topological_result = surface->MatchesTopology(params);
|
||||
if (topological_result != MatchTopologyResult::FullMatch) {
|
||||
return RecycleSurface(overlaps, params, gpu_addr, preserve_contents,
|
||||
topological_result);
|
||||
|
@ -620,7 +620,7 @@ private:
|
|||
if (current_surface->GetGpuAddr() == gpu_addr) {
|
||||
std::optional<std::pair<TSurface, TView>> view =
|
||||
TryReconstructSurface(overlaps, params, gpu_addr);
|
||||
if (view.has_value()) {
|
||||
if (view) {
|
||||
return *view;
|
||||
}
|
||||
}
|
||||
|
@ -630,7 +630,7 @@ private:
|
|||
// Now we check if the candidate is a mipmap/layer of the overlap
|
||||
std::optional<TView> view =
|
||||
current_surface->EmplaceView(params, gpu_addr, candidate_size);
|
||||
if (view.has_value()) {
|
||||
if (view) {
|
||||
const bool is_mirage = !current_surface->MatchFormat(params.pixel_format);
|
||||
if (is_mirage) {
|
||||
// On a mirage view, we need to recreate the surface under this new view
|
||||
|
@ -669,7 +669,7 @@ private:
|
|||
// using the overlaps. If a single overlap fails, this will fail.
|
||||
std::optional<std::pair<TSurface, TView>> view =
|
||||
TryReconstructSurface(overlaps, params, gpu_addr);
|
||||
if (view.has_value()) {
|
||||
if (view) {
|
||||
return *view;
|
||||
}
|
||||
}
|
||||
|
@ -738,16 +738,16 @@ private:
|
|||
std::vector<TSurface> surfaces;
|
||||
while (start <= end) {
|
||||
std::vector<TSurface>& list = registry[start];
|
||||
for (auto& s : list) {
|
||||
if (!s->IsPicked() && s->Overlaps(cache_addr, cache_addr_end)) {
|
||||
s->MarkAsPicked(true);
|
||||
surfaces.push_back(s);
|
||||
for (auto& surface : list) {
|
||||
if (!surface->IsPicked() && surface->Overlaps(cache_addr, cache_addr_end)) {
|
||||
surface->MarkAsPicked(true);
|
||||
surfaces.push_back(surface);
|
||||
}
|
||||
}
|
||||
start++;
|
||||
}
|
||||
for (auto& s : surfaces) {
|
||||
s->MarkAsPicked(false);
|
||||
for (auto& surface : surfaces) {
|
||||
surface->MarkAsPicked(false);
|
||||
}
|
||||
return surfaces;
|
||||
}
|
||||
|
|
Reference in New Issue