Vulkan顶点缓冲区渲染三角形与预期顶点不符求助
问题排查请求
此前通过gl_VertexIndex可以正常渲染三角形,改用顶点缓冲区实现后,渲染出的三角形形态异常。以下是相关代码,请帮忙排查原因。
缓冲区创建与更新代码
VulkanBuffer createVulkanBuffer(VulkanContext* context, uint32_t size) { VulkanBuffer output = {}; VkBufferCreateInfo createInfo = { VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO }; createInfo.usage = VK_BUFFER_USAGE_VERTEX_BUFFER_BIT; // i createInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE; createInfo.size = size; vkCreateBuffer(context->device, &createInfo, nullptr, &output.buffer); VkBufferMemoryRequirementsInfo2 requirementsInfo = { VK_STRUCTURE_TYPE_BUFFER_MEMORY_REQUIREMENTS_INFO_2 }; requirementsInfo.buffer = output.buffer; VkMemoryRequirements2 memoryRequirements = { VK_STRUCTURE_TYPE_MEMORY_REQUIREMENTS_2 }; vkGetBufferMemoryRequirements2(context->device, &requirementsInfo, &memoryRequirements); VkPhysicalDeviceMemoryProperties2 memoryProperties = { VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MEMORY_PROPERTIES_2 }; vkGetPhysicalDeviceMemoryProperties2(context->physicalDevice, &memoryProperties); int32_t memoryTypeIndex = findMemoryTypeIndex(&memoryProperties.memoryProperties, memoryRequirements.memoryRequirements.memoryTypeBits, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT); VkMemoryAllocateInfo allocInfo = { VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO }; allocInfo.allocationSize = memoryRequirements.memoryRequirements.size; allocInfo.memoryTypeIndex = memoryTypeIndex; vkAllocateMemory(context->device, &allocInfo, nullptr, &output.deviceMemory); VkBindBufferMemoryInfo memoryInfo = { VK_STRUCTURE_TYPE_BIND_BUFFER_MEMORY_INFO }; memoryInfo.buffer = output.buffer; memoryInfo.memory = output.deviceMemory; memoryInfo.memoryOffset = 0; vkBindBufferMemory2(context->device, 1, &memoryInfo); return output; } void updateBuffer(VulkanContext* context, VulkanBuffer* buffer, void* data, uint32_t sizeOfData) { void* pData; vkMapMemory(context->device, buffer->deviceMemory, 0, sizeOfData, 0, &pData); memcpy(pData, data, static_cast<size_t>(sizeOfData)); vkUnmapMemory(context->device, buffer->deviceMemory); }
三角形顶点数据
mathfu是仅头文件的数学库。
std::vector<mathfu::vec3> createTriangle2() { std::vector<mathfu::vec3> vertices; vertices.resize(3); vertices[0] = mathfu::vec3(-1.f, -1.f, 0.f); vertices[1] = mathfu::vec3(1.f, -1.f, 0.f); vertices[2] = mathfu::vec3(0.f, 1.f, 0.f); return vertices; }
管线创建用顶点描述符
VulkanVertexDescriptor createVertexDescriptor(uint32_t stride) { VulkanVertexDescriptor descriptor = {}; descriptor.bindingDescriptors.resize(1); descriptor.attributeDescriptors.resize(1); descriptor.bindingDescriptors[0].binding = 0; descriptor.bindingDescriptors[0].stride = stride; descriptor.bindingDescriptors[0].inputRate = VK_VERTEX_INPUT_RATE_VERTEX; descriptor.attributeDescriptors[0].binding = 0; descriptor.attributeDescriptors[0].location = 0; descriptor.attributeDescriptors[0].offset = 0; descriptor.attributeDescriptors[0].format = VK_FORMAT_R32G32B32_SFLOAT; return descriptor; }
函数调用代码
VkViewport viewport = { 0.f, (float)swapchain.height, (float)swapchain.width, -(float)swapchain.height, 0.f, 0.f }; // vertex data auto triangle = createTriangle2(); uint32_t vsize = sizeof(mathfu::vec3); uint32_t sizeOfTriangle = vsize * triangle.size(); VulkanBuffer buffer = createVulkanBuffer(context, sizeOfTriangle); updateBuffer(context, &buffer, triangle.data(), sizeOfTriangle); VulkanVertexDescriptor descriptor = createVertexDescriptor(vsize); VulkanPipeline pipeline = createGraphicsPipeline(context, renderpass, viewport, "../assets/shaders/spv/triangle_vert.spv", "../assets/shaders/spv/triangle_frag.spv", descriptor);
顶点与片段着色器
#version 460 layout(location = 0) in vec3 position; layout(location = 0) out vec3 color; vec3 positions[3] = vec3[] ( vec3(-1.0, -1.0, 0.0), vec3(1.0, -1.0, 0.0), vec3(0.0, 1.0, 0.0) ); void main() { gl_Position = vec4(position.xyz * 0.5, 1.0); color = abs(position.xyz); //gl_Position = vec4(positions[gl_VertexIndex].xyz, 1.0); } #version 460 layout(location = 0) in vec3 color; layout(location = 0) out vec4 finalColor; void main() { finalColor = vec4(color, 1.0); }
核心排查方向
- Viewport翻转问题:当前Viewport设置为
{0.f, (float)swapchain.height, (float)swapchain.width, -(float)swapchain.height, 0.f, 0.f},Y轴起始点在Swapchain底部且高度为负,会导致画面垂直翻转。之前用gl_VertexIndex时着色器硬编码顶点,翻转后视觉上兼容,现在用缓冲区顶点后,翻转会直接导致三角形形态扭曲。 - 顶点内存对齐问题:确认
mathfu::vec3的内存布局是否与VK_FORMAT_R32G32B32_SFLOAT完全匹配——是否是连续的三个32位浮点数,无额外padding。部分数学库会为内存对齐在vec3后追加一个float,导致stride计算错误,顶点数据读取错位。 - 绘制命令参数错误:检查绘制调用时是否传入了正确的顶点数量(应为3),若误用索引绘制且索引缓冲区异常,或顶点数传递错误,也会导致渲染异常。
- 缓冲区内存可见性:虽然使用了
VK_MEMORY_PROPERTY_HOST_COHERENT_BIT,部分驱动仍需显式调用vkFlushMappedMemoryRanges确保主机写入的数据被设备可见,可尝试添加该操作验证。
内容的提问来源于stack exchange,提问作者Miso_Soup
相关产品推荐
相关产品推荐

