Merge pull request #3805 from ReinUsesLisp/preserve-contents
texture_cache: Reintroduce preserve_contents accurately
This commit is contained in:
commit
da2b8295e1
|
@ -348,7 +348,7 @@ void RasterizerOpenGL::ConfigureFramebuffers() {
|
||||||
|
|
||||||
texture_cache.GuardRenderTargets(true);
|
texture_cache.GuardRenderTargets(true);
|
||||||
|
|
||||||
View depth_surface = texture_cache.GetDepthBufferSurface();
|
View depth_surface = texture_cache.GetDepthBufferSurface(true);
|
||||||
|
|
||||||
const auto& regs = gpu.regs;
|
const auto& regs = gpu.regs;
|
||||||
UNIMPLEMENTED_IF(regs.rt_separate_frag_data == 0);
|
UNIMPLEMENTED_IF(regs.rt_separate_frag_data == 0);
|
||||||
|
@ -357,7 +357,7 @@ void RasterizerOpenGL::ConfigureFramebuffers() {
|
||||||
FramebufferCacheKey key;
|
FramebufferCacheKey key;
|
||||||
const auto colors_count = static_cast<std::size_t>(regs.rt_control.count);
|
const auto colors_count = static_cast<std::size_t>(regs.rt_control.count);
|
||||||
for (std::size_t index = 0; index < colors_count; ++index) {
|
for (std::size_t index = 0; index < colors_count; ++index) {
|
||||||
View color_surface{texture_cache.GetColorBufferSurface(index)};
|
View color_surface{texture_cache.GetColorBufferSurface(index, true)};
|
||||||
if (!color_surface) {
|
if (!color_surface) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
@ -381,28 +381,52 @@ void RasterizerOpenGL::ConfigureFramebuffers() {
|
||||||
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, framebuffer_cache.GetFramebuffer(key));
|
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, framebuffer_cache.GetFramebuffer(key));
|
||||||
}
|
}
|
||||||
|
|
||||||
void RasterizerOpenGL::ConfigureClearFramebuffer(bool using_color_fb, bool using_depth_fb,
|
void RasterizerOpenGL::ConfigureClearFramebuffer(bool using_color, bool using_depth_stencil) {
|
||||||
bool using_stencil_fb) {
|
|
||||||
auto& gpu = system.GPU().Maxwell3D();
|
auto& gpu = system.GPU().Maxwell3D();
|
||||||
const auto& regs = gpu.regs;
|
const auto& regs = gpu.regs;
|
||||||
|
|
||||||
texture_cache.GuardRenderTargets(true);
|
texture_cache.GuardRenderTargets(true);
|
||||||
View color_surface;
|
View color_surface;
|
||||||
if (using_color_fb) {
|
|
||||||
|
if (using_color) {
|
||||||
|
// Determine if we have to preserve the contents.
|
||||||
|
// First we have to make sure all clear masks are enabled.
|
||||||
|
bool preserve_contents = !regs.clear_buffers.R || !regs.clear_buffers.G ||
|
||||||
|
!regs.clear_buffers.B || !regs.clear_buffers.A;
|
||||||
const std::size_t index = regs.clear_buffers.RT;
|
const std::size_t index = regs.clear_buffers.RT;
|
||||||
color_surface = texture_cache.GetColorBufferSurface(index);
|
if (regs.clear_flags.scissor) {
|
||||||
|
// Then we have to confirm scissor testing clears the whole image.
|
||||||
|
const auto& scissor = regs.scissor_test[0];
|
||||||
|
preserve_contents |= scissor.min_x > 0;
|
||||||
|
preserve_contents |= scissor.min_y > 0;
|
||||||
|
preserve_contents |= scissor.max_x < regs.rt[index].width;
|
||||||
|
preserve_contents |= scissor.max_y < regs.rt[index].height;
|
||||||
|
}
|
||||||
|
|
||||||
|
color_surface = texture_cache.GetColorBufferSurface(index, preserve_contents);
|
||||||
texture_cache.MarkColorBufferInUse(index);
|
texture_cache.MarkColorBufferInUse(index);
|
||||||
}
|
}
|
||||||
|
|
||||||
View depth_surface;
|
View depth_surface;
|
||||||
if (using_depth_fb || using_stencil_fb) {
|
if (using_depth_stencil) {
|
||||||
depth_surface = texture_cache.GetDepthBufferSurface();
|
bool preserve_contents = false;
|
||||||
|
if (regs.clear_flags.scissor) {
|
||||||
|
// For depth stencil clears we only have to confirm scissor test covers the whole image.
|
||||||
|
const auto& scissor = regs.scissor_test[0];
|
||||||
|
preserve_contents |= scissor.min_x > 0;
|
||||||
|
preserve_contents |= scissor.min_y > 0;
|
||||||
|
preserve_contents |= scissor.max_x < regs.zeta_width;
|
||||||
|
preserve_contents |= scissor.max_y < regs.zeta_height;
|
||||||
|
}
|
||||||
|
|
||||||
|
depth_surface = texture_cache.GetDepthBufferSurface(preserve_contents);
|
||||||
texture_cache.MarkDepthBufferInUse();
|
texture_cache.MarkDepthBufferInUse();
|
||||||
}
|
}
|
||||||
texture_cache.GuardRenderTargets(false);
|
texture_cache.GuardRenderTargets(false);
|
||||||
|
|
||||||
FramebufferCacheKey key;
|
FramebufferCacheKey key;
|
||||||
key.colors[0] = color_surface;
|
key.colors[0] = std::move(color_surface);
|
||||||
key.zeta = depth_surface;
|
key.zeta = std::move(depth_surface);
|
||||||
|
|
||||||
state_tracker.NotifyFramebuffer();
|
state_tracker.NotifyFramebuffer();
|
||||||
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, framebuffer_cache.GetFramebuffer(key));
|
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, framebuffer_cache.GetFramebuffer(key));
|
||||||
|
@ -422,8 +446,7 @@ void RasterizerOpenGL::Clear() {
|
||||||
if (regs.clear_buffers.R || regs.clear_buffers.G || regs.clear_buffers.B ||
|
if (regs.clear_buffers.R || regs.clear_buffers.G || regs.clear_buffers.B ||
|
||||||
regs.clear_buffers.A) {
|
regs.clear_buffers.A) {
|
||||||
use_color = true;
|
use_color = true;
|
||||||
}
|
|
||||||
if (use_color) {
|
|
||||||
state_tracker.NotifyColorMask0();
|
state_tracker.NotifyColorMask0();
|
||||||
glColorMaski(0, regs.clear_buffers.R != 0, regs.clear_buffers.G != 0,
|
glColorMaski(0, regs.clear_buffers.R != 0, regs.clear_buffers.G != 0,
|
||||||
regs.clear_buffers.B != 0, regs.clear_buffers.A != 0);
|
regs.clear_buffers.B != 0, regs.clear_buffers.A != 0);
|
||||||
|
@ -461,7 +484,7 @@ void RasterizerOpenGL::Clear() {
|
||||||
|
|
||||||
UNIMPLEMENTED_IF(regs.clear_flags.viewport);
|
UNIMPLEMENTED_IF(regs.clear_flags.viewport);
|
||||||
|
|
||||||
ConfigureClearFramebuffer(use_color, use_depth, use_stencil);
|
ConfigureClearFramebuffer(use_color, use_depth || use_stencil);
|
||||||
|
|
||||||
if (use_color) {
|
if (use_color) {
|
||||||
glClearBufferfv(GL_COLOR, 0, regs.clear_color);
|
glClearBufferfv(GL_COLOR, 0, regs.clear_color);
|
||||||
|
|
|
@ -95,7 +95,8 @@ private:
|
||||||
/// Configures the color and depth framebuffer states.
|
/// Configures the color and depth framebuffer states.
|
||||||
void ConfigureFramebuffers();
|
void ConfigureFramebuffers();
|
||||||
|
|
||||||
void ConfigureClearFramebuffer(bool using_color_fb, bool using_depth_fb, bool using_stencil_fb);
|
/// Configures the color and depth framebuffer for clearing.
|
||||||
|
void ConfigureClearFramebuffer(bool using_color, bool using_depth_stencil);
|
||||||
|
|
||||||
/// Configures the current constbuffers to use for the draw command.
|
/// Configures the current constbuffers to use for the draw command.
|
||||||
void SetupDrawConstBuffers(std::size_t stage_index, const Shader& shader);
|
void SetupDrawConstBuffers(std::size_t stage_index, const Shader& shader);
|
||||||
|
|
|
@ -656,7 +656,7 @@ RasterizerVulkan::Texceptions RasterizerVulkan::UpdateAttachments() {
|
||||||
Texceptions texceptions;
|
Texceptions texceptions;
|
||||||
for (std::size_t rt = 0; rt < Maxwell::NumRenderTargets; ++rt) {
|
for (std::size_t rt = 0; rt < Maxwell::NumRenderTargets; ++rt) {
|
||||||
if (update_rendertargets) {
|
if (update_rendertargets) {
|
||||||
color_attachments[rt] = texture_cache.GetColorBufferSurface(rt);
|
color_attachments[rt] = texture_cache.GetColorBufferSurface(rt, true);
|
||||||
}
|
}
|
||||||
if (color_attachments[rt] && WalkAttachmentOverlaps(*color_attachments[rt])) {
|
if (color_attachments[rt] && WalkAttachmentOverlaps(*color_attachments[rt])) {
|
||||||
texceptions[rt] = true;
|
texceptions[rt] = true;
|
||||||
|
@ -664,7 +664,7 @@ RasterizerVulkan::Texceptions RasterizerVulkan::UpdateAttachments() {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (update_rendertargets) {
|
if (update_rendertargets) {
|
||||||
zeta_attachment = texture_cache.GetDepthBufferSurface();
|
zeta_attachment = texture_cache.GetDepthBufferSurface(true);
|
||||||
}
|
}
|
||||||
if (zeta_attachment && WalkAttachmentOverlaps(*zeta_attachment)) {
|
if (zeta_attachment && WalkAttachmentOverlaps(*zeta_attachment)) {
|
||||||
texceptions[ZETA_TEXCEPTION_INDEX] = true;
|
texceptions[ZETA_TEXCEPTION_INDEX] = true;
|
||||||
|
|
|
@ -143,7 +143,7 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
const auto params{SurfaceParams::CreateForTexture(format_lookup_table, tic, entry)};
|
const auto params{SurfaceParams::CreateForTexture(format_lookup_table, tic, entry)};
|
||||||
const auto [surface, view] = GetSurface(gpu_addr, *cpu_addr, params, false);
|
const auto [surface, view] = GetSurface(gpu_addr, *cpu_addr, params, true, false);
|
||||||
if (guard_samplers) {
|
if (guard_samplers) {
|
||||||
sampled_textures.push_back(surface);
|
sampled_textures.push_back(surface);
|
||||||
}
|
}
|
||||||
|
@ -163,7 +163,7 @@ public:
|
||||||
return GetNullSurface(SurfaceParams::ExpectedTarget(entry));
|
return GetNullSurface(SurfaceParams::ExpectedTarget(entry));
|
||||||
}
|
}
|
||||||
const auto params{SurfaceParams::CreateForImage(format_lookup_table, tic, entry)};
|
const auto params{SurfaceParams::CreateForImage(format_lookup_table, tic, entry)};
|
||||||
const auto [surface, view] = GetSurface(gpu_addr, *cpu_addr, params, false);
|
const auto [surface, view] = GetSurface(gpu_addr, *cpu_addr, params, true, false);
|
||||||
if (guard_samplers) {
|
if (guard_samplers) {
|
||||||
sampled_textures.push_back(surface);
|
sampled_textures.push_back(surface);
|
||||||
}
|
}
|
||||||
|
@ -178,7 +178,7 @@ public:
|
||||||
return any_rt;
|
return any_rt;
|
||||||
}
|
}
|
||||||
|
|
||||||
TView GetDepthBufferSurface() {
|
TView GetDepthBufferSurface(bool preserve_contents) {
|
||||||
std::lock_guard lock{mutex};
|
std::lock_guard lock{mutex};
|
||||||
auto& maxwell3d = system.GPU().Maxwell3D();
|
auto& maxwell3d = system.GPU().Maxwell3D();
|
||||||
if (!maxwell3d.dirty.flags[VideoCommon::Dirty::ZetaBuffer]) {
|
if (!maxwell3d.dirty.flags[VideoCommon::Dirty::ZetaBuffer]) {
|
||||||
|
@ -199,7 +199,7 @@ public:
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
const auto depth_params{SurfaceParams::CreateForDepthBuffer(system)};
|
const auto depth_params{SurfaceParams::CreateForDepthBuffer(system)};
|
||||||
auto surface_view = GetSurface(gpu_addr, *cpu_addr, depth_params, true);
|
auto surface_view = GetSurface(gpu_addr, *cpu_addr, depth_params, preserve_contents, true);
|
||||||
if (depth_buffer.target)
|
if (depth_buffer.target)
|
||||||
depth_buffer.target->MarkAsRenderTarget(false, NO_RT);
|
depth_buffer.target->MarkAsRenderTarget(false, NO_RT);
|
||||||
depth_buffer.target = surface_view.first;
|
depth_buffer.target = surface_view.first;
|
||||||
|
@ -209,7 +209,7 @@ public:
|
||||||
return surface_view.second;
|
return surface_view.second;
|
||||||
}
|
}
|
||||||
|
|
||||||
TView GetColorBufferSurface(std::size_t index) {
|
TView GetColorBufferSurface(std::size_t index, bool preserve_contents) {
|
||||||
std::lock_guard lock{mutex};
|
std::lock_guard lock{mutex};
|
||||||
ASSERT(index < Tegra::Engines::Maxwell3D::Regs::NumRenderTargets);
|
ASSERT(index < Tegra::Engines::Maxwell3D::Regs::NumRenderTargets);
|
||||||
auto& maxwell3d = system.GPU().Maxwell3D();
|
auto& maxwell3d = system.GPU().Maxwell3D();
|
||||||
|
@ -239,8 +239,9 @@ public:
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
auto surface_view = GetSurface(gpu_addr, *cpu_addr,
|
auto surface_view =
|
||||||
SurfaceParams::CreateForFramebuffer(system, index), true);
|
GetSurface(gpu_addr, *cpu_addr, SurfaceParams::CreateForFramebuffer(system, index),
|
||||||
|
preserve_contents, true);
|
||||||
if (render_targets[index].target) {
|
if (render_targets[index].target) {
|
||||||
auto& surface = render_targets[index].target;
|
auto& surface = render_targets[index].target;
|
||||||
surface->MarkAsRenderTarget(false, NO_RT);
|
surface->MarkAsRenderTarget(false, NO_RT);
|
||||||
|
@ -300,9 +301,9 @@ public:
|
||||||
const std::optional<VAddr> src_cpu_addr =
|
const std::optional<VAddr> src_cpu_addr =
|
||||||
system.GPU().MemoryManager().GpuToCpuAddress(src_gpu_addr);
|
system.GPU().MemoryManager().GpuToCpuAddress(src_gpu_addr);
|
||||||
std::pair<TSurface, TView> dst_surface =
|
std::pair<TSurface, TView> dst_surface =
|
||||||
GetSurface(dst_gpu_addr, *dst_cpu_addr, dst_params, false);
|
GetSurface(dst_gpu_addr, *dst_cpu_addr, dst_params, true, false);
|
||||||
std::pair<TSurface, TView> src_surface =
|
std::pair<TSurface, TView> src_surface =
|
||||||
GetSurface(src_gpu_addr, *src_cpu_addr, src_params, false);
|
GetSurface(src_gpu_addr, *src_cpu_addr, src_params, true, false);
|
||||||
ImageBlit(src_surface.second, dst_surface.second, copy_config);
|
ImageBlit(src_surface.second, dst_surface.second, copy_config);
|
||||||
dst_surface.first->MarkAsModified(true, Tick());
|
dst_surface.first->MarkAsModified(true, Tick());
|
||||||
}
|
}
|
||||||
|
@ -532,18 +533,22 @@ private:
|
||||||
* @param overlaps The overlapping surfaces registered in the cache.
|
* @param overlaps The overlapping surfaces registered in the cache.
|
||||||
* @param params The parameters for the new surface.
|
* @param params The parameters for the new surface.
|
||||||
* @param gpu_addr The starting address of the new surface.
|
* @param gpu_addr The starting address of the new surface.
|
||||||
|
* @param preserve_contents Indicates that the new surface should be loaded from memory or left
|
||||||
|
* blank.
|
||||||
* @param untopological Indicates to the recycler that the texture has no way to match the
|
* @param untopological Indicates to the recycler that the texture has no way to match the
|
||||||
* overlaps due to topological reasons.
|
* overlaps due to topological reasons.
|
||||||
**/
|
**/
|
||||||
std::pair<TSurface, TView> RecycleSurface(std::vector<TSurface>& overlaps,
|
std::pair<TSurface, TView> RecycleSurface(std::vector<TSurface>& overlaps,
|
||||||
const SurfaceParams& params, const GPUVAddr gpu_addr,
|
const SurfaceParams& params, const GPUVAddr gpu_addr,
|
||||||
|
const bool preserve_contents,
|
||||||
const MatchTopologyResult untopological) {
|
const MatchTopologyResult untopological) {
|
||||||
|
const bool do_load = preserve_contents && Settings::IsGPULevelExtreme();
|
||||||
for (auto& surface : overlaps) {
|
for (auto& surface : overlaps) {
|
||||||
Unregister(surface);
|
Unregister(surface);
|
||||||
}
|
}
|
||||||
switch (PickStrategy(overlaps, params, gpu_addr, untopological)) {
|
switch (PickStrategy(overlaps, params, gpu_addr, untopological)) {
|
||||||
case RecycleStrategy::Ignore: {
|
case RecycleStrategy::Ignore: {
|
||||||
return InitializeSurface(gpu_addr, params, Settings::IsGPULevelExtreme());
|
return InitializeSurface(gpu_addr, params, do_load);
|
||||||
}
|
}
|
||||||
case RecycleStrategy::Flush: {
|
case RecycleStrategy::Flush: {
|
||||||
std::sort(overlaps.begin(), overlaps.end(),
|
std::sort(overlaps.begin(), overlaps.end(),
|
||||||
|
@ -553,7 +558,7 @@ private:
|
||||||
for (auto& surface : overlaps) {
|
for (auto& surface : overlaps) {
|
||||||
FlushSurface(surface);
|
FlushSurface(surface);
|
||||||
}
|
}
|
||||||
return InitializeSurface(gpu_addr, params);
|
return InitializeSurface(gpu_addr, params, preserve_contents);
|
||||||
}
|
}
|
||||||
case RecycleStrategy::BufferCopy: {
|
case RecycleStrategy::BufferCopy: {
|
||||||
auto new_surface = GetUncachedSurface(gpu_addr, params);
|
auto new_surface = GetUncachedSurface(gpu_addr, params);
|
||||||
|
@ -562,7 +567,7 @@ private:
|
||||||
}
|
}
|
||||||
default: {
|
default: {
|
||||||
UNIMPLEMENTED_MSG("Unimplemented Texture Cache Recycling Strategy!");
|
UNIMPLEMENTED_MSG("Unimplemented Texture Cache Recycling Strategy!");
|
||||||
return InitializeSurface(gpu_addr, params);
|
return InitializeSurface(gpu_addr, params, do_load);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -700,11 +705,14 @@ private:
|
||||||
* @param params The parameters on the new surface.
|
* @param params The parameters on the new surface.
|
||||||
* @param gpu_addr The starting address of the new surface.
|
* @param gpu_addr The starting address of the new surface.
|
||||||
* @param cpu_addr The starting address of the new surface on physical memory.
|
* @param cpu_addr The starting address of the new surface on physical memory.
|
||||||
|
* @param preserve_contents Indicates that the new surface should be loaded from memory or
|
||||||
|
* left blank.
|
||||||
*/
|
*/
|
||||||
std::optional<std::pair<TSurface, TView>> Manage3DSurfaces(std::vector<TSurface>& overlaps,
|
std::optional<std::pair<TSurface, TView>> Manage3DSurfaces(std::vector<TSurface>& overlaps,
|
||||||
const SurfaceParams& params,
|
const SurfaceParams& params,
|
||||||
const GPUVAddr gpu_addr,
|
const GPUVAddr gpu_addr,
|
||||||
const VAddr cpu_addr) {
|
const VAddr cpu_addr,
|
||||||
|
bool preserve_contents) {
|
||||||
if (params.target == SurfaceTarget::Texture3D) {
|
if (params.target == SurfaceTarget::Texture3D) {
|
||||||
bool failed = false;
|
bool failed = false;
|
||||||
if (params.num_levels > 1) {
|
if (params.num_levels > 1) {
|
||||||
|
@ -754,7 +762,7 @@ private:
|
||||||
return std::nullopt;
|
return std::nullopt;
|
||||||
}
|
}
|
||||||
Unregister(surface);
|
Unregister(surface);
|
||||||
return InitializeSurface(gpu_addr, params);
|
return InitializeSurface(gpu_addr, params, preserve_contents);
|
||||||
}
|
}
|
||||||
return std::nullopt;
|
return std::nullopt;
|
||||||
}
|
}
|
||||||
|
@ -765,7 +773,7 @@ private:
|
||||||
return {{surface, surface->GetMainView()}};
|
return {{surface, surface->GetMainView()}};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return InitializeSurface(gpu_addr, params);
|
return InitializeSurface(gpu_addr, params, preserve_contents);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -788,10 +796,13 @@ private:
|
||||||
*
|
*
|
||||||
* @param gpu_addr The starting address of the candidate surface.
|
* @param gpu_addr The starting address of the candidate surface.
|
||||||
* @param params The parameters on the candidate surface.
|
* @param params The parameters on the candidate surface.
|
||||||
|
* @param preserve_contents Indicates that the new surface should be loaded from memory or
|
||||||
|
* left blank.
|
||||||
* @param is_render Whether or not the surface is a render target.
|
* @param is_render Whether or not the surface is a render target.
|
||||||
**/
|
**/
|
||||||
std::pair<TSurface, TView> GetSurface(const GPUVAddr gpu_addr, const VAddr cpu_addr,
|
std::pair<TSurface, TView> GetSurface(const GPUVAddr gpu_addr, const VAddr cpu_addr,
|
||||||
const SurfaceParams& params, bool is_render) {
|
const SurfaceParams& params, bool preserve_contents,
|
||||||
|
bool is_render) {
|
||||||
// Step 1
|
// Step 1
|
||||||
// Check Level 1 Cache for a fast structural match. If candidate surface
|
// Check Level 1 Cache for a fast structural match. If candidate surface
|
||||||
// matches at certain level we are pretty much done.
|
// matches at certain level we are pretty much done.
|
||||||
|
@ -800,7 +811,8 @@ private:
|
||||||
const auto topological_result = current_surface->MatchesTopology(params);
|
const auto topological_result = current_surface->MatchesTopology(params);
|
||||||
if (topological_result != MatchTopologyResult::FullMatch) {
|
if (topological_result != MatchTopologyResult::FullMatch) {
|
||||||
std::vector<TSurface> overlaps{current_surface};
|
std::vector<TSurface> overlaps{current_surface};
|
||||||
return RecycleSurface(overlaps, params, gpu_addr, topological_result);
|
return RecycleSurface(overlaps, params, gpu_addr, preserve_contents,
|
||||||
|
topological_result);
|
||||||
}
|
}
|
||||||
|
|
||||||
const auto struct_result = current_surface->MatchesStructure(params);
|
const auto struct_result = current_surface->MatchesStructure(params);
|
||||||
|
@ -825,7 +837,7 @@ private:
|
||||||
|
|
||||||
// If none are found, we are done. we just load the surface and create it.
|
// If none are found, we are done. we just load the surface and create it.
|
||||||
if (overlaps.empty()) {
|
if (overlaps.empty()) {
|
||||||
return InitializeSurface(gpu_addr, params);
|
return InitializeSurface(gpu_addr, params, preserve_contents);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Step 3
|
// Step 3
|
||||||
|
@ -835,13 +847,15 @@ private:
|
||||||
for (const auto& surface : overlaps) {
|
for (const auto& surface : overlaps) {
|
||||||
const auto topological_result = surface->MatchesTopology(params);
|
const auto topological_result = surface->MatchesTopology(params);
|
||||||
if (topological_result != MatchTopologyResult::FullMatch) {
|
if (topological_result != MatchTopologyResult::FullMatch) {
|
||||||
return RecycleSurface(overlaps, params, gpu_addr, topological_result);
|
return RecycleSurface(overlaps, params, gpu_addr, preserve_contents,
|
||||||
|
topological_result);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check if it's a 3D texture
|
// Check if it's a 3D texture
|
||||||
if (params.block_depth > 0) {
|
if (params.block_depth > 0) {
|
||||||
auto surface = Manage3DSurfaces(overlaps, params, gpu_addr, cpu_addr);
|
auto surface =
|
||||||
|
Manage3DSurfaces(overlaps, params, gpu_addr, cpu_addr, preserve_contents);
|
||||||
if (surface) {
|
if (surface) {
|
||||||
return *surface;
|
return *surface;
|
||||||
}
|
}
|
||||||
|
@ -861,7 +875,8 @@ private:
|
||||||
return *view;
|
return *view;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return RecycleSurface(overlaps, params, gpu_addr, MatchTopologyResult::FullMatch);
|
return RecycleSurface(overlaps, params, gpu_addr, preserve_contents,
|
||||||
|
MatchTopologyResult::FullMatch);
|
||||||
}
|
}
|
||||||
// Now we check if the candidate is a mipmap/layer of the overlap
|
// Now we check if the candidate is a mipmap/layer of the overlap
|
||||||
std::optional<TView> view =
|
std::optional<TView> view =
|
||||||
|
@ -885,7 +900,7 @@ private:
|
||||||
pair.first->EmplaceView(params, gpu_addr, candidate_size);
|
pair.first->EmplaceView(params, gpu_addr, candidate_size);
|
||||||
if (mirage_view)
|
if (mirage_view)
|
||||||
return {pair.first, *mirage_view};
|
return {pair.first, *mirage_view};
|
||||||
return RecycleSurface(overlaps, params, gpu_addr,
|
return RecycleSurface(overlaps, params, gpu_addr, preserve_contents,
|
||||||
MatchTopologyResult::FullMatch);
|
MatchTopologyResult::FullMatch);
|
||||||
}
|
}
|
||||||
return {current_surface, *view};
|
return {current_surface, *view};
|
||||||
|
@ -901,7 +916,8 @@ private:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// We failed all the tests, recycle the overlaps into a new texture.
|
// We failed all the tests, recycle the overlaps into a new texture.
|
||||||
return RecycleSurface(overlaps, params, gpu_addr, MatchTopologyResult::FullMatch);
|
return RecycleSurface(overlaps, params, gpu_addr, preserve_contents,
|
||||||
|
MatchTopologyResult::FullMatch);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -1059,10 +1075,10 @@ private:
|
||||||
}
|
}
|
||||||
|
|
||||||
std::pair<TSurface, TView> InitializeSurface(GPUVAddr gpu_addr, const SurfaceParams& params,
|
std::pair<TSurface, TView> InitializeSurface(GPUVAddr gpu_addr, const SurfaceParams& params,
|
||||||
bool do_load = true) {
|
bool preserve_contents) {
|
||||||
auto new_surface{GetUncachedSurface(gpu_addr, params)};
|
auto new_surface{GetUncachedSurface(gpu_addr, params)};
|
||||||
Register(new_surface);
|
Register(new_surface);
|
||||||
if (do_load) {
|
if (preserve_contents) {
|
||||||
LoadSurface(new_surface);
|
LoadSurface(new_surface);
|
||||||
}
|
}
|
||||||
return {new_surface, new_surface->GetMainView()};
|
return {new_surface, new_surface->GetMainView()};
|
||||||
|
|
Reference in New Issue