我正在为我的游戏框架创建基于Vulkan的渲染器后端。目前,我正在加载具有大约10,000个唯一三角形(未索引-均为单个)的网格,其中每个顶点都有一个位置值,RGB值,没有法线且没有纹理坐标。每个三角形为72个字节,即。 1 * xyz浮点数+ 1 * RGB浮点数=每个顶点6个浮点数。 6 * 3顶点=每个三角形18个浮点数。 18 * 4 =每个三角形72个字节。顶点数据存储在设置了VK_BUFFER_USAGE_VERTEX_BUFFER_BIT标志的GPU本地缓冲区中。
目前,我还在所有网格上使用相同的vert和frag着色器,并使用CPU计算的MVP矩阵的推入常数。
如果我对vkCmdBindVertexBuffers()中的偏移参数使用72的倍数,则我的网格将分解,因为永远不会绘制缓冲区中的第一个三角形。我将偏移量逐帧增加了72帧,这消除了网格的出现,没有段错误或错误。启用LunarG标准验证,没有报告的验证错误,(我有很多错误检查和登录代码)。
顺便说一句,如果我不使用72的倍数,那么我会得到一些非常有趣的渲染,但不会崩溃!在renderdoc上运行的一台已有六年历史的计算机上,我也获得了650fps的帧速率。
这是绑定顶点缓冲区的代码...
vkCmdBindVertexBuffers, (cmd[swapindex], 0, 1, vertexBuffers, offsets)
现在,仅因为这在我的PC上运行正常并不意味着它是正确的。我感到困惑的一件事是Vulkan规范中有关内存对齐要求的领域,特别是在VkPhysicalDeviceLimits中。
VkPhysicalDeviceLimits中有以下几种:minTexelBufferOffsetAlignment,minUniformBufferOffsetAlignment和minStorageBufferOffsetAlignment。
规范说: 对齐成员满足与VkBuffer的使用相关的缓冲区描述符偏移对齐要求:
如果使用情况包括VK_BUFFER_USAGE_UNIFORM_TEXEL_BUFFER_BIT或VK_BUFFER_USAGE_STORAGE_TEXEL_BUFFER_BIT,则对齐方式必须是VkPhysicalDeviceLimits :: minTexelBufferOffsetAlignment的整数倍。
如果包括用法VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT,则对齐方式必须是VkPhysicalDeviceLimits :: minUniformBufferOffsetAlignment的整数倍。
如果包括使用情况VK_BUFFER_USAGE_STORAGE_BUFFER_BIT,则对齐方式必须是VkPhysicalDeviceLimits :: minStorageBufferOffsetAlignment的整数倍。
我正在使用bufferCreateInfo.usage = VK_BUFFER_USAGE_VERTEX_BUFFER_BIT(和VK_BUFFER_USAGE_TRANSFER_DST_BIT,VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT)通过vkCreateBuffer()在设备本地内存中创建顶点缓冲区。
问题... 由于我没有使用VK_BUFFER_USAGE_UNIFORM_TEXEL_BUFFER_BIT,VK_BUFFER_USAGE_STORAGE_TEXEL_BUFFER_BIT,VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT或VK_BUFFER_USAGE_STORAGE_BU偏移量创建一个缓冲区,所以我没有用VK_BUFFER_USAGE_TEX调用C,即为0,这是对内存的要求吗? >
我要问的原因是我想在设置了VK_BUFFER_USAGE_VERTEX_BUFFER_BIT标志的单个vkCreateBuffer()缓冲区中存储多个网格。然后,我可以为需要绘制的每个唯一网格偏移此“超级顶点缓冲区”,而无需分配多个顶点缓冲区。我知道分配顶点缓冲区的限制通常为4096(VkPhysicalDeviceLimits :: maxMemoryAllocationCount),但我宁愿使用一个“超级缓冲区”来提高性能,而不是分配多个顶点缓冲区。
这有意义吗?
更新: 我将代码更改为在vkCmdBindVertexBuffers()中不使用偏移,而在vkCmdDraw()中将firstVertex参数用作网格模型偏移,这会产生更高且更稳定的FPS。
答案 0 :(得分:1)
我没有在规范中看到任何对齐要求,尽管我认为这可能是一个疏忽。您可以尝试舍入为16的倍数;任何实际的对齐要求都不可能大于此。因此,如果您的第一个网格是5个三角形,则需要5 * 72字节,而第二个网格将从偏移量round_up(5 * 72,16)= 368开始。如果那不起作用,则可能是其他地方有一个错误。
但是,您可以只绑定一次完整的顶点缓冲区,然后对每个绘制使用vkCmdBindVertexBuffers
参数,以指示到网格起始处的缓冲区的索引,而不是对firstVertex
使用偏移量。