Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

False positive: vkCmdSetVertexInputEXT does not invalidate unbound bindings #9027

Open
Macdu opened this issue Dec 14, 2024 · 0 comments
Open

Comments

@Macdu
Copy link

Macdu commented Dec 14, 2024

The function PostCallRecordCmdSetVertexInputEXT does not invalidate vertex bindings which were not replaced.
This means that when calling CmdSetVertexInputEXT with 3 bindings, then again with only one binding, the last 2 bindings of the first call are still considered as active by the validation layer.

This causes in turn many false positive when binding vertex buffers and drawing. The following test shows two of them:

TEST_F(PositiveDynamicState, VertexInputRebinding) {
    SetTargetApiVersion(VK_API_VERSION_1_1);
    AddRequiredExtensions(VK_EXT_VERTEX_INPUT_DYNAMIC_STATE_EXTENSION_NAME);
    AddRequiredFeature(vkt::Feature::vertexInputDynamicState);
    RETURN_IF_SKIP(Init());
    InitRenderTarget();

    VkVertexInputBindingDescription2EXT bindings[2];
    bindings[0] = vku::InitStructHelper();
    bindings[0].binding = 0u;
    bindings[0].stride = sizeof(uint32_t);
    bindings[0].inputRate = VK_VERTEX_INPUT_RATE_VERTEX;
    bindings[0].divisor = 1u;
    bindings[1] = vku::InitStructHelper();
    bindings[1].binding = 1u;
    bindings[1].stride = sizeof(uint32_t);
    bindings[1].inputRate = VK_VERTEX_INPUT_RATE_VERTEX;
    bindings[1].divisor = 1u;

    VkVertexInputAttributeDescription2EXT attributes[2];
    attributes[0] = vku::InitStructHelper();
    attributes[0].location = 1u;
    attributes[0].binding = 0u;
    attributes[0].format = VK_FORMAT_R32_SFLOAT;
    attributes[0].offset = 0;

    attributes[1] = vku::InitStructHelper();
    attributes[1].location = 0u;
    attributes[1].binding = 1u;
    attributes[1].format = VK_FORMAT_R32_SINT;
    attributes[1].offset = 0;

    char const *vsSource = R"glsl(
        #version 450
        layout(location = 0) in float a;

        void main(){
            gl_Position = vec4(a);
        }
    )glsl";
    VkShaderObj vs(this, vsSource, VK_SHADER_STAGE_VERTEX_BIT);

    CreatePipelineHelper pipe(*this);
    pipe.AddDynamicState(VK_DYNAMIC_STATE_VERTEX_INPUT_EXT);
    pipe.shader_stages_ = {vs.GetStageCreateInfo(), pipe.fs_->GetStageCreateInfo()};
    pipe.CreateGraphicsPipeline();

    vkt::Buffer vertex_buffer(*m_device, 1024, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT);
    VkDeviceSize offset = 0;

    m_command_buffer.begin();
    m_command_buffer.BeginRenderPass(m_renderPassBeginInfo);
    vk::CmdBindPipeline(m_command_buffer.handle(), VK_PIPELINE_BIND_POINT_GRAPHICS, pipe.Handle());
    vk::CmdSetVertexInputEXT(m_command_buffer.handle(), 2, bindings, 2, attributes);

    attributes[0].location = 0;
    attributes[0].format = VK_FORMAT_R32_SFLOAT;
    vk::CmdSetVertexInputEXT(m_command_buffer.handle(), 1, bindings, 1, attributes);

    vk::CmdBindVertexBuffers(m_command_buffer.handle(), 0, 1, &vertex_buffer.handle(), &offset);
    vk::CmdDraw(m_command_buffer.handle(), 3u, 3u, 0u, 0u);
    m_command_buffer.EndRenderPass();
    m_command_buffer.end();
}

This code should output no validation error. However, it outputs the following 2:
Validation Error: [ VUID-vkCmdDraw-Input-08734 ] Object 0: handle = 0xcfef35000000000a, type = VK_OBJECT_TYPE_SHADER_MODULE; | MessageID = 0x267f4248 | vkCmdDraw(): vkCmdSetVertexInputEXT set pVertexAttributeDescriptions[1] (binding 1, location 0) with format VK_FORMAT_R32_SINT but the vertex shader input is numeric type float32. The Vulkan spec states: If there is a shader object bound to the VK_SHADER_STAGE_VERTEX_BIT stage or the bound graphics pipeline state was created with the VK_DYNAMIC_STATE_VERTEX_INPUT_EXT dynamic state enabled and either legacyVertexAttributes is not enabled or the SPIR-V Type associated with a given Input variable of the corresponding Location in the Vertex Execution Model OpEntryPoint is 64-bit, then the numeric type associated with all Input variables of the corresponding Location in the Vertex Execution Model OpEntryPoint must be the same as VkVertexInputAttributeDescription2EXT::format (https://www.khronos.org/registry/vulkan/specs/1.3-extensions/html/vkspec.html#VUID-vkCmdDraw-Input-08734)
and
Validation Error: [ VUID-vkCmdDraw-None-04008 ] Object 0: handle = 0x2193c684f10, type = VK_OBJECT_TYPE_COMMAND_BUFFER; Object 1: handle = 0xdcc8fd0000000012, type = VK_OBJECT_TYPE_PIPELINE; | MessageID = 0x255241c3 | vkCmdDraw(): Vertex binding 1 is VK_NULL_HANDLE. (Most likely you forgot to call vkCmdBindVertexBuffers). The Vulkan spec states: If the nullDescriptor feature is not enabled, all vertex input bindings accessed via vertex input variables declared in the vertex shader entry point's interface must not be VK_NULL_HANDLE (https://www.khronos.org/registry/vulkan/specs/1.3-extensions/html/vkspec.html#VUID-vkCmdDraw-None-04008).

Also note that this error started appearing when updating from SDK 1.3.290 to 1.3.296, the test above was not causing any validation error on SDK 1.3.290.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant