summaryrefslogtreecommitdiff
path: root/src/video_core/texture_cache
diff options
context:
space:
mode:
authorGravatar Fernando Sahmkow2019-05-08 17:45:59 -0400
committerGravatar ReinUsesLisp2019-06-20 21:36:12 -0300
commit4e2071b6d9b414fa0152deb5e9d55674d636afe4 (patch)
treede07e334d6d345852d289903be961f494b70b2a1 /src/video_core/texture_cache
parenttexture_cache: Implement guest flushing (diff)
downloadyuzu-4e2071b6d9b414fa0152deb5e9d55674d636afe4.tar.gz
yuzu-4e2071b6d9b414fa0152deb5e9d55674d636afe4.tar.xz
yuzu-4e2071b6d9b414fa0152deb5e9d55674d636afe4.zip
texture_cache: Correct premature texceptions
Due to our current infrastructure, it is possible for a mipmap to be set on as a render target before a texception of that mipmap's superset be set afterwards. This is problematic as we rely on texture views to set up texceptions and protecting render targets targets for 3D texture rendering. One simple solution is to configure framebuffers after texture setup but this brings other problems. This solution, forces a reconfiguration of the framebuffers after such event happens.
Diffstat (limited to 'src/video_core/texture_cache')
-rw-r--r--src/video_core/texture_cache/surface_base.h17
-rw-r--r--src/video_core/texture_cache/texture_cache.h26
2 files changed, 36 insertions, 7 deletions
diff --git a/src/video_core/texture_cache/surface_base.h b/src/video_core/texture_cache/surface_base.h
index 017ee999e..179e80ddb 100644
--- a/src/video_core/texture_cache/surface_base.h
+++ b/src/video_core/texture_cache/surface_base.h
@@ -55,6 +55,11 @@ public:
55 return (cache_addr < end) && (cache_addr_end > start); 55 return (cache_addr < end) && (cache_addr_end > start);
56 } 56 }
57 57
58 bool IsInside(const GPUVAddr other_start, const GPUVAddr other_end) {
59 const GPUVAddr gpu_addr_end = gpu_addr + guest_memory_size;
60 return (gpu_addr <= other_start && other_end <= gpu_addr_end);
61 }
62
58 // Use only when recycling a surface 63 // Use only when recycling a surface
59 void SetGpuAddr(const GPUVAddr new_addr) { 64 void SetGpuAddr(const GPUVAddr new_addr) {
60 gpu_addr = new_addr; 65 gpu_addr = new_addr;
@@ -105,6 +110,12 @@ public:
105 return params.target == target; 110 return params.target == target;
106 } 111 }
107 112
113 bool MatchesSubTexture(const SurfaceParams& rhs, const GPUVAddr other_gpu_addr) const {
114 return std::tie(gpu_addr, params.target, params.num_levels) ==
115 std::tie(other_gpu_addr, rhs.target, rhs.num_levels) &&
116 params.target == SurfaceTarget::Texture2D && params.num_levels == 1;
117 }
118
108 bool MatchesTopology(const SurfaceParams& rhs) const { 119 bool MatchesTopology(const SurfaceParams& rhs) const {
109 const u32 src_bpp{params.GetBytesPerPixel()}; 120 const u32 src_bpp{params.GetBytesPerPixel()};
110 const u32 dst_bpp{rhs.GetBytesPerPixel()}; 121 const u32 dst_bpp{rhs.GetBytesPerPixel()};
@@ -121,9 +132,9 @@ public:
121 } 132 }
122 // Tiled surface 133 // Tiled surface
123 if (std::tie(params.height, params.depth, params.block_width, params.block_height, 134 if (std::tie(params.height, params.depth, params.block_width, params.block_height,
124 params.block_depth, params.tile_width_spacing) == 135 params.block_depth, params.tile_width_spacing, params.num_levels) ==
125 std::tie(rhs.height, rhs.depth, rhs.block_width, rhs.block_height, rhs.block_depth, 136 std::tie(rhs.height, rhs.depth, rhs.block_width, rhs.block_height, rhs.block_depth,
126 rhs.tile_width_spacing)) { 137 rhs.tile_width_spacing, rhs.num_levels)) {
127 if (params.width == rhs.width) { 138 if (params.width == rhs.width) {
128 return MatchStructureResult::FullMatch; 139 return MatchStructureResult::FullMatch;
129 } 140 }
@@ -259,7 +270,7 @@ public:
259 270
260 std::optional<TView> EmplaceView(const SurfaceParams& view_params, const GPUVAddr view_addr) { 271 std::optional<TView> EmplaceView(const SurfaceParams& view_params, const GPUVAddr view_addr) {
261 if (view_addr < gpu_addr || params.target == SurfaceTarget::Texture3D || 272 if (view_addr < gpu_addr || params.target == SurfaceTarget::Texture3D ||
262 view_params.target == SurfaceTarget::Texture3D) { 273 params.num_levels == 1 || view_params.target == SurfaceTarget::Texture3D) {
263 return {}; 274 return {};
264 } 275 }
265 const auto layer_mipmap{GetLayerMipmap(view_addr)}; 276 const auto layer_mipmap{GetLayerMipmap(view_addr)};
diff --git a/src/video_core/texture_cache/texture_cache.h b/src/video_core/texture_cache/texture_cache.h
index 422bf3e58..96d108147 100644
--- a/src/video_core/texture_cache/texture_cache.h
+++ b/src/video_core/texture_cache/texture_cache.h
@@ -120,6 +120,10 @@ public:
120 return {}; 120 return {};
121 } 121 }
122 122
123 if (regs.color_mask[index].raw == 0) {
124 return {};
125 }
126
123 auto surface_view = GetSurface(gpu_addr, SurfaceParams::CreateForFramebuffer(system, index), 127 auto surface_view = GetSurface(gpu_addr, SurfaceParams::CreateForFramebuffer(system, index),
124 preserve_contents); 128 preserve_contents);
125 if (render_targets[index].target) 129 if (render_targets[index].target)
@@ -183,6 +187,12 @@ public:
183 return ++ticks; 187 return ++ticks;
184 } 188 }
185 189
190 bool ConsumeReconfigurationFlag() {
191 const bool result = force_reconfiguration;
192 force_reconfiguration = false;
193 return result;
194 }
195
186protected: 196protected:
187 TextureCache(Core::System& system, VideoCore::RasterizerInterface& rasterizer) 197 TextureCache(Core::System& system, VideoCore::RasterizerInterface& rasterizer)
188 : system{system}, rasterizer{rasterizer} { 198 : system{system}, rasterizer{rasterizer} {
@@ -219,9 +229,10 @@ protected:
219 rasterizer.UpdatePagesCachedCount(*cpu_addr, size, 1); 229 rasterizer.UpdatePagesCachedCount(*cpu_addr, size, 1);
220 } 230 }
221 231
222 void Unregister(TSurface surface) { 232 void Unregister(TSurface surface, const bool force_unregister = false) {
223 if (surface->IsProtected()) 233 if (surface->IsProtected() && !force_unregister) {
224 return; 234 return;
235 }
225 const GPUVAddr gpu_addr = surface->GetGpuAddr(); 236 const GPUVAddr gpu_addr = surface->GetGpuAddr();
226 const CacheAddr cache_ptr = surface->GetCacheAddr(); 237 const CacheAddr cache_ptr = surface->GetCacheAddr();
227 const std::size_t size = surface->GetSizeInBytes(); 238 const std::size_t size = surface->GetSizeInBytes();
@@ -365,8 +376,10 @@ private:
365 std::min(src_params.height, dst_height), 1); 376 std::min(src_params.height, dst_height), 1);
366 ImageCopy(surface, new_surface, copy_params); 377 ImageCopy(surface, new_surface, copy_params);
367 } 378 }
379 force_reconfiguration = false;
368 for (auto surface : overlaps) { 380 for (auto surface : overlaps) {
369 Unregister(surface); 381 force_reconfiguration |= surface->IsProtected();
382 Unregister(surface, true);
370 } 383 }
371 Register(new_surface); 384 Register(new_surface);
372 return {{new_surface, new_surface->GetMainView()}}; 385 return {{new_surface, new_surface->GetMainView()}};
@@ -379,6 +392,7 @@ private:
379 const auto cache_addr{ToCacheAddr(host_ptr)}; 392 const auto cache_addr{ToCacheAddr(host_ptr)};
380 const std::size_t candidate_size = params.GetGuestSizeInBytes(); 393 const std::size_t candidate_size = params.GetGuestSizeInBytes();
381 auto overlaps{GetSurfacesInRegion(cache_addr, candidate_size)}; 394 auto overlaps{GetSurfacesInRegion(cache_addr, candidate_size)};
395
382 if (overlaps.empty()) { 396 if (overlaps.empty()) {
383 return InitializeSurface(gpu_addr, params, preserve_contents); 397 return InitializeSurface(gpu_addr, params, preserve_contents);
384 } 398 }
@@ -403,7 +417,7 @@ private:
403 return RebuildSurface(current_surface, params); 417 return RebuildSurface(current_surface, params);
404 } 418 }
405 } 419 }
406 if (current_surface->GetSizeInBytes() <= candidate_size) { 420 if (!current_surface->IsInside(gpu_addr, gpu_addr + candidate_size)) {
407 return RecycleSurface(overlaps, params, gpu_addr, host_ptr, preserve_contents, 421 return RecycleSurface(overlaps, params, gpu_addr, host_ptr, preserve_contents,
408 false); 422 false);
409 } 423 }
@@ -530,6 +544,10 @@ private:
530 544
531 u64 ticks{}; 545 u64 ticks{};
532 546
547 // Sometimes Setup Textures can hit a surface that's on the render target, when this happens
548 // we force a reconfiguration of the frame buffer after setup.
549 bool force_reconfiguration;
550
533 // The internal Cache is different for the Texture Cache. It's based on buckets 551 // The internal Cache is different for the Texture Cache. It's based on buckets
534 // of 1MB. This fits better for the purpose of this cache as textures are normaly 552 // of 1MB. This fits better for the purpose of this cache as textures are normaly
535 // large in size. 553 // large in size.