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