diff options
| author | 2023-08-19 17:28:28 +0200 | |
|---|---|---|
| committer | 2023-08-19 17:28:28 +0200 | |
| commit | 6a5db5679b61d3d73244e42682f1b34d401e7736 (patch) | |
| tree | 5390c22be68674fd964b49a745c495f13cf71e0d /src | |
| parent | Merge pull request #11278 from Kelebek1/dma_sync (diff) | |
| parent | Masked depthstencil clears (diff) | |
| download | yuzu-6a5db5679b61d3d73244e42682f1b34d401e7736.tar.gz yuzu-6a5db5679b61d3d73244e42682f1b34d401e7736.tar.xz yuzu-6a5db5679b61d3d73244e42682f1b34d401e7736.zip | |
Merge pull request #11320 from Kelebek1/mask_depthstencil_clear
Support masked depthstencil clears
Diffstat (limited to 'src')
| -rw-r--r-- | src/video_core/host_shaders/CMakeLists.txt | 1 | ||||
| -rw-r--r-- | src/video_core/host_shaders/vulkan_depthstencil_clear.frag | 12 | ||||
| -rw-r--r-- | src/video_core/renderer_vulkan/blit_image.cpp | 79 | ||||
| -rw-r--r-- | src/video_core/renderer_vulkan/blit_image.h | 19 | ||||
| -rw-r--r-- | src/video_core/renderer_vulkan/vk_rasterizer.cpp | 30 |
5 files changed, 132 insertions, 9 deletions
diff --git a/src/video_core/host_shaders/CMakeLists.txt b/src/video_core/host_shaders/CMakeLists.txt index e61d9af80..c4d459077 100644 --- a/src/video_core/host_shaders/CMakeLists.txt +++ b/src/video_core/host_shaders/CMakeLists.txt | |||
| @@ -50,6 +50,7 @@ set(SHADER_FILES | |||
| 50 | vulkan_blit_depth_stencil.frag | 50 | vulkan_blit_depth_stencil.frag |
| 51 | vulkan_color_clear.frag | 51 | vulkan_color_clear.frag |
| 52 | vulkan_color_clear.vert | 52 | vulkan_color_clear.vert |
| 53 | vulkan_depthstencil_clear.frag | ||
| 53 | vulkan_fidelityfx_fsr_easu_fp16.comp | 54 | vulkan_fidelityfx_fsr_easu_fp16.comp |
| 54 | vulkan_fidelityfx_fsr_easu_fp32.comp | 55 | vulkan_fidelityfx_fsr_easu_fp32.comp |
| 55 | vulkan_fidelityfx_fsr_rcas_fp16.comp | 56 | vulkan_fidelityfx_fsr_rcas_fp16.comp |
diff --git a/src/video_core/host_shaders/vulkan_depthstencil_clear.frag b/src/video_core/host_shaders/vulkan_depthstencil_clear.frag new file mode 100644 index 000000000..1ac177c7e --- /dev/null +++ b/src/video_core/host_shaders/vulkan_depthstencil_clear.frag | |||
| @@ -0,0 +1,12 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-2.0-or-later | ||
| 3 | |||
| 4 | #version 460 core | ||
| 5 | |||
| 6 | layout (push_constant) uniform PushConstants { | ||
| 7 | vec4 clear_depth; | ||
| 8 | }; | ||
| 9 | |||
| 10 | void main() { | ||
| 11 | gl_FragDepth = clear_depth.x; | ||
| 12 | } | ||
diff --git a/src/video_core/renderer_vulkan/blit_image.cpp b/src/video_core/renderer_vulkan/blit_image.cpp index f74ae972e..1032c9d12 100644 --- a/src/video_core/renderer_vulkan/blit_image.cpp +++ b/src/video_core/renderer_vulkan/blit_image.cpp | |||
| @@ -16,6 +16,7 @@ | |||
| 16 | #include "video_core/host_shaders/vulkan_blit_depth_stencil_frag_spv.h" | 16 | #include "video_core/host_shaders/vulkan_blit_depth_stencil_frag_spv.h" |
| 17 | #include "video_core/host_shaders/vulkan_color_clear_frag_spv.h" | 17 | #include "video_core/host_shaders/vulkan_color_clear_frag_spv.h" |
| 18 | #include "video_core/host_shaders/vulkan_color_clear_vert_spv.h" | 18 | #include "video_core/host_shaders/vulkan_color_clear_vert_spv.h" |
| 19 | #include "video_core/host_shaders/vulkan_depthstencil_clear_frag_spv.h" | ||
| 19 | #include "video_core/renderer_vulkan/blit_image.h" | 20 | #include "video_core/renderer_vulkan/blit_image.h" |
| 20 | #include "video_core/renderer_vulkan/maxwell_to_vk.h" | 21 | #include "video_core/renderer_vulkan/maxwell_to_vk.h" |
| 21 | #include "video_core/renderer_vulkan/vk_scheduler.h" | 22 | #include "video_core/renderer_vulkan/vk_scheduler.h" |
| @@ -428,6 +429,7 @@ BlitImageHelper::BlitImageHelper(const Device& device_, Scheduler& scheduler_, | |||
| 428 | blit_depth_stencil_frag(BuildShader(device, VULKAN_BLIT_DEPTH_STENCIL_FRAG_SPV)), | 429 | blit_depth_stencil_frag(BuildShader(device, VULKAN_BLIT_DEPTH_STENCIL_FRAG_SPV)), |
| 429 | clear_color_vert(BuildShader(device, VULKAN_COLOR_CLEAR_VERT_SPV)), | 430 | clear_color_vert(BuildShader(device, VULKAN_COLOR_CLEAR_VERT_SPV)), |
| 430 | clear_color_frag(BuildShader(device, VULKAN_COLOR_CLEAR_FRAG_SPV)), | 431 | clear_color_frag(BuildShader(device, VULKAN_COLOR_CLEAR_FRAG_SPV)), |
| 432 | clear_stencil_frag(BuildShader(device, VULKAN_DEPTHSTENCIL_CLEAR_FRAG_SPV)), | ||
| 431 | convert_depth_to_float_frag(BuildShader(device, CONVERT_DEPTH_TO_FLOAT_FRAG_SPV)), | 433 | convert_depth_to_float_frag(BuildShader(device, CONVERT_DEPTH_TO_FLOAT_FRAG_SPV)), |
| 432 | convert_float_to_depth_frag(BuildShader(device, CONVERT_FLOAT_TO_DEPTH_FRAG_SPV)), | 434 | convert_float_to_depth_frag(BuildShader(device, CONVERT_FLOAT_TO_DEPTH_FRAG_SPV)), |
| 433 | convert_abgr8_to_d24s8_frag(BuildShader(device, CONVERT_ABGR8_TO_D24S8_FRAG_SPV)), | 435 | convert_abgr8_to_d24s8_frag(BuildShader(device, CONVERT_ABGR8_TO_D24S8_FRAG_SPV)), |
| @@ -593,6 +595,28 @@ void BlitImageHelper::ClearColor(const Framebuffer* dst_framebuffer, u8 color_ma | |||
| 593 | scheduler.InvalidateState(); | 595 | scheduler.InvalidateState(); |
| 594 | } | 596 | } |
| 595 | 597 | ||
| 598 | void BlitImageHelper::ClearDepthStencil(const Framebuffer* dst_framebuffer, bool depth_clear, | ||
| 599 | f32 clear_depth, u8 stencil_mask, u32 stencil_ref, | ||
| 600 | u32 stencil_compare_mask, const Region2D& dst_region) { | ||
| 601 | const BlitDepthStencilPipelineKey key{ | ||
| 602 | .renderpass = dst_framebuffer->RenderPass(), | ||
| 603 | .depth_clear = depth_clear, | ||
| 604 | .stencil_mask = stencil_mask, | ||
| 605 | .stencil_compare_mask = stencil_compare_mask, | ||
| 606 | .stencil_ref = stencil_ref, | ||
| 607 | }; | ||
| 608 | const VkPipeline pipeline = FindOrEmplaceClearStencilPipeline(key); | ||
| 609 | const VkPipelineLayout layout = *clear_color_pipeline_layout; | ||
| 610 | scheduler.RequestRenderpass(dst_framebuffer); | ||
| 611 | scheduler.Record([pipeline, layout, clear_depth, dst_region](vk::CommandBuffer cmdbuf) { | ||
| 612 | cmdbuf.BindPipeline(VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline); | ||
| 613 | BindBlitState(cmdbuf, dst_region); | ||
| 614 | cmdbuf.PushConstants(layout, VK_SHADER_STAGE_FRAGMENT_BIT, clear_depth); | ||
| 615 | cmdbuf.Draw(3, 1, 0, 0); | ||
| 616 | }); | ||
| 617 | scheduler.InvalidateState(); | ||
| 618 | } | ||
| 619 | |||
| 596 | void BlitImageHelper::Convert(VkPipeline pipeline, const Framebuffer* dst_framebuffer, | 620 | void BlitImageHelper::Convert(VkPipeline pipeline, const Framebuffer* dst_framebuffer, |
| 597 | const ImageView& src_image_view) { | 621 | const ImageView& src_image_view) { |
| 598 | const VkPipelineLayout layout = *one_texture_pipeline_layout; | 622 | const VkPipelineLayout layout = *one_texture_pipeline_layout; |
| @@ -820,6 +844,61 @@ VkPipeline BlitImageHelper::FindOrEmplaceClearColorPipeline(const BlitImagePipel | |||
| 820 | return *clear_color_pipelines.back(); | 844 | return *clear_color_pipelines.back(); |
| 821 | } | 845 | } |
| 822 | 846 | ||
| 847 | VkPipeline BlitImageHelper::FindOrEmplaceClearStencilPipeline( | ||
| 848 | const BlitDepthStencilPipelineKey& key) { | ||
| 849 | const auto it = std::ranges::find(clear_stencil_keys, key); | ||
| 850 | if (it != clear_stencil_keys.end()) { | ||
| 851 | return *clear_stencil_pipelines[std::distance(clear_stencil_keys.begin(), it)]; | ||
| 852 | } | ||
| 853 | clear_stencil_keys.push_back(key); | ||
| 854 | const std::array stages = MakeStages(*clear_color_vert, *clear_stencil_frag); | ||
| 855 | const auto stencil = VkStencilOpState{ | ||
| 856 | .failOp = VK_STENCIL_OP_KEEP, | ||
| 857 | .passOp = VK_STENCIL_OP_REPLACE, | ||
| 858 | .depthFailOp = VK_STENCIL_OP_KEEP, | ||
| 859 | .compareOp = VK_COMPARE_OP_ALWAYS, | ||
| 860 | .compareMask = key.stencil_compare_mask, | ||
| 861 | .writeMask = key.stencil_mask, | ||
| 862 | .reference = key.stencil_ref, | ||
| 863 | }; | ||
| 864 | const VkPipelineDepthStencilStateCreateInfo depth_stencil_ci{ | ||
| 865 | .sType = VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO, | ||
| 866 | .pNext = nullptr, | ||
| 867 | .flags = 0, | ||
| 868 | .depthTestEnable = VK_FALSE, | ||
| 869 | .depthWriteEnable = key.depth_clear, | ||
| 870 | .depthCompareOp = VK_COMPARE_OP_ALWAYS, | ||
| 871 | .depthBoundsTestEnable = VK_FALSE, | ||
| 872 | .stencilTestEnable = VK_TRUE, | ||
| 873 | .front = stencil, | ||
| 874 | .back = stencil, | ||
| 875 | .minDepthBounds = 0.0f, | ||
| 876 | .maxDepthBounds = 0.0f, | ||
| 877 | }; | ||
| 878 | clear_stencil_pipelines.push_back(device.GetLogical().CreateGraphicsPipeline({ | ||
| 879 | .sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO, | ||
| 880 | .pNext = nullptr, | ||
| 881 | .flags = 0, | ||
| 882 | .stageCount = static_cast<u32>(stages.size()), | ||
| 883 | .pStages = stages.data(), | ||
| 884 | .pVertexInputState = &PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO, | ||
| 885 | .pInputAssemblyState = &PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO, | ||
| 886 | .pTessellationState = nullptr, | ||
| 887 | .pViewportState = &PIPELINE_VIEWPORT_STATE_CREATE_INFO, | ||
| 888 | .pRasterizationState = &PIPELINE_RASTERIZATION_STATE_CREATE_INFO, | ||
| 889 | .pMultisampleState = &PIPELINE_MULTISAMPLE_STATE_CREATE_INFO, | ||
| 890 | .pDepthStencilState = &depth_stencil_ci, | ||
| 891 | .pColorBlendState = &PIPELINE_COLOR_BLEND_STATE_GENERIC_CREATE_INFO, | ||
| 892 | .pDynamicState = &PIPELINE_DYNAMIC_STATE_CREATE_INFO, | ||
| 893 | .layout = *clear_color_pipeline_layout, | ||
| 894 | .renderPass = key.renderpass, | ||
| 895 | .subpass = 0, | ||
| 896 | .basePipelineHandle = VK_NULL_HANDLE, | ||
| 897 | .basePipelineIndex = 0, | ||
| 898 | })); | ||
| 899 | return *clear_stencil_pipelines.back(); | ||
| 900 | } | ||
| 901 | |||
| 823 | void BlitImageHelper::ConvertPipeline(vk::Pipeline& pipeline, VkRenderPass renderpass, | 902 | void BlitImageHelper::ConvertPipeline(vk::Pipeline& pipeline, VkRenderPass renderpass, |
| 824 | bool is_target_depth) { | 903 | bool is_target_depth) { |
| 825 | if (pipeline) { | 904 | if (pipeline) { |
diff --git a/src/video_core/renderer_vulkan/blit_image.h b/src/video_core/renderer_vulkan/blit_image.h index 2976a7d91..dcfe217aa 100644 --- a/src/video_core/renderer_vulkan/blit_image.h +++ b/src/video_core/renderer_vulkan/blit_image.h | |||
| @@ -27,6 +27,16 @@ struct BlitImagePipelineKey { | |||
| 27 | Tegra::Engines::Fermi2D::Operation operation; | 27 | Tegra::Engines::Fermi2D::Operation operation; |
| 28 | }; | 28 | }; |
| 29 | 29 | ||
| 30 | struct BlitDepthStencilPipelineKey { | ||
| 31 | constexpr auto operator<=>(const BlitDepthStencilPipelineKey&) const noexcept = default; | ||
| 32 | |||
| 33 | VkRenderPass renderpass; | ||
| 34 | bool depth_clear; | ||
| 35 | u8 stencil_mask; | ||
| 36 | u32 stencil_compare_mask; | ||
| 37 | u32 stencil_ref; | ||
| 38 | }; | ||
| 39 | |||
| 30 | class BlitImageHelper { | 40 | class BlitImageHelper { |
| 31 | public: | 41 | public: |
| 32 | explicit BlitImageHelper(const Device& device, Scheduler& scheduler, | 42 | explicit BlitImageHelper(const Device& device, Scheduler& scheduler, |
| @@ -64,6 +74,10 @@ public: | |||
| 64 | void ClearColor(const Framebuffer* dst_framebuffer, u8 color_mask, | 74 | void ClearColor(const Framebuffer* dst_framebuffer, u8 color_mask, |
| 65 | const std::array<f32, 4>& clear_color, const Region2D& dst_region); | 75 | const std::array<f32, 4>& clear_color, const Region2D& dst_region); |
| 66 | 76 | ||
| 77 | void ClearDepthStencil(const Framebuffer* dst_framebuffer, bool depth_clear, f32 clear_depth, | ||
| 78 | u8 stencil_mask, u32 stencil_ref, u32 stencil_compare_mask, | ||
| 79 | const Region2D& dst_region); | ||
| 80 | |||
| 67 | private: | 81 | private: |
| 68 | void Convert(VkPipeline pipeline, const Framebuffer* dst_framebuffer, | 82 | void Convert(VkPipeline pipeline, const Framebuffer* dst_framebuffer, |
| 69 | const ImageView& src_image_view); | 83 | const ImageView& src_image_view); |
| @@ -76,6 +90,8 @@ private: | |||
| 76 | [[nodiscard]] VkPipeline FindOrEmplaceDepthStencilPipeline(const BlitImagePipelineKey& key); | 90 | [[nodiscard]] VkPipeline FindOrEmplaceDepthStencilPipeline(const BlitImagePipelineKey& key); |
| 77 | 91 | ||
| 78 | [[nodiscard]] VkPipeline FindOrEmplaceClearColorPipeline(const BlitImagePipelineKey& key); | 92 | [[nodiscard]] VkPipeline FindOrEmplaceClearColorPipeline(const BlitImagePipelineKey& key); |
| 93 | [[nodiscard]] VkPipeline FindOrEmplaceClearStencilPipeline( | ||
| 94 | const BlitDepthStencilPipelineKey& key); | ||
| 79 | 95 | ||
| 80 | void ConvertPipeline(vk::Pipeline& pipeline, VkRenderPass renderpass, bool is_target_depth); | 96 | void ConvertPipeline(vk::Pipeline& pipeline, VkRenderPass renderpass, bool is_target_depth); |
| 81 | 97 | ||
| @@ -108,6 +124,7 @@ private: | |||
| 108 | vk::ShaderModule blit_depth_stencil_frag; | 124 | vk::ShaderModule blit_depth_stencil_frag; |
| 109 | vk::ShaderModule clear_color_vert; | 125 | vk::ShaderModule clear_color_vert; |
| 110 | vk::ShaderModule clear_color_frag; | 126 | vk::ShaderModule clear_color_frag; |
| 127 | vk::ShaderModule clear_stencil_frag; | ||
| 111 | vk::ShaderModule convert_depth_to_float_frag; | 128 | vk::ShaderModule convert_depth_to_float_frag; |
| 112 | vk::ShaderModule convert_float_to_depth_frag; | 129 | vk::ShaderModule convert_float_to_depth_frag; |
| 113 | vk::ShaderModule convert_abgr8_to_d24s8_frag; | 130 | vk::ShaderModule convert_abgr8_to_d24s8_frag; |
| @@ -122,6 +139,8 @@ private: | |||
| 122 | std::vector<vk::Pipeline> blit_depth_stencil_pipelines; | 139 | std::vector<vk::Pipeline> blit_depth_stencil_pipelines; |
| 123 | std::vector<BlitImagePipelineKey> clear_color_keys; | 140 | std::vector<BlitImagePipelineKey> clear_color_keys; |
| 124 | std::vector<vk::Pipeline> clear_color_pipelines; | 141 | std::vector<vk::Pipeline> clear_color_pipelines; |
| 142 | std::vector<BlitDepthStencilPipelineKey> clear_stencil_keys; | ||
| 143 | std::vector<vk::Pipeline> clear_stencil_pipelines; | ||
| 125 | vk::Pipeline convert_d32_to_r32_pipeline; | 144 | vk::Pipeline convert_d32_to_r32_pipeline; |
| 126 | vk::Pipeline convert_r32_to_d32_pipeline; | 145 | vk::Pipeline convert_r32_to_d32_pipeline; |
| 127 | vk::Pipeline convert_d16_to_r16_pipeline; | 146 | vk::Pipeline convert_d16_to_r16_pipeline; |
diff --git a/src/video_core/renderer_vulkan/vk_rasterizer.cpp b/src/video_core/renderer_vulkan/vk_rasterizer.cpp index 89aa243d2..032f694bc 100644 --- a/src/video_core/renderer_vulkan/vk_rasterizer.cpp +++ b/src/video_core/renderer_vulkan/vk_rasterizer.cpp | |||
| @@ -428,15 +428,27 @@ void RasterizerVulkan::Clear(u32 layer_count) { | |||
| 428 | if (aspect_flags == 0) { | 428 | if (aspect_flags == 0) { |
| 429 | return; | 429 | return; |
| 430 | } | 430 | } |
| 431 | scheduler.Record([clear_depth = regs.clear_depth, clear_stencil = regs.clear_stencil, | 431 | |
| 432 | clear_rect, aspect_flags](vk::CommandBuffer cmdbuf) { | 432 | if (use_stencil && regs.stencil_front_mask != 0xFF && regs.stencil_front_mask != 0) { |
| 433 | VkClearAttachment attachment; | 433 | Region2D dst_region = { |
| 434 | attachment.aspectMask = aspect_flags; | 434 | Offset2D{.x = clear_rect.rect.offset.x, .y = clear_rect.rect.offset.y}, |
| 435 | attachment.colorAttachment = 0; | 435 | Offset2D{.x = clear_rect.rect.offset.x + static_cast<s32>(clear_rect.rect.extent.width), |
| 436 | attachment.clearValue.depthStencil.depth = clear_depth; | 436 | .y = clear_rect.rect.offset.y + |
| 437 | attachment.clearValue.depthStencil.stencil = clear_stencil; | 437 | static_cast<s32>(clear_rect.rect.extent.height)}}; |
| 438 | cmdbuf.ClearAttachments(attachment, clear_rect); | 438 | blit_image.ClearDepthStencil(framebuffer, use_depth, regs.clear_depth, |
| 439 | }); | 439 | static_cast<u8>(regs.stencil_front_mask), regs.clear_stencil, |
| 440 | regs.stencil_front_func_mask, dst_region); | ||
| 441 | } else { | ||
| 442 | scheduler.Record([clear_depth = regs.clear_depth, clear_stencil = regs.clear_stencil, | ||
| 443 | clear_rect, aspect_flags](vk::CommandBuffer cmdbuf) { | ||
| 444 | VkClearAttachment attachment; | ||
| 445 | attachment.aspectMask = aspect_flags; | ||
| 446 | attachment.colorAttachment = 0; | ||
| 447 | attachment.clearValue.depthStencil.depth = clear_depth; | ||
| 448 | attachment.clearValue.depthStencil.stencil = clear_stencil; | ||
| 449 | cmdbuf.ClearAttachments(attachment, clear_rect); | ||
| 450 | }); | ||
| 451 | } | ||
| 440 | } | 452 | } |
| 441 | 453 | ||
| 442 | void RasterizerVulkan::DispatchCompute() { | 454 | void RasterizerVulkan::DispatchCompute() { |