《Vulkan Tutorial》 笔记 14:Render Passes
本部分结果可参考 14_Render_Passes
本章涉及到的关键对象和流程如下所示
在设置完 Fixed functions 后,在完成创建 Pipeline 时最后依赖的就是 Render Pass。开发者需要告诉 Vulkan 在渲染时需要使用的 Framebuffer Attachments,以及每个 Framebuffer 有多少个 Color / Depth Buffer,需要有多少次采样点(MSAA)等等信息,这些信息都会封装在 Render Pass 中。
为创建 Render Pass,在 GraphicsPipelineMgr 中增加函数 createRenderPass 和 destroyRenderPass,在 HelloTriangleApplication 的 initVulkan 和 cleanup 中分别调用这两个函数:
1 |
|
#Attachment Description
在 createRenderPass 中首先需要创建 VkAttachmentDescription 对象,表示 Framebuffer 中的 Attachment。Framebuffer 中的 Attachment 可以是 Color Buffer / Depth Buffer / Stencil Buffer 等等。目前仅需创建一个 Color Attachment,用于输出到 Swap Chain:
1 | void GraphicsPipelineMgr::createRenderPass() |
- Color Attachment 的格式与创建的 SwapChain 中的 Image 格式相同
- 目前因为未开启 MSAA,因此
samples的类型为VK_SAMPLE_COUNT_1_BIT。 loadOp设定在渲染前,该如何对待 Framebuffer 中已有的数据:VK_ATTACHMENT_LOAD_OP_CLEAR:清空已有的数据VK_ATTACHMENT_LOAD_OP_DONT_CARE:对如何处理已有数据的行为是未定义的,因为并不关心这些数据VK_ATTACHMENT_LOAD_OP_LOAD:保留并加载已有的数据(如需要保留上一次渲染结果时使用)
storeOp设定渲染后,该如何对待渲染的结果数据,可能的选项为:VK_ATTACHMENT_STORE_OP_STORE:渲染的结果数据会存储在内存中,并在后续读取VK_ATTACHMENT_STORE_OP_DONT_CARE:对如何处理渲染结果数据的行为是未定义的
- 因为
loadOp及storeOp只设定 Color 和 Depth 的数据,因此还需要stencilLoadOp和stencilStoreOp设定 Stencil 数据。 initialLayout和finalLayout用于设定 Image 的 Layout- Vulkan 中都通过
VkImage表示 Textures 和 Framebuffers,可以根据使用 VkImage 的目的来修改内存中像素的 Layout,比较常用的可选参数为:VK_IMAGE_LAYOUT_UNDEFINED:Image 的初始内容不重要,可能会被丢弃VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL:Image 会用于 Color AttachmentVK_IMAGE_LAYOUT_PRESENT_SRC_KHR:Image 会用于作为 Swap Chain 的 Presentation SourceVK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL:Image 会作为内存拷贝的目的地
initialLayout表示渲染前 Image 的 Layout,因为这里将loadOp设定为VK_ATTACHMENT_LOAD_OP_CLEAR,即每次渲染前都会清空 Image 数据,所以这里并不关心 Layout,设定为VK_IMAGE_LAYOUT_UNDEFINEDfinalLayout表示渲染后 Image 的 Layout,这里因为最终图像用于 Swap Chain 的 Present,所以选为VK_IMAGE_LAYOUT_PRESENT_SRC_KHR。
- Vulkan 中都通过
关于 Layout 的配置项,会在后续的 Texture 章节中进一步介绍。
#Subpasses and attachment references
一个 RenderPass 可以包含多个 Subpasses,Subpass 是一系列依赖于之前 pass 执行后 Framebuffer 内容的渲染操作。如有一系列的后处理,每一个后处理都依赖于前一个处理的结果。
当把一系列的 Subpasses 封装在一个 Renderpass 中后,Vulkan 可以重新排列这些 Subpasses 或节省带宽以获得最好的性能。
对于每一个 Subpass,它都可以引用一个或多个 Attachment。通过结构体 VkAttachmentReference 表示 Attachment Reference,如下:
1 | void GraphicsPipelineMgr::createRenderPass() |
其中:
attachment表示定义的一系列 Attachments 中需要引用的 Attachment 的 Index 值,因为之前只定义了一个VkAttachmentDescription,因此这里引用第一个,设为 0。layout设定 Attachment 在被 Subpass 使用时希望的 Layout。Vulkan 会在 Subpass 启动时自动的将 Attachment 转换到设定的 Layout。这里希望在 Subpass
运行时将 Attachment 作为 Color Buffer,因此设定为VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL。
创建完 Attachment Reference 后,即可创建 Subpass:
1 | void GraphicsPipelineMgr::createRenderPass() |
其中:
pipelineBindPoint表示 Subpass 在管线中的绑定点,这里是用于渲染的,所以作为 GRAPHICS,在 Vulkan 的规划中还会支持 Compute Subpass。pColorAttachments表示 Subpass 引用的 Color Attachment,除了 Color Attachment,还可以依赖:pInputAttachments:从 Shader 中读取的 AttachmentpResolveAttachments:用于 MSAA 的 Color AttachmentpDepthStencilAttachment:表示 Depth 和 Stencil 的 AttachmentpPreserveAttachments:这些 attachment 在本 subpass 不被访问,但其内容需要在后续 subpass 保持不变
#Render Pass
最后装填结构体 VkRenderPassCreateInfo 创建 RenderPass:
1 | void GraphicsPipelineMgr::createRenderPass() |
destroyRenderPass 函数中即调用 vkDestroyRenderPass 销毁 Render Pass。
1 | void GraphicsPipelineMgr::destroyRenderPass() |

