yuzu-emu
/
yuzu-mainline
Archived
1
0
Fork 0

texture_cache: Remove preserve_contents

preserve_contents was always true. We can't assume we don't have to
preserve clears because scissored and color masked clears exist.

This removes preserve_contents and assumes it as true at all times.
This commit is contained in:
ReinUsesLisp 2020-04-11 01:50:58 -03:00
parent 51c6688e21
commit 94b0e2e5da
3 changed files with 31 additions and 47 deletions

View File

@ -345,7 +345,7 @@ void RasterizerOpenGL::ConfigureFramebuffers() {
texture_cache.GuardRenderTargets(true); texture_cache.GuardRenderTargets(true);
View depth_surface = texture_cache.GetDepthBufferSurface(true); View depth_surface = texture_cache.GetDepthBufferSurface();
const auto& regs = gpu.regs; const auto& regs = gpu.regs;
UNIMPLEMENTED_IF(regs.rt_separate_frag_data == 0); UNIMPLEMENTED_IF(regs.rt_separate_frag_data == 0);
@ -354,7 +354,7 @@ void RasterizerOpenGL::ConfigureFramebuffers() {
FramebufferCacheKey key; FramebufferCacheKey key;
const auto colors_count = static_cast<std::size_t>(regs.rt_control.count); const auto colors_count = static_cast<std::size_t>(regs.rt_control.count);
for (std::size_t index = 0; index < colors_count; ++index) { for (std::size_t index = 0; index < colors_count; ++index) {
View color_surface{texture_cache.GetColorBufferSurface(index, true)}; View color_surface{texture_cache.GetColorBufferSurface(index)};
if (!color_surface) { if (!color_surface) {
continue; continue;
} }
@ -387,12 +387,12 @@ void RasterizerOpenGL::ConfigureClearFramebuffer(bool using_color_fb, bool using
View color_surface; View color_surface;
if (using_color_fb) { if (using_color_fb) {
const std::size_t index = regs.clear_buffers.RT; const std::size_t index = regs.clear_buffers.RT;
color_surface = texture_cache.GetColorBufferSurface(index, true); color_surface = texture_cache.GetColorBufferSurface(index);
texture_cache.MarkColorBufferInUse(index); texture_cache.MarkColorBufferInUse(index);
} }
View depth_surface; View depth_surface;
if (using_depth_fb || using_stencil_fb) { if (using_depth_fb || using_stencil_fb) {
depth_surface = texture_cache.GetDepthBufferSurface(true); depth_surface = texture_cache.GetDepthBufferSurface();
texture_cache.MarkDepthBufferInUse(); texture_cache.MarkDepthBufferInUse();
} }
texture_cache.GuardRenderTargets(false); texture_cache.GuardRenderTargets(false);

View File

@ -599,7 +599,7 @@ RasterizerVulkan::Texceptions RasterizerVulkan::UpdateAttachments() {
Texceptions texceptions; Texceptions texceptions;
for (std::size_t rt = 0; rt < Maxwell::NumRenderTargets; ++rt) { for (std::size_t rt = 0; rt < Maxwell::NumRenderTargets; ++rt) {
if (update_rendertargets) { if (update_rendertargets) {
color_attachments[rt] = texture_cache.GetColorBufferSurface(rt, true); color_attachments[rt] = texture_cache.GetColorBufferSurface(rt);
} }
if (color_attachments[rt] && WalkAttachmentOverlaps(*color_attachments[rt])) { if (color_attachments[rt] && WalkAttachmentOverlaps(*color_attachments[rt])) {
texceptions[rt] = true; texceptions[rt] = true;
@ -607,7 +607,7 @@ RasterizerVulkan::Texceptions RasterizerVulkan::UpdateAttachments() {
} }
if (update_rendertargets) { if (update_rendertargets) {
zeta_attachment = texture_cache.GetDepthBufferSurface(true); zeta_attachment = texture_cache.GetDepthBufferSurface();
} }
if (zeta_attachment && WalkAttachmentOverlaps(*zeta_attachment)) { if (zeta_attachment && WalkAttachmentOverlaps(*zeta_attachment)) {
texceptions[ZETA_TEXCEPTION_INDEX] = true; texceptions[ZETA_TEXCEPTION_INDEX] = true;

View File

@ -108,7 +108,7 @@ public:
} }
const auto params{SurfaceParams::CreateForTexture(format_lookup_table, tic, entry)}; const auto params{SurfaceParams::CreateForTexture(format_lookup_table, tic, entry)};
const auto [surface, view] = GetSurface(gpu_addr, *cpu_addr, params, true, false); const auto [surface, view] = GetSurface(gpu_addr, *cpu_addr, params, false);
if (guard_samplers) { if (guard_samplers) {
sampled_textures.push_back(surface); sampled_textures.push_back(surface);
} }
@ -128,7 +128,7 @@ public:
return GetNullSurface(SurfaceParams::ExpectedTarget(entry)); return GetNullSurface(SurfaceParams::ExpectedTarget(entry));
} }
const auto params{SurfaceParams::CreateForImage(format_lookup_table, tic, entry)}; const auto params{SurfaceParams::CreateForImage(format_lookup_table, tic, entry)};
const auto [surface, view] = GetSurface(gpu_addr, *cpu_addr, params, true, false); const auto [surface, view] = GetSurface(gpu_addr, *cpu_addr, params, false);
if (guard_samplers) { if (guard_samplers) {
sampled_textures.push_back(surface); sampled_textures.push_back(surface);
} }
@ -143,7 +143,7 @@ public:
return any_rt; return any_rt;
} }
TView GetDepthBufferSurface(bool preserve_contents) { TView GetDepthBufferSurface() {
std::lock_guard lock{mutex}; std::lock_guard lock{mutex};
auto& maxwell3d = system.GPU().Maxwell3D(); auto& maxwell3d = system.GPU().Maxwell3D();
if (!maxwell3d.dirty.flags[VideoCommon::Dirty::ZetaBuffer]) { if (!maxwell3d.dirty.flags[VideoCommon::Dirty::ZetaBuffer]) {
@ -164,7 +164,7 @@ public:
return {}; return {};
} }
const auto depth_params{SurfaceParams::CreateForDepthBuffer(system)}; const auto depth_params{SurfaceParams::CreateForDepthBuffer(system)};
auto surface_view = GetSurface(gpu_addr, *cpu_addr, depth_params, preserve_contents, true); auto surface_view = GetSurface(gpu_addr, *cpu_addr, depth_params, true);
if (depth_buffer.target) if (depth_buffer.target)
depth_buffer.target->MarkAsRenderTarget(false, NO_RT); depth_buffer.target->MarkAsRenderTarget(false, NO_RT);
depth_buffer.target = surface_view.first; depth_buffer.target = surface_view.first;
@ -174,7 +174,7 @@ public:
return surface_view.second; return surface_view.second;
} }
TView GetColorBufferSurface(std::size_t index, bool preserve_contents) { TView GetColorBufferSurface(std::size_t index) {
std::lock_guard lock{mutex}; std::lock_guard lock{mutex};
ASSERT(index < Tegra::Engines::Maxwell3D::Regs::NumRenderTargets); ASSERT(index < Tegra::Engines::Maxwell3D::Regs::NumRenderTargets);
auto& maxwell3d = system.GPU().Maxwell3D(); auto& maxwell3d = system.GPU().Maxwell3D();
@ -204,9 +204,8 @@ public:
return {}; return {};
} }
auto surface_view = auto surface_view = GetSurface(gpu_addr, *cpu_addr,
GetSurface(gpu_addr, *cpu_addr, SurfaceParams::CreateForFramebuffer(system, index), SurfaceParams::CreateForFramebuffer(system, index), true);
preserve_contents, true);
if (render_targets[index].target) if (render_targets[index].target)
render_targets[index].target->MarkAsRenderTarget(false, NO_RT); render_targets[index].target->MarkAsRenderTarget(false, NO_RT);
render_targets[index].target = surface_view.first; render_targets[index].target = surface_view.first;
@ -260,9 +259,9 @@ public:
const std::optional<VAddr> src_cpu_addr = const std::optional<VAddr> src_cpu_addr =
system.GPU().MemoryManager().GpuToCpuAddress(src_gpu_addr); system.GPU().MemoryManager().GpuToCpuAddress(src_gpu_addr);
std::pair<TSurface, TView> dst_surface = std::pair<TSurface, TView> dst_surface =
GetSurface(dst_gpu_addr, *dst_cpu_addr, dst_params, true, false); GetSurface(dst_gpu_addr, *dst_cpu_addr, dst_params, false);
std::pair<TSurface, TView> src_surface = std::pair<TSurface, TView> src_surface =
GetSurface(src_gpu_addr, *src_cpu_addr, src_params, true, false); GetSurface(src_gpu_addr, *src_cpu_addr, src_params, false);
ImageBlit(src_surface.second, dst_surface.second, copy_config); ImageBlit(src_surface.second, dst_surface.second, copy_config);
dst_surface.first->MarkAsModified(true, Tick()); dst_surface.first->MarkAsModified(true, Tick());
} }
@ -451,22 +450,18 @@ private:
* @param overlaps The overlapping surfaces registered in the cache. * @param overlaps The overlapping surfaces registered in the cache.
* @param params The parameters for the new surface. * @param params The parameters for the new surface.
* @param gpu_addr The starting address of the new surface. * @param gpu_addr The starting address of the new surface.
* @param preserve_contents Indicates that the new surface should be loaded from memory or left
* blank.
* @param untopological Indicates to the recycler that the texture has no way to match the * @param untopological Indicates to the recycler that the texture has no way to match the
* overlaps due to topological reasons. * overlaps due to topological reasons.
**/ **/
std::pair<TSurface, TView> RecycleSurface(std::vector<TSurface>& overlaps, std::pair<TSurface, TView> RecycleSurface(std::vector<TSurface>& overlaps,
const SurfaceParams& params, const GPUVAddr gpu_addr, const SurfaceParams& params, const GPUVAddr gpu_addr,
const bool preserve_contents,
const MatchTopologyResult untopological) { const MatchTopologyResult untopological) {
const bool do_load = preserve_contents && Settings::values.use_accurate_gpu_emulation;
for (auto& surface : overlaps) { for (auto& surface : overlaps) {
Unregister(surface); Unregister(surface);
} }
switch (PickStrategy(overlaps, params, gpu_addr, untopological)) { switch (PickStrategy(overlaps, params, gpu_addr, untopological)) {
case RecycleStrategy::Ignore: { case RecycleStrategy::Ignore: {
return InitializeSurface(gpu_addr, params, do_load); return InitializeSurface(gpu_addr, params, Settings::values.use_accurate_gpu_emulation);
} }
case RecycleStrategy::Flush: { case RecycleStrategy::Flush: {
std::sort(overlaps.begin(), overlaps.end(), std::sort(overlaps.begin(), overlaps.end(),
@ -476,7 +471,7 @@ private:
for (auto& surface : overlaps) { for (auto& surface : overlaps) {
FlushSurface(surface); FlushSurface(surface);
} }
return InitializeSurface(gpu_addr, params, preserve_contents); return InitializeSurface(gpu_addr, params);
} }
case RecycleStrategy::BufferCopy: { case RecycleStrategy::BufferCopy: {
auto new_surface = GetUncachedSurface(gpu_addr, params); auto new_surface = GetUncachedSurface(gpu_addr, params);
@ -485,7 +480,7 @@ private:
} }
default: { default: {
UNIMPLEMENTED_MSG("Unimplemented Texture Cache Recycling Strategy!"); UNIMPLEMENTED_MSG("Unimplemented Texture Cache Recycling Strategy!");
return InitializeSurface(gpu_addr, params, do_load); return InitializeSurface(gpu_addr, params);
} }
} }
} }
@ -621,14 +616,11 @@ private:
* @param params The parameters on the new surface. * @param params The parameters on the new surface.
* @param gpu_addr The starting address of the new surface. * @param gpu_addr The starting address of the new surface.
* @param cache_addr The starting address of the new surface on physical memory. * @param cache_addr The starting address of the new surface on physical memory.
* @param preserve_contents Indicates that the new surface should be loaded from memory or
* left blank.
*/ */
std::optional<std::pair<TSurface, TView>> Manage3DSurfaces(std::vector<TSurface>& overlaps, std::optional<std::pair<TSurface, TView>> Manage3DSurfaces(std::vector<TSurface>& overlaps,
const SurfaceParams& params, const SurfaceParams& params,
const GPUVAddr gpu_addr, const GPUVAddr gpu_addr,
const VAddr cpu_addr, const VAddr cpu_addr) {
bool preserve_contents) {
if (params.target == SurfaceTarget::Texture3D) { if (params.target == SurfaceTarget::Texture3D) {
bool failed = false; bool failed = false;
if (params.num_levels > 1) { if (params.num_levels > 1) {
@ -677,7 +669,7 @@ private:
return std::nullopt; return std::nullopt;
} }
Unregister(surface); Unregister(surface);
return InitializeSurface(gpu_addr, params, preserve_contents); return InitializeSurface(gpu_addr, params);
} }
return std::nullopt; return std::nullopt;
} }
@ -688,7 +680,7 @@ private:
return {{surface, surface->GetMainView()}}; return {{surface, surface->GetMainView()}};
} }
} }
return InitializeSurface(gpu_addr, params, preserve_contents); return InitializeSurface(gpu_addr, params);
} }
} }
@ -711,13 +703,10 @@ private:
* *
* @param gpu_addr The starting address of the candidate surface. * @param gpu_addr The starting address of the candidate surface.
* @param params The parameters on the candidate surface. * @param params The parameters on the candidate surface.
* @param preserve_contents Indicates that the new surface should be loaded from memory or
* left blank.
* @param is_render Whether or not the surface is a render target. * @param is_render Whether or not the surface is a render target.
**/ **/
std::pair<TSurface, TView> GetSurface(const GPUVAddr gpu_addr, const VAddr cpu_addr, std::pair<TSurface, TView> GetSurface(const GPUVAddr gpu_addr, const VAddr cpu_addr,
const SurfaceParams& params, bool preserve_contents, const SurfaceParams& params, bool is_render) {
bool is_render) {
// Step 1 // Step 1
// Check Level 1 Cache for a fast structural match. If candidate surface // Check Level 1 Cache for a fast structural match. If candidate surface
// matches at certain level we are pretty much done. // matches at certain level we are pretty much done.
@ -726,8 +715,7 @@ private:
const auto topological_result = current_surface->MatchesTopology(params); const auto topological_result = current_surface->MatchesTopology(params);
if (topological_result != MatchTopologyResult::FullMatch) { if (topological_result != MatchTopologyResult::FullMatch) {
std::vector<TSurface> overlaps{current_surface}; std::vector<TSurface> overlaps{current_surface};
return RecycleSurface(overlaps, params, gpu_addr, preserve_contents, return RecycleSurface(overlaps, params, gpu_addr, topological_result);
topological_result);
} }
const auto struct_result = current_surface->MatchesStructure(params); const auto struct_result = current_surface->MatchesStructure(params);
@ -752,7 +740,7 @@ private:
// If none are found, we are done. we just load the surface and create it. // If none are found, we are done. we just load the surface and create it.
if (overlaps.empty()) { if (overlaps.empty()) {
return InitializeSurface(gpu_addr, params, preserve_contents); return InitializeSurface(gpu_addr, params);
} }
// Step 3 // Step 3
@ -762,15 +750,13 @@ private:
for (const auto& surface : overlaps) { for (const auto& surface : overlaps) {
const auto topological_result = surface->MatchesTopology(params); const auto topological_result = surface->MatchesTopology(params);
if (topological_result != MatchTopologyResult::FullMatch) { if (topological_result != MatchTopologyResult::FullMatch) {
return RecycleSurface(overlaps, params, gpu_addr, preserve_contents, return RecycleSurface(overlaps, params, gpu_addr, topological_result);
topological_result);
} }
} }
// Check if it's a 3D texture // Check if it's a 3D texture
if (params.block_depth > 0) { if (params.block_depth > 0) {
auto surface = auto surface = Manage3DSurfaces(overlaps, params, gpu_addr, cpu_addr);
Manage3DSurfaces(overlaps, params, gpu_addr, cpu_addr, preserve_contents);
if (surface) { if (surface) {
return *surface; return *surface;
} }
@ -790,8 +776,7 @@ private:
return *view; return *view;
} }
} }
return RecycleSurface(overlaps, params, gpu_addr, preserve_contents, return RecycleSurface(overlaps, params, gpu_addr, MatchTopologyResult::FullMatch);
MatchTopologyResult::FullMatch);
} }
// Now we check if the candidate is a mipmap/layer of the overlap // Now we check if the candidate is a mipmap/layer of the overlap
std::optional<TView> view = std::optional<TView> view =
@ -815,7 +800,7 @@ private:
pair.first->EmplaceView(params, gpu_addr, candidate_size); pair.first->EmplaceView(params, gpu_addr, candidate_size);
if (mirage_view) if (mirage_view)
return {pair.first, *mirage_view}; return {pair.first, *mirage_view};
return RecycleSurface(overlaps, params, gpu_addr, preserve_contents, return RecycleSurface(overlaps, params, gpu_addr,
MatchTopologyResult::FullMatch); MatchTopologyResult::FullMatch);
} }
return {current_surface, *view}; return {current_surface, *view};
@ -831,8 +816,7 @@ private:
} }
} }
// We failed all the tests, recycle the overlaps into a new texture. // We failed all the tests, recycle the overlaps into a new texture.
return RecycleSurface(overlaps, params, gpu_addr, preserve_contents, return RecycleSurface(overlaps, params, gpu_addr, MatchTopologyResult::FullMatch);
MatchTopologyResult::FullMatch);
} }
/** /**
@ -990,10 +974,10 @@ private:
} }
std::pair<TSurface, TView> InitializeSurface(GPUVAddr gpu_addr, const SurfaceParams& params, std::pair<TSurface, TView> InitializeSurface(GPUVAddr gpu_addr, const SurfaceParams& params,
bool preserve_contents) { bool do_load = true) {
auto new_surface{GetUncachedSurface(gpu_addr, params)}; auto new_surface{GetUncachedSurface(gpu_addr, params)};
Register(new_surface); Register(new_surface);
if (preserve_contents) { if (do_load) {
LoadSurface(new_surface); LoadSurface(new_surface);
} }
return {new_surface, new_surface->GetMainView()}; return {new_surface, new_surface->GetMainView()};