diff options
| author | 2019-05-07 13:58:37 -0400 | |
|---|---|---|
| committer | 2019-06-20 21:36:12 -0300 | |
| commit | b711cdce782ee604edc3c52628eb76e6b9a08b72 (patch) | |
| tree | 0bbe1ee88b50d2ed5aa9886bf23c3c326015b11e /src/video_core/texture_cache | |
| parent | Implement Texture Cache V2 (diff) | |
| download | yuzu-b711cdce782ee604edc3c52628eb76e6b9a08b72.tar.gz yuzu-b711cdce782ee604edc3c52628eb76e6b9a08b72.tar.xz yuzu-b711cdce782ee604edc3c52628eb76e6b9a08b72.zip | |
Corrections to Structural Matching
The texture will now be reconstructed if the width only matches on GoB
alignment.
Diffstat (limited to 'src/video_core/texture_cache')
| -rw-r--r-- | src/video_core/texture_cache/surface_base.h | 66 | ||||
| -rw-r--r-- | src/video_core/texture_cache/texture_cache.h | 11 |
2 files changed, 53 insertions, 24 deletions
diff --git a/src/video_core/texture_cache/surface_base.h b/src/video_core/texture_cache/surface_base.h index 5fd7add0a..9c048eb88 100644 --- a/src/video_core/texture_cache/surface_base.h +++ b/src/video_core/texture_cache/surface_base.h | |||
| @@ -16,9 +16,8 @@ | |||
| 16 | #include "video_core/texture_cache/surface_params.h" | 16 | #include "video_core/texture_cache/surface_params.h" |
| 17 | #include "video_core/texture_cache/surface_view.h" | 17 | #include "video_core/texture_cache/surface_view.h" |
| 18 | 18 | ||
| 19 | template<class ForwardIt, class T, class Compare=std::less<>> | 19 | template <class ForwardIt, class T, class Compare = std::less<>> |
| 20 | ForwardIt binary_find(ForwardIt first, ForwardIt last, const T& value, Compare comp={}) | 20 | ForwardIt binary_find(ForwardIt first, ForwardIt last, const T& value, Compare comp = {}) { |
| 21 | { | ||
| 22 | // Note: BOTH type T and the type after ForwardIt is dereferenced | 21 | // Note: BOTH type T and the type after ForwardIt is dereferenced |
| 23 | // must be implicitly convertible to BOTH Type1 and Type2, used in Compare. | 22 | // must be implicitly convertible to BOTH Type1 and Type2, used in Compare. |
| 24 | // This is stricter than lower_bound requirement (see above) | 23 | // This is stricter than lower_bound requirement (see above) |
| @@ -33,8 +32,14 @@ class MemoryManager; | |||
| 33 | 32 | ||
| 34 | namespace VideoCommon { | 33 | namespace VideoCommon { |
| 35 | 34 | ||
| 36 | using VideoCore::Surface::SurfaceTarget; | ||
| 37 | using VideoCore::MortonSwizzleMode; | 35 | using VideoCore::MortonSwizzleMode; |
| 36 | using VideoCore::Surface::SurfaceTarget; | ||
| 37 | |||
| 38 | enum class MatchStructureResult : u32 { | ||
| 39 | FullMatch = 0, | ||
| 40 | SemiMatch = 1, | ||
| 41 | None = 2, | ||
| 42 | }; | ||
| 38 | 43 | ||
| 39 | class SurfaceBaseImpl { | 44 | class SurfaceBaseImpl { |
| 40 | public: | 45 | public: |
| @@ -106,17 +111,26 @@ public: | |||
| 106 | return std::tie(src_bpp, params.is_tiled) == std::tie(dst_bpp, rhs.is_tiled); | 111 | return std::tie(src_bpp, params.is_tiled) == std::tie(dst_bpp, rhs.is_tiled); |
| 107 | } | 112 | } |
| 108 | 113 | ||
| 109 | bool MatchesStructure(const SurfaceParams& rhs) const { | 114 | MatchStructureResult MatchesStructure(const SurfaceParams& rhs) const { |
| 110 | if (params.is_tiled) { | 115 | if (params.is_tiled) { |
| 111 | const u32 a_width1 = params.GetBlockAlignedWidth(); | 116 | if (std::tie(params.height, params.depth, params.block_width, params.block_height, |
| 112 | const u32 a_width2 = rhs.GetBlockAlignedWidth(); | 117 | params.block_depth, params.tile_width_spacing) == |
| 113 | return std::tie(a_width1, params.height, params.depth, params.block_width, | 118 | std::tie(rhs.height, rhs.depth, rhs.block_width, rhs.block_height, rhs.block_depth, |
| 114 | params.block_height, params.block_depth, params.tile_width_spacing) == | 119 | rhs.tile_width_spacing)) { |
| 115 | std::tie(a_width2, rhs.height, rhs.depth, rhs.block_width, rhs.block_height, | 120 | if (params.width == rhs.width) { |
| 116 | rhs.block_depth, rhs.tile_width_spacing); | 121 | return MatchStructureResult::FullMatch; |
| 122 | } | ||
| 123 | if (params.GetBlockAlignedWidth() == rhs.GetBlockAlignedWidth()) { | ||
| 124 | return MatchStructureResult::SemiMatch; | ||
| 125 | } | ||
| 126 | } | ||
| 127 | return MatchStructureResult::None; | ||
| 117 | } else { | 128 | } else { |
| 118 | return std::tie(params.width, params.height, params.pitch) == | 129 | if (std::tie(params.width, params.height, params.pitch) == |
| 119 | std::tie(rhs.width, rhs.height, rhs.pitch); | 130 | std::tie(rhs.width, rhs.height, rhs.pitch)) { |
| 131 | return MatchStructureResult::FullMatch; | ||
| 132 | } | ||
| 133 | return MatchStructureResult::None; | ||
| 120 | } | 134 | } |
| 121 | } | 135 | } |
| 122 | 136 | ||
| @@ -126,15 +140,16 @@ public: | |||
| 126 | const GPUVAddr relative_address = candidate_gpu_addr - gpu_addr; | 140 | const GPUVAddr relative_address = candidate_gpu_addr - gpu_addr; |
| 127 | const u32 layer = relative_address / layer_size; | 141 | const u32 layer = relative_address / layer_size; |
| 128 | const GPUVAddr mipmap_address = relative_address - layer_size * layer; | 142 | const GPUVAddr mipmap_address = relative_address - layer_size * layer; |
| 129 | const auto mipmap_it = binary_find(mipmap_offsets.begin(), mipmap_offsets.end(), mipmap_address); | 143 | const auto mipmap_it = |
| 144 | binary_find(mipmap_offsets.begin(), mipmap_offsets.end(), mipmap_address); | ||
| 130 | if (mipmap_it != mipmap_offsets.end()) { | 145 | if (mipmap_it != mipmap_offsets.end()) { |
| 131 | return {{layer, std::distance(mipmap_offsets.begin(), mipmap_it)}}; | 146 | return {{layer, std::distance(mipmap_offsets.begin(), mipmap_it)}}; |
| 132 | } | 147 | } |
| 133 | return {}; | 148 | return {}; |
| 134 | } | 149 | } |
| 135 | 150 | ||
| 136 | std::vector<CopyParams> BreakDown() const { | 151 | std::vector<CopyParams> BreakDown(const SurfaceParams& in_params) const { |
| 137 | auto set_up_copy = [](CopyParams& cp, const SurfaceParams& params, const u32 depth, | 152 | auto set_up_copy = [](CopyParams& cp, const u32 width, const u32 height, const u32 depth, |
| 138 | const u32 level) { | 153 | const u32 level) { |
| 139 | cp.source_x = 0; | 154 | cp.source_x = 0; |
| 140 | cp.source_y = 0; | 155 | cp.source_y = 0; |
| @@ -144,8 +159,8 @@ public: | |||
| 144 | cp.dest_z = 0; | 159 | cp.dest_z = 0; |
| 145 | cp.source_level = level; | 160 | cp.source_level = level; |
| 146 | cp.dest_level = level; | 161 | cp.dest_level = level; |
| 147 | cp.width = params.GetMipWidth(level); | 162 | cp.width = width; |
| 148 | cp.height = params.GetMipHeight(level); | 163 | cp.height = height; |
| 149 | cp.depth = depth; | 164 | cp.depth = depth; |
| 150 | }; | 165 | }; |
| 151 | const u32 layers = params.depth; | 166 | const u32 layers = params.depth; |
| @@ -156,7 +171,11 @@ public: | |||
| 156 | const u32 layer_offset = layer * mipmaps; | 171 | const u32 layer_offset = layer * mipmaps; |
| 157 | for (std::size_t level = 0; level < mipmaps; level++) { | 172 | for (std::size_t level = 0; level < mipmaps; level++) { |
| 158 | CopyParams& cp = result[layer_offset + level]; | 173 | CopyParams& cp = result[layer_offset + level]; |
| 159 | set_up_copy(cp, params, layer, level); | 174 | const u32 width = |
| 175 | std::min(params.GetMipWidth(level), in_params.GetMipWidth(level)); | ||
| 176 | const u32 height = | ||
| 177 | std::min(params.GetMipHeight(level), in_params.GetMipHeight(level)); | ||
| 178 | set_up_copy(cp, width, height, layer, level); | ||
| 160 | } | 179 | } |
| 161 | } | 180 | } |
| 162 | return result; | 181 | return result; |
| @@ -164,7 +183,11 @@ public: | |||
| 164 | std::vector<CopyParams> result{mipmaps}; | 183 | std::vector<CopyParams> result{mipmaps}; |
| 165 | for (std::size_t level = 0; level < mipmaps; level++) { | 184 | for (std::size_t level = 0; level < mipmaps; level++) { |
| 166 | CopyParams& cp = result[level]; | 185 | CopyParams& cp = result[level]; |
| 167 | set_up_copy(cp, params, params.GetMipDepth(level), level); | 186 | const u32 width = std::min(params.GetMipWidth(level), in_params.GetMipWidth(level)); |
| 187 | const u32 height = | ||
| 188 | std::min(params.GetMipHeight(level), in_params.GetMipHeight(level)); | ||
| 189 | const u32 depth = std::min(params.GetMipDepth(level), in_params.GetMipDepth(level)); | ||
| 190 | set_up_copy(cp, width, height, depth, level); | ||
| 168 | } | 191 | } |
| 169 | return result; | 192 | return result; |
| 170 | } | 193 | } |
| @@ -254,7 +277,8 @@ public: | |||
| 254 | std::optional<TView> EmplaceView(const SurfaceParams& view_params, const GPUVAddr view_addr) { | 277 | std::optional<TView> EmplaceView(const SurfaceParams& view_params, const GPUVAddr view_addr) { |
| 255 | if (view_addr < gpu_addr) | 278 | if (view_addr < gpu_addr) |
| 256 | return {}; | 279 | return {}; |
| 257 | if (params.target == SurfaceTarget::Texture3D || view_params.target == SurfaceTarget::Texture3D) { | 280 | if (params.target == SurfaceTarget::Texture3D || |
| 281 | view_params.target == SurfaceTarget::Texture3D) { | ||
| 258 | return {}; | 282 | return {}; |
| 259 | } | 283 | } |
| 260 | const std::size_t size = view_params.GetGuestSizeInBytes(); | 284 | const std::size_t size = view_params.GetGuestSizeInBytes(); |
diff --git a/src/video_core/texture_cache/texture_cache.h b/src/video_core/texture_cache/texture_cache.h index eb0d9bc10..f3b28453a 100644 --- a/src/video_core/texture_cache/texture_cache.h +++ b/src/video_core/texture_cache/texture_cache.h | |||
| @@ -284,7 +284,7 @@ private: | |||
| 284 | const SurfaceParams& params) { | 284 | const SurfaceParams& params) { |
| 285 | const auto gpu_addr = current_surface->GetGpuAddr(); | 285 | const auto gpu_addr = current_surface->GetGpuAddr(); |
| 286 | TSurface new_surface = GetUncachedSurface(gpu_addr, params); | 286 | TSurface new_surface = GetUncachedSurface(gpu_addr, params); |
| 287 | std::vector<CopyParams> bricks = current_surface->BreakDown(); | 287 | std::vector<CopyParams> bricks = current_surface->BreakDown(params); |
| 288 | for (auto& brick : bricks) { | 288 | for (auto& brick : bricks) { |
| 289 | ImageCopy(current_surface, new_surface, brick); | 289 | ImageCopy(current_surface, new_surface, brick); |
| 290 | } | 290 | } |
| @@ -370,11 +370,16 @@ private: | |||
| 370 | 370 | ||
| 371 | if (overlaps.size() == 1) { | 371 | if (overlaps.size() == 1) { |
| 372 | TSurface current_surface = overlaps[0]; | 372 | TSurface current_surface = overlaps[0]; |
| 373 | if (current_surface->MatchesStructure(params) && | 373 | MatchStructureResult s_result = current_surface->MatchesStructure(params); |
| 374 | if (s_result != MatchStructureResult::None && | ||
| 374 | current_surface->GetGpuAddr() == gpu_addr && | 375 | current_surface->GetGpuAddr() == gpu_addr && |
| 375 | (params.target != SurfaceTarget::Texture3D || | 376 | (params.target != SurfaceTarget::Texture3D || |
| 376 | current_surface->MatchTarget(params.target))) { | 377 | current_surface->MatchTarget(params.target))) { |
| 377 | return ManageStructuralMatch(current_surface, params); | 378 | if (s_result == MatchStructureResult::FullMatch) { |
| 379 | return ManageStructuralMatch(current_surface, params); | ||
| 380 | } else { | ||
| 381 | return RebuildMirage(current_surface, params); | ||
| 382 | } | ||
| 378 | } | 383 | } |
| 379 | if (current_surface->GetSizeInBytes() <= candidate_size) { | 384 | if (current_surface->GetSizeInBytes() <= candidate_size) { |
| 380 | return RecycleSurface(overlaps, params, gpu_addr, host_ptr, preserve_contents, | 385 | return RecycleSurface(overlaps, params, gpu_addr, host_ptr, preserve_contents, |