[Vulkan教程]绘制一个三角形/图形管线基础/渲染通道(Render passes)

设置

在我们创建管线前,我们需要告诉Vulkan我们在渲染时需要得帧缓冲附件。我们需要指定有多少颜色和深度缓冲区,每个缓冲区使用多少个采样,它们的内容在渲染时该被如何处理。这些内容被封装到一个渲染通道对象。我们创建一个函数createRenderPass来创建它。然后在createGraphicsPipeline后面调用:

void initVulkan() {
    createInstance();
    setupDebugMessenger();
    createSurface();
    pickPhysicalDevice();
    createLogicalDevice();
    createSwapChain();
    createImageViews();
    createRenderPass();
    createGraphicsPipeline();
}

...

void createRenderPass() {

}

附件说明(Attachment description)

我们这里只使用一个颜色缓冲区附件,它用交换链中的一个图像表示。

void createRenderPass() {
    VkAttachmentDescription colorAttachment{};
    colorAttachment.format = swapChainImageFormat;
    colorAttachment.samples = VK_SAMPLE_COUNT_1_BIT;
}

颜色附件的格式format应和交换链图像的格式匹配,我们现在还不是用多重采样,这里设置采样值为1。

colorAttachment.loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR;
colorAttachment.storeOp = VK_ATTACHMENT_STORE_OP_STORE;

loadOpstoreOp决定附件中的数据在渲染之前和渲染之后如何处理。loadOp可选:

  • VK_ATTACHMENT_LOAD_OP_LOAD:保持先用内容
  • VK_ATTACHMENT_LOAD_OP_CLEAR:用一个常量填充
  • VK_ATTACHMENT_LOAD_OP_DONT_CARE:内容未定义,我们不关系它们

我们这里选择在渲染一帧前清除帧缓冲。storeOp两选:

  • VK_ATTACHMENT_STORE_OP_STORE:渲染的内容将保存到内存中并且可在之后读
  • VK_ATTACHMENT_STORE_OP_DONT_CARE:渲染之后,帧缓冲的内容将是未定义状态

为了在屏幕上呈现三角形,我们这里选择保存操作。

colorAttachment.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
colorAttachment.stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;

loadOpstoreOp应用于颜色和深度数据,而stencilLoadOpstencilStoreOp应用于模板数据。我们这边不会用到模板,所以加载和存储的结果无关紧要。

colorAttachment.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
colorAttachment.finalLayout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR;

纹理和帧缓冲在Vulkan中由VkImage表示。图像对象需要一个确定的像素格式,但像素的布局取决于你怎么用。

常见的布局有:

  • VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL:作为颜色缓冲的图像
  • VK_IMAGE_LAYOUT_PRESENT_SRC_KHR:将在交换链中呈现的图像
  • VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL:将作为内存复制操作的目标图像

之后在纹理章节,我们还会更深入的讨论这个内容,我们这里要知道图像不同的操作需要不同的布局。

initialLayout指定渲染开始时图像的布局,finalLayout指定渲染完成时自动变换到的图像布局。将initialLayout设置为VK_IMAGE_LAYOUT_UNDEFINED意思是我们不关心以前的布局。使用它的图像的内容不能保证被保留,但这不重要,我们总归要在开始绘制时清理图像。我们希望图像在渲染后使用交换链进行展示,这就是我们将finalLayout设为VK_IMAGE_LAYOUT_PRESENT_SRC_KHR的原因。

子通道和附件引用(Subpasses and attachment references)

一个渲染通道可以包含多个子通道。子通道是渲染操作的后续渲染操作,依赖前一个通道中帧缓冲区的内容,例如一个接一个的后处理效果序列。如果我将这些渲染操作合并到一个渲染通道中,Vulkan可以重排这些操作节省内存带宽并获得更好的性能。对于我们第一个三角形,我们使用一个子通道就行了。

每个子通道都引用了一个或多个附件。VkAttachmentReference结构体:

VkAttachmentReference colorAttachmentRef{};
colorAttachmentRef.attachment = 0;
colorAttachmentRef.layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;

attachment参数通过附件描述数组的下标指定要引用的附件。我们的数组只会包含一个VkAtachmentDescription,所以这里下标用0layout指定了我们希望附件在子通道中的布局。子通道启用时,Vulkan会自动将附件转换到这个布局。我们会将附件用作颜色缓冲区,VK_IMAGE_LAYOUT_COLOR_ATACHMENT_OPTIMAL布局会提供最佳性能。

子通道通过VkSubpassDescription描述:

VkSubpassDescription subpass{};
subpass.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS;

Vulkan将来可能支持计算子通道,所以我们需要明确说明这是一个图形子通道,然后,设置对颜色附件的引用:

subpass.colorAttachmentCount = 1;
subpass.pColorAttachments = &colorAttachmentRef;

附件的序号被片元着色器通过layout(location=0)out vec4 outColor直接引用。
其他类型的附件同样可以被子通道引用:

  • pInputAttachments:被着色器读的附件
  • pResolveAtachments:用于多重采样颜色附件的附件
  • pDepthStencilAtachment:用于深度和模板数据的附件
  • pPreserveAtachments:不被附件使用但需要被保留的数据

渲染通道

现在,一个基本的子通道和其附件已经声明好了,我们可以创建渲染通道了。在pipelineLayout上面创建一个新的类成员来保存VkRenderPass对象:

VkRenderPass renderPass;
VkPipelineLayout pipelineLayout;

然后可以使用附件和子通道数组填充VkRenderPassCreateInfo结构体。VkAttachmentReference对象通过数组索引引用附件。

VkRenderPassCreateInfo renderPassInfo{};
renderPassInfo.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO;
renderPassInfo.attachmentCount = 1;
renderPassInfo.pAttachments = &colorAttachment;
renderPassInfo.subpassCount = 1;
renderPassInfo.pSubpasses = &subpass;

if (vkCreateRenderPass(device, &renderPassInfo, nullptr, &renderPass) != VK_SUCCESS) {
    throw std::runtime_error("failed to create render pass!");
}

同管线布局,渲染管线会在程序生命周期内使用,所以在最后销毁它:

void cleanup() {
    vkDestroyPipelineLayout(device, pipelineLayout, nullptr);
    vkDestroyRenderPass(device, renderPass, nullptr);
    ...
}

我们已经做了很多工作了,在下一章中,我们就将它们都汇集到一起,最终创建图形管线对象。

目录
上一节 绘制一个三角形/图形管线基础/固定功能(Fixed functions)
下一节 绘制一个三角形/图形管线基础/汇总(Conclusion)

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值