summaryrefslogtreecommitdiff
path: root/src/video_core/texture_cache
diff options
context:
space:
mode:
authorGravatar Fernando Sahmkow2019-05-07 13:58:37 -0400
committerGravatar ReinUsesLisp2019-06-20 21:36:12 -0300
commitb711cdce782ee604edc3c52628eb76e6b9a08b72 (patch)
tree0bbe1ee88b50d2ed5aa9886bf23c3c326015b11e /src/video_core/texture_cache
parentImplement Texture Cache V2 (diff)
downloadyuzu-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.h66
-rw-r--r--src/video_core/texture_cache/texture_cache.h11
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
19template<class ForwardIt, class T, class Compare=std::less<>> 19template <class ForwardIt, class T, class Compare = std::less<>>
20ForwardIt binary_find(ForwardIt first, ForwardIt last, const T& value, Compare comp={}) 20ForwardIt 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
34namespace VideoCommon { 33namespace VideoCommon {
35 34
36using VideoCore::Surface::SurfaceTarget;
37using VideoCore::MortonSwizzleMode; 35using VideoCore::MortonSwizzleMode;
36using VideoCore::Surface::SurfaceTarget;
37
38enum class MatchStructureResult : u32 {
39 FullMatch = 0,
40 SemiMatch = 1,
41 None = 2,
42};
38 43
39class SurfaceBaseImpl { 44class SurfaceBaseImpl {
40public: 45public:
@@ -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,