mirror of
https://github.com/yuzu-emu/yuzu.git
synced 2024-07-04 23:31:19 +01:00
vk_rasterizer: Don't preserve contents on full screen clears
There's no need to load contents from the CPU when a clear resets all the contents of the underlying memory. This is already implemented on OpenGL and the texture cache.
This commit is contained in:
parent
de644d506f
commit
cf137ea40b
2 changed files with 58 additions and 7 deletions
|
@ -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
|
} // Anonymous namespace
|
||||||
|
|
||||||
class BufferBindings final {
|
class BufferBindings final {
|
||||||
|
@ -344,7 +387,7 @@ void RasterizerVulkan::Draw(bool is_indexed, bool is_instanced) {
|
||||||
|
|
||||||
buffer_cache.Unmap();
|
buffer_cache.Unmap();
|
||||||
|
|
||||||
const Texceptions texceptions = UpdateAttachments();
|
const Texceptions texceptions = UpdateAttachments(false);
|
||||||
SetupImageTransitions(texceptions, color_attachments, zeta_attachment);
|
SetupImageTransitions(texceptions, color_attachments, zeta_attachment);
|
||||||
|
|
||||||
key.renderpass_params = GetRenderPassParams(texceptions);
|
key.renderpass_params = GetRenderPassParams(texceptions);
|
||||||
|
@ -400,7 +443,7 @@ void RasterizerVulkan::Clear() {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
[[maybe_unused]] const auto texceptions = UpdateAttachments();
|
[[maybe_unused]] const auto texceptions = UpdateAttachments(true);
|
||||||
DEBUG_ASSERT(texceptions.none());
|
DEBUG_ASSERT(texceptions.none());
|
||||||
SetupImageTransitions(0, color_attachments, zeta_attachment);
|
SetupImageTransitions(0, color_attachments, zeta_attachment);
|
||||||
|
|
||||||
|
@ -677,9 +720,12 @@ void RasterizerVulkan::FlushWork() {
|
||||||
draw_counter = 0;
|
draw_counter = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
RasterizerVulkan::Texceptions RasterizerVulkan::UpdateAttachments() {
|
RasterizerVulkan::Texceptions RasterizerVulkan::UpdateAttachments(bool is_clear) {
|
||||||
MICROPROFILE_SCOPE(Vulkan_RenderTargets);
|
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];
|
const bool update_rendertargets = dirty[VideoCommon::Dirty::RenderTargets];
|
||||||
dirty[VideoCommon::Dirty::RenderTargets] = false;
|
dirty[VideoCommon::Dirty::RenderTargets] = false;
|
||||||
|
|
||||||
|
@ -688,7 +734,8 @@ 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, 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])) {
|
if (color_attachments[rt] && WalkAttachmentOverlaps(*color_attachments[rt])) {
|
||||||
texceptions[rt] = true;
|
texceptions[rt] = true;
|
||||||
|
@ -696,7 +743,8 @@ RasterizerVulkan::Texceptions RasterizerVulkan::UpdateAttachments() {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (update_rendertargets) {
|
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)) {
|
if (zeta_attachment && WalkAttachmentOverlaps(*zeta_attachment)) {
|
||||||
texceptions[ZETA_TEXCEPTION_INDEX] = true;
|
texceptions[ZETA_TEXCEPTION_INDEX] = true;
|
||||||
|
|
|
@ -159,7 +159,10 @@ private:
|
||||||
|
|
||||||
void FlushWork();
|
void FlushWork();
|
||||||
|
|
||||||
Texceptions UpdateAttachments();
|
/// @brief Updates the currently bound attachments
|
||||||
|
/// @param is_clear True when the framebuffer is updated as a clear
|
||||||
|
/// @return Bitfield of attachments being used as sampled textures
|
||||||
|
Texceptions UpdateAttachments(bool is_clear);
|
||||||
|
|
||||||
std::tuple<VkFramebuffer, VkExtent2D> ConfigureFramebuffers(VkRenderPass renderpass);
|
std::tuple<VkFramebuffer, VkExtent2D> ConfigureFramebuffers(VkRenderPass renderpass);
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue