diff options
Diffstat (limited to 'src/video_core/texture_cache')
| -rw-r--r-- | src/video_core/texture_cache/surface_base.h | 17 | ||||
| -rw-r--r-- | src/video_core/texture_cache/texture_cache.h | 26 |
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 | |||
| 186 | protected: | 196 | protected: |
| 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. |