diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/video_core/renderer_vulkan/vk_rasterizer.cpp | 60 | ||||
| -rw-r--r-- | src/video_core/renderer_vulkan/vk_rasterizer.h | 5 |
2 files changed, 58 insertions, 7 deletions
diff --git a/src/video_core/renderer_vulkan/vk_rasterizer.cpp b/src/video_core/renderer_vulkan/vk_rasterizer.cpp index 184b2238a..a5fd68358 100644 --- a/src/video_core/renderer_vulkan/vk_rasterizer.cpp +++ b/src/video_core/renderer_vulkan/vk_rasterizer.cpp | |||
| @@ -143,6 +143,49 @@ Tegra::Texture::FullTextureInfo GetTextureInfo(const Engine& engine, const Entry | |||
| 143 | } | 143 | } |
| 144 | } | 144 | } |
| 145 | 145 | ||
| 146 | /// @brief Determine if an attachment to be updated has to preserve contents | ||
| 147 | /// @param is_clear True when a clear is being executed | ||
| 148 | /// @param regs 3D registers | ||
| 149 | /// @return True when the contents have to be preserved | ||
| 150 | bool HasToPreserveColorContents(bool is_clear, const Maxwell& regs) { | ||
| 151 | if (!is_clear) { | ||
| 152 | return true; | ||
| 153 | } | ||
| 154 | // First we have to make sure all clear masks are enabled. | ||
| 155 | if (!regs.clear_buffers.R || !regs.clear_buffers.G || !regs.clear_buffers.B || | ||
| 156 | !regs.clear_buffers.A) { | ||
| 157 | return true; | ||
| 158 | } | ||
| 159 | // If scissors are disabled, the whole screen is cleared | ||
| 160 | if (!regs.clear_flags.scissor) { | ||
| 161 | return false; | ||
| 162 | } | ||
| 163 | // Then we have to confirm scissor testing clears the whole image | ||
| 164 | const std::size_t index = regs.clear_buffers.RT; | ||
| 165 | const auto& scissor = regs.scissor_test[0]; | ||
| 166 | return scissor.min_x > 0 || scissor.min_y > 0 || scissor.max_x < regs.rt[index].width || | ||
| 167 | scissor.max_y < regs.rt[index].height; | ||
| 168 | } | ||
| 169 | |||
| 170 | /// @brief Determine if an attachment to be updated has to preserve contents | ||
| 171 | /// @param is_clear True when a clear is being executed | ||
| 172 | /// @param regs 3D registers | ||
| 173 | /// @return True when the contents have to be preserved | ||
| 174 | bool HasToPreserveDepthContents(bool is_clear, const Maxwell& regs) { | ||
| 175 | // If we are not clearing, the contents have to be preserved | ||
| 176 | if (!is_clear) { | ||
| 177 | return true; | ||
| 178 | } | ||
| 179 | // For depth stencil clears we only have to confirm scissor test covers the whole image | ||
| 180 | if (!regs.clear_flags.scissor) { | ||
| 181 | return false; | ||
| 182 | } | ||
| 183 | // Make sure the clear cover the whole image | ||
| 184 | const auto& scissor = regs.scissor_test[0]; | ||
| 185 | return scissor.min_x > 0 || scissor.min_y > 0 || scissor.max_x < regs.zeta_width || | ||
| 186 | scissor.max_y < regs.zeta_height; | ||
| 187 | } | ||
| 188 | |||
| 146 | } // Anonymous namespace | 189 | } // Anonymous namespace |
| 147 | 190 | ||
| 148 | class BufferBindings final { | 191 | class BufferBindings final { |
| @@ -344,7 +387,7 @@ void RasterizerVulkan::Draw(bool is_indexed, bool is_instanced) { | |||
| 344 | 387 | ||
| 345 | buffer_cache.Unmap(); | 388 | buffer_cache.Unmap(); |
| 346 | 389 | ||
| 347 | const Texceptions texceptions = UpdateAttachments(); | 390 | const Texceptions texceptions = UpdateAttachments(false); |
| 348 | SetupImageTransitions(texceptions, color_attachments, zeta_attachment); | 391 | SetupImageTransitions(texceptions, color_attachments, zeta_attachment); |
| 349 | 392 | ||
| 350 | key.renderpass_params = GetRenderPassParams(texceptions); | 393 | key.renderpass_params = GetRenderPassParams(texceptions); |
| @@ -400,7 +443,7 @@ void RasterizerVulkan::Clear() { | |||
| 400 | return; | 443 | return; |
| 401 | } | 444 | } |
| 402 | 445 | ||
| 403 | [[maybe_unused]] const auto texceptions = UpdateAttachments(); | 446 | [[maybe_unused]] const auto texceptions = UpdateAttachments(true); |
| 404 | DEBUG_ASSERT(texceptions.none()); | 447 | DEBUG_ASSERT(texceptions.none()); |
| 405 | SetupImageTransitions(0, color_attachments, zeta_attachment); | 448 | SetupImageTransitions(0, color_attachments, zeta_attachment); |
| 406 | 449 | ||
| @@ -677,9 +720,12 @@ void RasterizerVulkan::FlushWork() { | |||
| 677 | draw_counter = 0; | 720 | draw_counter = 0; |
| 678 | } | 721 | } |
| 679 | 722 | ||
| 680 | RasterizerVulkan::Texceptions RasterizerVulkan::UpdateAttachments() { | 723 | RasterizerVulkan::Texceptions RasterizerVulkan::UpdateAttachments(bool is_clear) { |
| 681 | MICROPROFILE_SCOPE(Vulkan_RenderTargets); | 724 | MICROPROFILE_SCOPE(Vulkan_RenderTargets); |
| 682 | auto& dirty = system.GPU().Maxwell3D().dirty.flags; | 725 | auto& maxwell3d = system.GPU().Maxwell3D(); |
| 726 | auto& dirty = maxwell3d.dirty.flags; | ||
| 727 | auto& regs = maxwell3d.regs; | ||
| 728 | |||
| 683 | const bool update_rendertargets = dirty[VideoCommon::Dirty::RenderTargets]; | 729 | const bool update_rendertargets = dirty[VideoCommon::Dirty::RenderTargets]; |
| 684 | dirty[VideoCommon::Dirty::RenderTargets] = false; | 730 | dirty[VideoCommon::Dirty::RenderTargets] = false; |
| 685 | 731 | ||
| @@ -688,7 +734,8 @@ RasterizerVulkan::Texceptions RasterizerVulkan::UpdateAttachments() { | |||
| 688 | Texceptions texceptions; | 734 | Texceptions texceptions; |
| 689 | for (std::size_t rt = 0; rt < Maxwell::NumRenderTargets; ++rt) { | 735 | for (std::size_t rt = 0; rt < Maxwell::NumRenderTargets; ++rt) { |
| 690 | if (update_rendertargets) { | 736 | if (update_rendertargets) { |
| 691 | color_attachments[rt] = texture_cache.GetColorBufferSurface(rt, true); | 737 | const bool preserve_contents = HasToPreserveColorContents(is_clear, regs); |
| 738 | color_attachments[rt] = texture_cache.GetColorBufferSurface(rt, preserve_contents); | ||
| 692 | } | 739 | } |
| 693 | if (color_attachments[rt] && WalkAttachmentOverlaps(*color_attachments[rt])) { | 740 | if (color_attachments[rt] && WalkAttachmentOverlaps(*color_attachments[rt])) { |
| 694 | texceptions[rt] = true; | 741 | texceptions[rt] = true; |
| @@ -696,7 +743,8 @@ RasterizerVulkan::Texceptions RasterizerVulkan::UpdateAttachments() { | |||
| 696 | } | 743 | } |
| 697 | 744 | ||
| 698 | if (update_rendertargets) { | 745 | if (update_rendertargets) { |
| 699 | zeta_attachment = texture_cache.GetDepthBufferSurface(true); | 746 | const bool preserve_contents = HasToPreserveDepthContents(is_clear, regs); |
| 747 | zeta_attachment = texture_cache.GetDepthBufferSurface(preserve_contents); | ||
| 700 | } | 748 | } |
| 701 | if (zeta_attachment && WalkAttachmentOverlaps(*zeta_attachment)) { | 749 | if (zeta_attachment && WalkAttachmentOverlaps(*zeta_attachment)) { |
| 702 | texceptions[ZETA_TEXCEPTION_INDEX] = true; | 750 | texceptions[ZETA_TEXCEPTION_INDEX] = true; |
diff --git a/src/video_core/renderer_vulkan/vk_rasterizer.h b/src/video_core/renderer_vulkan/vk_rasterizer.h index c8c187606..83e00e7e9 100644 --- a/src/video_core/renderer_vulkan/vk_rasterizer.h +++ b/src/video_core/renderer_vulkan/vk_rasterizer.h | |||
| @@ -159,7 +159,10 @@ private: | |||
| 159 | 159 | ||
| 160 | void FlushWork(); | 160 | void FlushWork(); |
| 161 | 161 | ||
| 162 | Texceptions UpdateAttachments(); | 162 | /// @brief Updates the currently bound attachments |
| 163 | /// @param is_clear True when the framebuffer is updated as a clear | ||
| 164 | /// @return Bitfield of attachments being used as sampled textures | ||
| 165 | Texceptions UpdateAttachments(bool is_clear); | ||
| 163 | 166 | ||
| 164 | std::tuple<VkFramebuffer, VkExtent2D> ConfigureFramebuffers(VkRenderPass renderpass); | 167 | std::tuple<VkFramebuffer, VkExtent2D> ConfigureFramebuffers(VkRenderPass renderpass); |
| 165 | 168 | ||