为什么这个颜色混合状态无效(Vulkan)

Why is this color blend state invalid (Vulkan)

我正在尝试使用动态渲染制作管道,为此我有这个功能:

vk::UniquePipeline CreateGraphicsPipeline(
    vk::Device& device,
    Renderer::ShaderProgram& program)
{
    const auto& modules = program.GetShaderModules();
    const auto& stage_flags = program.GetShaderStageFlags();
    const auto& binding_descriptions = program.GetBindingDescriptions();
    const auto& attribute_descriptions = program.GetAttributeDescriptions();
    const auto& shader_config = program.GetShaderConfig();

    Assert(modules.size() == stage_flags.size(), "");

    const uint shader_stage_count = stage_flags.size();
    Assert(shader_stage_count <= MAXIMUM_SHADER_STAGE_COUNT, "");
    std::array<vk::PipelineShaderStageCreateInfo, MAXIMUM_SHADER_STAGE_COUNT> shader_infos;

    for(uint i=0; i < shader_stage_count; i++)
    {
        shader_infos[i].stage = stage_flags[i];
        shader_infos[i].module = *modules[i];
        shader_infos[i].pName = "main";
    }

    vk::PipelineVertexInputStateCreateInfo vertexInputInfo{};
    vertexInputInfo.vertexAttributeDescriptionCount =
        static_cast<uint32_t>(attribute_descriptions.size());
    vertexInputInfo.pVertexAttributeDescriptions = attribute_descriptions.data();
    vertexInputInfo.vertexBindingDescriptionCount = binding_descriptions.size();
    vertexInputInfo.pVertexBindingDescriptions = binding_descriptions.data();

    // Select rasterization algorithm and indexed drawing.
    vk::PipelineInputAssemblyStateCreateInfo inputAssembly{};
    inputAssembly.topology = shader_config.topology;
    inputAssembly.primitiveRestartEnable = VK_FALSE;

    // Setup rasterization details.
    vk::PipelineRasterizationStateCreateInfo rasterizer = {};
    rasterizer.depthClampEnable = VK_FALSE;
    rasterizer.rasterizerDiscardEnable = VK_TRUE;
    rasterizer.polygonMode = shader_config.polygon_mode;
    rasterizer.cullMode = shader_config.cull_mode;
    rasterizer.frontFace = shader_config.front_face;
    rasterizer.depthBiasEnable = VK_FALSE;
    rasterizer.depthBiasConstantFactor = 0.0;
    rasterizer.depthBiasClamp = 0.0;
    rasterizer.depthBiasSlopeFactor = 0.0;
    rasterizer.lineWidth = shader_config.line_width;

    vk::PipelineMultisampleStateCreateInfo multisampling{};
    multisampling.sampleShadingEnable = VK_FALSE;
    multisampling.rasterizationSamples = vk::SampleCountFlagBits::e1;

    vk::PipelineColorBlendAttachmentState color_blend_attachment{};
    color_blend_attachment.colorWriteMask =
        vk::ColorComponentFlagBits::eR |
        vk::ColorComponentFlagBits::eG |
        vk::ColorComponentFlagBits::eB |
        vk::ColorComponentFlagBits::eA;
    color_blend_attachment.blendEnable = VK_FALSE;

    vk::PipelineColorBlendStateCreateInfo color_blending{};
    color_blending.logicOpEnable = VK_FALSE;
    color_blending.logicOp = vk::LogicOp::eCopy;
    color_blending.attachmentCount = 1;
    color_blending.pAttachments = &color_blend_attachment;
    color_blending.blendConstants[0] = 0.0f;
    color_blending.blendConstants[1] = 0.0f;
    color_blending.blendConstants[2] = 0.0f;
    color_blending.blendConstants[3] = 0.0f;

    vk::PipelineLayoutCreateInfo pipelineLayoutInfo{};
    pipelineLayoutInfo.setLayoutCount = 0;
    pipelineLayoutInfo.pushConstantRangeCount = 0;

    auto [result, pipelineLayout] = device.createPipelineLayout(pipelineLayoutInfo);
    Assert(result == vk::Result::eSuccess, "");

    const std::array<vk::DynamicState, 3> dynamic_state_enables =
    {
        vk::DynamicState::eViewport,
        vk::DynamicState::eScissor,
        vk::DynamicState::eLineWidth
    };
    vk::PipelineDynamicStateCreateInfo dynamic_state = {};
    dynamic_state.dynamicStateCount = dynamic_state_enables.size();
    dynamic_state.pDynamicStates = dynamic_state_enables.data();

    vk::PipelineDepthStencilStateCreateInfo depth_stencil{};
    depth_stencil.depthTestEnable = false;
    depth_stencil.depthWriteEnable = true;
    depth_stencil.depthCompareOp = vk::CompareOp::eAlways;
    depth_stencil.depthBoundsTestEnable = false;
    depth_stencil.stencilTestEnable = false;
    depth_stencil.minDepthBounds = 0.0f;
    depth_stencil.maxDepthBounds = 1.0f;

    vk::GraphicsPipelineCreateInfo pipelineInfo{};
    pipelineInfo.stageCount = shader_stage_count;
    pipelineInfo.pStages = shader_infos.data();
    pipelineInfo.pVertexInputState = &vertexInputInfo;
    pipelineInfo.pInputAssemblyState = &inputAssembly;
    pipelineInfo.pViewportState = nullptr; // Handled via dynamic rendering.
    pipelineInfo.pRasterizationState = &rasterizer;
    pipelineInfo.pMultisampleState = &multisampling;
    pipelineInfo.pColorBlendState = &color_blending;
    pipelineInfo.layout = pipelineLayout;
    pipelineInfo.pDynamicState = &dynamic_state;
    pipelineInfo.pDepthStencilState = &depth_stencil;
    pipelineInfo.basePipelineHandle = nullptr;

    vk::Format format = vk::Format::eR8G8B8A8Unorm;
    vk::PipelineRenderingCreateInfo pipeline_rendering_create_info{};
    pipeline_rendering_create_info.colorAttachmentCount = 1;
    pipeline_rendering_create_info.pColorAttachmentFormats = &format;
    pipeline_rendering_create_info.depthAttachmentFormat = vk::Format::eUndefined;
    pipeline_rendering_create_info.stencilAttachmentFormat = vk::Format::eUndefined;

    pipelineInfo.pNext = &pipeline_rendering_create_info;

    auto [result_tmp, graphics_pipeline] =
        device.createGraphicsPipelineUnique({}, pipelineInfo);
    return std::move(graphics_pipeline);
}

特别是这两个结构:

vk::PipelineColorBlendAttachmentState color_blend_attachment{};
    color_blend_attachment.colorWriteMask =
        vk::ColorComponentFlagBits::eR |
        vk::ColorComponentFlagBits::eG |
        vk::ColorComponentFlagBits::eB |
        vk::ColorComponentFlagBits::eA;
    color_blend_attachment.blendEnable = VK_FALSE;

    vk::PipelineColorBlendStateCreateInfo color_blending{};
    color_blending.logicOpEnable = VK_FALSE;
    color_blending.logicOp = vk::LogicOp::eCopy;
    color_blending.attachmentCount = 1;
    color_blending.pAttachments = &color_blend_attachment;
    color_blending.blendConstants[0] = 0.0f;
    color_blending.blendConstants[1] = 0.0f;
    color_blending.blendConstants[2] = 0.0f;
    color_blending.blendConstants[3] = 0.0f;

我的验证层报告如下:

Message ID name: VUID-VkGraphicsPipelineCreateInfo-renderPass-06054
Message: Validation Error: [ VUID-VkGraphicsPipelineCreateInfo-renderPass-06054 ] Object 0: handle = 0x1f8e280, name = Logical device: NVIDIA GeForce GTX 1070, type = VK_OBJECT_TYPE_DEVICE; | MessageID = 0x6882ec30 | vkCreateGraphicsPipelines(): Pipeline 0 has VkPipelineRenderingCreateInfoKHR::colorAttachmentCount (1) and an invalid pColorBlendState structure The Vulkan spec states: If renderPass is VK_NULL_HANDLE, the pipeline is being created with fragment output interface state, and VkPipelineRenderingCreateInfo::colorAttachmentCount is not equal to 0, pColorBlendState must be a valid pointer to a valid VkPipelineColorBlendStateCreateInfo structure (https://vulkan.lunarg.com/doc/view/1.3.204.1/linux/1.3-extensions/vkspec.html#VUID-VkGraphicsPipelineCreateInfo-renderPass-06054)
Severity: VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT

这对我来说很奇怪,当我进行非动态渲染时,这些混合状态很好。

使用图层VK_LAYER_LUNARG_api_dump

我将此视为我的管道的创建信息:

vkCreateGraphicsPipelines(device, pipelineCache, createInfoCount, pCreateInfos, pAllocator, pPipelines) returns VkResult VK_SUCCESS (0):
    device:                         VkDevice = 0x128be90 [Logical device: NVIDIA GeForce GTX 1070]
    pipelineCache:                  VkPipelineCache = 0
    createInfoCount:                uint32_t = 1
    pCreateInfos:                   const VkGraphicsPipelineCreateInfo* = 0x7ffe0575b958
        pCreateInfos[0]:                const VkGraphicsPipelineCreateInfo = 0x7ffe0575b958:
            sType:                          VkStructureType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO (28)
            pNext:                          const void* = VkPipelineRenderingCreateInfo
            flags:                          VkPipelineCreateFlags = 0
            stageCount:                     uint32_t = 2
            pStages:                        const VkPipelineShaderStageCreateInfo* = 0x7ffe0575bd80
                pStages[0]:                     const VkPipelineShaderStageCreateInfo = 0x7ffe0575bd80:
                    sType:                          VkStructureType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO (18)
                    pNext:                          const void* = NULL
                    flags:                          VkPipelineShaderStageCreateFlags = 0
                    stage:                          VkShaderStageFlagBits = 1 (VK_SHADER_STAGE_VERTEX_BIT)
                    module:                         VkShaderModule = 0x16bd340
                    pName:                          const char* = "main"
                    pSpecializationInfo:            const VkSpecializationInfo* = NULL
                pStages[1]:                     const VkPipelineShaderStageCreateInfo = 0x7ffe0575bdb0:
                    sType:                          VkStructureType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO (18)
                    pNext:                          const void* = NULL
                    flags:                          VkPipelineShaderStageCreateFlags = 0
                    stage:                          VkShaderStageFlagBits = 16 (VK_SHADER_STAGE_FRAGMENT_BIT)
                    module:                         VkShaderModule = 0x16bdb10
                    pName:                          const char* = "main"
                    pSpecializationInfo:            const VkSpecializationInfo* = NULL
            pVertexInputState:              const VkPipelineVertexInputStateCreateInfo* = 0x7ffe0575bd48:
                sType:                          VkStructureType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO (19)
                pNext:                          const void* = NULL
                flags:                          VkPipelineVertexInputStateCreateFlags = 0
                vertexBindingDescriptionCount:  uint32_t = 1
                pVertexBindingDescriptions:     const VkVertexInputBindingDescription* = 0x16bcd90
                    pVertexBindingDescriptions[0]:  const VkVertexInputBindingDescription = 0x16bcd90:
                        binding:                        uint32_t = 0
                        stride:                         uint32_t = 20
                        inputRate:                      VkVertexInputRate = VK_VERTEX_INPUT_RATE_VERTEX (0)
                vertexAttributeDescriptionCount: uint32_t = 2
                pVertexAttributeDescriptions:   const VkVertexInputAttributeDescription* = 0x16b9a30
                    pVertexAttributeDescriptions[0]: const VkVertexInputAttributeDescription = 0x16b9a30:
                        location:                       uint32_t = 0
                        binding:                        uint32_t = 0
                        format:                         VkFormat = VK_FORMAT_R32G32_SFLOAT (103)
                        offset:                         uint32_t = 0
                    pVertexAttributeDescriptions[1]: const VkVertexInputAttributeDescription = 0x16b9a40:
                        location:                       uint32_t = 1
                        binding:                        uint32_t = 0
                        format:                         VkFormat = VK_FORMAT_R32G32B32_SFLOAT (106)
                        offset:                         uint32_t = 8
            pInputAssemblyState:            const VkPipelineInputAssemblyStateCreateInfo* = 0x7ffe0575bd20:
                sType:                          VkStructureType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO (20)
                pNext:                          const void* = NULL
                flags:                          VkPipelineInputAssemblyStateCreateFlags = 0
                topology:                       VkPrimitiveTopology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST (3)
                primitiveRestartEnable:         VkBool32 = 0
            pTessellationState:             const VkPipelineTessellationStateCreateInfo* = NULL
            pViewportState:                 const VkPipelineViewportStateCreateInfo* = NULL
            pRasterizationState:            const VkPipelineRasterizationStateCreateInfo* = 0x7ffe0575bcd8:
                sType:                          VkStructureType = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO (23)
                pNext:                          const void* = NULL
                flags:                          VkPipelineRasterizationStateCreateFlags = 0
                depthClampEnable:               VkBool32 = 0
                rasterizerDiscardEnable:        VkBool32 = 1
                polygonMode:                    VkPolygonMode = VK_POLYGON_MODE_FILL (0)
                cullMode:                       VkCullModeFlags = 2 (VK_CULL_MODE_BACK_BIT)
                frontFace:                      VkFrontFace = VK_FRONT_FACE_CLOCKWISE (1)
                depthBiasEnable:                VkBool32 = 0
                depthBiasConstantFactor:        float = 0
                depthBiasClamp:                 float = 0
                depthBiasSlopeFactor:           float = 0
                lineWidth:                      float = 3
            pMultisampleState:              const VkPipelineMultisampleStateCreateInfo* = 0x7ffe0575bc90:
                sType:                          VkStructureType = VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO (24)
                pNext:                          const void* = NULL
                flags:                          VkPipelineMultisampleStateCreateFlags = 0
                rasterizationSamples:           VkSampleCountFlagBits = 1 (VK_SAMPLE_COUNT_1_BIT)
                sampleShadingEnable:            VkBool32 = 0
                minSampleShading:               float = 0
                pSampleMask:                    const VkSampleMask* = NULL
                alphaToCoverageEnable:          VkBool32 = 0
                alphaToOneEnable:               VkBool32 = 0
            pDepthStencilState:             const VkPipelineDepthStencilStateCreateInfo* = 0x7ffe0575ba30:
                sType:                          VkStructureType = VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO (25)
                pNext:                          const void* = NULL
                flags:                          VkPipelineDepthStencilStateCreateFlags = 0
                depthTestEnable:                VkBool32 = 0
                depthWriteEnable:               VkBool32 = 1
                depthCompareOp:                 VkCompareOp = VK_COMPARE_OP_ALWAYS (7)
                depthBoundsTestEnable:          VkBool32 = 0
                stencilTestEnable:              VkBool32 = 0
                front:                          VkStencilOpState = 0x7ffe0575ba58:
                    failOp:                         VkStencilOp = VK_STENCIL_OP_KEEP (0)
                    passOp:                         VkStencilOp = VK_STENCIL_OP_KEEP (0)
                    depthFailOp:                    VkStencilOp = VK_STENCIL_OP_KEEP (0)
                    compareOp:                      VkCompareOp = VK_COMPARE_OP_NEVER (0)
                    compareMask:                    uint32_t = 0
                    writeMask:                      uint32_t = 0
                    reference:                      uint32_t = 0
                back:                           VkStencilOpState = 0x7ffe0575ba74:
                    failOp:                         VkStencilOp = VK_STENCIL_OP_KEEP (0)
                    passOp:                         VkStencilOp = VK_STENCIL_OP_KEEP (0)
                    depthFailOp:                    VkStencilOp = VK_STENCIL_OP_KEEP (0)
                    compareOp:                      VkCompareOp = VK_COMPARE_OP_NEVER (0)
                    compareMask:                    uint32_t = 0
                    writeMask:                      uint32_t = 0
                    reference:                      uint32_t = 0
                minDepthBounds:                 float = 0
                maxDepthBounds:                 float = 1
            pColorBlendState:               const VkPipelineColorBlendStateCreateInfo* = 0x7ffe0575bc00:
                sType:                          VkStructureType = VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO (26)
                pNext:                          const void* = NULL
                flags:                          VkPipelineColorBlendStateCreateFlags = 0
                logicOpEnable:                  VkBool32 = 0
                logicOp:                        VkLogicOp = VK_LOGIC_OP_COPY (3)
                attachmentCount:                uint32_t = 1
                pAttachments:                   const VkPipelineColorBlendAttachmentState* = 0x7ffe0575bc68
                    pAttachments[0]:                const VkPipelineColorBlendAttachmentState = 0x7ffe0575bc68:
                        blendEnable:                    VkBool32 = 0
                        srcColorBlendFactor:            VkBlendFactor = VK_BLEND_FACTOR_ZERO (0)
                        dstColorBlendFactor:            VkBlendFactor = VK_BLEND_FACTOR_ZERO (0)
                        colorBlendOp:                   VkBlendOp = VK_BLEND_OP_ADD (0)
                        srcAlphaBlendFactor:            VkBlendFactor = VK_BLEND_FACTOR_ZERO (0)
                        dstAlphaBlendFactor:            VkBlendFactor = VK_BLEND_FACTOR_ZERO (0)
                        alphaBlendOp:                   VkBlendOp = VK_BLEND_OP_ADD (0)
                        colorWriteMask:                 VkColorComponentFlags = 15 (VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT)
                blendConstants:                 float[4] = 0x7ffe0575bc28
                    blendConstants[0]:              float = 0
                    blendConstants[1]:              float = 0
                    blendConstants[2]:              float = 0
                    blendConstants[3]:              float = 0
            pDynamicState:                  const VkPipelineDynamicStateCreateInfo* = 0x7ffe0575baa0:
                sType:                          VkStructureType = VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO (27)
                pNext:                          const void* = NULL
                flags:                          VkPipelineDynamicStateCreateFlags = 0
                dynamicStateCount:              uint32_t = 3
                pDynamicStates:                 const VkDynamicState* = 0x7ffe0575bac0
                    pDynamicStates[0]:              const VkDynamicState = VK_DYNAMIC_STATE_VIEWPORT (0)
                    pDynamicStates[1]:              const VkDynamicState = VK_DYNAMIC_STATE_SCISSOR (1)
                    pDynamicStates[2]:              const VkDynamicState = VK_DYNAMIC_STATE_LINE_WIDTH (2)
            layout:                         VkPipelineLayout = 0x16bf960
            renderPass:                     VkRenderPass = 0
            subpass:                        uint32_t = 0
            basePipelineHandle:             VkPipeline = 0
            basePipelineIndex:              int32_t = 0
        pNext:                          VkPipelineRenderingCreateInfo = 0x7ffe0575b908:
            sType:                          VkStructureType = VK_STRUCTURE_TYPE_PIPELINE_RENDERING_CREATE_INFO (1000044002)
            pNext:                          const void* = NULL
            viewMask:                       uint32_t = 0
            colorAttachmentCount:           uint32_t = 1
            pColorAttachmentFormats:        const VkFormat* = 0x7ffe0575b934
                pColorAttachmentFormats[0]:     const VkFormat = VK_FORMAT_R8G8B8A8_UNORM (37)
            depthAttachmentFormat:          VkFormat = VK_FORMAT_UNDEFINED (0)
            stencilAttachmentFormat:        VkFormat = VK_FORMAT_UNDEFINED (0)
    pAllocator:                     const VkAllocationCallbacks* = NULL
    pPipelines:                     VkPipeline* = 0x7ffe0575c138
        pPipelines[0]:                  VkPipeline = 0x16be210

据我所知,从 gdb 可以看出指针 pColorBlendState 没问题。

它正在层中得到修复,因此希望它会在 Vulkan SDK 的某些后续版本中得到修复。

同时我认为删除片段着色器或 rasterizerDiscardEnable = VK_FALSE 应该消除错误。