summaryrefslogtreecommitdiff
path: root/src/video_core/texture_cache
diff options
context:
space:
mode:
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.