【发布时间】:2020-12-12 21:56:02
【问题描述】:
在我的 Vulkan 应用程序中,我想要一个内存缓冲区来存储多个不同大小的纹理。然后,我想要一个VkImageView 对应于缓冲区中的每个纹理。我不确定如何创建这样的缓冲区,这就是我想出的:
// Create images
VkImage images[TEXTURE_COUNT];
for (int i = 0; i < TEXTURE_COUNT, i++) {
VkImageCreateInfo imageCreateInfo{};
// Specific to texture i
imageCreateInfo.extent.width = ...
iamgeCreateInfo.extent.height = ...
// Other imageCreateInfo properties are constant across all textures
...
VkCreateImage(device, &imageCreateInfo, nullptr, &images[i]);
}
// Find total size of memory buffer & image offsets
int totalSize = 0;
int offsets[TEXTURE_COUNT];
for (int i = 0; i < TEXTURE_COUNT; i++) {
VkMemoryRequirements memoryRequirements;
vkGetImageMemoryRequirements(device, images[i], &memoryRequirements);
offsets[i] = totalSize;
totalSize += memoryRequirements.size;
}
// Get memory type index of memory buffer
VkMemoryRequirements firstImageMemoryRequirements;
vkGetImageMemoryRequirements(device, images[0], &firstImageMemoryRequirements);
int memoryTypeIndex = ... // Get memory type index using firstImageMemoryRequirements.memoryTypeBits
// Allocate memory
VkMemoryAllocateInfo memoryAllocateInfo{};
memoryAllocateInfo.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO;
memoryAllocateInfo.allocationSize = totalSize;
memoryAllocateInfo.memoryTypeIndex = memoryTypeIndex;
VkMemory memory;
vkAllocateMemory(device, &memoryAllocateInfo, nullptr, &memory)
// Bind images to memory at corresponding offset
VkBindImageMemoryInfo bindImageMemoryInfos[TEXTURE_COUNT];
for (int i = 0; i < TEXTURE_COUNT, i++) {
VkBindImageMemoryInfo bindImageMemoryInfo{};
bindImageMemoryInfo.sType = VK_STRUCTURE_TYPE_BIND_IMAGE_MEMORY_INFO;
bindImageMemoryInfo.image = images[i];
bindImageMemoryInfo.memory = memory;
bindImageMemoryInfo.memoryOffset = offsets[i];
bindImageMemoryInfos[i] = bindImageMemoryInfo;
}
vkBindImageMemory2(device, TEXTURE_COUNT, &bindImageMemoryInfos);
// Create image views
VkImageView imageViews[TEXTURE_COUNT];
for (int i = 0; i < TEXTURE_COUNT; i++) {
VkImageViewCreateInfo imageViewCreateInfo{};
imageViewCreateInfo.image = images[i];
...
VkCreateImageView(device, &imageViewCreateInfo, nullptr, &imageViews[i]);
}
// Now I have a bunch of image views tied to each texture,
// where each texture is stored in one memory buffer at a certain offset.
这看起来是否合理,或者这不是正确的方法?对我来说似乎有点奇怪的一件事是当我获取内存缓冲区的内存类型索引时。为了得到这个,你需要一张我有TEXTURE_COUNT的图像,所以我只选择第一张图像。每个纹理的唯一图像属性是范围宽度和高度,所以我希望这不会影响每个图像的内存类型位。我假设每个图像都将具有相同的内存类型位,因此我可以使用第一个图像的内存类型位来获取内存类型索引。对这个假设的想法也很好。
【问题讨论】:
-
1.我建议至少检查每个图像是否具有相同的内存类型,只是为了捕捉愚蠢的错误,例如意外在数组中包含不同类型的图像。 2.肯定应该累积偏移数组吗?即
offsets[i] = memoryRequirements.size;行对于第一个元素应该为零,对于第二个元素,该图像的大小,等等? -
@stridecolossus 对,我的偏移量错了。我已将其更改为
offsets[i] = totalSize;,您对检查内存类型以捕获错误提出了很好的意见。 -
仅供参考:将内存分配称为“缓冲区”并不是一个好主意,因为“缓冲区”一词在 Vulkan 中已经具有非常具体(并且不同)的含义.