Vulkan中动态统一缓冲区的缓冲区内存分配



我想把这个问题分成三部分:-

  1. 限制的概念是什么。minUniformBufferOffsetAlignment为什么我们需要使用它来获得所需的对齐,并从中导出缓冲区的偏移量?Vulkan不能自动区分不同的数据类型和它们各自的对齐方式吗?

  2. 在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字节,但据我所知,他的动态对齐计算结果是(64+256=320//,我认为这在vulkan中是不允许的),我不太明白这种动态对齐计算是如何工作的

  3. 这个dynamicAlign变量如何反映到

    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));
    
  1. 最小UBO对齐是对您的限制。也就是说,它告诉你每个UBO的开始都必须是该对齐的倍数。它告诉您必须将数据放入内存中的何处,以便系统使用该数据。

    这不是Vulkan可以自动让你做的事情。Vulkan是一个明确的API:你生活在限制范围内,反之亦然。请注意,OpenGL对UBO数据有同样的限制。

  2. 这个代码被破坏得很厉害,但它是意外工作的。(sizeof(glm::mat4) / uboAlignment)的结果是,因为整数的除法总是会导致整数。由于标准要求minUniformBufferOffsetAlignment不小于256,因此将64除以该值将始终产生零,向下取整。并且CCD_ 3仍然为零。

    所以剩下的代码只有一部分是((sizeof(glm::mat4) % uboAlignment) > 0 ? uboAlignment : 0)64%256是192,大于0,所以结果是uboAlignment

    所以它是有效的,但只是偶然的。他可能只是直接使用了minUniformBufferOffsetAlignment

  3. 首先,内存映射是一个非常重要的操作。你不应该仅仅为了设置矩阵而映射内存,然后立即取消映射。如果你打算通过映射修改内存,你应该保持它的映射,直到你准备删除它。这不会抑制性能,阻止你按照允许的使用方法使用内存,或其他任何事情。

    其次,正如规范中明确概述的那样,如果您创建了一个可以用作统一缓冲区的VkBuffer,那么您指定的偏移量必须符合minUniformBufferOffsetAlignment。类似地,当使用这样的缓冲区作为UBO资源时,您提供的偏移量也必须minUniformBufferOffsetAlignment对齐,无论偏移量是动态的还是静态的。

1.:缓冲区大小需要是它的倍数。你需要意识到你实际上在缓冲区的哪个部分存储了一些东西,而你没有在哪里存储。如果你的数据不完全适合你的缓冲区,它需要以倍数放大。

2.:你的计算失败了。整数运算。结果只有256。

3.:无需复制缓冲区中实际上不包含数据的部分。允许部分复制,只是缓冲区本身更大。

最新更新