diff --git a/src/video_core/host_shaders/vulkan_color_clear.frag b/src/video_core/host_shaders/vulkan_color_clear.frag index 617bf01e17..d17ce12b1a 100644 --- a/src/video_core/host_shaders/vulkan_color_clear.frag +++ b/src/video_core/host_shaders/vulkan_color_clear.frag @@ -1,3 +1,6 @@ +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + // SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later @@ -7,8 +10,10 @@ layout (push_constant) uniform PushConstants { vec4 clear_color; }; -layout(location = 0) out vec4 color; +layout(location = 0) out vec4 colors[8]; void main() { - color = clear_color; + for (int index = 0; index < 8; ++index) { + colors[index] = clear_color; + } } diff --git a/src/video_core/renderer_vulkan/blit_image.cpp b/src/video_core/renderer_vulkan/blit_image.cpp index 6821ae9550..92f2d0ea5c 100644 --- a/src/video_core/renderer_vulkan/blit_image.cpp +++ b/src/video_core/renderer_vulkan/blit_image.cpp @@ -279,6 +279,44 @@ constexpr VkPipelineDepthStencilStateCreateInfo PIPELINE_DEPTH_ONLY_STATE_CREATE .maxDepthBounds = 0.0f, }; +constexpr VkPipelineDepthStencilStateCreateInfo PIPELINE_DEPTH_STENCIL_STATE_DISABLED_CREATE_INFO{ + .sType = VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO, + .pNext = nullptr, + .flags = 0, + .depthTestEnable = VK_FALSE, + .depthWriteEnable = VK_FALSE, + .depthCompareOp = VK_COMPARE_OP_ALWAYS, + .depthBoundsTestEnable = VK_FALSE, + .stencilTestEnable = VK_FALSE, + .front = VkStencilOpState{}, + .back = VkStencilOpState{}, + .minDepthBounds = 0.0f, + .maxDepthBounds = 0.0f, +}; + +using BlendAttachments = std::array; + +[[nodiscard]] VkPipelineColorBlendStateCreateInfo MakeColorBlendState( + const BlendAttachments& attachments, const RenderingFormats& formats) { + return VkPipelineColorBlendStateCreateInfo{ + .sType = VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO, + .pNext = nullptr, + .flags = 0, + .logicOpEnable = VK_FALSE, + .logicOp = VK_LOGIC_OP_CLEAR, + .attachmentCount = formats.num_colors, + .pAttachments = attachments.data(), + .blendConstants = {0.0f, 0.0f, 0.0f, 0.0f}, + }; +} + +[[nodiscard]] VkPipelineMultisampleStateCreateInfo MakeMultisampleState( + VkSampleCountFlagBits samples) { + VkPipelineMultisampleStateCreateInfo multisample_ci = PIPELINE_MULTISAMPLE_STATE_CREATE_INFO; + multisample_ci.rasterizationSamples = samples; + return multisample_ci; +} + template inline constexpr VkSamplerCreateInfo SAMPLER_CREATE_INFO{ .sType = VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO, @@ -628,6 +666,8 @@ void BlitImageHelper::BlitColor(const Framebuffer* dst_framebuffer, const ImageV const BlitImagePipelineKey key{ .formats = dst_framebuffer->Formats(), .operation = operation, + .samples = dst_framebuffer->Samples(), + .target = 0, }; VkSampler sampler = *nearest_sampler; if (is_linear) { @@ -645,6 +685,8 @@ void BlitImageHelper::BlitColor(const Framebuffer* dst_framebuffer, VkImageView const BlitImagePipelineKey key{ .formats = dst_framebuffer->Formats(), .operation = Tegra::Engines::Fermi2D::Operation::SrcCopy, + .samples = dst_framebuffer->Samples(), + .target = 0, }; const VkPipelineLayout layout = *one_texture_pipeline_layout; const VkPipeline pipeline = FindOrEmplaceColorPipeline(key); @@ -763,6 +805,8 @@ void BlitImageHelper::BlitDepthStencil(const Framebuffer* dst_framebuffer, const BlitImagePipelineKey key{ .formats = dst_framebuffer->Formats(), .operation = operation, + .samples = dst_framebuffer->Samples(), + .target = 0, }; VkPipeline pipeline{}; VkImageView src_stencil_view = VK_NULL_HANDLE; @@ -778,26 +822,22 @@ void BlitImageHelper::BlitDepthStencil(const Framebuffer* dst_framebuffer, void BlitImageHelper::ConvertD32ToR32(const Framebuffer* dst_framebuffer, const ImageView& src_image_view) { - ConvertDepthToColorPipeline(convert_d32_to_r32_pipeline, dst_framebuffer->Formats()); - Convert(*convert_d32_to_r32_pipeline, dst_framebuffer, src_image_view); + Convert(*convert_depth_to_float_frag, dst_framebuffer, src_image_view); } void BlitImageHelper::ConvertR32ToD32(const Framebuffer* dst_framebuffer, const ImageView& src_image_view) { - ConvertColorToDepthPipeline(convert_r32_to_d32_pipeline, dst_framebuffer->Formats()); - Convert(*convert_r32_to_d32_pipeline, dst_framebuffer, src_image_view); + Convert(*convert_float_to_depth_frag, dst_framebuffer, src_image_view); } void BlitImageHelper::ConvertD16ToR16(const Framebuffer* dst_framebuffer, const ImageView& src_image_view) { - ConvertDepthToColorPipeline(convert_d16_to_r16_pipeline, dst_framebuffer->Formats()); - Convert(*convert_d16_to_r16_pipeline, dst_framebuffer, src_image_view); + Convert(*convert_depth_to_float_frag, dst_framebuffer, src_image_view); } void BlitImageHelper::ConvertR16ToD16(const Framebuffer* dst_framebuffer, const ImageView& src_image_view) { - ConvertColorToDepthPipeline(convert_r16_to_d16_pipeline, dst_framebuffer->Formats()); - Convert(*convert_r16_to_d16_pipeline, dst_framebuffer, src_image_view); + Convert(*convert_float_to_depth_frag, dst_framebuffer, src_image_view); } void BlitImageHelper::ConvertABGR8ToD24S8(const Framebuffer* dst_framebuffer, @@ -807,45 +847,37 @@ void BlitImageHelper::ConvertABGR8ToD24S8(const Framebuffer* dst_framebuffer, LOG_WARNING(Render_Vulkan, "ConvertABGR8ToD24S8 requires shader_stencil_export, skipping"); return; } - ConvertPipelineDepthTargetEx(convert_abgr8_to_d24s8_pipeline, dst_framebuffer->Formats(), - convert_abgr8_to_d24s8_frag); - Convert(*convert_abgr8_to_d24s8_pipeline, dst_framebuffer, src_image_view); + Convert(*convert_abgr8_to_d24s8_frag, dst_framebuffer, src_image_view); } void BlitImageHelper::ConvertABGR8ToD32F(const Framebuffer* dst_framebuffer, const ImageView& src_image_view) { - ConvertPipelineDepthTargetEx(convert_abgr8_to_d32f_pipeline, dst_framebuffer->Formats(), - convert_abgr8_to_d32f_frag); - Convert(*convert_abgr8_to_d32f_pipeline, dst_framebuffer, src_image_view); + Convert(*convert_abgr8_to_d32f_frag, dst_framebuffer, src_image_view); } void BlitImageHelper::ConvertD32FToABGR8(const Framebuffer* dst_framebuffer, ImageView& src_image_view) { - ConvertPipelineColorTargetEx(convert_d32f_to_abgr8_pipeline, dst_framebuffer->Formats(), - convert_d32f_to_abgr8_frag); - ConvertDepthStencil(*convert_d32f_to_abgr8_pipeline, dst_framebuffer, src_image_view); + ConvertDepthStencil(*convert_d32f_to_abgr8_frag, dst_framebuffer, src_image_view); } void BlitImageHelper::ConvertD24S8ToABGR8(const Framebuffer* dst_framebuffer, ImageView& src_image_view) { - ConvertPipelineColorTargetEx(convert_d24s8_to_abgr8_pipeline, dst_framebuffer->Formats(), - convert_d24s8_to_abgr8_frag); - ConvertDepthStencil(*convert_d24s8_to_abgr8_pipeline, dst_framebuffer, src_image_view); + ConvertDepthStencil(*convert_d24s8_to_abgr8_frag, dst_framebuffer, src_image_view); } void BlitImageHelper::ConvertS8D24ToABGR8(const Framebuffer* dst_framebuffer, ImageView& src_image_view) { - ConvertPipelineColorTargetEx(convert_s8d24_to_abgr8_pipeline, dst_framebuffer->Formats(), - convert_s8d24_to_abgr8_frag); - ConvertDepthStencil(*convert_s8d24_to_abgr8_pipeline, dst_framebuffer, src_image_view); + ConvertDepthStencil(*convert_s8d24_to_abgr8_frag, dst_framebuffer, src_image_view); } -void BlitImageHelper::ClearColor(const Framebuffer* dst_framebuffer, u8 color_mask, +void BlitImageHelper::ClearColor(const Framebuffer* dst_framebuffer, u32 target, u8 color_mask, const std::array& clear_color, const Region2D& dst_region) { const BlitImagePipelineKey key{ .formats = dst_framebuffer->Formats(), .operation = Tegra::Engines::Fermi2D::Operation::BlendPremult, + .samples = dst_framebuffer->Samples(), + .target = target, }; const VkPipeline pipeline = FindOrEmplaceClearColorPipeline(key); const VkPipelineLayout layout = *clear_color_pipeline_layout; @@ -873,6 +905,7 @@ void BlitImageHelper::ClearDepthStencil(const Framebuffer* dst_framebuffer, bool .stencil_mask = stencil_mask, .stencil_compare_mask = stencil_compare_mask, .stencil_ref = stencil_ref, + .samples = dst_framebuffer->Samples(), }; const VkPipeline pipeline = FindOrEmplaceClearStencilPipeline(key); const VkPipelineLayout layout = *clear_color_pipeline_layout; @@ -1079,9 +1112,11 @@ void BlitImageHelper::CopyMSAA(VkImage dst_image, VideoCore::Surface::PixelForma aspect_info, false); } -void BlitImageHelper::Convert(VkPipeline pipeline, const Framebuffer* dst_framebuffer, +void BlitImageHelper::Convert(VkShaderModule module, const Framebuffer* dst_framebuffer, const ImageView& src_image_view) { const VkPipelineLayout layout = *one_texture_pipeline_layout; + const VkPipeline pipeline = + FindOrEmplaceConvertPipeline(dst_framebuffer->Formats(), module, layout); const VkImageView src_view = src_image_view.Handle(Shader::TextureType::Color2D); const VkSampler sampler = *nearest_sampler; const VkExtent2D extent = GetConversionExtent(src_image_view); @@ -1128,9 +1163,12 @@ void BlitImageHelper::Convert(VkPipeline pipeline, const Framebuffer* dst_frameb scheduler.InvalidateState(); } -void BlitImageHelper::ConvertDepthStencil(VkPipeline pipeline, const Framebuffer* dst_framebuffer, +void BlitImageHelper::ConvertDepthStencil(VkShaderModule module, + const Framebuffer* dst_framebuffer, ImageView& src_image_view) { const VkPipelineLayout layout = *two_textures_pipeline_layout; + const VkPipeline pipeline = + FindOrEmplaceConvertPipeline(dst_framebuffer->Formats(), module, layout); const VkImageView src_depth_view = src_image_view.DepthView(); const VkImageView src_stencil_view = src_image_view.StencilView(); const VkSampler sampler = *nearest_sampler; @@ -1187,28 +1225,12 @@ VkPipeline BlitImageHelper::FindOrEmplaceColorPipeline(const BlitImagePipelineKe blit_color_keys.push_back(key); const std::array stages = MakeStages(*full_screen_vert, *blit_color_to_color_frag); - const VkPipelineColorBlendAttachmentState blend_attachment{ - .blendEnable = VK_FALSE, - .srcColorBlendFactor = VK_BLEND_FACTOR_ZERO, - .dstColorBlendFactor = VK_BLEND_FACTOR_ZERO, - .colorBlendOp = VK_BLEND_OP_ADD, - .srcAlphaBlendFactor = VK_BLEND_FACTOR_ZERO, - .dstAlphaBlendFactor = VK_BLEND_FACTOR_ZERO, - .alphaBlendOp = VK_BLEND_OP_ADD, - .colorWriteMask = VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | - VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT, - }; + BlendAttachments blend_attachments{}; + blend_attachments[key.target] = PIPELINE_COLOR_BLEND_ATTACHMENT_STATE; // TODO: programmable blending - const VkPipelineColorBlendStateCreateInfo color_blend_create_info{ - .sType = VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO, - .pNext = nullptr, - .flags = 0, - .logicOpEnable = VK_FALSE, - .logicOp = VK_LOGIC_OP_CLEAR, - .attachmentCount = 1, - .pAttachments = &blend_attachment, - .blendConstants = {0.0f, 0.0f, 0.0f, 0.0f}, - }; + const VkPipelineColorBlendStateCreateInfo color_blend_create_info = + MakeColorBlendState(blend_attachments, key.formats); + const VkPipelineMultisampleStateCreateInfo multisample_ci = MakeMultisampleState(key.samples); const VkPipelineInputAssemblyStateCreateInfo input_assembly_ci = GetPipelineInputAssemblyStateCreateInfo(device); const VkPipelineRenderingCreateInfo rendering_ci = key.formats.CreateInfo(); blit_color_pipelines.push_back(device.GetLogical().CreateGraphicsPipeline({ @@ -1222,8 +1244,8 @@ VkPipeline BlitImageHelper::FindOrEmplaceColorPipeline(const BlitImagePipelineKe .pTessellationState = nullptr, .pViewportState = &PIPELINE_VIEWPORT_STATE_CREATE_INFO, .pRasterizationState = &PIPELINE_RASTERIZATION_STATE_CREATE_INFO, - .pMultisampleState = &PIPELINE_MULTISAMPLE_STATE_CREATE_INFO, - .pDepthStencilState = nullptr, + .pMultisampleState = &multisample_ci, + .pDepthStencilState = &PIPELINE_DEPTH_STENCIL_STATE_DISABLED_CREATE_INFO, .pColorBlendState = &color_blend_create_info, .pDynamicState = &PIPELINE_DYNAMIC_STATE_CREATE_INFO, .layout = *one_texture_pipeline_layout, @@ -1241,6 +1263,7 @@ VkPipeline BlitImageHelper::FindOrEmplaceDepthStencilPipeline(const BlitImagePip } blit_depth_stencil_keys.push_back(key); const std::array stages = MakeStages(*full_screen_vert, *blit_depth_stencil_frag); + const VkPipelineMultisampleStateCreateInfo multisample_ci = MakeMultisampleState(key.samples); const VkPipelineInputAssemblyStateCreateInfo input_assembly_ci = GetPipelineInputAssemblyStateCreateInfo(device); const VkPipelineRenderingCreateInfo rendering_ci = key.formats.CreateInfo(); blit_depth_stencil_pipelines.push_back(device.GetLogical().CreateGraphicsPipeline({ @@ -1254,7 +1277,7 @@ VkPipeline BlitImageHelper::FindOrEmplaceDepthStencilPipeline(const BlitImagePip .pTessellationState = nullptr, .pViewportState = &PIPELINE_VIEWPORT_STATE_CREATE_INFO, .pRasterizationState = &PIPELINE_RASTERIZATION_STATE_CREATE_INFO, - .pMultisampleState = &PIPELINE_MULTISAMPLE_STATE_CREATE_INFO, + .pMultisampleState = &multisample_ci, .pDepthStencilState = &PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO, .pColorBlendState = &PIPELINE_COLOR_BLEND_STATE_EMPTY_CREATE_INFO, .pDynamicState = &PIPELINE_DYNAMIC_STATE_CREATE_INFO, @@ -1284,16 +1307,11 @@ VkPipeline BlitImageHelper::FindOrEmplaceClearColorPipeline(const BlitImagePipel .colorWriteMask = VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT, }; - const VkPipelineColorBlendStateCreateInfo color_blend_state_generic_create_info{ - .sType = VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO, - .pNext = nullptr, - .flags = 0, - .logicOpEnable = VK_FALSE, - .logicOp = VK_LOGIC_OP_CLEAR, - .attachmentCount = 1, - .pAttachments = &color_blend_attachment_state, - .blendConstants = {0.0f, 0.0f, 0.0f, 0.0f}, - }; + BlendAttachments blend_attachments{}; + blend_attachments[key.target] = color_blend_attachment_state; + const VkPipelineColorBlendStateCreateInfo color_blend_create_info = + MakeColorBlendState(blend_attachments, key.formats); + const VkPipelineMultisampleStateCreateInfo multisample_ci = MakeMultisampleState(key.samples); const VkPipelineInputAssemblyStateCreateInfo input_assembly_ci = GetPipelineInputAssemblyStateCreateInfo(device); const VkPipelineRenderingCreateInfo rendering_ci = key.formats.CreateInfo(); clear_color_pipelines.push_back(device.GetLogical().CreateGraphicsPipeline({ @@ -1307,9 +1325,9 @@ VkPipeline BlitImageHelper::FindOrEmplaceClearColorPipeline(const BlitImagePipel .pTessellationState = nullptr, .pViewportState = &PIPELINE_VIEWPORT_STATE_CREATE_INFO, .pRasterizationState = &PIPELINE_RASTERIZATION_STATE_CREATE_INFO, - .pMultisampleState = &PIPELINE_MULTISAMPLE_STATE_CREATE_INFO, - .pDepthStencilState = &PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO, - .pColorBlendState = &color_blend_state_generic_create_info, + .pMultisampleState = &multisample_ci, + .pDepthStencilState = &PIPELINE_DEPTH_STENCIL_STATE_DISABLED_CREATE_INFO, + .pColorBlendState = &color_blend_create_info, .pDynamicState = &PIPELINE_DYNAMIC_STATE_CREATE_INFO, .layout = *clear_color_pipeline_layout, .subpass = 0, @@ -1350,6 +1368,10 @@ VkPipeline BlitImageHelper::FindOrEmplaceClearStencilPipeline( .minDepthBounds = 0.0f, .maxDepthBounds = 0.0f, }; + const BlendAttachments blend_attachments{}; + const VkPipelineColorBlendStateCreateInfo color_blend_create_info = + MakeColorBlendState(blend_attachments, key.formats); + const VkPipelineMultisampleStateCreateInfo multisample_ci = MakeMultisampleState(key.samples); const VkPipelineInputAssemblyStateCreateInfo input_assembly_ci = GetPipelineInputAssemblyStateCreateInfo(device); const VkPipelineRenderingCreateInfo rendering_ci = key.formats.CreateInfo(); clear_stencil_pipelines.push_back(device.GetLogical().CreateGraphicsPipeline({ @@ -1363,9 +1385,9 @@ VkPipeline BlitImageHelper::FindOrEmplaceClearStencilPipeline( .pTessellationState = nullptr, .pViewportState = &PIPELINE_VIEWPORT_STATE_CREATE_INFO, .pRasterizationState = &PIPELINE_RASTERIZATION_STATE_CREATE_INFO, - .pMultisampleState = &PIPELINE_MULTISAMPLE_STATE_CREATE_INFO, + .pMultisampleState = &multisample_ci, .pDepthStencilState = &depth_stencil_ci, - .pColorBlendState = &PIPELINE_COLOR_BLEND_STATE_GENERIC_CREATE_INFO, + .pColorBlendState = &color_blend_create_info, .pDynamicState = &PIPELINE_DYNAMIC_STATE_CREATE_INFO, .layout = *clear_color_pipeline_layout, .subpass = 0, @@ -1716,26 +1738,30 @@ VkPipeline BlitImageHelper::FindOrEmplaceMSAACopyDepthPipeline(const MSAACopyPip return *pipelines.back(); } -void BlitImageHelper::ConvertDepthToColorPipeline(vk::Pipeline& pipeline, - const RenderingFormats& formats) { - ConvertPipeline(pipeline, formats, false); -} - -void BlitImageHelper::ConvertColorToDepthPipeline(vk::Pipeline& pipeline, - const RenderingFormats& formats) { - ConvertPipeline(pipeline, formats, true); -} - -void BlitImageHelper::ConvertPipelineEx(vk::Pipeline& pipeline, const RenderingFormats& formats, - vk::ShaderModule& module, bool single_texture, - bool is_target_depth) { - if (pipeline) { - return; +VkPipeline BlitImageHelper::FindOrEmplaceConvertPipeline(const RenderingFormats& formats, + VkShaderModule module, + VkPipelineLayout layout) { + const ConvertPipelineKey key{ + .formats = formats, + .module = module, + }; + const auto it = std::ranges::find(convert_keys, key); + if (it != convert_keys.end()) { + return *convert_pipelines[std::distance(convert_keys.begin(), it)]; } - const std::array stages = MakeStages(*full_screen_vert, *module); - const VkPipelineInputAssemblyStateCreateInfo input_assembly_ci = GetPipelineInputAssemblyStateCreateInfo(device); + convert_keys.push_back(key); + const VkPipelineDepthStencilStateCreateInfo* depth_stencil_ci = nullptr; + const VkPipelineColorBlendStateCreateInfo* color_blend_ci = + &PIPELINE_COLOR_BLEND_STATE_GENERIC_CREATE_INFO; + if (formats.num_colors == 0) { + depth_stencil_ci = &PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO; + color_blend_ci = &PIPELINE_COLOR_BLEND_STATE_EMPTY_CREATE_INFO; + } + const std::array stages = MakeStages(*full_screen_vert, module); + const VkPipelineInputAssemblyStateCreateInfo input_assembly_ci = + GetPipelineInputAssemblyStateCreateInfo(device); const VkPipelineRenderingCreateInfo rendering_ci = formats.CreateInfo(); - pipeline = device.GetLogical().CreateGraphicsPipeline(VkGraphicsPipelineCreateInfo{ + convert_pipelines.push_back(device.GetLogical().CreateGraphicsPipeline({ .sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO, .pNext = &rendering_ci, .flags = 0, @@ -1747,60 +1773,15 @@ void BlitImageHelper::ConvertPipelineEx(vk::Pipeline& pipeline, const RenderingF .pViewportState = &PIPELINE_VIEWPORT_STATE_CREATE_INFO, .pRasterizationState = &PIPELINE_RASTERIZATION_STATE_CREATE_INFO, .pMultisampleState = &PIPELINE_MULTISAMPLE_STATE_CREATE_INFO, - .pDepthStencilState = is_target_depth ? &PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO : nullptr, - .pColorBlendState = is_target_depth ? &PIPELINE_COLOR_BLEND_STATE_EMPTY_CREATE_INFO - : &PIPELINE_COLOR_BLEND_STATE_GENERIC_CREATE_INFO, + .pDepthStencilState = depth_stencil_ci, + .pColorBlendState = color_blend_ci, .pDynamicState = &PIPELINE_DYNAMIC_STATE_CREATE_INFO, - .layout = single_texture ? *one_texture_pipeline_layout : *two_textures_pipeline_layout, + .layout = layout, .subpass = 0, .basePipelineHandle = VK_NULL_HANDLE, .basePipelineIndex = 0, - }); -} - -void BlitImageHelper::ConvertPipelineColorTargetEx(vk::Pipeline& pipeline, - const RenderingFormats& formats, - vk::ShaderModule& module) { - ConvertPipelineEx(pipeline, formats, module, false, false); -} - -void BlitImageHelper::ConvertPipelineDepthTargetEx(vk::Pipeline& pipeline, - const RenderingFormats& formats, - vk::ShaderModule& module) { - ConvertPipelineEx(pipeline, formats, module, true, true); -} - -void BlitImageHelper::ConvertPipeline(vk::Pipeline& pipeline, const RenderingFormats& formats, - bool is_target_depth) { - if (pipeline) { - return; - } - VkShaderModule frag_shader = - is_target_depth ? *convert_float_to_depth_frag : *convert_depth_to_float_frag; - const std::array stages = MakeStages(*full_screen_vert, frag_shader); - const VkPipelineInputAssemblyStateCreateInfo input_assembly_ci = GetPipelineInputAssemblyStateCreateInfo(device); - const VkPipelineRenderingCreateInfo rendering_ci = formats.CreateInfo(); - pipeline = device.GetLogical().CreateGraphicsPipeline(VkGraphicsPipelineCreateInfo{ - .sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO, - .pNext = &rendering_ci, - .flags = 0, - .stageCount = static_cast(stages.size()), - .pStages = stages.data(), - .pVertexInputState = &PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO, - .pInputAssemblyState = &input_assembly_ci, - .pTessellationState = nullptr, - .pViewportState = &PIPELINE_VIEWPORT_STATE_CREATE_INFO, - .pRasterizationState = &PIPELINE_RASTERIZATION_STATE_CREATE_INFO, - .pMultisampleState = &PIPELINE_MULTISAMPLE_STATE_CREATE_INFO, - .pDepthStencilState = is_target_depth ? &PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO : nullptr, - .pColorBlendState = is_target_depth ? &PIPELINE_COLOR_BLEND_STATE_EMPTY_CREATE_INFO - : &PIPELINE_COLOR_BLEND_STATE_GENERIC_CREATE_INFO, - .pDynamicState = &PIPELINE_DYNAMIC_STATE_CREATE_INFO, - .layout = *one_texture_pipeline_layout, - .subpass = 0, - .basePipelineHandle = VK_NULL_HANDLE, - .basePipelineIndex = 0, - }); + })); + return *convert_pipelines.back(); } } // namespace Vulkan diff --git a/src/video_core/renderer_vulkan/blit_image.h b/src/video_core/renderer_vulkan/blit_image.h index d4038c8dae..bc1db246ff 100644 --- a/src/video_core/renderer_vulkan/blit_image.h +++ b/src/video_core/renderer_vulkan/blit_image.h @@ -33,6 +33,8 @@ struct BlitImagePipelineKey { RenderingFormats formats; Tegra::Engines::Fermi2D::Operation operation; + VkSampleCountFlagBits samples; + u32 target; }; struct BlitDepthStencilPipelineKey { @@ -43,6 +45,14 @@ struct BlitDepthStencilPipelineKey { u8 stencil_mask; u32 stencil_compare_mask; u32 stencil_ref; + VkSampleCountFlagBits samples; +}; + +struct ConvertPipelineKey { + constexpr auto operator<=>(const ConvertPipelineKey&) const noexcept = default; + + RenderingFormats formats; + VkShaderModule module; }; enum class MSAACopyFormatClass : u32 { @@ -117,7 +127,7 @@ public: void ConvertS8D24ToABGR8(const Framebuffer* dst_framebuffer, ImageView& src_image_view); - void ClearColor(const Framebuffer* dst_framebuffer, u8 color_mask, + void ClearColor(const Framebuffer* dst_framebuffer, u32 target, u8 color_mask, const std::array& clear_color, const Region2D& dst_region); void ClearDepthStencil(const Framebuffer* dst_framebuffer, bool depth_clear, f32 clear_depth, @@ -156,10 +166,10 @@ private: std::span copies, const MSAACopyAspectInfo& aspect_info, bool copy_stencil); - void Convert(VkPipeline pipeline, const Framebuffer* dst_framebuffer, + void Convert(VkShaderModule module, const Framebuffer* dst_framebuffer, const ImageView& src_image_view); - void ConvertDepthStencil(VkPipeline pipeline, const Framebuffer* dst_framebuffer, + void ConvertDepthStencil(VkShaderModule module, const Framebuffer* dst_framebuffer, ImageView& src_image_view); [[nodiscard]] VkPipeline FindOrEmplaceColorPipeline(const BlitImagePipelineKey& key); @@ -179,22 +189,9 @@ private: [[nodiscard]] VkPipeline FindOrEmplaceBlitDepthPipeline(const RenderingFormats& formats); [[nodiscard]] VkPipeline FindOrEmplaceResolveDepthStencilPipeline( const RenderingFormats& formats, bool resolve_stencil); - - void ConvertPipeline(vk::Pipeline& pipeline, const RenderingFormats& formats, - bool is_target_depth); - - void ConvertDepthToColorPipeline(vk::Pipeline& pipeline, const RenderingFormats& formats); - - void ConvertColorToDepthPipeline(vk::Pipeline& pipeline, const RenderingFormats& formats); - - void ConvertPipelineEx(vk::Pipeline& pipeline, const RenderingFormats& formats, - vk::ShaderModule& module, bool single_texture, bool is_target_depth); - - void ConvertPipelineColorTargetEx(vk::Pipeline& pipeline, const RenderingFormats& formats, - vk::ShaderModule& module); - - void ConvertPipelineDepthTargetEx(vk::Pipeline& pipeline, const RenderingFormats& formats, - vk::ShaderModule& module); + [[nodiscard]] VkPipeline FindOrEmplaceConvertPipeline(const RenderingFormats& formats, + VkShaderModule module, + VkPipelineLayout layout); const Device& device; Scheduler& scheduler; @@ -271,15 +268,8 @@ private: vk::ImageView dst_view; }; std::deque msaa_copy_resources; - vk::Pipeline convert_d32_to_r32_pipeline; - vk::Pipeline convert_r32_to_d32_pipeline; - vk::Pipeline convert_d16_to_r16_pipeline; - vk::Pipeline convert_r16_to_d16_pipeline; - vk::Pipeline convert_abgr8_to_d24s8_pipeline; - vk::Pipeline convert_abgr8_to_d32f_pipeline; - vk::Pipeline convert_d32f_to_abgr8_pipeline; - vk::Pipeline convert_d24s8_to_abgr8_pipeline; - vk::Pipeline convert_s8d24_to_abgr8_pipeline; + std::vector convert_keys; + std::vector convert_pipelines; }; } // namespace Vulkan diff --git a/src/video_core/renderer_vulkan/vk_query_cache.cpp b/src/video_core/renderer_vulkan/vk_query_cache.cpp index 3fab3eb7fd..adf6d763ac 100644 --- a/src/video_core/renderer_vulkan/vk_query_cache.cpp +++ b/src/video_core/renderer_vulkan/vk_query_cache.cpp @@ -1421,24 +1421,19 @@ void QueryCacheRuntime::HostConditionalRenderingCompareValueImpl(VideoCommon::Lo impl->hcr_buffer = buffer->Handle(); impl->hcr_offset = offset; } - if (impl->hcr_is_set) { - if (impl->hcr_setup.buffer == impl->hcr_buffer && - impl->hcr_setup.offset == impl->hcr_offset) { - return; - } + VkConditionalRenderingFlagsEXT flags = 0; + if (is_equal) { + flags = VK_CONDITIONAL_RENDERING_INVERTED_BIT_EXT; } - bool was_running = impl->is_hcr_running; - if (was_running) { - PauseHostConditionalRendering(); + if (impl->hcr_is_set && impl->hcr_setup.buffer == impl->hcr_buffer && + impl->hcr_setup.offset == impl->hcr_offset && impl->hcr_setup.flags == flags) { + return; } + PauseHostConditionalRendering(); impl->hcr_setup.buffer = impl->hcr_buffer; impl->hcr_setup.offset = impl->hcr_offset; - impl->hcr_setup.flags = is_equal ? VK_CONDITIONAL_RENDERING_INVERTED_BIT_EXT : 0; + impl->hcr_setup.flags = flags; impl->hcr_is_set = true; - impl->is_hcr_running = false; - if (was_running) { - ResumeHostConditionalRendering(); - } } void QueryCacheRuntime::HostConditionalRenderingCompareBCImpl(DAddr address, bool is_equal, @@ -1455,20 +1450,16 @@ void QueryCacheRuntime::HostConditionalRenderingCompareBCImpl(DAddr address, boo to_resolve = buffer->Handle(); to_resolve_offset = static_cast(offset); } - bool was_running = impl->is_hcr_running; - if (was_running) { - PauseHostConditionalRendering(); - } + PauseHostConditionalRendering(); impl->conditional_resolve_pass->Resolve(*impl->hcr_resolve_buffer, to_resolve, to_resolve_offset, compare_to_zero); impl->hcr_setup.buffer = *impl->hcr_resolve_buffer; impl->hcr_setup.offset = 0; - impl->hcr_setup.flags = is_equal ? 0 : VK_CONDITIONAL_RENDERING_INVERTED_BIT_EXT; - impl->hcr_is_set = true; - impl->is_hcr_running = false; - if (was_running) { - ResumeHostConditionalRendering(); + impl->hcr_setup.flags = 0; + if (!is_equal) { + impl->hcr_setup.flags = VK_CONDITIONAL_RENDERING_INVERTED_BIT_EXT; } + impl->hcr_is_set = true; } bool QueryCacheRuntime::HostConditionalRenderingCompareValue(VideoCommon::LookupData object_1, diff --git a/src/video_core/renderer_vulkan/vk_rasterizer.cpp b/src/video_core/renderer_vulkan/vk_rasterizer.cpp index 27332f8129..18d715f058 100644 --- a/src/video_core/renderer_vulkan/vk_rasterizer.cpp +++ b/src/video_core/renderer_vulkan/vk_rasterizer.cpp @@ -550,7 +550,8 @@ void RasterizerVulkan::Clear(u32 layer_count) { Offset2D{.x = clear_rect.rect.offset.x + s32(clear_rect.rect.extent.width), .y = clear_rect.rect.offset.y + s32(clear_rect.rect.extent.height)}}; request_renderpass(); - blit_image.ClearColor(framebuffer, color_mask, regs.clear_color, dst_region); + blit_image.ClearColor(framebuffer, color_attachment, color_mask, regs.clear_color, + dst_region); } else if (!clear_on_load || !scheduler.OverrideLoadOps(framebuffer, 1u << color_attachment, VK_ATTACHMENT_LOAD_OP_CLEAR, clear_value)) { diff --git a/src/video_core/renderer_vulkan/vk_scheduler.cpp b/src/video_core/renderer_vulkan/vk_scheduler.cpp index b23a6f0c88..4c63d0b890 100644 --- a/src/video_core/renderer_vulkan/vk_scheduler.cpp +++ b/src/video_core/renderer_vulkan/vk_scheduler.cpp @@ -4,8 +4,10 @@ // SPDX-FileCopyrightText: Copyright 2019 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later +#include #include #include +#include #include #include @@ -116,6 +118,7 @@ void Scheduler::DispatchWork() { } event_cv.notify_all(); recorded_attachments = nullptr; + ended_attachments = nullptr; AcquireNewChunk(); } } @@ -169,29 +172,41 @@ bool Scheduler::OverrideLoadOps(const Framebuffer* framebuffer, u32 attachments, if (!renderpass_pristine || recorded_attachments == nullptr) { return false; } - const auto set_load_op = [&](VkRenderingAttachmentInfo& attachment, bool discards_msaa) { + const auto set_load_op = [&](VkRenderingAttachmentInfo& attachment) { attachment.loadOp = load_op; attachment.clearValue = value; - if (discards_msaa && load_op == VK_ATTACHMENT_LOAD_OP_CLEAR) { - attachment.storeOp = VK_ATTACHMENT_STORE_OP_DONT_CARE; - } }; for (u32 slot = 0; slot < recorded_attachments->num_colors; ++slot) { if ((attachments & (1u << slot)) != 0) { - set_load_op(recorded_attachments->colors[slot], framebuffer->DiscardsMsaaColor()); + set_load_op(recorded_attachments->colors[slot]); } } if ((attachments & DEPTH_ATTACHMENT_BIT) != 0) { - set_load_op(recorded_attachments->depth, framebuffer->DiscardsMsaaDepthStencil()); + set_load_op(recorded_attachments->depth); } if ((attachments & STENCIL_ATTACHMENT_BIT) != 0) { - set_load_op(recorded_attachments->stencil, framebuffer->DiscardsMsaaDepthStencil()); + set_load_op(recorded_attachments->stencil); } attachments_touched |= attachments; attachments_written |= attachments; return true; } +void Scheduler::DiscardResolvedAttachments(VkImageView resolve_view) { + if (ended_attachments == nullptr) { + return; + } + const auto discard = [resolve_view](VkRenderingAttachmentInfo& attachment) { + if (attachment.resolveImageView == resolve_view) { + attachment.storeOp = VK_ATTACHMENT_STORE_OP_DONT_CARE; + } + }; + std::ranges::for_each(std::span(ended_attachments->colors).first(ended_attachments->num_colors), + discard); + discard(ended_attachments->depth); + discard(ended_attachments->stencil); +} + void Scheduler::RequestOutsideRenderPassOperationContext() { EndRenderPass(); PublishComputeWrites(); @@ -420,8 +435,8 @@ void Scheduler::EndRenderPass() } if (recorded_attachments != nullptr) { RelaxAttachmentOps(*recorded_attachments); - recorded_attachments = nullptr; } + ended_attachments = std::exchange(recorded_attachments, nullptr); query_cache->CounterClose(VideoCommon::QueryType::StreamingByteCount); diff --git a/src/video_core/renderer_vulkan/vk_scheduler.h b/src/video_core/renderer_vulkan/vk_scheduler.h index 21385549ee..e6917998ea 100644 --- a/src/video_core/renderer_vulkan/vk_scheduler.h +++ b/src/video_core/renderer_vulkan/vk_scheduler.h @@ -69,6 +69,8 @@ public: bool OverrideLoadOps(const Framebuffer* framebuffer, u32 attachments, VkAttachmentLoadOp load_op, const VkClearValue& value); + void DiscardResolvedAttachments(VkImageView resolve_view); + /// Requests the current execution context to be able to execute operations only allowed outside /// of a renderpass. void RequestOutsideRenderPassOperationContext(); @@ -338,6 +340,7 @@ private: u32 attachments_touched = 0; u32 attachments_written = 0; RenderingAttachments* recorded_attachments = nullptr; + RenderingAttachments* ended_attachments = nullptr; VkMemoryBarrier2 renderpass_write_barrier{}; VkMemoryBarrier2 compute_write_barrier{}; VkMemoryBarrier2 upload_write_barrier{}; diff --git a/src/video_core/renderer_vulkan/vk_texture_cache.cpp b/src/video_core/renderer_vulkan/vk_texture_cache.cpp index a7c22db002..330c414b4e 100644 --- a/src/video_core/renderer_vulkan/vk_texture_cache.cpp +++ b/src/video_core/renderer_vulkan/vk_texture_cache.cpp @@ -1838,6 +1838,11 @@ void TextureCacheRuntime::CopyImageMSAA(Image& dst, Image& src, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, region); cmdbuf.PipelineBarrier(0, {}, {}, post_barriers); }); + const bool is_color = aspect_mask == VK_IMAGE_ASPECT_COLOR_BIT; + if ((is_color && ENABLE_MSAA_COLOR_DISCARD) || + (!is_color && ENABLE_MSAA_DEPTH_STENCIL_DISCARD)) { + scheduler.DiscardResolvedAttachments(*shadow->view); + } return; } } @@ -3076,11 +3081,6 @@ void Framebuffer::CreateFramebuffer(TextureCacheRuntime& runtime, samples != VK_SAMPLE_COUNT_1_BIT && depth_image != VK_NULL_HANDLE && runtime.device.IsTiler() && SupportsDepthStencilResolve(runtime.device, depth_format); - discard_msaa_color = - ENABLE_MSAA_RESOLVE_CONSUME && ENABLE_MSAA_COLOR_DISCARD && do_resolve_color; - discard_msaa_depth_stencil = ENABLE_MSAA_RESOLVE_CONSUME && - ENABLE_MSAA_DEPTH_STENCIL_DISCARD && do_resolve_depth_stencil; - runtime_ptr = &runtime; id = ++runtime.framebuffer_serial; render_area.width = (std::min)(render_area.width, width); diff --git a/src/video_core/renderer_vulkan/vk_texture_cache.h b/src/video_core/renderer_vulkan/vk_texture_cache.h index adce1678f7..67f31f1156 100644 --- a/src/video_core/renderer_vulkan/vk_texture_cache.h +++ b/src/video_core/renderer_vulkan/vk_texture_cache.h @@ -250,14 +250,6 @@ public: return is_rescaled; } - [[nodiscard]] bool DiscardsMsaaColor() const noexcept { - return discard_msaa_color; - } - - [[nodiscard]] bool DiscardsMsaaDepthStencil() const noexcept { - return discard_msaa_depth_stencil; - } - /// Records that a render pass has begun, so its resolve attachments will hold valid contents /// once it ends. void MarkResolveShadowsUpToDate() const; @@ -278,8 +270,6 @@ private: std::array resolve_shadow_images{}; u32 num_resolve_shadows = 0; TextureCacheRuntime* runtime_ptr{nullptr}; - bool discard_msaa_color{}; - bool discard_msaa_depth_stencil{}; }; class Image : public VideoCommon::ImageBase {