Vulkan vkCmdDrawIndexed 仅使用 VertexBuffer 中的第一个值
Vulkan vkCmdDrawIndexed used only first Value from VertexBuffer
我正在尝试在 Vulkan 中实现实例化网格渲染。
我的问题是 Vulkan 仅使用绑定 VertexBuffer 中的第一个顶点并复制所有索引的值。
输出 RenderDoc:
RenderDoc output Duplicated Vertex Input
这些应该是正确的值 {{<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 } }
};
我已经多次检查 VertexBuffer,它包含正确的值。
这是我的 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);
}
我检查了几次数据是否在暂存缓冲区中,并且在修改 createBuffer Prozess 之后也在 verticesBuffer 中。它们正确地存储在那里。
我发现了错误。
错误在这里:
bindingDesciption = {
models.agent.bindingDescription,
InstanceData::getBindingDescription()
};
绑定发生时,models.agent.bindingDescription尚未初始化。结果,VkVertexInputBindingDescription 出现了错误。
models.agent.bindingDescription 填充了 VkVertexInputBindingDescription 的标准值:
binding = 0
stroke = 0
inputRate = VK_VERTEX_INPUT_RATE_VERTEX
我正在尝试在 Vulkan 中实现实例化网格渲染。
我的问题是 Vulkan 仅使用绑定 VertexBuffer 中的第一个顶点并复制所有索引的值。 输出 RenderDoc:
RenderDoc output Duplicated Vertex Input
这些应该是正确的值 {{<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 } }
};
我已经多次检查 VertexBuffer,它包含正确的值。
这是我的 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);
}
我检查了几次数据是否在暂存缓冲区中,并且在修改 createBuffer Prozess 之后也在 verticesBuffer 中。它们正确地存储在那里。
我发现了错误。 错误在这里:
bindingDesciption = {
models.agent.bindingDescription,
InstanceData::getBindingDescription()
};
绑定发生时,models.agent.bindingDescription尚未初始化。结果,VkVertexInputBindingDescription 出现了错误。 models.agent.bindingDescription 填充了 VkVertexInputBindingDescription 的标准值:
binding = 0
stroke = 0
inputRate = VK_VERTEX_INPUT_RATE_VERTEX