[英]Buffer memory allocation for Dynamic uniform buffer in Vulkan
我想将这个问题分为三个部分:
limit.minUniformBufferOffsetAlignment的概念是什么,为什么我们需要使用它来获得所需的对齐方式并从中得出缓冲区的偏移量? Vulkan不能自动区分不同的数据类型及其各自的对齐方式吗?
在Sascha Willems示例中,他计算出一个4X4矩阵的动态对齐方式,如下所示
size_t uboAlignment = vulkanDevice->properties.limits.minUniformBufferOffsetAlignment dynamicAlignment = (sizeof(glm::mat4) / uboAlignment) * uboAlignment + ((sizeof(glm::mat4) % uboAlignment) > 0 ? uboAlignment : 0);
一个4X4矩阵为64字节,允许的最小对齐大小为256字节,但据我所知他的dynamicAlignment计算结果为(64 + 256 = 320 //我认为这在vulkan中是不允许的),我不太了解此dynamicAlignment的方式计算工作
此dynamicAlignment变量如何反映为
VkBufferCreateInfo bufferInfo = {}; bufferInfo.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO; bufferInfo.size = size;
和内存映射类似
void * data; vkMapMemory(device, uniformStagingBufferMemory, 0, sizeof(matrix), 0, &data); memcpy(data, &matrix, sizeof(matrix)); vkUnmapMemory(device, uniformStagingBufferMemory); copyBuffer(uniformStagingBuffer, uniformBuffer, sizeof(matrix));
UBO的最小对齐方式是对您的限制。 也就是说,它告诉您每个UBO的开始必须是该对齐方式的某个倍数。 它告诉您必须将数据放置在内存中的位置,以便系统使用该数据。
Vulkan不能自动使您做到这一点。 Vulkan是一个显式的API:您生活在它的限制之内,反之亦然。 请注意,OpenGL 对UBO数据具有相同的限制 。
该代码已被破坏,但它是偶然发生的。 (sizeof(glm::mat4) / uboAlignment)
的结果为零 ,因为整数除法将始终产生整数 。 而且由于标准要求minUniformBufferOffsetAlignment
不小于256,因此将64除以该值将始终产生零,并四舍五入。 并且0 * uboAlignment
仍为零。
因此,剩下的唯一代码部分是((sizeof(glm::mat4) % uboAlignment) > 0 ? uboAlignment : 0)
64%256是192,即> 0,因此结果是uboAlignment
。
这样就行了,但只是偶然。 他可能还直接使用过minUniformBufferOffsetAlignment
。
首先,内存映射是一项非常繁重的操作。 您永远不要只为了设置矩阵就映射内存,然后立即取消映射。 如果打算通过映射修改内存,则应保持映射状态,直到准备删除它为止。 这不会抑制性能,不会阻止您按照允许的使用方法或其他任何方式使用该内存。
其次,如规范所明确概述的那样,如果您创建一个VkBuffer
统一缓冲区的VkBuffer
,则您指定的偏移量必须遵守minUniformBufferOffsetAlignment
。 同样,将此类缓冲区用作UBO资源时,无论偏移是动态还是静态,您提供的偏移也必须与minUniformBufferOffsetAlignment
对齐。
1 .:缓冲区大小必须是该大小的倍数。 而且,您需要知道在缓冲区的哪个部分中实际存储了什么内容以及未存储的位置。 如果您的数据不完全适合您的缓冲区,则它需要成倍增加。
2 .:您的计算已关闭。 整数算术。 结果仅为256。
3 .:无需复制缓冲区中实际上不包含您的数据的部分。 允许部分复制,只是缓冲区本身更大。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.