diff --git a/MobileGL/MG_Backend/DirectVulkan/Renderer/PipelineFactory.cpp b/MobileGL/MG_Backend/DirectVulkan/Renderer/PipelineFactory.cpp index 5d27f1a3..f8135d24 100644 --- a/MobileGL/MG_Backend/DirectVulkan/Renderer/PipelineFactory.cpp +++ b/MobileGL/MG_Backend/DirectVulkan/Renderer/PipelineFactory.cpp @@ -525,6 +525,16 @@ namespace MobileGL::MG_Backend::DirectVulkan { } effectiveStages = &adjustedStages; } + // A static rasterizer discard leaves the pipeline without fragment shader state, and then + // pStages may not name a fragment stage (VUID-VkGraphicsPipelineCreateInfo-pStages-06894). + // Nothing would run it anyway. + if (payload.rasterizerDiscardEnable) { + if (effectiveStages != &adjustedStages) adjustedStages = *effectiveStages; + std::erase_if(adjustedStages, [](const VkPipelineShaderStageCreateInfo& stageInfo) { + return stageInfo.stage == VK_SHADER_STAGE_FRAGMENT_BIT; + }); + effectiveStages = &adjustedStages; + } { VkShaderStageFlags stagesPresent = 0; for (const auto& stageInfo : *effectiveStages) { diff --git a/MobileGL/MG_Backend/DirectVulkan/Renderer/WireDiscardStateProbe.cpp b/MobileGL/MG_Backend/DirectVulkan/Renderer/WireDiscardStateProbe.cpp index a20c2576..75ae6860 100644 --- a/MobileGL/MG_Backend/DirectVulkan/Renderer/WireDiscardStateProbe.cpp +++ b/MobileGL/MG_Backend/DirectVulkan/Renderer/WireDiscardStateProbe.cpp @@ -265,7 +265,9 @@ namespace MobileGL::MG_Backend::DirectVulkan { dynamic.dynamicStateCount = 2; dynamic.pDynamicStates = kDynamic; VkGraphicsPipelineCreateInfo info{VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO}; - info.stageCount = 2; + // As PipelineFactory builds it: a static discard has no fragment shader state, so no + // fragment stage (VUID-VkGraphicsPipelineCreateInfo-pStages-06894). + info.stageCount = discard ? 1u : 2u; info.pStages = stages; info.pVertexInputState = &vertexInput; info.pInputAssemblyState = &assembly;