【Vulkan入门】08-CreateRenderPass
目录
- 先叨叨
- git信息
- 关键代码
- TestPipeLine::CreateRenderPass()
先叨叨
上篇已经为Pipeline编写好了程序(Shader)。接下来要为Pipeline创建RenderPass。
关于RenderPass,在【Vulkan入门】06-Pipeline介绍中已经作了简单的介绍。这里再详细说一下。
RenderPass实则描述了Pipeline在渲染时所需要的内存空间(Memory)。 RenderPass中描述了很多内存空间,有的空间用于存储深度信息,有的用于存储颜色信息, 有的存储模板信息等。每次描画我们都需要告诉Vulkan当前的Pipeline要使用哪个RenderPass。
一个RenderPass可以供给多个Pipeline使用,而一个Pipeline只能使用一个RenderPass。目前例子中只有一个Pipeline和一个RenderPass。
这里需要注意一点,RenderPass只是描述了内存的内容、用途和属性,并没有管理内存空间。内存空间需要由FrameBuffer对象来管理。下一篇会介绍如何创建FrameBuffer
git信息
- repository: https://gitee.com/J8_series/easy-car-ui
- tag: 08-CreateRenderPass
- url: https://gitee.com/J8_series/easy-car-ui/tree/08-CreateRenderPass
关键代码
TestPipeLine::CreateRenderPass()
-
内存空间对于RenderPass来说叫作Attachment。目前例子只使用一块内存保存图像的颜色,因此只声明一个colorAttachment对象。
- format是VK_FORMAT_R8G8B8A8_UINT,代表存储RGB颜色。
- samples是VK_SAMPLE_COUNT_1_BIT代表采样数为1
- loadOp是VK_ATTACHMENT_LOAD_OP_CLEAR,代表使用前需要清空内存空间。
- storeOp是VK_ATTACHMENT_STORE_OP_STORE,代表该内存空间的内容是由Pipeline写入的。因为我们想让Pipeline将颜色值写到这块内存中。
- stencilLoadOp和stencilStoreOp 根模板和深度缓存操作有关。目前并不关心所以赋值_DONT_CARE。
- initialLayout是VK_IMAGE_LAYOUT_UNDEFINED,代表我们没有定义它初始化时的数据来源。
- finalLayout是VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,代表我们想让Vulkan在渲染后把它设置成便于传输的状态。因为我想在渲染后把这块内存的内容读出来,然后渲染到屏幕上。
-
每个RenderPass中可以包含多个SubPass, 每个SubPass会引用多个Attachment。之前说每次描画我们都要告诉Vulkan,Pipeline需要使用哪个RenderPass。更准确的说法是,要告诉Vulkan,Pipeline需要使用哪个RenderPass的哪个SubPass。
-
多个SubPass之间可以存在依赖关系。比如第一个SubPass可以作为第二个SubPass的输入。
目前例子中只有一个SubPass引用了唯一的colorAttachment。
void TestPipeLine::CreateRenderPass()
{
//https://registry.khronos.org/vulkan/specs/latest/html/vkspec.html#VkAttachmentDescription
VkAttachmentDescription colorAttachment{};
colorAttachment.format = VK_FORMAT_R8G8B8A8_UINT;
colorAttachment.samples = VK_SAMPLE_COUNT_1_BIT;
colorAttachment.loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR;
colorAttachment.storeOp = VK_ATTACHMENT_STORE_OP_STORE;
colorAttachment.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
colorAttachment.stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
colorAttachment.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
colorAttachment.finalLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL;
//https://registry.khronos.org/vulkan/specs/latest/html/vkspec.html#VkAttachmentReference
VkAttachmentReference colorAttachmentRef{};
colorAttachmentRef.attachment = 0;
colorAttachmentRef.layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
//https://registry.khronos.org/vulkan/specs/latest/html/vkspec.html#VkSubpassDescription
VkSubpassDescription subpass{};
subpass.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS;
subpass.colorAttachmentCount = 1;
subpass.pColorAttachments = &colorAttachmentRef;
//https://registry.khronos.org/vulkan/specs/latest/html/vkspec.html#VkSubpassDependency
VkSubpassDependency dependency{};
dependency.srcSubpass = VK_SUBPASS_EXTERNAL;
dependency.dstSubpass = 0;
dependency.srcStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
dependency.srcAccessMask = 0;
dependency.dstStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
dependency.dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
//https://registry.khronos.org/vulkan/specs/latest/html/vkspec.html#VkRenderPassCreateInfo
VkRenderPassCreateInfo createInfo{};
createInfo.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO;
createInfo.attachmentCount = 1;
createInfo.pAttachments = &colorAttachment;
createInfo.subpassCount = 1;
createInfo.pSubpasses = &subpass;
createInfo.dependencyCount = 1;
createInfo.pDependencies = &dependency;
//https://registry.khronos.org/vulkan/specs/latest/html/vkspec.html#vkCreateRenderPass
if (VK_SUCCESS != vkCreateRenderPass(m_device, &createInfo, nullptr, &m_renderPass))
{
throw std::runtime_error("To create render pass is failed!");
}
}