7.3 Framebuffer
帧缓冲区是一个用来表示一些存储渲染结果的图像的对象。这影响管线最后几个阶段:深度和stencil测试,混合,logic 操作,多采样等等。一个帧缓冲区对象通过使用renderpass的引用来创建,可以和多个有类似附件排放的renderpass一同使用。调用vkCreateFramebuffer()可创建一个帧缓冲区对象,其原型如下:
VkResultvkCreateFramebuffer (
VkDevice device,
const VkFramebufferCreateInfo* pCreateInfo,
const VkAllocationCallbacks* pAllocator,
VkFramebuffer* pFramebuffer);
将用来创建帧缓冲区的设备通过device传递,剩下的参数描述了新创建的哦帧缓冲区对象,通过一个VkFramebufferCreateInfo类型的数据pCreateInfo来传递。VkFramebufferCreateInfo的定义:
typedefstruct VkFramebufferCreateInfo {
VkStructureType sType;
const void* pNext;
VkFramebufferCreateFlags flags;
VkRenderPass renderPass;
uint32_t attachmentCount;
const VkImageView* pAttachments;
uint32_t width;
uint32_t height;
uint32_t layers;
}VkFramebufferCreateInfo;
VkFramebufferCreateInfo的sType域应被置为VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO, pNext应置为nullptr。flags被保留使用,应置为0。
和被创建的帧缓冲区兼容renderpass对象的handle通过renderPass传递。为了和帧缓冲区对象保持兼容,若两个renderpass的附件相同,它们也应保持兼容。
和帧缓冲区对象绑定的一系列图像通过一个VkImageView类型数组的指针pAttachments传递。pAttachments数组的长度通过attachmentCount指定。组成renderpass的pass引用图像附件,这些引用通过pAttachments数组的索引来指定。如果你知道特定的renderpass不使用某一些附件,但是你想要帧缓冲区和多个renderpass对象保持兼容或者和应用程序中的图像的布局保持一致,pAttachments中的一些图像handle可以是VkNullHandle。
尽管帧缓冲区中每一张图像都有原生的宽度、高度,和(array 图像意义上)层数,你必须指定帧缓冲区的位数。这些维数通过VkFramebufferCreateInfo 类型数据的width, height,and layers域传递。渲染到一些图像外部的帧缓冲区的区域导致没有在继续时向附加图像的位于图像外部的那些部分呈现渲染到图像的那些部分。
支持的帧缓冲区最大数量依赖于设备。可查询VkPhysicalDeviceLimits类型数据的maxFramebufferWidth, maxFramebufferHeight, 和maxFramebufferLayers域来获知帧缓冲区的最大个数。这些参数提供了支持的最大宽度、高度和层数。Vulkan标准保证最小支持宽度和高度是4096像素,层数至少为256.然而,绝大多数桌面级硬件支持16,384像素的宽度和高度,2048层。
也可以创建不带附件的帧缓冲区。它也被称作attachmentless framebuffer。在这种情况下,帧缓冲区的维数只通过width,height, 和 layers域指定。这种类型的帧缓冲区通常和片元着色器一起使用产生其他的效果,比如存储图像或者遮挡查询,这些可以为其他方面的渲染做度量而无需把渲染结果存储在其他地方。
如果vkCreateFramebuffer()调用成功,它将把新的VkFramebuffer handle写入pFramebuffer所指向的变量。如果它要求使用主机内存,就将会用到pAllocator所指向的分配器。如果pAllocator不为nullptr,那么在销毁帧缓冲区时就需要一个兼容的分配器。
如你将在第八章“绘制”所见,我们将和renderpass结合起来使用帧缓冲区来绘制到帧缓冲区绑定的图像。当你使用完了帧缓冲区,你应该调用vkDestroyFramebuffer()来销毁它,其原型如下:
voidvkDestroyFramebuffer (
VkDevice device,
VkFramebuffer framebuffer,
const VkAllocationCallbacks* pAllocator);
device是创建帧缓冲区的设备的handle,framebuffer是需被销毁的帧缓冲区对象昂的handle。如果在创建帧缓冲区时使用了内存分配器,那么一个匹配的内存分配器通过pAllocator传递。
销毁帧缓冲区对象并不影响附着到它上面的图像。图像可以同时附着到多个帧缓冲区上,可同时以多种范式被使用。然而,即使图形没有被销毁,也不应该使用帧缓冲区,包括在设备的命令缓冲区中访问它。你应该保证任何使用这个帧缓冲区的已提交或在帧缓冲区销毁后未提交的命令缓冲区都已经完成了执行。