Input Attachments
prepare
- loadAssets: 加载模型
- prepareUniformBuffers
- updateUniformBuffers
- setupRenderPass: 重写了父类的方法, 创建 Attachment
-
创建的数量是: swapChain.imageCount
-
每个 Attachment 都需要创建 color 和 depth 附件
- VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT
- VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT
-
初始化每个 Attachment 的参数
-
创建subpass: std::array<VkSubpassDescription,2> subpassDescriptions
- VkAttachmentReference
- 创建一个给 Attachment 填充颜色和深度的subpass
- 创建一个swap chain 填充颜色的 subpass
- 再创建两个引用 VkAttachmentReference inputReferences
- 将 fragment shader 中的输出写入Attachment : InputAttachments
- swap chain 的subpass 中引入 InputAttachments, 填充颜色
-
创建 VkSubpassDependency
dependencies[0].srcSubpass = VK_SUBPASS_EXTERNAL; dependencies[0].dstSubpass = 0; //源为管线 dependencies[0].srcStageMask = VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT; //输出到 color attachment 中 dependencies[0].dstStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT; //读取方式 dependencies[0].srcAccessMask = VK_ACCESS_MEMORY_READ_BIT; dependencies[0].dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT; dependencies[0].dependencyFlags = VK_DEPENDENCY_BY_REGION_BIT; // This dependency transitions the input attachment from color attachment to shader read dependencies[1].srcSubpass = 0; dependencies[1].dstSubpass = 1; //源为 color attachment dependencies[1].srcStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT; //输出到 fragment shader 中 dependencies[1].dstStageMask = VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT; dependencies[1].srcAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT; //读取方式 dependencies[1].dstAccessMask = VK_ACCESS_SHADER_READ_BIT; dependencies[1].dependencyFlags = VK_DEPENDENCY_BY_REGION_BIT; dependencies[2].srcSubpass = 0; dependencies[2].dstSubpass = VK_SUBPASS_EXTERNAL; //源为 color attachment dependencies[2].srcStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT; // 输出到管线中 dependencies[2].dstStageMask = VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT; dependencies[2].srcAccessMask = VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT; dependencies[2].dstAccessMask = VK_ACCESS_MEMORY_READ_BIT; dependencies[2].dependencyFlags = VK_DEPENDENCY_BY_REGION_BIT;
-
vkCreateRenderPass
-
- setupDescriptors
- 创建3个pool
- VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER
- VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER
- VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT
- Attachment write
- vkCreateDescriptorSetLayout
- vkCreatePipelineLayout
- vkAllocateDescriptorSets
- vkUpdateDescriptorSets
- Attachment read
- descriptorSetLayoutBinding: 三个
- VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT: 颜色
- VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT: 深度
- VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER
- vkCreateDescriptorSetLayout
- vkCreatePipelineLayout
- vkAllocateDescriptorSets
- vkUpdateDescriptorSets
- descriptorSetLayoutBinding: 三个
- 创建3个pool
- preparePipelines: attachment 需创建两个pipeline, 一个写 Attachment, 一个读 attachment
- VkGraphicsPipelineCreateInfo: 多出了为Attachment配置的代码
- pipelineCI.renderPass = renderPass;
- Attachment write
- pipelineCI.subpass = 0;
- pipelineCI.layout = pipelineLayouts.attachmentWrite;
- vkCreateGraphicsPipelines
- Attachment read
- pipelineCI.subpass = 1
- pipelineCI.layout = pipelineLayouts.attachmentRead;
- vkCreateGraphicsPipelines
- VkGraphicsPipelineCreateInfo: 多出了为Attachment配置的代码
- buildCommandBuffers: 分别为两个 subpass 创建 CommandBuffer
/* First sub pass Fills the attachments */ { vks::debugmarker::beginRegion(drawCmdBuffers[i], "Subpass 0: Writing attachments", glm::vec4(1.0f, 1.0f, 1.0f, 1.0f)); vkCmdBindPipeline(drawCmdBuffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, pipelines.attachmentWrite); vkCmdBindDescriptorSets(drawCmdBuffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, pipelineLayouts.attachmentWrite, 0, 1, &descriptorSets.attachmentWrite, 0, NULL); scene.draw(drawCmdBuffers[i]); vks::debugmarker::endRegion(drawCmdBuffers[i]); } /* Second sub pass Render a full screen quad, reading from the previously written attachments via input attachments */ { vks::debugmarker::beginRegion(drawCmdBuffers[i], "Subpass 1: Reading attachments", glm::vec4(1.0f, 1.0f, 1.0f, 1.0f)); vkCmdNextSubpass(drawCmdBuffers[i], VK_SUBPASS_CONTENTS_INLINE); vkCmdBindPipeline(drawCmdBuffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, pipelines.attachmentRead); vkCmdBindDescriptorSets(drawCmdBuffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, pipelineLayouts.attachmentRead, 0, 1, &descriptorSets.attachmentRead[i], 0, NULL); vkCmdDraw(drawCmdBuffers[i], 3, 1, 0, 0); vks::debugmarker::endRegion(drawCmdBuffers[i]); }
render
- draw
- updateUniformBuffers
小结
本节主要讲怎样使用 Attachments 进行渲染. 但是我觉得这里的重点是怎样使用subpass进行渲染.
Sub Passes
prepare
- loadAssets: 加载模型和纹理
- initLights: 设置光源
- prepareUniformBuffers
- updateUniformBufferDeferredMatrices
- updateUniformBufferDeferredLights
- setupFrameBuffer: 重写父类方法
- 当屏幕大小发生遍布重写设置Gbuffer: createGBufferAttachments
- writeDescriptorSets
- vkUpdateDescriptorSets
- 正向渲染
- writeDescriptorSets
- vkUpdateDescriptorSets
- vkCreateFramebuffer
- setupRenderPass: 重写父类方法
- createGBufferAttachments: 创建Gbuffer
- createAttachment – position
- createAttachment – normal
- createAttachment – albedo
- VkAttachmentDescription: 有5个, 与上一节相似,主要设置,怎么写入gbuffer,怎么从gbuffer读数据
- vkCreateRenderPass
- createGBufferAttachments: 创建Gbuffer
- setupDescriptorSetLayout
- vkCreateDescriptorSetLayout
- vkCreatePipelineLayout
- preparePipelines: 中增加了 blendAttachmentStates
- colorBlendState.attachmentCount = static_cast<uint32_t>(blendAttachmentStates.size());
- colorBlendState.pAttachments = blendAttachmentStates.data();
- setupDescriptorPool
- 创建3个pool
- VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER
- VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER
- VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT
- 创建3个pool
- setupDescriptorSet
- vkAllocateDescriptorSets
- writeDescriptorSets
- prepareCompositionPass:
- Descriptor set layout
- descriptorSetLayoutBinding
- Position input attachment
- Normal input attachment
- Albedo input attachment
- Light positions
-vkCreateDescriptorSetLayout
- descriptorSetLayoutBinding
- Pipeline layout
- vkCreatePipelineLayout
- Descriptor sets
- vkAllocateDescriptorSets
- writeDescriptorSets
- writeDescriptorSet
- Position texture target
- Normals texture target
- Albedo texture target
- Fragment shader lights
-vkUpdateDescriptorSets
- writeDescriptorSet
- Pipeline
- pipelineCreateInfo
- vkCreateGraphicsPipelines
- Transparent (forward) pipeline
- vkCreateDescriptorSetLayout
- vkCreatePipelineLayout
- vkAllocateDescriptorSets
- vkUpdateDescriptorSets
- vkCreateGraphicsPipelines
- Descriptor set layout
- buildCommandBuffers: subpass有3个
- 第一个将场景数据写入Gbuffer
- 第二个用gbuffer数据渲染到attachment中
- 第三个正向渲染
render
- draw
- updateUniformBufferDeferredMatrices
- updateUniformBufferDeferredLights
小结
本节主要讲延迟渲染的方法. 总体来说就是更详细介绍了subpass的使用方法.
Offscreen Renderings
prepare
- loadAssets: 加载模型
- prepareOffscreen: 准备离屏渲染资源
- 准备的资源如下
struct OffscreenPass { int32_t width, height; VkFramebuffer frameBuffer; FrameBufferAttachment color, depth; VkRenderPass renderPass; VkSampler sampler; VkDescriptorImageInfo descriptor; } offscreenPass;
- vkCreateImage(color)
- vkGetImageMemoryRequirements
- vkAllocateMemory
- vkBindImageMemory
- vkCreateImageView
- vkCreateSampler
- vkCreateImage(depth)
- vkGetImageMemoryRequirements
- vkAllocateMemory
- vkBindImageMemory
- vkCreateImageView
- attchmentDescriptions: 分别为color和depth
- subpassDescription: 附加Attachment引用
- vkCreateRenderPass
- vkCreateFramebuffer: 将渲染后的资源写入 frame buffer
- prepareUniformBuffers
- updateUniformBuffers
- updateUniformBufferOffscreen: 离屏pass更新uniform
- setupDescriptorSetLayout
- vkCreateDescriptorSetLayout
- vkCreatePipelineLayout
- preparePipelines: 新建四个pipelines
- Render-target debug display
- Mirror
- Phong shading pipelines
- Offscreen
- setupDescriptorPool
- setupDescriptorSet: 为三个pipeline设置
- Mirror plane descriptor set (Mirror)
- Shaded descriptor sets (Phong shading pipelines)
- Offscreen
- buildCommandBuffers: subpass有2个
- First render pass: Offscreen rendering
- Scene rendering with applied radial blur
render
- draw
- updateUniformBuffers
- updateUniformBufferOffscreen
小结
离屏渲染也就是将渲染结果写入 attachment中 . 是 attachment 结合 subpass的一种实用方法.