我无法让 Vulkan vkCmdBindVertexBuffers2 工作,我不知道为什么

I can't get Vulkan vkCmdBindVertexBuffers2 to work and I don't know why

提问人:gmmo 提问时间:11/6/2023 最后编辑:solidpixelgmmo 更新时间:11/6/2023 访问量:38

问:

我正在尝试使用此 API 绑定我的顶点缓冲区:

https://registry.khronos.org/vulkan/specs/1.3-extensions/man/html/vkCmdBindVertexBuffers2.html

它与标准 API 对应项几乎相同,只是允许设置动态步幅。

https://registry.khronos.org/vulkan/specs/1.3-extensions/man/html/vkCmdBindVertexBuffers.html

但是,在我的测试程序中,它一直崩溃,验证层也没有显示任何:(我无法发现错误。这是我尝试过的:

我的顶点数组:

const std::vector<Vertex> vertices =
{
    {{0.0f, 0.0f},  {0.21f, 0.41f, 0.61f}},
    {{0.0f, 1.0f},  {0.21f, 0.41f, 0.61f}},
    {{1.0f, 0.0f},  {0.21f, 0.41f, 0.61f}},
    {{1.0f, 1.0f},  {0.21f, 0.41f, 0.61f}},
};

我的顶点、attribs 和 desc

struct Vertex {
    glm::vec2 pos;
    glm::vec3 color;

    static VkVertexInputBindingDescription getBindingDescription() {
        VkVertexInputBindingDescription bindingDescription{};
        bindingDescription.binding = 0;
        bindingDescription.stride = sizeof(Vertex);
        bindingDescription.inputRate = VK_VERTEX_INPUT_RATE_VERTEX;
        return bindingDescription;
    }

    static std::array<VkVertexInputAttributeDescription, 2> getAttributeDescriptions() {
        std::array<VkVertexInputAttributeDescription, 2> attributeDescriptions{};
        attributeDescriptions[0].binding = 0;
        attributeDescriptions[0].location = 0;
        attributeDescriptions[0].format = VK_FORMAT_R32G32_SFLOAT;
        attributeDescriptions[0].offset = offsetof(Vertex, pos);
        attributeDescriptions[1].binding = 0;
        attributeDescriptions[1].location = 1;
        attributeDescriptions[1].format = VK_FORMAT_R32G32B32_SFLOAT;
        attributeDescriptions[1].offset = offsetof(Vertex, color);
        return attributeDescriptions;
    }
};

管道创建时没有任何错误 这是我在绑定顶点缓冲区时所拥有的。

            VkBuffer vertexBuffers[] = {vertexBuffer};
            VkDeviceSize offsets[] = {0};

            // 5 floats x 4 vertices
            VkDeviceSize    sizes[] = {sizeof(float) * 5 * 4};
            VkDeviceSize    strides[] = { sizeof(Vertex) };

#if 0
            // this works
            vkCmdBindVertexBuffers(commandBuffer, 0, 1, vertexBuffers, offsets);
#else
            // this crashes :(
            vkCmdBindVertexBuffers2(commandBuffer, 0, 1, vertexBuffers, offsets, sizes, strides);
#endif

            vkCmdDraw(commandBuffer, static_cast<uint32_t>(vertices.size()), 1, 0, 0);

更糟糕的是,如果我使用没有额外参数的标准 vkCmdBindVertexBuffers,它可以正常工作。它只是用三条画一个四边形。

我正在使用 vulkan API

Vulkan Version:1.3.236

根据文档,我不需要启用扩展。但为了以防万一,我还尝试通过动态状态启用扩展,如下所示:

const std::vector<const char*> deviceExtensions = {
    VK_KHR_SWAPCHAIN_EXTENSION_NAME,
    VK_EXT_EXTENDED_DYNAMIC_STATE_EXTENSION_NAME,
    VK_EXT_EXTENDED_DYNAMIC_STATE_2_EXTENSION_NAME,
};

...

        std::vector<VkDynamicState> dynamicStates = {
            VK_DYNAMIC_STATE_VIEWPORT,
            VK_DYNAMIC_STATE_SCISSOR,
            VK_DYNAMIC_STATE_VERTEX_INPUT_BINDING_STRIDE_EXT,
            VK_DYNAMIC_STATE_VERTEX_INPUT_BINDING_STRIDE,
        };
        VkPipelineDynamicStateCreateInfo dynamicState{};
        dynamicState.sType = VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO;
        dynamicState.dynamicStateCount = static_cast<uint32_t>(dynamicStates.size());
        dynamicState.pDynamicStates = dynamicStates.data();

但没什么区别。完全相同的崩溃:(

这是崩溃,请注意所有指针和句柄都有效。它发生在对“vkCmdBindVertexBuffers2”的调用中

enter image description here

有人可以帮助我发现错误吗?我真的看不出来。

非常感谢您抽出时间接受采访。

武尔坎

评论

0赞 vandench 11/6/2023
vkCmdBindVertexBuffers2可能是 null。该函数是否与?vkGetDeviceProcAddr
0赞 gmmo 11/6/2023
不,这只是版本要求。见下文,但感谢您阅读。

答:

0赞 gmmo 11/6/2023 #1

答案来自我在 Discord 上的讨论:

https://discord.com/channels/427551838099996672/427951557045387276/1170966659171876934

基本上,我错过了指定此扩展所需的 API 1.3.x。奇怪的是,验证层没有报告任何内容。


// this is the issue, V 1.0.0 does not support the API
//appInfo.apiVersion = VK_API_VERSION_1_0;

// the quick fix
appInfo.apiVersion = VK_MAKE_VERSION(1, 3, 0);

然而,正确的修复需要检查 VkPhysicalDeviceProperties.apiVersion 以查看我的显卡是否支持它。

非常感谢 Alex 在 discord 上向我展示了这个问题。