Vulkan教程翻译之七 创建 Depth Buffer

原文链接:https://vulkan.lunarg.com/doc/sdk/1.2.131.2/windows/tutorial/html/06-init_depth_buffer.html

创建 Depth Buffer

这一章节的代码文件是 06-init_depth_buffer.cpp

Depth buffer 是可选的,但是在最终的示例里,你需要 depth buffer 来渲染3D立方体。而且你只需要一个就能渲染每一帧,即使 swapchain 有多个 image。这是因为你在使用 swapchain 里的每个 image 时,可以重复使用相同的 depth buffer。

不像 vkCreateSwapchainKHR() 那样,swapchain 里的每个 image 都为你创建好了,你需要创建并分配你自己的 image 来表示 depth buffer。

步骤是:

  1. 创建 depth buffer image 对象
  2. 分配 depth buffer 设备内存
  3. 绑定内存到 image 对象上
  4. 创建 depth buffer 的 image view

最终你得到的看起来像这样:

Vulkan教程翻译之七 创建 Depth Buffer_第1张图片

创建 Depth Buffer Image 对象

为了创建 image 对象给 depth buffer,我们会填充这个熟悉的创建信息的结构体:

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);

这只是给 image 创建了一个对象。还没有为 depth buffer image 分配内存,但是请注意,你已经填了信息表明你想要一个匹配窗口尺寸的 depth buffer。

为 Depth Buffer 分配内存

此时,即使你知道宽,高,和缓冲区单元的大小,仍然不能确切地知道该分配多少内存。这是有原因的,比如,GPU硬件可能会有对齐约束。这些约束在每个设备是不同的。

Vulkan 提供了一个函数,你可以用它填充为分配 image 内存需要的所有东西:

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();

虽然可以尝试通过宽x高x(depth texel 大小)来猜测分配空间的尺寸,但是可能对齐约束需要附加的空间。所以最好不要猜测所需要的数量,而是按需要的大小申请。

memory_type_from_properties() 函数是一个示例里的实用函数,确定要使用的适当的内存类型索引。因为在这里你正在分配的是设备内存,内存是可以直接从GPU访问的,所以还要额外考虑到,比如对齐和缓存行为。Vulkan 规范里的 "Device Memory" 一节对更多的细节可以作很好的参考。

最终,你可以分配内存了:

vkAllocateMemory(info.device, &mem_alloc, NULL, &info.depth.mem);

绑定内存到 Depth Buffer

现在你有了一个 depth buffer 的 image 对象,和分配给 depth buffer 的一些设备内存。

接下来,通过绑定它们使内存和对象关联起来:

vkBindImageMemory(info.device, info.depth.image, info.depth.mem, 0);

创建 Image View

像 swapchain image 一样,你需要创建一个 image view 来说明关于如何使用 depth buffer 的一些细节。例如,如下你创建的 image view 表明了该 image 会被用来作为一个 depth buffer,并且是 16-bit 格式。

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);

 

你可能感兴趣的:(Vulkan教程翻译,vulkan)