|
|
|
@ -143,6 +143,49 @@ Tegra::Texture::FullTextureInfo GetTextureInfo(const Engine& engine, const Entry |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
/// @brief Determine if an attachment to be updated has to preserve contents
|
|
|
|
/// @param is_clear True when a clear is being executed
|
|
|
|
/// @param regs 3D registers
|
|
|
|
/// @return True when the contents have to be preserved
|
|
|
|
bool HasToPreserveColorContents(bool is_clear, const Maxwell& regs) { |
|
|
|
if (!is_clear) { |
|
|
|
return true; |
|
|
|
} |
|
|
|
// First we have to make sure all clear masks are enabled.
|
|
|
|
if (!regs.clear_buffers.R || !regs.clear_buffers.G || !regs.clear_buffers.B || |
|
|
|
!regs.clear_buffers.A) { |
|
|
|
return true; |
|
|
|
} |
|
|
|
// If scissors are disabled, the whole screen is cleared
|
|
|
|
if (!regs.clear_flags.scissor) { |
|
|
|
return false; |
|
|
|
} |
|
|
|
// Then we have to confirm scissor testing clears the whole image
|
|
|
|
const std::size_t index = regs.clear_buffers.RT; |
|
|
|
const auto& scissor = regs.scissor_test[0]; |
|
|
|
return scissor.min_x > 0 || scissor.min_y > 0 || scissor.max_x < regs.rt[index].width || |
|
|
|
scissor.max_y < regs.rt[index].height; |
|
|
|
} |
|
|
|
|
|
|
|
/// @brief Determine if an attachment to be updated has to preserve contents
|
|
|
|
/// @param is_clear True when a clear is being executed
|
|
|
|
/// @param regs 3D registers
|
|
|
|
/// @return True when the contents have to be preserved
|
|
|
|
bool HasToPreserveDepthContents(bool is_clear, const Maxwell& regs) { |
|
|
|
// If we are not clearing, the contents have to be preserved
|
|
|
|
if (!is_clear) { |
|
|
|
return true; |
|
|
|
} |
|
|
|
// For depth stencil clears we only have to confirm scissor test covers the whole image
|
|
|
|
if (!regs.clear_flags.scissor) { |
|
|
|
return false; |
|
|
|
} |
|
|
|
// Make sure the clear cover the whole image
|
|
|
|
const auto& scissor = regs.scissor_test[0]; |
|
|
|
return scissor.min_x > 0 || scissor.min_y > 0 || scissor.max_x < regs.zeta_width || |
|
|
|
scissor.max_y < regs.zeta_height; |
|
|
|
} |
|
|
|
|
|
|
|
} // Anonymous namespace
|
|
|
|
|
|
|
|
class BufferBindings final { |
|
|
|
@ -344,7 +387,7 @@ void RasterizerVulkan::Draw(bool is_indexed, bool is_instanced) { |
|
|
|
|
|
|
|
buffer_cache.Unmap(); |
|
|
|
|
|
|
|
const Texceptions texceptions = UpdateAttachments(); |
|
|
|
const Texceptions texceptions = UpdateAttachments(false); |
|
|
|
SetupImageTransitions(texceptions, color_attachments, zeta_attachment); |
|
|
|
|
|
|
|
key.renderpass_params = GetRenderPassParams(texceptions); |
|
|
|
@ -400,7 +443,7 @@ void RasterizerVulkan::Clear() { |
|
|
|
return; |
|
|
|
} |
|
|
|
|
|
|
|
[[maybe_unused]] const auto texceptions = UpdateAttachments(); |
|
|
|
[[maybe_unused]] const auto texceptions = UpdateAttachments(true); |
|
|
|
DEBUG_ASSERT(texceptions.none()); |
|
|
|
SetupImageTransitions(0, color_attachments, zeta_attachment); |
|
|
|
|
|
|
|
@ -677,9 +720,12 @@ void RasterizerVulkan::FlushWork() { |
|
|
|
draw_counter = 0; |
|
|
|
} |
|
|
|
|
|
|
|
RasterizerVulkan::Texceptions RasterizerVulkan::UpdateAttachments() { |
|
|
|
RasterizerVulkan::Texceptions RasterizerVulkan::UpdateAttachments(bool is_clear) { |
|
|
|
MICROPROFILE_SCOPE(Vulkan_RenderTargets); |
|
|
|
auto& dirty = system.GPU().Maxwell3D().dirty.flags; |
|
|
|
auto& maxwell3d = system.GPU().Maxwell3D(); |
|
|
|
auto& dirty = maxwell3d.dirty.flags; |
|
|
|
auto& regs = maxwell3d.regs; |
|
|
|
|
|
|
|
const bool update_rendertargets = dirty[VideoCommon::Dirty::RenderTargets]; |
|
|
|
dirty[VideoCommon::Dirty::RenderTargets] = false; |
|
|
|
|
|
|
|
@ -688,7 +734,8 @@ RasterizerVulkan::Texceptions RasterizerVulkan::UpdateAttachments() { |
|
|
|
Texceptions texceptions; |
|
|
|
for (std::size_t rt = 0; rt < Maxwell::NumRenderTargets; ++rt) { |
|
|
|
if (update_rendertargets) { |
|
|
|
color_attachments[rt] = texture_cache.GetColorBufferSurface(rt, true); |
|
|
|
const bool preserve_contents = HasToPreserveColorContents(is_clear, regs); |
|
|
|
color_attachments[rt] = texture_cache.GetColorBufferSurface(rt, preserve_contents); |
|
|
|
} |
|
|
|
if (color_attachments[rt] && WalkAttachmentOverlaps(*color_attachments[rt])) { |
|
|
|
texceptions[rt] = true; |
|
|
|
@ -696,7 +743,8 @@ RasterizerVulkan::Texceptions RasterizerVulkan::UpdateAttachments() { |
|
|
|
} |
|
|
|
|
|
|
|
if (update_rendertargets) { |
|
|
|
zeta_attachment = texture_cache.GetDepthBufferSurface(true); |
|
|
|
const bool preserve_contents = HasToPreserveDepthContents(is_clear, regs); |
|
|
|
zeta_attachment = texture_cache.GetDepthBufferSurface(preserve_contents); |
|
|
|
} |
|
|
|
if (zeta_attachment && WalkAttachmentOverlaps(*zeta_attachment)) { |
|
|
|
texceptions[ZETA_TEXCEPTION_INDEX] = true; |
|
|
|
|