创建深度缓冲区
本节的代码是 06-init_depth_buffer.cpp
深度缓冲区是可选的,但在示例最后渲染3D方块时,你需要一个深度缓冲区。而且在渲染每帧时,你只需要一个,即使交换链里有不止一个图像。因为深度缓冲区在交换链的图像中是可重用的。
与vkCreateSwapchainKHR()
不同的是,交换链中的每一个图像都是为你创建的,你需要创建和分配您自己的图像来表示深度缓冲。
步骤是:
- 创建深度缓冲区图像对象
- 分配深度缓冲设备内存
- 绑定内存到图像对象
- 创建深度缓冲图像视图
你得到的结果是这样的:
创建深度缓冲图像对象
为了创建深度缓冲的图像对象,我们需要填充熟悉的create info结构:
image_info.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO;
image_info.pNext = NULL;
image_info.imageType = VK_IMAGE_TYPE_2D;
image_info.format = VK_FORMAT_D16_UNORM;
image_info.extent.width = info.width;
image_info.extent.height = info.height;
image_info.extent.depth = 1;
image_info.mipLevels = 1;
image_info.arrayLayers = 1;
image_info.samples = NUM_SAMPLES;
image_info.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
image_info.usage = VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT;
image_info.queueFamilyIndexCount = 0;
image_info.pQueueFamilyIndices = NULL;
image_info.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
image_info.flags = 0;
vkCreateImage(info.device, &image_info, NULL, &info.depth.image);
这只是为图像创建一个对象。目前还没有为深度缓冲图像内存本身分配内存,但是请注意,您已经填入了信息,以表明您想要一个与窗口大小匹配的深度缓冲。
为深度缓冲分配内存
在这一点上,即使您知道缓冲区元素的宽度、高度和大小,您仍然不能确定要分配多少内存。这是因为GPU硬件可能会有对齐的限制。这些限制在不同的设备之间有所不同。
Vulkan提供了一个函数,用于找出为图像分配内存所需的一切:
vkGetImageMemoryRequirements(info.device, info.depth.image, &mem_reqs);
然后,您可以使用这个内存需求信息来填充一个内存分配的请求结构。这个需求信息的一个关键部分是内存大小,您可以使用它来填充分配请求结构,如下所示。
VkMemoryAllocateInfo mem_alloc = {};
mem_alloc.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO;
mem_alloc.pNext = NULL;
mem_alloc.allocationSize = mem_reqs.size;
mem_alloc.memoryTypeIndex = memory_type_from_properties();
虽然通过将宽度乘以大小(深度texel)来猜测分配的大小是很有诱惑力的,但是有可能存在需要额外填充的对齐约束。因此,最好不要试着猜测所需的数量,而是请求所需的大小。
memory_type_from_properties()
函数是一个样本实用函数,它决定要使用的适当的内存类型索引。一旦你在这里分配设备内存,可以直接从GPU访问的内存,当然还有其他的考虑,比如对齐和缓存行为。Vulkan规范中的设备内存部分是对许多细节的一个很好的参考。
最后,你可以分配内存:
vkAllocateMemory(info.device, &mem_alloc, NULL, &info.depth.mem);
将内存绑定到深度缓冲
现在你有了一个用于深度缓冲的图像对象和为深度缓冲分配的一些设备内存。
接下来,将内存与对象关联起来:
vkBindImageMemory(info.device, info.depth.image, info.depth.mem, 0);
创建图像视图
与交换链图像一样,你需要创建一个图像视图来指示您将如何使用深度缓冲的一些细节。例如,你在下面创建的图像视图表明图像将被用作深度缓冲,并且具有16位格式。
VkImageViewCreateInfo view_info = {};
view_info.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO;
view_info.pNext = NULL;
view_info.image = info.depth.image;
view_info.format = VK_FORMAT_D16_UNORM;
view_info.components.r = VK_COMPONENT_SWIZZLE_R;
view_info.components.g = VK_COMPONENT_SWIZZLE_G;
view_info.components.b = VK_COMPONENT_SWIZZLE_B;
view_info.components.a = VK_COMPONENT_SWIZZLE_A;
view_info.subresourceRange.aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT;
view_info.subresourceRange.baseMipLevel = 0;
view_info.subresourceRange.levelCount = 1;
view_info.subresourceRange.baseArrayLayer = 0;
view_info.subresourceRange.layerCount = 1;
view_info.viewType = VK_IMAGE_VIEW_TYPE_2D;
view_info.flags = 0;
res = vkCreateImageView(info.device, &view_info, NULL, &info.depth.view);
© Copyright 2016 LunarG, Inc