当前位置: 首页 > article >正文

Vulkan 学习(11)---- Vulkan RenderPass 创建

目录

      • RenderPass 概述
      • RenderPass 创建
        • 附件描述
        • 子通道和子通道描述
        • 子通道依赖
        • 参考代码

RenderPass 概述

Vulkan 渲染通道(RenderPass) 定义了整个渲染管线一次执行的过程,包括了渲染所使用的所有资源和操作的描述(比如指定渲染管线的渲染目标,告诉管线要渲染到哪里)

RenderPass 本质上是一个渲染流程的完整描述(管理渲染流程),包括如何渲染这些数据的元数据和指令,但是不包括实际的数据(图像),通过与 FrameBuffer 结合来获取实际的图像数据

Vulkan编程,RenderPass是必不可少的,它必须包含一个或者多个子通道(SubPass)

每个子通道表示一个渲染阶段,并且都是使用 RenderPass 中定义的资源描述这个阶段的渲染的步骤

RenderPass 是通过附件(Attachment)的形式描述图像资源,包括颜色附件(Color Attachment)、深度/模板附件(Depth/Stencil Attachment)、用于多重采样的的解析附件(Resolve Attachment)和输入附件(Input Attachment)等,

RenderPassFrameBuffer 的关系密切,FrameBuffer 代表了 RenderPass 使用的具体内存集合,定义了 RenderPass 中每个 ImageView 与附件的对应关系

RenderPass 使得开发者能够更精细的控制渲染过程,优化性能,同时适应现代GPU架构的特点

RenderPass 创建

vkCreateRenderPass 的函数原型如下:

VKAPI_ATTR VkResult VKAPI_CALL vkCreateRenderPass(
    VkDevice                                    device,
    const VkRenderPassCreateInfo*               pCreateInfo,
    const VkAllocationCallbacks*                pAllocator,
    VkRenderPass*                               pRenderPass);

关键结构 VkRenderPassCreateInfo 的结构:

typedef struct VkRenderPassCreateInfo {
    VkStructureType                   sType;
    const void*                       pNext;
    VkRenderPassCreateFlags           flags;
    uint32_t                          attachmentCount; // 附件数量
    const VkAttachmentDescription*    pAttachments; // 附件描述
    uint32_t                          subpassCount; // 子通道数量
    const VkSubpassDescription*       pSubpasses; // 子通道描述
    uint32_t                          dependencyCount; // 子通道依赖数量
    const VkSubpassDependency*        pDependencies; // 子通道依赖描述
} VkRenderPassCreateInfo;`
附件描述

附件描述定义了在渲染过程中使用的图像资源,包括它们的格式,样本数、加载和存储操作等
比如定义一个深度附件和模板附件:

    // 定义颜色附件描述
    VkAttachmentDescription colorAttachment = {};
    colorAttachment.format = VK_FORMAT_R8G8B8A8_UNORM; // 交换链图像格式
    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_PRESENT_SRC_KHR; // 最终布局

    // 定义深度模板附件描述
    VkAttachmentDescription depthAttachment = {};
    depthAttachment.format = VK_FORMAT_R8G8B8A8_UNORM;
    depthAttachment.samples = VK_SAMPLE_COUNT_1_BIT; // 采样数
    depthAttachment.loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR; // 在渲染前清除附件
    depthAttachment.storeOp = VK_ATTACHMENT_STORE_OP_DONT_CARE; // 渲染后不需要存储附件内容
    depthAttachment.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE; // 不关心模板加载操作
    depthAttachment.stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE; // 不关心模板存储操作
    depthAttachment.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; // 初始布局
    depthAttachment.finalLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL; // 最终布局
子通道和子通道描述

VkSubpassDescription 是用于定义子通道的结构体,每个子通道表示一个渲染阶段:

typedef struct VkSubpassDescription {
    VkSubpassDescriptionFlags       flags;// 子通道描述的附加标志,目前必须为0
    VkPipelineBindPoint             pipelineBindPoint; // 管线绑定点,必须是 VK_PIPELINE_BIND_POINT_GRAPHICS
    uint32_t                        inputAttachmentCount;// 输入附件的数量
    const VkAttachmentReference*    pInputAttachments; // 输入附件数组 
    uint32_t                        colorAttachmentCount; // 颜色附件数量
    const VkAttachmentReference*    pColorAttachments; // 颜色附件数组
    const VkAttachmentReference*    pResolveAttachments; // 解析附件数组
    const VkAttachmentReference*    pDepthStencilAttachment; // 深度附件数组
    uint32_t                        preserveAttachmentCount;
    const uint32_t*                 pPreserveAttachments;
} VkSubpassDescription;

子通道描述了渲染管道一个阶段及其输入输出附件:

// 定义颜色附件引用
VkAttachmentReference colorAttachmentRef = {};
colorAttachmentRef.attachment = 0; // 绑定到第一个附件描述
colorAttachmentRef.layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; // 最佳颜色附件布局

// 定义深度模板附件引用
VkAttachmentReference depthAttachmentRef = {};
depthAttachmentRef.attachment = 1; // 绑定到第二个附件描述
depthAttachmentRef.layout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL; // 最佳深度模板附件布局

// 定义子通道描述
VkSubpassDescription subpass = {};
subpass.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS; // 图形管线绑定点
subpass.colorAttachmentCount = 1; // 颜色附件数量
subpass.pColorAttachments = &colorAttachmentRef; // 颜色附件引用
subpass.pDepthStencilAttachment = &depthAttachmentRef; // 深度模板附件引用
子通道依赖

TBD

参考代码
 // 定义颜色附件描述
 VkAttachmentDescription colorAttachment = {};
 colorAttachment.format = VK_FORMAT_R8G8B8A8_UNORM; // 交换链图像格式
 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_PRESENT_SRC_KHR; // 最终布局

 // 定义深度模板附件描述
 VkAttachmentDescription depthAttachment = {};
 //depthAttachment.format = findDepthFormat(physicalDevice); // 深度模板格式
 depthAttachment.format = VK_FORMAT_R8G8B8A8_UNORM;
 depthAttachment.samples = VK_SAMPLE_COUNT_1_BIT; // 采样数
 depthAttachment.loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR; // 在渲染前清除附件
 depthAttachment.storeOp = VK_ATTACHMENT_STORE_OP_DONT_CARE; // 渲染后不需要存储附件内容
 depthAttachment.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE; // 不关心模板加载操作
 depthAttachment.stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE; // 不关心模板存储操作
 depthAttachment.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; // 初始布局
 depthAttachment.finalLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL; // 最终布局

 // 定义颜色附件引用
 VkAttachmentReference colorAttachmentRef = {};
 colorAttachmentRef.attachment = 0; // 绑定到第一个附件描述
 colorAttachmentRef.layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; // 最佳颜色附件布局
 
 // 定义深度模板附件引用
 VkAttachmentReference depthAttachmentRef = {};
 depthAttachmentRef.attachment = 1; // 绑定到第二个附件描述
 depthAttachmentRef.layout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL; // 最佳深度模板附件布局

 // 定义子通道描述
 VkSubpassDescription subpass = {};
 subpass.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS; // 图形管线绑定点
 subpass.colorAttachmentCount = 1; // 颜色附件数量
 subpass.pColorAttachments = &colorAttachmentRef; // 颜色附件引用
 subpass.pDepthStencilAttachment = &depthAttachmentRef; // 深度模板附件引用

 // 定义子通道依赖
 // 子通道依赖数组,用于布局转换
 //std::array<VkSubpassDependency, 2> dependencies;
 VkSubpassDependency dependencies[2];
 // 第一个依赖关系
 dependencies[0].srcSubpass = VK_SUBPASS_EXTERNAL; // 外部到第一个子通道的依赖
 dependencies[0].dstSubpass = 0; // 目标子通道索引为0,即第一个子通道
 dependencies[0].srcStageMask = VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT | VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT; // 源阶段掩码:早期和晚期片段测试阶段
 dependencies[0].dstStageMask = VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT | VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT; // 目标阶段掩码:早期和晚期片段测试阶段
 dependencies[0].srcAccessMask = VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT; // 源访问掩码:深度模板附件写入
 dependencies[0].dstAccessMask = VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT | VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT; // 目标访问掩码:深度模板附件写入和读取
 dependencies[0].dependencyFlags = 0; // 无额外依赖标志

 // 第二个依赖关系
 dependencies[1].srcSubpass = VK_SUBPASS_EXTERNAL; // 外部到第一个子通道的依赖
 dependencies[1].dstSubpass = 0; // 目标子通道索引为0,即第一个子通道
 dependencies[1].srcStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT; // 源阶段掩码:颜色附件输出阶段
 dependencies[1].dstStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT; // 目标阶段掩码:颜色附件输出阶段
 dependencies[1].srcAccessMask = 0; // 源访问掩码:无特定访问类型
 dependencies[1].dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT | VK_ACCESS_COLOR_ATTACHMENT_READ_BIT; // 目标访问掩码:颜色附件写入和读取
 dependencies[1].dependencyFlags = 0; // 无额外依赖标志


 // 创建 RenderPass
 VkAttachmentDescription attachments[] = { colorAttachment, depthAttachment }; // 定义附件数组
 
 VkRenderPassCreateInfo renderPassInfo = {};
 renderPassInfo.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO;
 renderPassInfo.attachmentCount = 2; // 附件数量
 renderPassInfo.pAttachments = attachments; // 附件描述
 renderPassInfo.subpassCount = 1; // 子通道数量
 renderPassInfo.pSubpasses = &subpass; // 子通道描述
 renderPassInfo.dependencyCount = 2; // 子通道依赖数量
 renderPassInfo.pDependencies = dependencies; // 子通道依赖描述
 
 if (vkCreateRenderPass(device, &renderPassInfo, nullptr, &renderPass) != VK_SUCCESS) {
     throw std::runtime_error("failed to create render pass!");
 }

http://www.kler.cn/a/447762.html

相关文章:

  • 设计模式の享元模板代理模式
  • node express服务器配置orm框架sequilize
  • 【集合】Java 8 - Stream API 17种常用操作与案例详解
  • RunCam WiFiLink连接手机图传测试
  • golang断言
  • 3D Gaussian Splatting for Real-Time Radiance Field Rendering-简洁版
  • Liunx下MySQL:表的约束
  • OpenTK 中帧缓存的深度解析与应用实践
  • Gemini 2.0:面向智能体时代的全新 AI 模型
  • 均值聚类算法
  • 【Jenkins】Declarative和Scripted两种脚本模式有什么具体的区别
  • 关于 node-sass 库在windows下编译错误
  • C#都可以找哪些工作?
  • 【机器人】机械臂轨迹和转矩控制对比
  • 语言学习大冒险:粤语、英语、西语的酸甜苦辣
  • 编写Linux系统rhel9的网络配置脚本
  • PYTHON 自动化办公:更改图片尺寸大小
  • Spring之我见 - 从IOC谈到AOP实现原理
  • YOLO模型分布式训练:步骤与操作方式
  • 【面经】python后端开发工程师
  • CFD POST导出动画
  • Open3D 进阶(26)Hierarchical Clustering算法实现点云分割
  • 【C语言1】C语言常见概念(总结复习篇)——库函数、ASCII码、转义字符
  • 入门靶机:DC-1的渗透测试
  • OpenAI直播发布第11天:ChatGPT桌面客户端升级,就这?
  • 一些经济政治学类书籍推荐 --- 以及与之相关我的经历和理解