Implement VK_EXT_extended_dynamic_state3 Test: dEQP-VK.pipeline.*.extended_dynamic_state.* Change-Id: Id2a1566f3db316369b7fcba08811e1d5cf468406 Reviewed-on: https://swiftshader-review.googlesource.com/c/SwiftShader/+/77908 Kokoro-Result: kokoro <noreply+kokoro@google.com> Commit-Queue: Shahbaz Youssefi <syoussefi@google.com> Tested-by: Shahbaz Youssefi <syoussefi@google.com> Reviewed-by: Jason Macnak <natsu@google.com>
diff --git a/src/Device/Context.cpp b/src/Device/Context.cpp index ee753ba..32e953c 100644 --- a/src/Device/Context.cpp +++ b/src/Device/Context.cpp
@@ -164,12 +164,30 @@ case VK_DYNAMIC_STATE_DEPTH_BIAS_ENABLE: dynamicStateFlags.preRasterization.dynamicDepthBiasEnable = true; break; + case VK_DYNAMIC_STATE_DEPTH_CLAMP_ENABLE_EXT: + dynamicStateFlags.preRasterization.dynamicDepthClampEnable = true; + break; + case VK_DYNAMIC_STATE_DEPTH_CLIP_ENABLE_EXT: + dynamicStateFlags.preRasterization.dynamicDepthClipEnable = true; + break; + case VK_DYNAMIC_STATE_DEPTH_CLIP_NEGATIVE_ONE_TO_ONE_EXT: + dynamicStateFlags.preRasterization.dynamicDepthClipNegativeOneToOne = true; + break; case VK_DYNAMIC_STATE_CULL_MODE: dynamicStateFlags.preRasterization.dynamicCullMode = true; break; case VK_DYNAMIC_STATE_FRONT_FACE: dynamicStateFlags.preRasterization.dynamicFrontFace = true; break; + case VK_DYNAMIC_STATE_POLYGON_MODE_EXT: + dynamicStateFlags.preRasterization.dynamicPolygonMode = true; + break; + case VK_DYNAMIC_STATE_LINE_RASTERIZATION_MODE_EXT: + dynamicStateFlags.preRasterization.dynamicLineRasterizationMode = true; + break; + case VK_DYNAMIC_STATE_PROVOKING_VERTEX_MODE_EXT: + dynamicStateFlags.preRasterization.dynamicProvokingVertexMode = true; + break; case VK_DYNAMIC_STATE_VIEWPORT: dynamicStateFlags.preRasterization.dynamicViewport = true; break; @@ -218,10 +236,36 @@ dynamicStateFlags.fragment.dynamicStencilReference = true; break; + // Fragment or fragment output interface: + case VK_DYNAMIC_STATE_RASTERIZATION_SAMPLES_EXT: + dynamicStateFlags.fragment.dynamicRasterizationSamples = true; + dynamicStateFlags.fragmentOutputInterface.dynamicRasterizationSamples = true; + break; + case VK_DYNAMIC_STATE_SAMPLE_MASK_EXT: + dynamicStateFlags.fragment.dynamicSampleMask = true; + dynamicStateFlags.fragmentOutputInterface.dynamicSampleMask = true; + break; + case VK_DYNAMIC_STATE_ALPHA_TO_COVERAGE_ENABLE_EXT: + dynamicStateFlags.fragment.dynamicAlphaToCoverageEnable = true; + dynamicStateFlags.fragmentOutputInterface.dynamicAlphaToCoverageEnable = true; + break; + // Fragment output interface: case VK_DYNAMIC_STATE_BLEND_CONSTANTS: dynamicStateFlags.fragmentOutputInterface.dynamicBlendConstants = true; break; + case VK_DYNAMIC_STATE_COLOR_BLEND_ENABLE_EXT: + dynamicStateFlags.fragmentOutputInterface.dynamicColorBlendEnable = true; + break; + case VK_DYNAMIC_STATE_COLOR_BLEND_EQUATION_EXT: + dynamicStateFlags.fragmentOutputInterface.dynamicColorBlendEquation = true; + break; + case VK_DYNAMIC_STATE_COLOR_BLEND_ADVANCED_EXT: + dynamicStateFlags.fragmentOutputInterface.dynamicColorBlendAdvanced = true; + break; + case VK_DYNAMIC_STATE_COLOR_WRITE_MASK_EXT: + dynamicStateFlags.fragmentOutputInterface.dynamicColorWriteMask = true; + break; default: UNSUPPORTED("VkDynamicState %d", int(dynamicState)); @@ -482,7 +526,7 @@ return 0; } -void MultisampleState::set(const VkPipelineMultisampleStateCreateInfo *multisampleState) +void MultisampleState::set(const FragmentOutputInterfaceDynamicStateFlags &dynamicStateFlags, const VkPipelineMultisampleStateCreateInfo *multisampleState) { if(multisampleState->flags != 0) { @@ -510,21 +554,24 @@ sampleCount = 4; break; default: - UNSUPPORTED("Unsupported sample count"); + if(!dynamicStateFlags.dynamicRasterizationSamples) + { + UNSUPPORTED("Unsupported sample count"); + } + sampleCount = 4; } - VkSampleMask sampleMask; if(multisampleState->pSampleMask) { - sampleMask = multisampleState->pSampleMask[0]; + staticSampleMask = multisampleState->pSampleMask[0]; } else // "If pSampleMask is NULL, it is treated as if the mask has all bits set to 1." { - sampleMask = ~0; + staticSampleMask = ~0; } alphaToCoverage = (multisampleState->alphaToCoverageEnable != VK_FALSE); - multiSampleMask = sampleMask & ((unsigned)0xFFFFFFFF >> (32 - sampleCount)); + multiSampleMask = staticSampleMask & ((unsigned)0xFFFFFFFF >> (32 - sampleCount)); } void VertexInputInterfaceState::initialize(const VkPipelineVertexInputStateCreateInfo *vertexInputState, @@ -539,6 +586,21 @@ UNSUPPORTED("vertexInputState->flags"); } + // The spec says: + // + // If the VK_EXT_extended_dynamic_state3 extension is enabled, it can be NULL if the + // pipeline is created with both VK_DYNAMIC_STATE_PRIMITIVE_RESTART_ENABLE, and + // VK_DYNAMIC_STATE_PRIMITIVE_TOPOLOGY dynamic states set and + // dynamicPrimitiveTopologyUnrestricted is VK_TRUE. + // + // SwiftShader sets dynamicPrimitiveTopologyUnrestricted to VK_TRUE. + if(inputAssemblyState == nullptr) + { + ASSERT(dynamicStateFlags.dynamicPrimitiveRestartEnable && + dynamicStateFlags.dynamicPrimitiveTopology); + return; + } + if(inputAssemblyState->flags != 0) { // Vulkan 1.2: "flags is reserved for future use." "flags must be 0" @@ -629,85 +691,121 @@ pipelineLayout = layout; dynamicStateFlags = allDynamicStateFlags.preRasterization; - if(rasterizationState->flags != 0) + // The spec says: + // + // If the VK_EXT_extended_dynamic_state3 extension is enabled, it can be NULL if the + // pipeline is created with all of VK_DYNAMIC_STATE_DEPTH_CLAMP_ENABLE_EXT, + // VK_DYNAMIC_STATE_RASTERIZER_DISCARD_ENABLE, VK_DYNAMIC_STATE_POLYGON_MODE_EXT, + // VK_DYNAMIC_STATE_CULL_MODE, VK_DYNAMIC_STATE_FRONT_FACE, + // VK_DYNAMIC_STATE_DEPTH_BIAS_ENABLE, VK_DYNAMIC_STATE_DEPTH_BIAS, and + // VK_DYNAMIC_STATE_LINE_WIDTH dynamic states set. + if(rasterizationState == nullptr) { - // Vulkan 1.2: "flags is reserved for future use." "flags must be 0" - UNSUPPORTED("pCreateInfo->pRasterizationState->flags 0x%08X", int(rasterizationState->flags)); + ASSERT(dynamicStateFlags.dynamicDepthClampEnable && + dynamicStateFlags.dynamicRasterizerDiscardEnable && + dynamicStateFlags.dynamicPolygonMode && + dynamicStateFlags.dynamicCullMode && + dynamicStateFlags.dynamicFrontFace && + dynamicStateFlags.dynamicDepthBiasEnable && + dynamicStateFlags.dynamicDepthBias && + dynamicStateFlags.dynamicLineWidth); } - - rasterizerDiscard = rasterizationState->rasterizerDiscardEnable != VK_FALSE; - cullMode = rasterizationState->cullMode; - frontFace = rasterizationState->frontFace; - polygonMode = rasterizationState->polygonMode; - depthBiasEnable = rasterizationState->depthBiasEnable; - constantDepthBias = rasterizationState->depthBiasConstantFactor; - slopeDepthBias = rasterizationState->depthBiasSlopeFactor; - depthBiasClamp = rasterizationState->depthBiasClamp; - depthRangeUnrestricted = device->hasExtension(VK_EXT_DEPTH_RANGE_UNRESTRICTED_EXTENSION_NAME); - depthClampEnable = rasterizationState->depthClampEnable != VK_FALSE; - depthClipEnable = !depthClampEnable; - - // From the Vulkan spec for vkCmdSetDepthBias: - // The bias value O for a polygon is: - // O = dbclamp(...) - // where dbclamp(x) = - // * x depthBiasClamp = 0 or NaN - // * min(x, depthBiasClamp) depthBiasClamp > 0 - // * max(x, depthBiasClamp) depthBiasClamp < 0 - // So it should be safe to resolve NaNs to 0.0f. - if(std::isnan(depthBiasClamp)) + else { - depthBiasClamp = 0.0f; - } - - if(!dynamicStateFlags.dynamicLineWidth) - { - lineWidth = rasterizationState->lineWidth; - } - - const VkBaseInStructure *extensionCreateInfo = reinterpret_cast<const VkBaseInStructure *>(rasterizationState->pNext); - while(extensionCreateInfo) - { - switch(extensionCreateInfo->sType) + if(rasterizationState->flags != 0) { - case VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_LINE_STATE_CREATE_INFO_EXT: - { - const VkPipelineRasterizationLineStateCreateInfoEXT *lineStateCreateInfo = reinterpret_cast<const VkPipelineRasterizationLineStateCreateInfoEXT *>(extensionCreateInfo); - lineRasterizationMode = lineStateCreateInfo->lineRasterizationMode; - } - break; - case VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_PROVOKING_VERTEX_STATE_CREATE_INFO_EXT: - { - const VkPipelineRasterizationProvokingVertexStateCreateInfoEXT *provokingVertexModeCreateInfo = - reinterpret_cast<const VkPipelineRasterizationProvokingVertexStateCreateInfoEXT *>(extensionCreateInfo); - provokingVertexMode = provokingVertexModeCreateInfo->provokingVertexMode; - } - break; - case VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_DEPTH_CLIP_STATE_CREATE_INFO_EXT: - { - const auto *depthClipInfo = reinterpret_cast<const VkPipelineRasterizationDepthClipStateCreateInfoEXT *>(extensionCreateInfo); - // Reserved for future use. - ASSERT(depthClipInfo->flags == 0); - depthClipEnable = depthClipInfo->depthClipEnable != VK_FALSE; - } - break; - case VK_STRUCTURE_TYPE_APPLICATION_INFO: - // SwiftShader doesn't interact with application info, but dEQP includes it - break; - case VK_STRUCTURE_TYPE_MAX_ENUM: - // dEQP tests that this value is ignored. - break; - default: - UNSUPPORTED("pCreateInfo->pRasterizationState->pNext sType = %s", vk::Stringify(extensionCreateInfo->sType).c_str()); - break; + // Vulkan 1.2: "flags is reserved for future use." "flags must be 0" + UNSUPPORTED("pCreateInfo->pRasterizationState->flags 0x%08X", int(rasterizationState->flags)); } - extensionCreateInfo = extensionCreateInfo->pNext; + rasterizerDiscard = rasterizationState->rasterizerDiscardEnable != VK_FALSE; + cullMode = rasterizationState->cullMode; + frontFace = rasterizationState->frontFace; + polygonMode = rasterizationState->polygonMode; + depthBiasEnable = rasterizationState->depthBiasEnable; + constantDepthBias = rasterizationState->depthBiasConstantFactor; + slopeDepthBias = rasterizationState->depthBiasSlopeFactor; + depthBiasClamp = rasterizationState->depthBiasClamp; + depthRangeUnrestricted = device->hasExtension(VK_EXT_DEPTH_RANGE_UNRESTRICTED_EXTENSION_NAME); + depthClampEnable = rasterizationState->depthClampEnable != VK_FALSE; + depthClipEnable = !depthClampEnable; + depthClipEnableIsExplicit = false; + + // From the Vulkan spec for vkCmdSetDepthBias: + // The bias value O for a polygon is: + // O = dbclamp(...) + // where dbclamp(x) = + // * x depthBiasClamp = 0 or NaN + // * min(x, depthBiasClamp) depthBiasClamp > 0 + // * max(x, depthBiasClamp) depthBiasClamp < 0 + // So it should be safe to resolve NaNs to 0.0f. + if(std::isnan(depthBiasClamp)) + { + depthBiasClamp = 0.0f; + } + + if(!dynamicStateFlags.dynamicLineWidth) + { + lineWidth = rasterizationState->lineWidth; + } + + const VkBaseInStructure *extensionCreateInfo = reinterpret_cast<const VkBaseInStructure *>(rasterizationState->pNext); + while(extensionCreateInfo) + { + switch(extensionCreateInfo->sType) + { + case VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_LINE_STATE_CREATE_INFO_EXT: + { + const VkPipelineRasterizationLineStateCreateInfoEXT *lineStateCreateInfo = reinterpret_cast<const VkPipelineRasterizationLineStateCreateInfoEXT *>(extensionCreateInfo); + lineRasterizationMode = lineStateCreateInfo->lineRasterizationMode; + } + break; + case VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_PROVOKING_VERTEX_STATE_CREATE_INFO_EXT: + { + const VkPipelineRasterizationProvokingVertexStateCreateInfoEXT *provokingVertexModeCreateInfo = + reinterpret_cast<const VkPipelineRasterizationProvokingVertexStateCreateInfoEXT *>(extensionCreateInfo); + provokingVertexMode = provokingVertexModeCreateInfo->provokingVertexMode; + } + break; + case VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_DEPTH_CLIP_STATE_CREATE_INFO_EXT: + { + const auto *depthClipInfo = reinterpret_cast<const VkPipelineRasterizationDepthClipStateCreateInfoEXT *>(extensionCreateInfo); + // Reserved for future use. + ASSERT(depthClipInfo->flags == 0); + depthClipEnable = depthClipInfo->depthClipEnable != VK_FALSE; + depthClipEnableIsExplicit = !dynamicStateFlags.dynamicDepthClipEnable; + } + break; + case VK_STRUCTURE_TYPE_APPLICATION_INFO: + // SwiftShader doesn't interact with application info, but dEQP includes it + break; + case VK_STRUCTURE_TYPE_MAX_ENUM: + // dEQP tests that this value is ignored. + break; + default: + UNSUPPORTED("pCreateInfo->pRasterizationState->pNext sType = %s", vk::Stringify(extensionCreateInfo->sType).c_str()); + break; + } + + extensionCreateInfo = extensionCreateInfo->pNext; + } + } + + // The spec says: + // + // If the VK_EXT_extended_dynamic_state3 extension is enabled, it can be NULL if the + // pipeline is created with both VK_DYNAMIC_STATE_VIEWPORT_WITH_COUNT, and + // VK_DYNAMIC_STATE_SCISSOR_WITH_COUNT dynamic states set. + if(viewportState == nullptr) + { + ASSERT(dynamicStateFlags.dynamicViewportWithCount && + dynamicStateFlags.dynamicScissorWithCount); + return; } if(!rasterizerDiscard || dynamicStateFlags.dynamicRasterizerDiscardEnable) { - extensionCreateInfo = reinterpret_cast<const VkBaseInStructure *>(viewportState->pNext); + const VkBaseInStructure *extensionCreateInfo = reinterpret_cast<const VkBaseInStructure *>(viewportState->pNext); while(extensionCreateInfo != nullptr) { switch(extensionCreateInfo->sType) @@ -771,6 +869,25 @@ depthBiasEnable = dynamicState.depthBiasEnable; } + if(dynamicStateFlags.dynamicDepthClampEnable) + { + depthClampEnable = dynamicState.depthClampEnable; + if(!depthClipEnableIsExplicit && !dynamicStateFlags.dynamicDepthClipEnable) + { + depthClipEnable = !dynamicState.depthClampEnable; + } + } + + if(dynamicStateFlags.dynamicDepthClipEnable) + { + depthClipEnable = dynamicState.depthClipEnable; + } + + if(dynamicStateFlags.dynamicDepthClipNegativeOneToOne) + { + depthClipNegativeOneToOne = dynamicState.depthClipNegativeOneToOne; + } + if(dynamicStateFlags.dynamicCullMode) { cullMode = dynamicState.cullMode; @@ -781,6 +898,21 @@ frontFace = dynamicState.frontFace; } + if(dynamicStateFlags.dynamicPolygonMode) + { + polygonMode = dynamicState.polygonMode; + } + + if(dynamicStateFlags.dynamicLineRasterizationMode) + { + lineRasterizationMode = dynamicState.lineRasterizationMode; + } + + if(dynamicStateFlags.dynamicProvokingVertexMode) + { + provokingVertexMode = dynamicState.provokingVertexMode; + } + if(dynamicStateFlags.dynamicViewport) { viewport = dynamicState.viewport; @@ -817,6 +949,20 @@ pipelineLayout = layout; dynamicStateFlags = allDynamicStateFlags.fragment; + // The spec says: + // + // If the VK_EXT_extended_dynamic_state3 extension is enabled, it can be NULL if the + // pipeline is created with all of VK_DYNAMIC_STATE_DEPTH_TEST_ENABLE, + // VK_DYNAMIC_STATE_DEPTH_WRITE_ENABLE, VK_DYNAMIC_STATE_DEPTH_COMPARE_OP, + // VK_DYNAMIC_STATE_DEPTH_BOUNDS_TEST_ENABLE, VK_DYNAMIC_STATE_STENCIL_TEST_ENABLE, + // VK_DYNAMIC_STATE_STENCIL_OP, and VK_DYNAMIC_STATE_DEPTH_BOUNDS dynamic states set. + // + // But pDepthStencilState can still be nullptr if no subpass uses depth/stencil. + if(depthStencilState == nullptr) + { + return; + } + if(renderPass) { const VkSubpassDescription &subpass = renderPass->getSubpass(subpassIndex); @@ -981,7 +1127,43 @@ { dynamicStateFlags = allDynamicStateFlags.fragmentOutputInterface; - multisample.set(multisampleState); + // The spec says: + // + // If the VK_EXT_extended_dynamic_state3 extension is enabled, it [pMultisampleState] can be + // NULL if the pipeline is created with all of VK_DYNAMIC_STATE_RASTERIZATION_SAMPLES_EXT, + // VK_DYNAMIC_STATE_SAMPLE_MASK_EXT, and VK_DYNAMIC_STATE_ALPHA_TO_COVERAGE_ENABLE_EXT + // dynamic states set, and either the alphaToOne feature is not enabled or + // VK_DYNAMIC_STATE_ALPHA_TO_ONE_ENABLE_EXT is set, in which case + // VkPipelineMultisampleStateCreateInfo::sampleShadingEnable is assumed to be VK_FALSE. + // + // SwiftShader does not support alphaToOne. + if(multisampleState == nullptr) + { + ASSERT(dynamicStateFlags.dynamicRasterizationSamples && + dynamicStateFlags.dynamicSampleMask && + dynamicStateFlags.dynamicAlphaToCoverageEnable); + } + else + { + multisample.set(dynamicStateFlags, multisampleState); + } + + // The spec says: + // + // If the VK_EXT_extended_dynamic_state3 extension is enabled, it [pColorBlendState] can be + // NULL if the pipeline is created with all of VK_DYNAMIC_STATE_LOGIC_OP_ENABLE_EXT, + // VK_DYNAMIC_STATE_LOGIC_OP_EXT, VK_DYNAMIC_STATE_COLOR_BLEND_ENABLE_EXT, + // VK_DYNAMIC_STATE_COLOR_BLEND_EQUATION_EXT, VK_DYNAMIC_STATE_COLOR_WRITE_MASK_EXT, and + // VK_DYNAMIC_STATE_BLEND_CONSTANTS dynamic states set. + // + // SwiftShader does not support logic op; if everything else is static there is no need to + // look at colorBlendState. + // + // pColorBlendState may be nullptr if there are no attachments. + if(colorBlendState == nullptr) + { + return; + } if(renderPass) { @@ -1025,10 +1207,66 @@ void FragmentOutputInterfaceState::applyState(const DynamicState &dynamicState) { + // State that affects both Fragment and Fragment Output subsets are always stored in the + // Fragment Output subset in SwiftShader + if(dynamicStateFlags.dynamicRasterizationSamples) + { + multisample.sampleCount = dynamicState.rasterizationSamples; + } + + if(dynamicStateFlags.dynamicSampleMask || dynamicStateFlags.dynamicRasterizationSamples) + { + unsigned int sampleMask = dynamicStateFlags.dynamicSampleMask ? dynamicState.sampleMask : multisample.staticSampleMask; + multisample.multiSampleMask = sampleMask & ((unsigned)0xFFFFFFFF >> (32 - multisample.sampleCount)); + } + + if(dynamicStateFlags.dynamicAlphaToCoverageEnable) + { + multisample.alphaToCoverage = dynamicState.alphaToCoverageEnable; + } + if(dynamicStateFlags.dynamicBlendConstants) { blendConstants = dynamicState.blendConstants; } + + if(dynamicStateFlags.dynamicColorBlendEnable) + { + for(uint32_t i = 0; i < sw::MAX_COLOR_BUFFERS; ++i) + { + blendState[i].alphaBlendEnable = dynamicState.colorBlendEnables[i] != VK_FALSE; + } + } + + if(dynamicStateFlags.dynamicColorBlendEquation) + { + for(uint32_t i = 0; i < sw::MAX_COLOR_BUFFERS; ++i) + { + blendState[i].sourceBlendFactor = dynamicState.colorBlendEquations[i].srcColorBlendFactor; + blendState[i].destBlendFactor = dynamicState.colorBlendEquations[i].dstColorBlendFactor; + blendState[i].sourceBlendFactorAlpha = dynamicState.colorBlendEquations[i].srcAlphaBlendFactor; + blendState[i].destBlendFactorAlpha = dynamicState.colorBlendEquations[i].dstAlphaBlendFactor; + blendState[i].blendOperationAlpha = dynamicState.colorBlendEquations[i].alphaBlendOp; + } + } + + // colorBlendOp may be set either by COLOR_BLEND_EQUATION or COLOR_BLEND_ADVANCED dynamic + // states + if(dynamicStateFlags.dynamicColorBlendEquation || dynamicStateFlags.dynamicColorBlendAdvanced) + { + for(uint32_t i = 0; i < sw::MAX_COLOR_BUFFERS; ++i) + { + blendState[i].blendOperation = dynamicState.colorBlendEquations[i].colorBlendOp; + } + } + + if(dynamicStateFlags.dynamicColorWriteMask) + { + for(uint32_t i = 0; i < sw::MAX_COLOR_BUFFERS; ++i) + { + colorWriteMask[i] = dynamicState.colorWriteMasks[i]; + } + } } void FragmentOutputInterfaceState::setColorBlendState(const VkPipelineColorBlendStateCreateInfo *colorBlendState) @@ -1076,14 +1314,17 @@ extensionColorBlendInfo = extensionColorBlendInfo->pNext; } - ASSERT(colorBlendState->attachmentCount <= sw::MAX_COLOR_BUFFERS); - for(auto i = 0u; i < colorBlendState->attachmentCount; i++) + if(colorBlendState->pAttachments) { - const VkPipelineColorBlendAttachmentState &attachment = colorBlendState->pAttachments[i]; - colorWriteMask[i] = attachment.colorWriteMask; - blendState[i] = { (attachment.blendEnable != VK_FALSE), - attachment.srcColorBlendFactor, attachment.dstColorBlendFactor, attachment.colorBlendOp, - attachment.srcAlphaBlendFactor, attachment.dstAlphaBlendFactor, attachment.alphaBlendOp }; + ASSERT(colorBlendState->attachmentCount <= sw::MAX_COLOR_BUFFERS); + for(auto i = 0u; i < colorBlendState->attachmentCount; i++) + { + const VkPipelineColorBlendAttachmentState &attachment = colorBlendState->pAttachments[i]; + colorWriteMask[i] = attachment.colorWriteMask; + blendState[i] = { (attachment.blendEnable != VK_FALSE), + attachment.srcColorBlendFactor, attachment.dstColorBlendFactor, attachment.colorBlendOp, + attachment.srcAlphaBlendFactor, attachment.dstAlphaBlendFactor, attachment.alphaBlendOp }; + } } } @@ -1301,7 +1542,8 @@ vk::Format format = attachments.colorBuffer[location]->getFormat(VK_IMAGE_ASPECT_COLOR_BIT); - if(blendOperation(state.blendOperation, state.sourceBlendFactor, state.destBlendFactor, format) == VK_BLEND_OP_DST_EXT && + if(state.alphaBlendEnable && + blendOperation(state.blendOperation, state.sourceBlendFactor, state.destBlendFactor, format) == VK_BLEND_OP_DST_EXT && blendOperation(state.blendOperationAlpha, state.sourceBlendFactorAlpha, state.destBlendFactorAlpha, format) == VK_BLEND_OP_DST_EXT) { return 0; @@ -1335,8 +1577,8 @@ // If rasterizer discard is enabled (and not dynamically overridable), ignore the fragment // and fragment output subsets, as they will not be used. if((validSubset & VK_GRAPHICS_PIPELINE_LIBRARY_PRE_RASTERIZATION_SHADERS_BIT_EXT) != 0 && - pCreateInfo->pRasterizationState->rasterizerDiscardEnable && - !dynamicStateFlags.preRasterization.dynamicRasterizerDiscardEnable) + !dynamicStateFlags.preRasterization.dynamicRasterizerDiscardEnable && + pCreateInfo->pRasterizationState->rasterizerDiscardEnable) { validSubset &= ~(VK_GRAPHICS_PIPELINE_LIBRARY_FRAGMENT_SHADER_BIT_EXT | VK_GRAPHICS_PIPELINE_LIBRARY_FRAGMENT_OUTPUT_INTERFACE_BIT_EXT); }
diff --git a/src/Device/Context.hpp b/src/Device/Context.hpp index c1798bb..dd83d41 100644 --- a/src/Device/Context.hpp +++ b/src/Device/Context.hpp
@@ -52,8 +52,14 @@ bool dynamicLineWidth : 1; bool dynamicDepthBias : 1; bool dynamicDepthBiasEnable : 1; + bool dynamicDepthClampEnable : 1; + bool dynamicDepthClipEnable : 1; + bool dynamicDepthClipNegativeOneToOne : 1; bool dynamicCullMode : 1; bool dynamicFrontFace : 1; + bool dynamicPolygonMode : 1; + bool dynamicLineRasterizationMode : 1; + bool dynamicProvokingVertexMode : 1; bool dynamicViewport : 1; bool dynamicScissor : 1; bool dynamicViewportWithCount : 1; @@ -73,16 +79,28 @@ bool dynamicStencilCompareMask : 1; bool dynamicStencilWriteMask : 1; bool dynamicStencilReference : 1; + // Shared with FragmentOutputInterfaceDynamicStateFlags + bool dynamicRasterizationSamples : 1; + bool dynamicSampleMask : 1; + bool dynamicAlphaToCoverageEnable : 1; }; struct FragmentOutputInterfaceDynamicStateFlags { bool dynamicBlendConstants : 1; + bool dynamicColorBlendEnable : 1; + bool dynamicColorBlendEquation : 1; + bool dynamicColorBlendAdvanced : 1; + bool dynamicColorWriteMask : 1; + // Share dwith FragmentDynamicStateFlags + bool dynamicRasterizationSamples : 1; + bool dynamicSampleMask : 1; + bool dynamicAlphaToCoverageEnable : 1; }; struct DynamicStateFlags { - // Note: InputsDynamicStateFlags is kept local to Inputs + // Note: InputsDynamicStateFlags is kept local to Inputs VertexInputInterfaceDynamicStateFlags vertexInputInterface; PreRasterizationDynamicStateFlags preRasterization; FragmentDynamicStateFlags fragment; @@ -162,10 +180,14 @@ bool alphaToCoverage = false; int sampleCount = 0; + // multiSampleMask is derived from sample count and sample mask. When sample count is + // dynamic but sample mask is static, the static value of sample mask is needed to derive + // this value dynamically. unsigned int multiSampleMask = 0; + unsigned int staticSampleMask = 0; float minSampleShading = 0.0f; - void set(const VkPipelineMultisampleStateCreateInfo *multisampleState); + void set(const FragmentOutputInterfaceDynamicStateFlags &dynamicStateFlags, const VkPipelineMultisampleStateCreateInfo *multisampleState); }; struct BlendState : sw::Memset<BlendState> @@ -231,7 +253,13 @@ VkCompareOp depthCompareOp = VK_COMPARE_OP_NEVER; VkBool32 depthTestEnable = VK_FALSE; VkBool32 depthWriteEnable = VK_FALSE; + VkBool32 depthClampEnable = VK_FALSE; + VkBool32 depthClipEnable = VK_FALSE; + VkBool32 depthClipNegativeOneToOne = VK_FALSE; VkFrontFace frontFace = VK_FRONT_FACE_COUNTER_CLOCKWISE; + VkPolygonMode polygonMode = VK_POLYGON_MODE_FILL; + VkLineRasterizationModeEXT lineRasterizationMode = VK_LINE_RASTERIZATION_MODE_DEFAULT_EXT; + VkProvokingVertexModeEXT provokingVertexMode = VK_PROVOKING_VERTEX_MODE_FIRST_VERTEX_EXT; VkPrimitiveTopology primitiveTopology = VK_PRIMITIVE_TOPOLOGY_POINT_LIST; uint32_t scissorCount = 0; VkRect2D scissors[vk::MAX_VIEWPORTS] = {}; @@ -244,6 +272,12 @@ VkBool32 rasterizerDiscardEnable = VK_FALSE; VkBool32 depthBiasEnable = VK_FALSE; VkBool32 primitiveRestartEnable = VK_FALSE; + VkBool32 alphaToCoverageEnable = VK_FALSE; + VkSampleCountFlagBits rasterizationSamples = VK_SAMPLE_COUNT_1_BIT; + VkSampleMask sampleMask = 0x1; + VkBool32 colorBlendEnables[sw::MAX_COLOR_BUFFERS] = {}; + VkColorBlendEquationEXT colorBlendEquations[sw::MAX_COLOR_BUFFERS] = {}; + VkColorComponentFlags colorWriteMasks[sw::MAX_COLOR_BUFFERS] = {}; DynamicVertexInputBindingState vertexInputBindings[MAX_VERTEX_INPUT_BINDINGS]; DynamicVertexInputAttributeState vertexInputAttributes[sw::MAX_INTERFACE_COMPONENTS / 4]; }; @@ -318,7 +352,9 @@ bool rasterizerDiscard = false; bool depthClampEnable = false; + // depthClipEnable is implicitly !depthClampEnable. However, it may be explicitly set by VkPipelineRasterizationDepthClipStateCreateInfoEXT / dynamic state. bool depthClipEnable = false; + bool depthClipEnableIsExplicit = true; bool depthClipNegativeOneToOne = false; bool depthBiasEnable = false; bool depthRangeUnrestricted = false;
diff --git a/src/Vulkan/VkCommandBuffer.cpp b/src/Vulkan/VkCommandBuffer.cpp index cd664c6..c61e132 100644 --- a/src/Vulkan/VkCommandBuffer.cpp +++ b/src/Vulkan/VkCommandBuffer.cpp
@@ -917,6 +917,264 @@ const VkBool32 primitiveRestartEnable; }; +class CmdSetDepthClampEnable : public vk::CommandBuffer::Command +{ +public: + CmdSetDepthClampEnable(VkBool32 depthClampEnable) + : depthClampEnable(depthClampEnable) + {} + + void execute(vk::CommandBuffer::ExecutionState &executionState) override + { + executionState.dynamicState.depthClampEnable = depthClampEnable; + } + + std::string description() override { return "vkCmdSetDepthClampEnable()"; } + +private: + const VkBool32 depthClampEnable; +}; + +class CmdSetPolygonMode : public vk::CommandBuffer::Command +{ +public: + CmdSetPolygonMode(VkPolygonMode polygonMode) + : polygonMode(polygonMode) + {} + + void execute(vk::CommandBuffer::ExecutionState &executionState) override + { + executionState.dynamicState.polygonMode = polygonMode; + } + + std::string description() override { return "vkCmdSetPolygonMode()"; } + +private: + const VkPolygonMode polygonMode; +}; + +class CmdSetRasterizationSamples : public vk::CommandBuffer::Command +{ +public: + CmdSetRasterizationSamples(VkSampleCountFlagBits rasterizationSamples) + : rasterizationSamples(rasterizationSamples) + {} + + void execute(vk::CommandBuffer::ExecutionState &executionState) override + { + executionState.dynamicState.rasterizationSamples = rasterizationSamples; + } + + std::string description() override { return "vkCmdSetRasterizationSamples()"; } + +private: + const VkSampleCountFlagBits rasterizationSamples; +}; + +class CmdSetSampleMask : public vk::CommandBuffer::Command +{ +public: + CmdSetSampleMask(VkSampleCountFlagBits samples, const VkSampleMask *pSampleMask) + : sampleMask(pSampleMask[0]) + {} + + void execute(vk::CommandBuffer::ExecutionState &executionState) override + { + executionState.dynamicState.sampleMask = sampleMask; + } + + std::string description() override { return "vkCmdSetSampleMask()"; } + +private: + const VkSampleMask sampleMask; +}; + +class CmdSetAlphaToCoverageEnable : public vk::CommandBuffer::Command +{ +public: + CmdSetAlphaToCoverageEnable(VkBool32 alphaToCoverageEnable) + : alphaToCoverageEnable(alphaToCoverageEnable) + {} + + void execute(vk::CommandBuffer::ExecutionState &executionState) override + { + executionState.dynamicState.alphaToCoverageEnable = alphaToCoverageEnable; + } + + std::string description() override { return "vkCmdSetAlphaToCoverageEnable()"; } + +private: + const VkBool32 alphaToCoverageEnable; +}; + +class CmdSetColorBlendEnable : public vk::CommandBuffer::Command +{ +public: + CmdSetColorBlendEnable(uint32_t firstAttachment, uint32_t attachmentCount, const VkBool32 *pColorBlendEnables) + : firstAttachment(firstAttachment) + , colorBlendEnables(pColorBlendEnables, pColorBlendEnables + attachmentCount) + {} + + void execute(vk::CommandBuffer::ExecutionState &executionState) override + { + for(size_t i = 0; i < colorBlendEnables.size(); ++i) + { + executionState.dynamicState.colorBlendEnables[firstAttachment + i] = colorBlendEnables[i] != VK_FALSE; + } + } + + std::string description() override { return "vkCmdSetColorBlendEnable()"; } + +private: + const uint32_t firstAttachment; + const std::vector<VkBool32> colorBlendEnables; +}; + +class CmdSetColorBlendEquation : public vk::CommandBuffer::Command +{ +public: + CmdSetColorBlendEquation(uint32_t firstAttachment, uint32_t attachmentCount, const VkColorBlendEquationEXT *pColorBlendEquations) + : firstAttachment(firstAttachment) + , colorBlendEquations(pColorBlendEquations, pColorBlendEquations + attachmentCount) + {} + + void execute(vk::CommandBuffer::ExecutionState &executionState) override + { + std::copy(colorBlendEquations.begin(), colorBlendEquations.end(), executionState.dynamicState.colorBlendEquations + firstAttachment); + } + + std::string description() override { return "vkCmdSetColorBlendEquation()"; } + +private: + const uint32_t firstAttachment; + const std::vector<VkColorBlendEquationEXT> colorBlendEquations; +}; + +class CmdSetColorWriteMask : public vk::CommandBuffer::Command +{ +public: + CmdSetColorWriteMask(uint32_t firstAttachment, uint32_t attachmentCount, const VkColorComponentFlags *pColorWriteMasks) + : firstAttachment(firstAttachment) + , colorWriteMasks(pColorWriteMasks, pColorWriteMasks + attachmentCount) + {} + + void execute(vk::CommandBuffer::ExecutionState &executionState) override + { + std::copy(colorWriteMasks.begin(), colorWriteMasks.end(), executionState.dynamicState.colorWriteMasks + firstAttachment); + } + + std::string description() override { return "vkCmdSetColorWriteMask()"; } + +private: + const uint32_t firstAttachment; + const std::vector<VkColorComponentFlags> colorWriteMasks; +}; + +class CmdSetDepthClipEnable : public vk::CommandBuffer::Command +{ +public: + CmdSetDepthClipEnable(VkBool32 depthClipEnable) + : depthClipEnable(depthClipEnable) + {} + + void execute(vk::CommandBuffer::ExecutionState &executionState) override + { + executionState.dynamicState.depthClipEnable = depthClipEnable; + } + + std::string description() override { return "vkCmdSetDepthClipEnable()"; } + +private: + const VkBool32 depthClipEnable; +}; + +class CmdSetColorBlendAdvanced : public vk::CommandBuffer::Command +{ +public: + CmdSetColorBlendAdvanced(uint32_t firstAttachment, uint32_t attachmentCount, const VkColorBlendAdvancedEXT *pColorBlendAdvanced) + : firstAttachment(firstAttachment) + , colorBlendAdvanced(pColorBlendAdvanced, pColorBlendAdvanced + attachmentCount) + {} + + void execute(vk::CommandBuffer::ExecutionState &executionState) override + { + for(size_t i = 0; i < colorBlendAdvanced.size(); ++i) + { + // blendOverlap, srcPremultiplied and dstPremultiplied cannot be controlled because + // the revelant features are not exposed. + ASSERT(colorBlendAdvanced[i].blendOverlap == VK_BLEND_OVERLAP_UNCORRELATED_EXT); + ASSERT(colorBlendAdvanced[i].dstPremultiplied == VK_TRUE); + ASSERT(colorBlendAdvanced[i].srcPremultiplied == VK_TRUE); + // clampResults is not implemented, there is no corresponding static state it seems. + if(colorBlendAdvanced[i].clampResults == VK_TRUE) + { + UNSUPPORTED("VkColorBlendAdvancedEXT::clampResults"); + } + executionState.dynamicState.colorBlendEquations[firstAttachment + i].colorBlendOp = colorBlendAdvanced[i].advancedBlendOp; + } + } + + std::string description() override { return "vkCmdSetColorBlendAdvanced()"; } + +private: + const uint32_t firstAttachment; + const std::vector<VkColorBlendAdvancedEXT> colorBlendAdvanced; +}; + +class CmdSetProvokingVertexMode : public vk::CommandBuffer::Command +{ +public: + CmdSetProvokingVertexMode(VkProvokingVertexModeEXT provokingVertexMode) + : provokingVertexMode(provokingVertexMode) + {} + + void execute(vk::CommandBuffer::ExecutionState &executionState) override + { + executionState.dynamicState.provokingVertexMode = provokingVertexMode; + } + + std::string description() override { return "vkCmdSetProvokingVertexMode()"; } + +private: + const VkProvokingVertexModeEXT provokingVertexMode; +}; + +class CmdSetLineRasterizationMode : public vk::CommandBuffer::Command +{ +public: + CmdSetLineRasterizationMode(VkLineRasterizationModeEXT lineRasterizationMode) + : lineRasterizationMode(lineRasterizationMode) + {} + + void execute(vk::CommandBuffer::ExecutionState &executionState) override + { + executionState.dynamicState.lineRasterizationMode = lineRasterizationMode; + } + + std::string description() override { return "vkCmdSetLineRasterizationMode()"; } + +private: + const VkLineRasterizationModeEXT lineRasterizationMode; +}; + +class CmdSetDepthClipNegativeOneToOne : public vk::CommandBuffer::Command +{ +public: + CmdSetDepthClipNegativeOneToOne(VkBool32 depthClipNegativeOneToOne) + : depthClipNegativeOneToOne(depthClipNegativeOneToOne) + {} + + void execute(vk::CommandBuffer::ExecutionState &executionState) override + { + executionState.dynamicState.depthClipNegativeOneToOne = depthClipNegativeOneToOne; + } + + std::string description() override { return "vkCmdSetDepthClipNegativeOneToOne()"; } + +private: + const VkBool32 depthClipNegativeOneToOne; +}; + class CmdSetVertexInput : public vk::CommandBuffer::Command { public: @@ -2136,6 +2394,71 @@ addCommand<::CmdSetPrimitiveRestartEnable>(primitiveRestartEnable); } +void CommandBuffer::setDepthClampEnable(VkBool32 depthClampEnable) +{ + addCommand<::CmdSetDepthClampEnable>(depthClampEnable); +} + +void CommandBuffer::setPolygonMode(VkPolygonMode polygonMode) +{ + addCommand<::CmdSetPolygonMode>(polygonMode); +} + +void CommandBuffer::setRasterizationSamples(VkSampleCountFlagBits rasterizationSamples) +{ + addCommand<::CmdSetRasterizationSamples>(rasterizationSamples); +} + +void CommandBuffer::setSampleMask(VkSampleCountFlagBits samples, const VkSampleMask *pSampleMask) +{ + addCommand<::CmdSetSampleMask>(samples, pSampleMask); +} + +void CommandBuffer::setAlphaToCoverageEnable(VkBool32 alphaToCoverageEnable) +{ + addCommand<::CmdSetAlphaToCoverageEnable>(alphaToCoverageEnable); +} + +void CommandBuffer::setColorBlendEnable(uint32_t firstAttachment, uint32_t attachmentCount, const VkBool32 *pColorBlendEnables) +{ + addCommand<::CmdSetColorBlendEnable>(firstAttachment, attachmentCount, pColorBlendEnables); +} + +void CommandBuffer::setColorBlendEquation(uint32_t firstAttachment, uint32_t attachmentCount, const VkColorBlendEquationEXT *pColorBlendEquations) +{ + addCommand<::CmdSetColorBlendEquation>(firstAttachment, attachmentCount, pColorBlendEquations); +} + +void CommandBuffer::setColorWriteMask(uint32_t firstAttachment, uint32_t attachmentCount, const VkColorComponentFlags *pColorWriteMasks) +{ + addCommand<::CmdSetColorWriteMask>(firstAttachment, attachmentCount, pColorWriteMasks); +} + +void CommandBuffer::setDepthClipEnable(VkBool32 depthClipEnable) +{ + addCommand<::CmdSetDepthClipEnable>(depthClipEnable); +} + +void CommandBuffer::setColorBlendAdvanced(uint32_t firstAttachment, uint32_t attachmentCount, const VkColorBlendAdvancedEXT *pColorBlendAdvanced) +{ + addCommand<::CmdSetColorBlendAdvanced>(firstAttachment, attachmentCount, pColorBlendAdvanced); +} + +void CommandBuffer::setProvokingVertexMode(VkProvokingVertexModeEXT provokingVertexMode) +{ + addCommand<::CmdSetProvokingVertexMode>(provokingVertexMode); +} + +void CommandBuffer::setLineRasterizationMode(VkLineRasterizationModeEXT lineRasterizationMode) +{ + addCommand<::CmdSetLineRasterizationMode>(lineRasterizationMode); +} + +void CommandBuffer::setDepthClipNegativeOneToOne(VkBool32 negativeOneToOne) +{ + addCommand<::CmdSetDepthClipNegativeOneToOne>(negativeOneToOne); +} + void CommandBuffer::setVertexInput(uint32_t vertexBindingDescriptionCount, const VkVertexInputBindingDescription2EXT *pVertexBindingDescriptions, uint32_t vertexAttributeDescriptionCount,
diff --git a/src/Vulkan/VkCommandBuffer.hpp b/src/Vulkan/VkCommandBuffer.hpp index f7345c4..683198e 100644 --- a/src/Vulkan/VkCommandBuffer.hpp +++ b/src/Vulkan/VkCommandBuffer.hpp
@@ -143,6 +143,19 @@ void setRasterizerDiscardEnable(VkBool32 rasterizerDiscardEnable); void setDepthBiasEnable(VkBool32 depthBiasEnable); void setPrimitiveRestartEnable(VkBool32 primitiveRestartEnable); + void setDepthClampEnable(VkBool32 depthClampEnable); + void setPolygonMode(VkPolygonMode polygonMode); + void setRasterizationSamples(VkSampleCountFlagBits rasterizationSamples); + void setSampleMask(VkSampleCountFlagBits samples, const VkSampleMask* pSampleMask); + void setAlphaToCoverageEnable(VkBool32 alphaToCoverageEnable); + void setColorBlendEnable(uint32_t firstAttachment, uint32_t attachmentCount, const VkBool32* pColorBlendEnables); + void setColorBlendEquation(uint32_t firstAttachment, uint32_t attachmentCount, const VkColorBlendEquationEXT* pColorBlendEquations); + void setColorWriteMask(uint32_t firstAttachment, uint32_t attachmentCount, const VkColorComponentFlags* pColorWriteMasks); + void setDepthClipEnable(VkBool32 depthClipEnable); + void setColorBlendAdvanced(uint32_t firstAttachment, uint32_t attachmentCount, const VkColorBlendAdvancedEXT* pColorBlendAdvanced); + void setProvokingVertexMode(VkProvokingVertexModeEXT provokingVertexMode); + void setLineRasterizationMode(VkLineRasterizationModeEXT lineRasterizationMode); + void setDepthClipNegativeOneToOne(VkBool32 negativeOneToOne); void setVertexInput(uint32_t vertexBindingDescriptionCount, const VkVertexInputBindingDescription2EXT* pVertexBindingDescriptions, uint32_t vertexAttributeDescriptionCount,
diff --git a/src/Vulkan/VkGetProcAddress.cpp b/src/Vulkan/VkGetProcAddress.cpp index 0d6615c..e9c328b 100644 --- a/src/Vulkan/VkGetProcAddress.cpp +++ b/src/Vulkan/VkGetProcAddress.cpp
@@ -407,7 +407,7 @@ MAKE_VULKAN_DEVICE_ENTRY(vkCmdSetDepthBoundsTestEnable), MAKE_VULKAN_DEVICE_ENTRY(vkCmdSetStencilTestEnable), MAKE_VULKAN_DEVICE_ENTRY(vkCmdSetStencilOp), - // VK_EXT_extended_dynamic_state2 (partial promotion, VKCmdSetLogicOpEXT and VKCmdSetPatchControlPointsEXT are not promoted) + // VK_EXT_extended_dynamic_state2 (partial promotion, vkCmdSetLogicOpEXT and vkCmdSetPatchControlPointsEXT are not promoted) MAKE_VULKAN_DEVICE_ENTRY(vkCmdSetRasterizerDiscardEnable), MAKE_VULKAN_DEVICE_ENTRY(vkCmdSetDepthBiasEnable), MAKE_VULKAN_DEVICE_ENTRY(vkCmdSetPrimitiveRestartEnable), @@ -562,6 +562,33 @@ MAKE_VULKAN_DEVICE_ENTRY(vkCmdSetLogicOpEXT), MAKE_VULKAN_DEVICE_ENTRY(vkCmdSetPatchControlPointsEXT), } }, + // VK_EXT_extended_dynamic_state3 + { + VK_EXT_EXTENDED_DYNAMIC_STATE_3_EXTENSION_NAME, + { + MAKE_VULKAN_DEVICE_ENTRY(vkCmdSetAlphaToCoverageEnableEXT), + MAKE_VULKAN_DEVICE_ENTRY(vkCmdSetAlphaToOneEnableEXT), + MAKE_VULKAN_DEVICE_ENTRY(vkCmdSetColorBlendEnableEXT), + MAKE_VULKAN_DEVICE_ENTRY(vkCmdSetColorBlendEquationEXT), + MAKE_VULKAN_DEVICE_ENTRY(vkCmdSetColorWriteMaskEXT), + MAKE_VULKAN_DEVICE_ENTRY(vkCmdSetDepthClampEnableEXT), + MAKE_VULKAN_DEVICE_ENTRY(vkCmdSetLogicOpEnableEXT), + MAKE_VULKAN_DEVICE_ENTRY(vkCmdSetPolygonModeEXT), + MAKE_VULKAN_DEVICE_ENTRY(vkCmdSetRasterizationSamplesEXT), + MAKE_VULKAN_DEVICE_ENTRY(vkCmdSetSampleMaskEXT), + MAKE_VULKAN_DEVICE_ENTRY(vkCmdSetTessellationDomainOriginEXT), + // +VK_EXT_blend_operation_advanced + MAKE_VULKAN_DEVICE_ENTRY(vkCmdSetColorBlendAdvancedEXT), + // +VK_EXT_depth_clip_control + MAKE_VULKAN_DEVICE_ENTRY(vkCmdSetDepthClipNegativeOneToOneEXT), + // +VK_EXT_depth_clip_enable + MAKE_VULKAN_DEVICE_ENTRY(vkCmdSetDepthClipEnableEXT), + // +VK_EXT_provoking_vertex + MAKE_VULKAN_DEVICE_ENTRY(vkCmdSetProvokingVertexModeEXT), + // +VK_EXT_line_rasterization + MAKE_VULKAN_DEVICE_ENTRY(vkCmdSetLineRasterizationModeEXT), + MAKE_VULKAN_DEVICE_ENTRY(vkCmdSetLineStippleEnableEXT), + } }, // VK_EXT_vertex_input_dynamic_state { VK_EXT_VERTEX_INPUT_DYNAMIC_STATE_EXTENSION_NAME,
diff --git a/src/Vulkan/VkPhysicalDevice.cpp b/src/Vulkan/VkPhysicalDevice.cpp index 5d5edcf..9725e05 100644 --- a/src/Vulkan/VkPhysicalDevice.cpp +++ b/src/Vulkan/VkPhysicalDevice.cpp
@@ -499,10 +499,57 @@ static void getPhysicalDeviceExtendedDynamicState2FeaturesEXT(VkPhysicalDeviceExtendedDynamicState2FeaturesEXT *features) { features->extendedDynamicState2 = VK_TRUE; + + // logicOp is not supported features->extendedDynamicState2LogicOp = VK_FALSE; + // Tessellation shaders are not supported features->extendedDynamicState2PatchControlPoints = VK_FALSE; } +static void getPhysicalDeviceExtendedDynamicState3FeaturesEXT(VkPhysicalDeviceExtendedDynamicState3FeaturesEXT *features) +{ + features->extendedDynamicState3DepthClampEnable = VK_TRUE; + features->extendedDynamicState3PolygonMode = VK_TRUE; + features->extendedDynamicState3RasterizationSamples = VK_TRUE; + features->extendedDynamicState3SampleMask = VK_TRUE; + features->extendedDynamicState3AlphaToCoverageEnable = VK_TRUE; + features->extendedDynamicState3ColorBlendEnable = VK_TRUE; + features->extendedDynamicState3ColorBlendEquation = VK_TRUE; + features->extendedDynamicState3ColorWriteMask = VK_TRUE; + features->extendedDynamicState3DepthClipEnable = VK_TRUE; + features->extendedDynamicState3ColorBlendAdvanced = VK_TRUE; + features->extendedDynamicState3ProvokingVertexMode = VK_TRUE; + features->extendedDynamicState3LineRasterizationMode = VK_TRUE; + features->extendedDynamicState3DepthClipNegativeOneToOne = VK_TRUE; + + // Tessellation shaders are not supported + features->extendedDynamicState3TessellationDomainOrigin = VK_FALSE; + // logicOp is not supported + features->extendedDynamicState3LogicOpEnable = VK_FALSE; + // alphaToOne is not supported + features->extendedDynamicState3AlphaToOneEnable = VK_FALSE; + // Stippled lines are not supported + features->extendedDynamicState3LineStippleEnable = VK_FALSE; + // VK_EXT_transform_feedback is not supported + features->extendedDynamicState3RasterizationStream = VK_FALSE; + // VK_EXT_conservative_rasterization is not supported + features->extendedDynamicState3ConservativeRasterizationMode = VK_FALSE; + features->extendedDynamicState3ExtraPrimitiveOverestimationSize = VK_FALSE; + // VK_EXT_sample_locations is not supported + features->extendedDynamicState3SampleLocationsEnable = VK_FALSE; + // Various NV extensions that are not supported + features->extendedDynamicState3ViewportWScalingEnable = VK_FALSE; + features->extendedDynamicState3ViewportSwizzle = VK_FALSE; + features->extendedDynamicState3CoverageToColorEnable = VK_FALSE; + features->extendedDynamicState3CoverageToColorLocation = VK_FALSE; + features->extendedDynamicState3CoverageModulationMode = VK_FALSE; + features->extendedDynamicState3CoverageModulationTableEnable = VK_FALSE; + features->extendedDynamicState3CoverageModulationTable = VK_FALSE; + features->extendedDynamicState3CoverageReductionMode = VK_FALSE; + features->extendedDynamicState3RepresentativeFragmentTestEnable = VK_FALSE; + features->extendedDynamicState3ShadingRateImageEnable = VK_FALSE; +} + static void getPhysicalDeviceVertexInputDynamicStateFeaturesEXT(VkPhysicalDeviceVertexInputDynamicStateFeaturesEXT *features) { features->vertexInputDynamicState = VK_TRUE; @@ -641,6 +688,9 @@ case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTENDED_DYNAMIC_STATE_2_FEATURES_EXT: getPhysicalDeviceExtendedDynamicState2FeaturesEXT(reinterpret_cast<VkPhysicalDeviceExtendedDynamicState2FeaturesEXT *>(curExtension)); break; + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTENDED_DYNAMIC_STATE_3_FEATURES_EXT: + getPhysicalDeviceExtendedDynamicState3FeaturesEXT(reinterpret_cast<VkPhysicalDeviceExtendedDynamicState3FeaturesEXT *>(curExtension)); + break; case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VERTEX_INPUT_DYNAMIC_STATE_FEATURES_EXT: getPhysicalDeviceVertexInputDynamicStateFeaturesEXT(reinterpret_cast<VkPhysicalDeviceVertexInputDynamicStateFeaturesEXT *>(curExtension)); break; @@ -1520,6 +1570,11 @@ getHostImageCopyProperties(properties); } +void PhysicalDevice::getProperties(VkPhysicalDeviceExtendedDynamicState3PropertiesEXT *properties) const +{ + properties->dynamicPrimitiveTopologyUnrestricted = VK_TRUE; +} + void PhysicalDevice::getProperties(VkPhysicalDeviceVulkan12Properties *properties) const { getDriverProperties(properties); @@ -1597,6 +1652,43 @@ CheckFeature(requested, supported, extendedDynamicState2PatchControlPoints); } +bool PhysicalDevice::hasExtendedFeatures(const VkPhysicalDeviceExtendedDynamicState3FeaturesEXT *requested) const +{ + auto supported = getSupportedFeatures(requested); + + return CheckFeature(requested, supported, extendedDynamicState3TessellationDomainOrigin) && + CheckFeature(requested, supported, extendedDynamicState3DepthClampEnable) && + CheckFeature(requested, supported, extendedDynamicState3PolygonMode) && + CheckFeature(requested, supported, extendedDynamicState3RasterizationSamples) && + CheckFeature(requested, supported, extendedDynamicState3SampleMask) && + CheckFeature(requested, supported, extendedDynamicState3AlphaToCoverageEnable) && + CheckFeature(requested, supported, extendedDynamicState3AlphaToOneEnable) && + CheckFeature(requested, supported, extendedDynamicState3LogicOpEnable) && + CheckFeature(requested, supported, extendedDynamicState3ColorBlendEnable) && + CheckFeature(requested, supported, extendedDynamicState3ColorBlendEquation) && + CheckFeature(requested, supported, extendedDynamicState3ColorWriteMask) && + CheckFeature(requested, supported, extendedDynamicState3RasterizationStream) && + CheckFeature(requested, supported, extendedDynamicState3ConservativeRasterizationMode) && + CheckFeature(requested, supported, extendedDynamicState3ExtraPrimitiveOverestimationSize) && + CheckFeature(requested, supported, extendedDynamicState3DepthClipEnable) && + CheckFeature(requested, supported, extendedDynamicState3SampleLocationsEnable) && + CheckFeature(requested, supported, extendedDynamicState3ColorBlendAdvanced) && + CheckFeature(requested, supported, extendedDynamicState3ProvokingVertexMode) && + CheckFeature(requested, supported, extendedDynamicState3LineRasterizationMode) && + CheckFeature(requested, supported, extendedDynamicState3LineStippleEnable) && + CheckFeature(requested, supported, extendedDynamicState3DepthClipNegativeOneToOne) && + CheckFeature(requested, supported, extendedDynamicState3ViewportWScalingEnable) && + CheckFeature(requested, supported, extendedDynamicState3ViewportSwizzle) && + CheckFeature(requested, supported, extendedDynamicState3CoverageToColorEnable) && + CheckFeature(requested, supported, extendedDynamicState3CoverageToColorLocation) && + CheckFeature(requested, supported, extendedDynamicState3CoverageModulationMode) && + CheckFeature(requested, supported, extendedDynamicState3CoverageModulationTableEnable) && + CheckFeature(requested, supported, extendedDynamicState3CoverageModulationTable) && + CheckFeature(requested, supported, extendedDynamicState3CoverageReductionMode) && + CheckFeature(requested, supported, extendedDynamicState3RepresentativeFragmentTestEnable) && + CheckFeature(requested, supported, extendedDynamicState3ShadingRateImageEnable); +} + bool PhysicalDevice::hasExtendedFeatures(const VkPhysicalDeviceProvokingVertexFeaturesEXT *requested) const { auto supported = getSupportedFeatures(requested);
diff --git a/src/Vulkan/VkPhysicalDevice.hpp b/src/Vulkan/VkPhysicalDevice.hpp index a12b8a6..9184362 100644 --- a/src/Vulkan/VkPhysicalDevice.hpp +++ b/src/Vulkan/VkPhysicalDevice.hpp
@@ -47,6 +47,7 @@ bool hasExtendedFeatures(const VkPhysicalDeviceBlendOperationAdvancedFeaturesEXT *features) const; bool hasExtendedFeatures(const VkPhysicalDeviceExtendedDynamicStateFeaturesEXT *features) const; bool hasExtendedFeatures(const VkPhysicalDeviceExtendedDynamicState2FeaturesEXT *features) const; + bool hasExtendedFeatures(const VkPhysicalDeviceExtendedDynamicState3FeaturesEXT *features) const; bool hasExtendedFeatures(const VkPhysicalDeviceVertexInputDynamicStateFeaturesEXT *features) const; bool hasExtendedFeatures(const VkPhysicalDevicePrivateDataFeatures *features) const; bool hasExtendedFeatures(const VkPhysicalDeviceTextureCompressionASTCHDRFeatures *features) const; @@ -98,6 +99,7 @@ void getProperties(VkPhysicalDeviceDepthStencilResolveProperties *properties) const; void getProperties(VkPhysicalDeviceCustomBorderColorPropertiesEXT *properties) const; void getProperties(VkPhysicalDeviceBlendOperationAdvancedPropertiesEXT *properties) const; + void getProperties(VkPhysicalDeviceExtendedDynamicState3PropertiesEXT *properties) const; void getProperties(VkPhysicalDeviceSubgroupSizeControlProperties *properties) const; void getProperties(VkPhysicalDeviceInlineUniformBlockProperties *properties) const; void getProperties(VkPhysicalDeviceTexelBufferAlignmentProperties *properties) const;
diff --git a/src/Vulkan/libVulkan.cpp b/src/Vulkan/libVulkan.cpp index 6e4dad0..1cd4b57 100644 --- a/src/Vulkan/libVulkan.cpp +++ b/src/Vulkan/libVulkan.cpp
@@ -483,6 +483,7 @@ { { VK_EXT_PRIMITIVE_TOPOLOGY_LIST_RESTART_EXTENSION_NAME, VK_EXT_PRIMITIVE_TOPOLOGY_LIST_RESTART_SPEC_VERSION } }, { { VK_EXT_RASTERIZATION_ORDER_ATTACHMENT_ACCESS_EXTENSION_NAME, VK_EXT_RASTERIZATION_ORDER_ATTACHMENT_ACCESS_SPEC_VERSION } }, { { VK_EXT_VERTEX_INPUT_DYNAMIC_STATE_EXTENSION_NAME, VK_EXT_VERTEX_INPUT_DYNAMIC_STATE_SPEC_VERSION } }, + { { VK_EXT_EXTENDED_DYNAMIC_STATE_3_EXTENSION_NAME, VK_EXT_EXTENDED_DYNAMIC_STATE_3_SPEC_VERSION } }, }; static uint32_t numSupportedExtensions(const ExtensionProperties *extensionProperties, uint32_t extensionPropertiesCount) @@ -1071,6 +1072,16 @@ } } break; + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTENDED_DYNAMIC_STATE_3_FEATURES_EXT: + { + const auto *dynamicStateFeatures = reinterpret_cast<const VkPhysicalDeviceExtendedDynamicState3FeaturesEXT *>(extensionCreateInfo); + bool hasFeatures = vk::Cast(physicalDevice)->hasExtendedFeatures(dynamicStateFeatures); + if(!hasFeatures) + { + return VK_ERROR_FEATURE_NOT_PRESENT; + } + } + break; case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VERTEX_INPUT_DYNAMIC_STATE_FEATURES_EXT: { const auto *dynamicStateFeatures = reinterpret_cast<const VkPhysicalDeviceVertexInputDynamicStateFeaturesEXT *>(extensionCreateInfo); @@ -3127,6 +3138,166 @@ UNREACHABLE("extendedDynamicState2PatchControlPoints not supported"); } +VKAPI_ATTR void VKAPI_CALL vkCmdSetDepthClampEnableEXT( + VkCommandBuffer commandBuffer, + VkBool32 depthClampEnable) +{ + TRACE("(VkCommandBuffer commandBuffer = %p, VkBool32 depthClampEnable = %d)", commandBuffer, depthClampEnable); + + vk::Cast(commandBuffer)->setDepthClampEnable(depthClampEnable); +} + +VKAPI_ATTR void VKAPI_CALL vkCmdSetLogicOpEnableEXT(VkCommandBuffer commandBuffer, VkBool32 logicOpEnable) +{ + TRACE("(VkCommandBuffer commandBuffer = %p, VkBool32 logicOp = %d)", commandBuffer, logicOpEnable); + + UNREACHABLE("extendedDynamicState3LogicOpEnable not supported"); +} + +VKAPI_ATTR void VKAPI_CALL vkCmdSetPolygonModeEXT( + VkCommandBuffer commandBuffer, + VkPolygonMode polygonMode) +{ + TRACE("(VkCommandBuffer commandBuffer = %p, VkPolygonMode polygonMode = %d)", commandBuffer, polygonMode); + + vk::Cast(commandBuffer)->setPolygonMode(polygonMode); +} + +VKAPI_ATTR void VKAPI_CALL vkCmdSetRasterizationSamplesEXT( + VkCommandBuffer commandBuffer, + VkSampleCountFlagBits rasterizationSamples) +{ + TRACE("(VkCommandBuffer commandBuffer = %p, VkSampleCountFlagBits rasterizationSamples = %d)", commandBuffer, rasterizationSamples); + + vk::Cast(commandBuffer)->setRasterizationSamples(rasterizationSamples); +} + +VKAPI_ATTR void VKAPI_CALL vkCmdSetSampleMaskEXT( + VkCommandBuffer commandBuffer, + VkSampleCountFlagBits samples, + const VkSampleMask *pSampleMask) +{ + TRACE("(VkCommandBuffer commandBuffer = %p, VkSampleCountFlagBits samples = %d, const VkSampleMask* pSampleMask = %p)", commandBuffer, samples, pSampleMask); + + vk::Cast(commandBuffer)->setSampleMask(samples, pSampleMask); +} + +VKAPI_ATTR void VKAPI_CALL vkCmdSetAlphaToCoverageEnableEXT( + VkCommandBuffer commandBuffer, + VkBool32 alphaToCoverageEnable) +{ + TRACE("(VkCommandBuffer commandBuffer = %p, VkBool32 alphaToCoverageEnable = %d)", commandBuffer, alphaToCoverageEnable); + + vk::Cast(commandBuffer)->setAlphaToCoverageEnable(alphaToCoverageEnable); +} + +VKAPI_ATTR void VKAPI_CALL vkCmdSetAlphaToOneEnableEXT( + VkCommandBuffer commandBuffer, + VkBool32 alphaToOneEnable) +{ + TRACE("(VkCommandBuffer commandBuffer = %p, VkBool32 alphaToOneEnable = %d)", commandBuffer, alphaToOneEnable); + + UNREACHABLE("extendedDynamicState3AlphaToOneEnable not supported"); +} + +VKAPI_ATTR void VKAPI_CALL vkCmdSetColorBlendEnableEXT( + VkCommandBuffer commandBuffer, + uint32_t firstAttachment, + uint32_t attachmentCount, + const VkBool32 *pColorBlendEnables) +{ + TRACE("(VkCommandBuffer commandBuffer = %p, uint32_t firstAttachment = %d, uint32_t attachmentCount = %d, const VkBool32* pColorBlendEnables = %p)", commandBuffer, firstAttachment, attachmentCount, pColorBlendEnables); + + vk::Cast(commandBuffer)->setColorBlendEnable(firstAttachment, attachmentCount, pColorBlendEnables); +} + +VKAPI_ATTR void VKAPI_CALL vkCmdSetColorBlendEquationEXT( + VkCommandBuffer commandBuffer, + uint32_t firstAttachment, + uint32_t attachmentCount, + const VkColorBlendEquationEXT *pColorBlendEquations) +{ + TRACE("(VkCommandBuffer commandBuffer = %p, uint32_t firstAttachment = %d, uint32_t attachmentCount = %d, const VkColorBlendEquationEXT* pColorBlendEquations = %p)", commandBuffer, firstAttachment, attachmentCount, pColorBlendEquations); + + vk::Cast(commandBuffer)->setColorBlendEquation(firstAttachment, attachmentCount, pColorBlendEquations); +} + +VKAPI_ATTR void VKAPI_CALL vkCmdSetColorWriteMaskEXT( + VkCommandBuffer commandBuffer, + uint32_t firstAttachment, + uint32_t attachmentCount, + const VkColorComponentFlags *pColorWriteMasks) +{ + TRACE("(VkCommandBuffer commandBuffer = %p, uint32_t firstAttachment = %d, uint32_t attachmentCount = %d, const VkColorComponentFlags* pColorWriteMasks = %p)", commandBuffer, firstAttachment, attachmentCount, pColorWriteMasks); + + vk::Cast(commandBuffer)->setColorWriteMask(firstAttachment, attachmentCount, pColorWriteMasks); +} + +VKAPI_ATTR void VKAPI_CALL vkCmdSetTessellationDomainOriginEXT( + VkCommandBuffer commandBuffer, + VkTessellationDomainOrigin domainOrigin) +{ + TRACE("(VkCommandBuffer commandBuffer = %p, VkTessellationDomainOrigin domainOrigin = %d)", commandBuffer, domainOrigin); + + UNREACHABLE("extendedDynamicState3TessellationDomainOrigin not supported"); +} + +VKAPI_ATTR void VKAPI_CALL vkCmdSetDepthClipEnableEXT( + VkCommandBuffer commandBuffer, + VkBool32 depthClipEnable) +{ + TRACE("(VkCommandBuffer commandBuffer = %p, VkBool32 depthClipEnable = %d)", commandBuffer, depthClipEnable); + + vk::Cast(commandBuffer)->setDepthClipEnable(depthClipEnable); +} + +VKAPI_ATTR void VKAPI_CALL vkCmdSetColorBlendAdvancedEXT( + VkCommandBuffer commandBuffer, + uint32_t firstAttachment, + uint32_t attachmentCount, + const VkColorBlendAdvancedEXT *pColorBlendAdvanced) +{ + TRACE("(VkCommandBuffer commandBuffer = %p, uint32_t firstAttachment = %d, uint32_t attachmentCount = %d, const VkColorBlendAdvancedEXT* pColorBlendAdvanced = %p)", commandBuffer, firstAttachment, attachmentCount, pColorBlendAdvanced); + + vk::Cast(commandBuffer)->setColorBlendAdvanced(firstAttachment, attachmentCount, pColorBlendAdvanced); +} + +VKAPI_ATTR void VKAPI_CALL vkCmdSetProvokingVertexModeEXT( + VkCommandBuffer commandBuffer, + VkProvokingVertexModeEXT provokingVertexMode) +{ + TRACE("(VkCommandBuffer commandBuffer = %p, VkProvokingVertexModeEXT provokingVertexMode = %d)", commandBuffer, provokingVertexMode); + + vk::Cast(commandBuffer)->setProvokingVertexMode(provokingVertexMode); +} + +VKAPI_ATTR void VKAPI_CALL vkCmdSetLineRasterizationModeEXT( + VkCommandBuffer commandBuffer, + VkLineRasterizationModeEXT lineRasterizationMode) +{ + TRACE("(VkCommandBuffer commandBuffer = %p, VkLineRasterizationModeEXT lineRasterizationMode = %d)", commandBuffer, lineRasterizationMode); + + vk::Cast(commandBuffer)->setLineRasterizationMode(lineRasterizationMode); +} + +VKAPI_ATTR void VKAPI_CALL vkCmdSetLineStippleEnableEXT( + VkCommandBuffer commandBuffer, + VkBool32 stippledLineEnable) +{ + TRACE("(VkCommandBuffer commandBuffer = %p, VkBool32 stippledLineEnable = %d)", commandBuffer, stippledLineEnable); + + UNREACHABLE("extendedDynamicState3LineStippleEnable not supported"); +} + +VKAPI_ATTR void VKAPI_CALL vkCmdSetDepthClipNegativeOneToOneEXT( + VkCommandBuffer commandBuffer, + VkBool32 negativeOneToOne) +{ + TRACE("(VkCommandBuffer commandBuffer = %p, VkBool32 negativeOneToOne = %d)", commandBuffer, negativeOneToOne); + + vk::Cast(commandBuffer)->setDepthClipNegativeOneToOne(negativeOneToOne); +} + VKAPI_ATTR void VKAPI_CALL vkCmdSetVertexInputEXT(VkCommandBuffer commandBuffer, uint32_t vertexBindingDescriptionCount, const VkVertexInputBindingDescription2EXT *pVertexBindingDescriptions, uint32_t vertexAttributeDescriptionCount, @@ -3960,6 +4131,12 @@ vk::Cast(physicalDevice)->getProperties(properties); } break; + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTENDED_DYNAMIC_STATE_3_PROPERTIES_EXT: + { + auto *properties = reinterpret_cast<VkPhysicalDeviceExtendedDynamicState3PropertiesEXT *>(extensionProperties); + vk::Cast(physicalDevice)->getProperties(properties); + } + break; default: // "the [driver] must skip over, without processing (other than reading the sType and pNext members) any structures in the chain with sType values not defined by [supported extenions]" UNSUPPORTED("pProperties->pNext sType = %s", vk::Stringify(extensionProperties->sType).c_str());