From d66f8385c38abc73c6b4f69a510282334f3faadf Mon Sep 17 00:00:00 2001 From: Philip Rebohle Date: Tue, 1 Aug 2023 16:58:46 +0200 Subject: [PATCH] [dxvk] Disable alpha to coverage if sample mask is written Matches D3D11 behaviour and fixes tree rendering in A Total War Saga: TROY. --- src/dxvk/dxvk_context.cpp | 3 ++- src/dxvk/dxvk_graphics.cpp | 21 ++++++++++++++++----- src/dxvk/dxvk_graphics.h | 2 ++ src/dxvk/dxvk_shader.cpp | 6 ++++-- 4 files changed, 24 insertions(+), 8 deletions(-) diff --git a/src/dxvk/dxvk_context.cpp b/src/dxvk/dxvk_context.cpp index f2a1e862..31e15e28 100644 --- a/src/dxvk/dxvk_context.cpp +++ b/src/dxvk/dxvk_context.cpp @@ -5769,7 +5769,8 @@ namespace dxvk { VkSampleMask sampleMask = m_state.gp.state.ms.sampleMask() & ((1u << sampleCount) - 1u); m_cmd->cmdSetMultisampleState(sampleCount, sampleMask); - if (m_device->features().extExtendedDynamicState3.extendedDynamicState3AlphaToCoverageEnable) + if (m_device->features().extExtendedDynamicState3.extendedDynamicState3AlphaToCoverageEnable + && !m_state.gp.flags.test(DxvkGraphicsPipelineFlag::HasSampleMaskExport)) m_cmd->cmdSetAlphaToCoverageState(m_state.gp.state.ms.enableAlphaToCoverage()); } diff --git a/src/dxvk/dxvk_graphics.cpp b/src/dxvk/dxvk_graphics.cpp index 0f2216ea..76df237d 100644 --- a/src/dxvk/dxvk_graphics.cpp +++ b/src/dxvk/dxvk_graphics.cpp @@ -301,9 +301,12 @@ namespace dxvk { msInfo.minSampleShading = 1.0f; } + // Alpha to coverage is not supported with sample mask exports. + cbUseDynamicAlphaToCoverage = !fs || !fs->flags().test(DxvkShaderFlag::ExportsSampleMask); + msSampleMask = state.ms.sampleMask() & ((1u << msInfo.rasterizationSamples) - 1); msInfo.pSampleMask = &msSampleMask; - msInfo.alphaToCoverageEnable = state.ms.enableAlphaToCoverage(); + msInfo.alphaToCoverageEnable = state.ms.enableAlphaToCoverage() && cbUseDynamicAlphaToCoverage; // We need to be fully consistent with the pipeline state here, and // while we could consistently infer it, just don't take any chances @@ -325,6 +328,7 @@ namespace dxvk { && msInfo.alphaToOneEnable == other.msInfo.alphaToOneEnable && msSampleMask == other.msSampleMask && cbUseDynamicBlendConstants == other.cbUseDynamicBlendConstants + && cbUseDynamicAlphaToCoverage == other.cbUseDynamicAlphaToCoverage && feedbackLoop == other.feedbackLoop; for (uint32_t i = 0; i < rtInfo.colorAttachmentCount && eq; i++) @@ -364,6 +368,7 @@ namespace dxvk { hash.add(uint32_t(msInfo.alphaToOneEnable)); hash.add(uint32_t(msSampleMask)); hash.add(uint32_t(cbUseDynamicBlendConstants)); + hash.add(uint32_t(cbUseDynamicAlphaToCoverage)); hash.add(uint32_t(feedbackLoop)); for (uint32_t i = 0; i < rtInfo.colorAttachmentCount; i++) @@ -402,7 +407,8 @@ namespace dxvk { dynamicStates[dynamicStateCount++] = VK_DYNAMIC_STATE_RASTERIZATION_SAMPLES_EXT; dynamicStates[dynamicStateCount++] = VK_DYNAMIC_STATE_SAMPLE_MASK_EXT; - if (device->features().extExtendedDynamicState3.extendedDynamicState3AlphaToCoverageEnable) + if (device->features().extExtendedDynamicState3.extendedDynamicState3AlphaToCoverageEnable + && state.cbUseDynamicAlphaToCoverage) dynamicStates[dynamicStateCount++] = VK_DYNAMIC_STATE_ALPHA_TO_COVERAGE_ENABLE_EXT; } @@ -944,8 +950,12 @@ namespace dxvk { if (m_barrier.access & VK_ACCESS_SHADER_WRITE_BIT) m_flags.set(DxvkGraphicsPipelineFlag::HasStorageDescriptors); - if (m_shaders.fs != nullptr && m_shaders.fs->flags().test(DxvkShaderFlag::HasSampleRateShading)) - m_flags.set(DxvkGraphicsPipelineFlag::HasSampleRateShading); + if (m_shaders.fs != nullptr) { + if (m_shaders.fs->flags().test(DxvkShaderFlag::HasSampleRateShading)) + m_flags.set(DxvkGraphicsPipelineFlag::HasSampleRateShading); + if (m_shaders.fs->flags().test(DxvkShaderFlag::ExportsSampleMask)) + m_flags.set(DxvkGraphicsPipelineFlag::HasSampleMaskExport); + } } @@ -1183,7 +1193,8 @@ namespace dxvk { return false; if (!canUseDynamicAlphaToCoverage - && (state.ms.enableAlphaToCoverage())) + && (state.ms.enableAlphaToCoverage()) + && !m_shaders.fs->flags().test(DxvkShaderFlag::ExportsSampleMask)) return false; } } diff --git a/src/dxvk/dxvk_graphics.h b/src/dxvk/dxvk_graphics.h index 262b3901..435677a8 100644 --- a/src/dxvk/dxvk_graphics.h +++ b/src/dxvk/dxvk_graphics.h @@ -31,6 +31,7 @@ namespace dxvk { HasTransformFeedback, HasStorageDescriptors, HasSampleRateShading, + HasSampleMaskExport, }; using DxvkGraphicsPipelineFlags = Flags; @@ -116,6 +117,7 @@ namespace dxvk { VkSampleMask msSampleMask = 0u; VkBool32 cbUseDynamicBlendConstants = VK_FALSE; + VkBool32 cbUseDynamicAlphaToCoverage = VK_FALSE; std::array cbAttachments = { }; std::array rtColorFormats = { }; diff --git a/src/dxvk/dxvk_shader.cpp b/src/dxvk/dxvk_shader.cpp index 3208c008..dbebf715 100644 --- a/src/dxvk/dxvk_shader.cpp +++ b/src/dxvk/dxvk_shader.cpp @@ -1296,8 +1296,10 @@ namespace dxvk { dynamicStates[dynamicStateCount++] = VK_DYNAMIC_STATE_RASTERIZATION_SAMPLES_EXT; dynamicStates[dynamicStateCount++] = VK_DYNAMIC_STATE_SAMPLE_MASK_EXT; - if (m_device->features().extExtendedDynamicState3.extendedDynamicState3AlphaToCoverageEnable) - dynamicStates[dynamicStateCount++] = VK_DYNAMIC_STATE_ALPHA_TO_COVERAGE_ENABLE_EXT; + if (!m_shaders.fs || !m_shaders.fs->flags().test(DxvkShaderFlag::ExportsSampleMask)) { + if (m_device->features().extExtendedDynamicState3.extendedDynamicState3AlphaToCoverageEnable) + dynamicStates[dynamicStateCount++] = VK_DYNAMIC_STATE_ALPHA_TO_COVERAGE_ENABLE_EXT; + } } VkPipelineDynamicStateCreateInfo dyInfo = { VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO };