Vulkan vkCmdDrawIndexed只使用了VertexBuffer中的第一个值
Vulkan vkCmdDrawIndexed used only first Value from VertexBuffer
我正在尝试在Vulkan中实现实例化网格渲染。
我的问题是Vulkan只使用绑定的VertexBuffer中的第一个顶点,并复制所有索引的值。输出RenderDoc:
RenderDoc输出重复顶点输入
这些应该是正确的值{{<inPosition>
}、{<inColor>
}、{<inTexCoord>
}}:
const vkf::Vertex vertices[] = {
{ { -0.2f, -0.5f, 0.0f },{ 1.0f, 0.0f, 0.0f },{ 1.0f, 0.0f } },
{ { 0.5f, -0.5f, 0.0f },{ 0.0f, 1.0f, 0.0f },{ 0.0f, 0.0f } },
{ { 0.5f, 0.5f, 0.0f },{ 0.0f, 0.0f, 1.0f },{ 0.0f, 1.0f } },
{ { -0.5f, 0.5f, 0.0f },{ 1.0f, 1.0f, 1.0f },{ 1.0f, 1.0f } }
};
我已经检查了多次"顶点缓冲区",它包含正确的值。
以下是从我的CommandBuffer创建截取的片段:
vkCmdBindPipeline(m_commandBuffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, pipelines.agents);
VkBuffer vertexBuffers[] = { models.agent.verticesBuffer };
VkBuffer instanceBuffers[] = { m_instanceBuffer.buffer };
VkDeviceSize offsets[] = { 0 };
vkCmdBindVertexBuffers(m_commandBuffers[i], 0, 1, vertexBuffers, offsets);
vkCmdBindVertexBuffers(m_commandBuffers[i], 1, 1, instanceBuffers, offsets);
vkCmdBindIndexBuffer(m_commandBuffers[i], models.agent.indexBuffer, 0, VK_INDEX_TYPE_UINT16);
vkCmdBindDescriptorSets(m_commandBuffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, m_pipelineLayouts.pipelineLayoutAgent, 0, 1, &descriptorSets.agent, 0, nullptr);
vkCmdDrawIndexed(m_commandBuffers[i], static_cast<uint32_t> (models.agent.indexCount), 5, 0, 0, 0);
我的第一个假设是我的约束性描述是错误的。但我看不出错误:
bindingDescription = {};
bindingDescription.binding = 0;
bindingDescription.stride = sizeof(Vertex);
bindingDescription.inputRate = VK_VERTEX_INPUT_RATE_VERTEX;
为什么只使用缓冲区中的第一个值?
编辑:
实例数据:
struct InstanceData
{
glm::vec3 pos;
glm::vec3 rot;
float scale;
static VkVertexInputBindingDescription getBindingDescription()
{
VkVertexInputBindingDescription bindingDescription = {};
bindingDescription.binding = INSTANCING_BIND_ID;
bindingDescription.stride = sizeof(InstanceData);
bindingDescription.inputRate = VK_VERTEX_INPUT_RATE_INSTANCE;
return bindingDescription;
}
};
整个VkPipelineVertexInputStateCreateInfo:
std::vector<VkVertexInputBindingDescription> bindingDesciption = {};
std::vector<VkVertexInputAttributeDescription> attributeDescriptions = {};
bindingDesciption = {
models.agent.bindingDescription,
InstanceData::getBindingDescription()
};
attributeDescriptions =
{
vertexInputAttributeDescription(VERTEX_BIND_ID, 0, VK_FORMAT_R32G32B32_SFLOAT, offsetof(vkf::Vertex, pos)),
vertexInputAttributeDescription(VERTEX_BIND_ID, 1, VK_FORMAT_R32G32B32_SFLOAT, offsetof(vkf::Vertex, color)),
vertexInputAttributeDescription(INSTANCING_BIND_ID, 2, VK_FORMAT_R32G32B32_SFLOAT, offsetof(InstanceData, pos)),
vertexInputAttributeDescription(VERTEX_BIND_ID, 3, VK_FORMAT_R32G32_SFLOAT, offsetof(vkf::Vertex, texCoord))
};
VkPipelineVertexInputStateCreateInfo vertexInputInfo = {};
vertexInputInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO;
vertexInputInfo.vertexBindingDescriptionCount = static_cast<uint32_t>(bindingDesciption.size());
vertexInputInfo.vertexAttributeDescriptionCount = static_cast<uint32_t>(attributeDescriptions.size());
vertexInputInfo.pVertexBindingDescriptions = bindingDesciption.data();
vertexInputInfo.pVertexAttributeDescriptions = attributeDescriptions.data();
编辑2
#define VERTEX_BIND_ID 0
#define INSTANCING_BIND_ID 1
编辑3:我正在使用VulkanMemoryAllocator。创建暂存缓冲区
size_t vertexBufferSize = sizeof(vkf::Vertex) *_countof(vertices);
createStagingBuffer(vertexBufferSize );
VkBuffer createStagingBuffer(VkDeviceSize size)
{
VkBuffer buffer;
VkBufferCreateInfo bufferInfo = { VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO };
bufferInfo.size = size;
bufferInfo.usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT;
bufferInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
VmaAllocationCreateInfo allocCreateInfo = {};
allocCreateInfo.usage = VMA_MEMORY_USAGE_CPU_TO_GPU;
allocCreateInfo.flags = VMA_ALLOCATION_CREATE_PERSISTENT_MAP_BIT;
VmaAllocationInfo allocInfo = {};
if (vmaCreateBuffer(m_allocator, &bufferInfo, &allocCreateInfo, &buffer, &m_allocation, &allocInfo) != VK_SUCCESS)
{
throw std::runtime_error("failed to create Buffer!");
}
return buffer;
}
复制顶点:
memcpy(mappedStaging, vertices, vertexBufferSize);
创建缓冲区:
createBuffer(vertexBufferSize, VK_BUFFER_USAGE_TRANSFER_DST_BIT | VK_BUFFER_USAGE_VERTEX_BUFFER_BIT, VMA_MEMORY_USAGE_GPU_ONLY);
VkBuffer createBuffer(VkDeviceSize size, VkBufferUsageFlags usage, VmaMemoryUsage vmaUsage)
{
VkBuffer buffer;
VkBufferCreateInfo bufferInfo = { VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO };
bufferInfo.size = size;
bufferInfo.usage = usage;
bufferInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
VmaAllocationCreateInfo allocCreateInfo = {};
allocCreateInfo.usage = vmaUsage;
allocCreateInfo.flags = 0;
VmaAllocationInfo allocInfo;
if (vmaCreateBuffer(m_allocator, &bufferInfo, &allocCreateInfo, &buffer, &m_allocation, &allocInfo) != VK_SUCCESS)
{
throw std::runtime_error("failed to create Buffer!");
}
return buffer;
}
这就是我如何从暂存转换缓冲区的方式:
copyBuffer(stagingVertexBuffer, verticesBuffer, vertexBufferSize);
void Base::copyBuffer(VkBuffer srcBuffer, VkBuffer dstBuffer, VkDeviceSize size)
{
VkCommandBuffer commandBuffer = beginSingleTimeCommands();
VkBufferCopy copyRegion = {};
copyRegion.dstOffset = 0;
copyRegion.srcOffset = 0;
copyRegion.size = size;
vkCmdCopyBuffer(commandBuffer, srcBuffer, dstBuffer, 1, ©Region);
endSingleTimeCommands(commandBuffer);
}
我检查了好几次数据是否在staging Buffer中,在修改了createBuffer Prozess之后,数据也在verticalsBuffer中。它们正确地存储在那里。
我发现了错误。错误就在这里:
bindingDesciption = {
models.agent.bindingDescription,
InstanceData::getBindingDescription()
};
绑定发生时,models.agent.bindingDescription尚未初始化。因此,VkVertexInputBindingDescription出现故障。models.agent.bindingDescription中填充了VkVertexInputBindingDescription:的标准值
binding = 0
stroke = 0
inputRate = VK_VERTEX_INPUT_RATE_VERTEX
相关文章:
- 为什么它只打印双链接列表的第一个值,而我的程序却崩溃了
- std::find,返回所有找到的值的替代方法,而不仅仅是存在重复的向量的第一个值
- 如何仅读取文本文件中的第一个值
- 在C++中,如何在第一个"system()"结束后执行第二个"system()"?
- 查找不在标准中的第一个值::设置<int>最小-最大值
- C++:忽略第一个 cin.ignore 之后的输入
- 在C++中打印多个矢量的第一个值
- C++去除前x个元素的有效方法,在不改变向量大小的情况下将第x+1个元素推到第一个
- C++第一个cout将不会打印
- 我们可以在第一个else-if条件结束后使用另一个else-if条件吗
- OpenGL:第二个VBO破坏了第一个VBO
- 为什么第一个Dynamic_cast没有投射到基类?
- OpenGL 2D游戏只绘制第二个精灵纹理而不是第一个
- C++ 为什么程序只读取第一个值
- 在我的第一个C++程序中需要一些帮助(简单)
- 为什么我的代码在第一个 if 语句处中断?
- 是否可以从另一个类对象调用一个类函数而不继承第一个类
- 无法使我的第一个Windows OpenGL窗口抬起并运行
- 将参数初始化为构造函数,而不是第一个
- 无法在硬件模式下创建 SGX 安全区 - "invalid launch token"即使文档将无效的启动令牌指定为第一个