提问人:gmmo 提问时间:11/6/2023 最后编辑:solidpixelgmmo 更新时间:11/6/2023 访问量:38
我无法让 Vulkan vkCmdBindVertexBuffers2 工作,我不知道为什么
I can't get Vulkan vkCmdBindVertexBuffers2 to work and I don't know why
问:
我正在尝试使用此 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”的调用中
有人可以帮助我发现错误吗?我真的看不出来。
非常感谢您抽出时间接受采访。
答:
答案来自我在 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 上向我展示了这个问题。
评论
vkCmdBindVertexBuffers2
可能是 null。该函数是否与?vkGetDeviceProcAddr