Corrections to Structural Matching
The texture will now be reconstructed if the width only matches on GoB alignment.
This commit is contained in:
		 Fernando Sahmkow
					Fernando Sahmkow
				
			
				
					committed by
					
						 ReinUsesLisp
						ReinUsesLisp
					
				
			
			
				
	
			
			
			 ReinUsesLisp
						ReinUsesLisp
					
				
			
						parent
						
							bc930754cc
						
					
				
				
					commit
					b711cdce78
				
			| @@ -16,9 +16,8 @@ | ||||
| #include "video_core/texture_cache/surface_params.h" | ||||
| #include "video_core/texture_cache/surface_view.h" | ||||
|  | ||||
| template<class ForwardIt, class T, class Compare=std::less<>> | ||||
| ForwardIt binary_find(ForwardIt first, ForwardIt last, const T& value, Compare comp={}) | ||||
| { | ||||
| template <class ForwardIt, class T, class Compare = std::less<>> | ||||
| ForwardIt binary_find(ForwardIt first, ForwardIt last, const T& value, Compare comp = {}) { | ||||
|     // Note: BOTH type T and the type after ForwardIt is dereferenced | ||||
|     // must be implicitly convertible to BOTH Type1 and Type2, used in Compare. | ||||
|     // This is stricter than lower_bound requirement (see above) | ||||
| @@ -33,8 +32,14 @@ class MemoryManager; | ||||
|  | ||||
| namespace VideoCommon { | ||||
|  | ||||
| using VideoCore::Surface::SurfaceTarget; | ||||
| using VideoCore::MortonSwizzleMode; | ||||
| using VideoCore::Surface::SurfaceTarget; | ||||
|  | ||||
| enum class MatchStructureResult : u32 { | ||||
|     FullMatch = 0, | ||||
|     SemiMatch = 1, | ||||
|     None = 2, | ||||
| }; | ||||
|  | ||||
| class SurfaceBaseImpl { | ||||
| public: | ||||
| @@ -106,17 +111,26 @@ public: | ||||
|         return std::tie(src_bpp, params.is_tiled) == std::tie(dst_bpp, rhs.is_tiled); | ||||
|     } | ||||
|  | ||||
|     bool MatchesStructure(const SurfaceParams& rhs) const { | ||||
|     MatchStructureResult MatchesStructure(const SurfaceParams& rhs) const { | ||||
|         if (params.is_tiled) { | ||||
|             const u32 a_width1 = params.GetBlockAlignedWidth(); | ||||
|             const u32 a_width2 = rhs.GetBlockAlignedWidth(); | ||||
|             return std::tie(a_width1, params.height, params.depth, params.block_width, | ||||
|                             params.block_height, params.block_depth, params.tile_width_spacing) == | ||||
|                    std::tie(a_width2, rhs.height, rhs.depth, rhs.block_width, rhs.block_height, | ||||
|                             rhs.block_depth, rhs.tile_width_spacing); | ||||
|             if (std::tie(params.height, params.depth, params.block_width, params.block_height, | ||||
|                          params.block_depth, params.tile_width_spacing) == | ||||
|                 std::tie(rhs.height, rhs.depth, rhs.block_width, rhs.block_height, rhs.block_depth, | ||||
|                          rhs.tile_width_spacing)) { | ||||
|                 if (params.width == rhs.width) { | ||||
|                     return MatchStructureResult::FullMatch; | ||||
|                 } | ||||
|                 if (params.GetBlockAlignedWidth() == rhs.GetBlockAlignedWidth()) { | ||||
|                     return MatchStructureResult::SemiMatch; | ||||
|                 } | ||||
|             } | ||||
|             return MatchStructureResult::None; | ||||
|         } else { | ||||
|             return std::tie(params.width, params.height, params.pitch) == | ||||
|                    std::tie(rhs.width, rhs.height, rhs.pitch); | ||||
|             if (std::tie(params.width, params.height, params.pitch) == | ||||
|                 std::tie(rhs.width, rhs.height, rhs.pitch)) { | ||||
|                 return MatchStructureResult::FullMatch; | ||||
|             } | ||||
|             return MatchStructureResult::None; | ||||
|         } | ||||
|     } | ||||
|  | ||||
| @@ -126,15 +140,16 @@ public: | ||||
|         const GPUVAddr relative_address = candidate_gpu_addr - gpu_addr; | ||||
|         const u32 layer = relative_address / layer_size; | ||||
|         const GPUVAddr mipmap_address = relative_address - layer_size * layer; | ||||
|         const auto mipmap_it = binary_find(mipmap_offsets.begin(), mipmap_offsets.end(), mipmap_address); | ||||
|         const auto mipmap_it = | ||||
|             binary_find(mipmap_offsets.begin(), mipmap_offsets.end(), mipmap_address); | ||||
|         if (mipmap_it != mipmap_offsets.end()) { | ||||
|             return {{layer, std::distance(mipmap_offsets.begin(), mipmap_it)}}; | ||||
|         } | ||||
|         return {}; | ||||
|     } | ||||
|  | ||||
|     std::vector<CopyParams> BreakDown() const { | ||||
|         auto set_up_copy = [](CopyParams& cp, const SurfaceParams& params, const u32 depth, | ||||
|     std::vector<CopyParams> BreakDown(const SurfaceParams& in_params) const { | ||||
|         auto set_up_copy = [](CopyParams& cp, const u32 width, const u32 height, const u32 depth, | ||||
|                               const u32 level) { | ||||
|             cp.source_x = 0; | ||||
|             cp.source_y = 0; | ||||
| @@ -144,8 +159,8 @@ public: | ||||
|             cp.dest_z = 0; | ||||
|             cp.source_level = level; | ||||
|             cp.dest_level = level; | ||||
|             cp.width = params.GetMipWidth(level); | ||||
|             cp.height = params.GetMipHeight(level); | ||||
|             cp.width = width; | ||||
|             cp.height = height; | ||||
|             cp.depth = depth; | ||||
|         }; | ||||
|         const u32 layers = params.depth; | ||||
| @@ -156,7 +171,11 @@ public: | ||||
|                 const u32 layer_offset = layer * mipmaps; | ||||
|                 for (std::size_t level = 0; level < mipmaps; level++) { | ||||
|                     CopyParams& cp = result[layer_offset + level]; | ||||
|                     set_up_copy(cp, params, layer, level); | ||||
|                     const u32 width = | ||||
|                         std::min(params.GetMipWidth(level), in_params.GetMipWidth(level)); | ||||
|                     const u32 height = | ||||
|                         std::min(params.GetMipHeight(level), in_params.GetMipHeight(level)); | ||||
|                     set_up_copy(cp, width, height, layer, level); | ||||
|                 } | ||||
|             } | ||||
|             return result; | ||||
| @@ -164,7 +183,11 @@ public: | ||||
|             std::vector<CopyParams> result{mipmaps}; | ||||
|             for (std::size_t level = 0; level < mipmaps; level++) { | ||||
|                 CopyParams& cp = result[level]; | ||||
|                 set_up_copy(cp, params, params.GetMipDepth(level), level); | ||||
|                 const u32 width = std::min(params.GetMipWidth(level), in_params.GetMipWidth(level)); | ||||
|                 const u32 height = | ||||
|                     std::min(params.GetMipHeight(level), in_params.GetMipHeight(level)); | ||||
|                 const u32 depth = std::min(params.GetMipDepth(level), in_params.GetMipDepth(level)); | ||||
|                 set_up_copy(cp, width, height, depth, level); | ||||
|             } | ||||
|             return result; | ||||
|         } | ||||
| @@ -254,7 +277,8 @@ public: | ||||
|     std::optional<TView> EmplaceView(const SurfaceParams& view_params, const GPUVAddr view_addr) { | ||||
|         if (view_addr < gpu_addr) | ||||
|             return {}; | ||||
|         if (params.target == SurfaceTarget::Texture3D || view_params.target == SurfaceTarget::Texture3D) { | ||||
|         if (params.target == SurfaceTarget::Texture3D || | ||||
|             view_params.target == SurfaceTarget::Texture3D) { | ||||
|             return {}; | ||||
|         } | ||||
|         const std::size_t size = view_params.GetGuestSizeInBytes(); | ||||
|   | ||||
| @@ -284,7 +284,7 @@ private: | ||||
|                                              const SurfaceParams& params) { | ||||
|         const auto gpu_addr = current_surface->GetGpuAddr(); | ||||
|         TSurface new_surface = GetUncachedSurface(gpu_addr, params); | ||||
|         std::vector<CopyParams> bricks = current_surface->BreakDown(); | ||||
|         std::vector<CopyParams> bricks = current_surface->BreakDown(params); | ||||
|         for (auto& brick : bricks) { | ||||
|             ImageCopy(current_surface, new_surface, brick); | ||||
|         } | ||||
| @@ -370,11 +370,16 @@ private: | ||||
|  | ||||
|         if (overlaps.size() == 1) { | ||||
|             TSurface current_surface = overlaps[0]; | ||||
|             if (current_surface->MatchesStructure(params) && | ||||
|             MatchStructureResult s_result = current_surface->MatchesStructure(params); | ||||
|             if (s_result != MatchStructureResult::None && | ||||
|                 current_surface->GetGpuAddr() == gpu_addr && | ||||
|                 (params.target != SurfaceTarget::Texture3D || | ||||
|                  current_surface->MatchTarget(params.target))) { | ||||
|                 return ManageStructuralMatch(current_surface, params); | ||||
|                 if (s_result == MatchStructureResult::FullMatch) { | ||||
|                     return ManageStructuralMatch(current_surface, params); | ||||
|                 } else { | ||||
|                     return RebuildMirage(current_surface, params); | ||||
|                 } | ||||
|             } | ||||
|             if (current_surface->GetSizeInBytes() <= candidate_size) { | ||||
|                 return RecycleSurface(overlaps, params, gpu_addr, host_ptr, preserve_contents, | ||||
|   | ||||
		Reference in New Issue
	
	Block a user