From cbef1f34515f0a34048278c8e9f1621d009112a2 Mon Sep 17 00:00:00 2001 From: CamilleLaVey Date: Mon, 24 Nov 2025 19:22:33 -0400 Subject: [PATCH] [vk, graphics, pipeline, rasterizer] Alpha Coverage Adjustment --- .../renderer_vulkan/vk_graphics_pipeline.cpp | 8 ++++++-- .../renderer_vulkan/vk_graphics_pipeline.h | 8 ++++++++ src/video_core/renderer_vulkan/vk_rasterizer.cpp | 16 ++++++++++------ 3 files changed, 24 insertions(+), 8 deletions(-) diff --git a/src/video_core/renderer_vulkan/vk_graphics_pipeline.cpp b/src/video_core/renderer_vulkan/vk_graphics_pipeline.cpp index 14b05260db..42600b4e55 100644 --- a/src/video_core/renderer_vulkan/vk_graphics_pipeline.cpp +++ b/src/video_core/renderer_vulkan/vk_graphics_pipeline.cpp @@ -265,6 +265,7 @@ GraphicsPipeline::GraphicsPipeline( std::ranges::copy(info->constant_buffer_used_sizes, uniform_buffer_sizes[stage].begin()); num_textures += Shader::NumDescriptors(info->texture_descriptors); } + fragment_has_color0_output = stage_infos[NUM_STAGES - 1].stores_frag_color[0]; auto func{[this, shader_notify, &render_pass_cache, &descriptor_pool, pipeline_statistics] { DescriptorLayoutBuilder builder{MakeBuilder(device, stage_infos)}; uses_push_descriptor = builder.CanUsePushDescriptor(); @@ -771,6 +772,7 @@ void GraphicsPipeline::MakePipeline(VkRenderPass render_pass) { provoking_vertex.pNext = std::exchange(rasterization_ci.pNext, &provoking_vertex); } + const bool supports_alpha_output = fragment_has_color0_output; const VkPipelineMultisampleStateCreateInfo multisample_ci{ .sType = VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO, .pNext = nullptr, @@ -779,8 +781,10 @@ void GraphicsPipeline::MakePipeline(VkRenderPass render_pass) { .sampleShadingEnable = Settings::values.sample_shading.GetValue() ? VK_TRUE : VK_FALSE, .minSampleShading = static_cast(Settings::values.sample_shading_fraction.GetValue()) / 100.0f, .pSampleMask = nullptr, - .alphaToCoverageEnable = key.state.alpha_to_coverage_enabled != 0 ? VK_TRUE : VK_FALSE, - .alphaToOneEnable = key.state.alpha_to_one_enabled != 0 ? VK_TRUE : VK_FALSE, + .alphaToCoverageEnable = + supports_alpha_output && key.state.alpha_to_coverage_enabled != 0 ? VK_TRUE : VK_FALSE, + .alphaToOneEnable = + supports_alpha_output && key.state.alpha_to_one_enabled != 0 ? VK_TRUE : VK_FALSE, }; const VkPipelineDepthStencilStateCreateInfo depth_stencil_ci{ .sType = VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO, diff --git a/src/video_core/renderer_vulkan/vk_graphics_pipeline.h b/src/video_core/renderer_vulkan/vk_graphics_pipeline.h index c8e89d60a4..80f44643e2 100644 --- a/src/video_core/renderer_vulkan/vk_graphics_pipeline.h +++ b/src/video_core/renderer_vulkan/vk_graphics_pipeline.h @@ -82,6 +82,13 @@ public: const std::array& infos); bool HasDynamicVertexInput() const noexcept { return key.state.dynamic_vertex_input; } + bool SupportsAlphaToCoverage() const noexcept { + return fragment_has_color0_output; + } + + bool SupportsAlphaToOne() const noexcept { + return fragment_has_color0_output; + } GraphicsPipeline& operator=(GraphicsPipeline&&) noexcept = delete; GraphicsPipeline(GraphicsPipeline&&) noexcept = delete; @@ -149,6 +156,7 @@ private: std::array enabled_uniform_buffer_masks{}; VideoCommon::UniformBufferSizes uniform_buffer_sizes{}; u32 num_textures{}; + bool fragment_has_color0_output{}; vk::DescriptorSetLayout descriptor_set_layout; DescriptorAllocator descriptor_allocator; diff --git a/src/video_core/renderer_vulkan/vk_rasterizer.cpp b/src/video_core/renderer_vulkan/vk_rasterizer.cpp index a7479e2af1..4d3a93e21b 100644 --- a/src/video_core/renderer_vulkan/vk_rasterizer.cpp +++ b/src/video_core/renderer_vulkan/vk_rasterizer.cpp @@ -1489,9 +1489,11 @@ void RasterizerVulkan::UpdateAlphaToCoverageEnable(Tegra::Engines::Maxwell3D::Re if (!state_tracker.TouchAlphaToCoverageEnable()) { return; } - scheduler.Record([enable = regs.anti_alias_alpha_control.alpha_to_coverage]( - vk::CommandBuffer cmdbuf) { - cmdbuf.SetAlphaToCoverageEnableEXT(enable != 0); + GraphicsPipeline* const pipeline = pipeline_cache.CurrentGraphicsPipeline(); + const bool enable = pipeline != nullptr && pipeline->SupportsAlphaToCoverage() && + regs.anti_alias_alpha_control.alpha_to_coverage != 0; + scheduler.Record([enable](vk::CommandBuffer cmdbuf) { + cmdbuf.SetAlphaToCoverageEnableEXT(enable ? VK_TRUE : VK_FALSE); }); } @@ -1499,9 +1501,11 @@ void RasterizerVulkan::UpdateAlphaToOneEnable(Tegra::Engines::Maxwell3D::Regs& r if (!state_tracker.TouchAlphaToOneEnable()) { return; } - scheduler.Record([enable = regs.anti_alias_alpha_control.alpha_to_one]( - vk::CommandBuffer cmdbuf) { - cmdbuf.SetAlphaToOneEnableEXT(enable != 0); + GraphicsPipeline* const pipeline = pipeline_cache.CurrentGraphicsPipeline(); + const bool enable = pipeline != nullptr && pipeline->SupportsAlphaToOne() && + regs.anti_alias_alpha_control.alpha_to_one != 0; + scheduler.Record([enable](vk::CommandBuffer cmdbuf) { + cmdbuf.SetAlphaToOneEnableEXT(enable ? VK_TRUE : VK_FALSE); }); }