Vulkan教程(15): Graphics pipeline之Render passes(渲染通道)
Vulkan官方英文原文: https://vulkan-tutorial.com/Drawing_a_triangle/Graphics_pipeline_basics/Render_passes
对应的Vulkan技术规格说明书版本: Vulkan 1.3.2
Setup
设置
Before we can finish creating the pipeline, we need to tell Vulkan about the framebuffer attachments that will be used while rendering. We need to specify how many color and depth buffers there will be, how many samples to use for each of them and how their contents should be handled throughout the rendering operations. All of this information is wrapped in a render pass object, for which we'll create a new createRenderPass function. Call this function from initVulkan before createGraphicsPipeline.
在我们完成管线创建之前,我们需要告诉Vulkan在渲染过程中将被使用的帧缓冲区附件的相关信息。我们需要指定将有多少个颜色和深度缓冲区(被应用),有多少(多重采样的)采样数用到这些缓冲区上以及在整个渲染操作中相关的内容如何处理。所有的这些信息都被 render pass 对象封装在内,为此,我们将创建一个 createRenderPass 函数。此函数在 initVulkan 函数中的 createGraphicsPipeline 函数之前调用。
void initVulkan() {createInstance();setupDebugMessenger();createSurface();pickPhysicalDevice();createLogicalDevice();createSwapChain();createImageViews();createRenderPass();createGraphicsPipeline();
}...void createRenderPass() {}
Attachment description
附件描述
In our case we'll have just a single color buffer attachment represented by one of the images from the swap chain.
在我们目前的例子中,我们只需要单个颜色缓冲区附件,它由swap chain中的一个图像表示。
void createRenderPass() {VkAttachmentDescription colorAttachment{};colorAttachment.format = swapChainImageFormat;colorAttachment.samples = VK_SAMPLE_COUNT_1_BIT;
}
The format of the color attachment should match the format of the swap chain images, and we're not doing anything with multisampling yet, so we'll stick to 1 sample.
颜色缓冲区附件的格式应该和对应的 swap chain中的图像匹配,我们也不需要多重采样,因此我们将采样数设置为1。
colorAttachment.loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR;
colorAttachment.storeOp = VK_ATTACHMENT_STORE_OP_STORE;
The loadOp and storeOp determine what to do with the data in the attachment before rendering and after rendering. We have the following choices for loadOp:
VK_ATTACHMENT_LOAD_OP_LOAD: Preserve the existing contents of the attachment
VK_ATTACHMENT_LOAD_OP_CLEAR: Clear the values to a constant at the start
VK_ATTACHMENT_LOAD_OP_DONT_CARE: Existing contents are undefined; we don't care about them
In our case, we're going to use the clear operation to clear the framebuffer to black before drawing a new frame. There are only two possibilities for the storeOp:
VK_ATTACHMENT_STORE_OP_STORE: Rendered contents will be stored in memory and can be read later
VK_ATTACHMENT_STORE_OP_DONT_CARE: Contents of the framebuffer will be undefined after the rendering operation
We're interested in seeing the rendered triangle on the screen, so we're going with the store operation here.
loadOp 和storeOp 两个变量决定在渲染操作之前和之后,相关附件中的数据如何处理。这个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;
The loadOp and storeOp apply to color and depth data, and stencilLoadOp / stencilStoreOp apply to stencil data. Our application won't do anything with the stencil buffer, so the results of loading and storing are irrelevant.
loadOp 和storeOp 这两个字段应用于颜色和深度数据(的相关操作),而 stencilLoadOp / stencilStoreOp 这两个字段则应用于模板数据(的相关操作)。我们的应用程序不需要用到模板缓冲区,因此模板的载入和存储在这里没啥影响。
colorAttachment.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
colorAttachment.finalLayout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR;
Textures and framebuffers in Vulkan are represented by VkImage objects with a certain pixel format, however the layout of the pixels in memory can change based on what you're trying to do with an image.
Some of the most common layouts are:
VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL: Images used as color attachment
VK_IMAGE_LAYOUT_PRESENT_SRC_KHR: Images to be presented in the swap chain
VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL: Images to be used as destination for a memory copy operation
We'll discuss this topic in more depth in the texturing chapter, but what's important to know right now is that images need to be transitioned to specific layouts that are suitable for the operation that they're going to be involved in next.
Vulkan中的纹理和帧缓冲区都用某种像素格式的 VkImage 对象表示,但是内存中的像素布局可以基于你想用图像做什么去改变。
常用的布局如下所示:
VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL: 图像作为颜色附件
VK_IMAGE_LAYOUT_PRESENT_SRC_KHR: 图像在交换链中用于呈现
VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL: 图像用于内存拷贝的目标
我们会在纹理章节更深入的讨论这主题,但现在重要的是,要知道图像需要转换到适合后续相关操作的指定布局。
The initialLayout specifies which layout the image will have before the render pass begins. The finalLayout specifies the layout to automatically transition to when the render pass finishes. Using VK_IMAGE_LAYOUT_UNDEFINED for initialLayout means that we don't care what previous layout the image was in. The caveat of this special value is that the contents of the image are not guaranteed to be preserved, but that doesn't matter since we're going to clear it anyway. We want the image to be ready for presentation using the swap chain after rendering, which is why we use VK_IMAGE_LAYOUT_PRESENT_SRC_KHR as finalLayout.
这个initialLayout 字段指定图像在渲染通道相关操作之前用哪种布局。finalLayout 字段指定的图像布局是渲染通道操作结束后自动转换到的图像布局。initialLayout赋值为VK_IMAGE_LAYOUT_UNDEFINED 表示我们不关心图像之前的布局。此特殊值的附加说明是图像的内容不会保证被保留,不过也没关系,因为我们总会清除掉它。我们希望图像渲染完毕后使用 swap chain 来显示,这就是我们为什么用VK_IMAGE_LAYOUT_PRESENT_SRC_KHR 给finalLayout赋值的原因。
一些图像布局的细节请见:Image Layouts
Subpasses and attachment references
子通道和附件引用
A single render pass can consist of multiple subpasses. Subpasses are subsequent rendering operations that depend on the contents of framebuffers in previous passes, for example a sequence of post-processing effects that are applied one after another. If you group these rendering operations into one render pass, then Vulkan is able to reorder the operations and conserve memory bandwidth for possibly better performance. For our very first triangle, however, we'll stick to a single subpass.
一个单独的渲染通道有多个子通道组成。子通道是后续的渲染操作,它基于之前在渲染通道中的帧缓冲区内容,例如,一个接一个应用的一系列后处理效果。假如你把这些渲染操作组成一个渲染通道,那么Vulkan能重新排序这些操作,并且节省内存带宽以便性能更好。然而,对于我们第一个三角形,我们只需单个子通道。
Every subpass references one or more of the attachments that we've described using the structure in the previous sections. These references are themselves VkAttachmentReference structs that look like this:
每一个子通道引用一个或多个附件,这些附件我们使用前些章节中讲的结构体信息来描述。这些引用本身就是 VkAttachmentReference 结构体,如下所示:
VkAttachmentReference colorAttachmentRef{};
colorAttachmentRef.attachment = 0;
colorAttachmentRef.layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
The attachment parameter specifies which attachment to reference by its index in the attachment descriptions array. Our array consists of a single VkAttachmentDescription, so its index is 0. The layout specifies which layout we would like the attachment to have during a subpass that uses this reference. Vulkan will automatically transition the attachment to this layout when the subpass is started. We intend to use the attachment to function as a color buffer and the VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL layout will give us the best performance, as its name implies.
attachment 参数指定用附件描述数组中的序号来引用哪个附件。 我们的数组由单个VkAttachmentDescription结构体对象组成,因此序号为0。这个layout 字段指定我们希望的附件布局, 子通道中使用此附件的引用。当子通道开始之际,Vulkan自动转换附件到这种布局。我们打算用此附件实现颜色缓冲区的功能,并且VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL 布局性能最佳,就如其名字的含义。
The subpass is described using a VkSubpassDescription structure:
子通道用一个VkSubpassDescription 结构体描述:
VkSubpassDescription subpass{};
subpass.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS;
Vulkan may also support compute subpasses in the future, so we have to be explicit about this being a graphics subpass. Next, we specify the reference to the color attachment:
Vulkan未来可能也会支持 compute subpasses 的功能,我们必须明确这是一个图形管线的子通道。接下来,我们指定颜色附件的引用:
subpass.colorAttachmentCount = 1;
subpass.pColorAttachments = &colorAttachmentRef;
The index of the attachment in this array is directly referenced from the fragment shader with the layout(location = 0) out vec4 outColor directive!
The following other types of attachments can be referenced by a subpass:
pInputAttachments: Attachments that are read from a shader
pResolveAttachments: Attachments used for multisampling color attachments
pDepthStencilAttachment: Attachment for depth and stencil data
pPreserveAttachments: Attachments that are not used by this subpass, but for which the data must be preserved
这个数组中附件的索引是被片段着色器直接用的,用 layout(location = 0) out vec4 outColor 的指令实现。
下面是能被子通道引用的其他附件类型:
pInputAttachments: 从shader中读取数据的附件
pResolveAttachments: 这类附件用于多重采用颜色附件
pDepthStencilAttachment: 深度和缓冲区数据附件
pPreserveAttachments: 这类附件不能被用于图形管线子通道,但是数据必须被保留
Render pass
渲染通道
Now that the attachment and a basic subpass referencing it have been described, we can create the render pass itself. Create a new class member variable to hold the VkRenderPass object right above the pipelineLayout variable:
现在已经介绍了附件和基本的子通道,我们能创建渲染通道本身了。在pipelineLayout 变量定义处之上创建一个新的类成员变量来持有 VkRenderPass 对象的引用:
VkRenderPass renderPass;
VkPipelineLayout pipelineLayout;
The render pass object can then be created by filling in the VkRenderPassCreateInfo structure with an array of attachments and subpasses. The VkAttachmentReference objects reference attachments using the indices of this array.
然后通过用若干附件和子通道填充 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!");
}
Just like the pipeline layout, the render pass will be referenced throughout the program, so it should only be cleaned up at the end:
就如图形管线布局一样,渲染通道对象也被程序全程引用,因此最后记得销毁:
void cleanup() {vkDestroyPipelineLayout(device, pipelineLayout, nullptr);vkDestroyRenderPass(device, renderPass, nullptr);...
}
That was a lot of work, but in the next chapter it all comes together to finally create the graphics pipeline object!
真是不少工作,不过要在下一个章所有的相关对象最终一起创建处图形管线对象!
相关文章:
Vulkan教程(15): Graphics pipeline之Render passes(渲染通道)
Vulkan官方英文原文: https://vulkan-tutorial.com/Drawing_a_triangle/Graphics_pipeline_basics/Render_passes对应的Vulkan技术规格说明书版本: Vulkan 1.3.2Setup设置Before we can finish creating the pipeline, we need to tell Vulkan about the…...

乐观锁、雪花算法、MyBatis-Plus多数据源
乐观锁、雪花算法、MyBatis-Plus多数据源e>雪花算法2、乐观锁a>场景b>乐观锁与悲观锁c>模拟修改冲突d>乐观锁实现流程e>Mybatis-Plus实现乐观锁七、通用枚举a>数据库表添加字段sexb>创建通用枚举类型c>配置扫描通用枚举d>测试九、多数据源1、创建…...

详解Redisson分布式限流的实现原理
我们目前在工作中遇到一个性能问题,我们有个定时任务需要处理大量的数据,为了提升吞吐量,所以部署了很多台机器,但这个任务在运行前需要从别的服务那拉取大量的数据,随着数据量的增大,如果同时多台机器并发…...
[python入门㊹] - python测试类
目录 ❤ 断言方法 assertEqual 和 assertNotEqual assertTrue 和 assertFalse assertIsNone 和 assertIsNotNone ❤ 一个要测试的类 ❤ 测试AnonymousSurvey类 ❤ setUp() 和 teardown() 方法 ❤ 断言方法 常用的断言方法: 方法 用途 assertEqual(a, b) 核实a …...

Web 框架 Flask 快速入门(二)表单
课程地址:Python Web 框架 Flask 快速入门 文章目录🌴 表单1、表单介绍2、表单的简单实现1. 代码2. 代码的执行逻辑3、使用wtf扩展实现4、bug记录:表单验证总是失败🌴 表单 1、表单介绍 当我们在网页上填写账号密码进行登录的时…...

C++基础(5) - 复合类型(上)
文章目录数组1、什么是数组2、数组的声明3、数组的初始化4、数组的访问5、二维数组6、memset —— 给数组中每一个元素赋同样的值字符串(字符数组)1、string.h 头文件1.1 strlen()1.2 strcmp()1.3 strcpy()1.4 strcat()string 类简介1、C11 字符串初始化…...
java重写(@Override)介绍及实例说明
1.概述方法的重写(override)是封装的特性之一。在子类中可以根据需要对基类中继承来的方法进行重写。重载和重写没有任何关系。作用:通过重写,子类既可以继承父类的东西,又可以灵活的扩充。1.override注解是告诉编译器…...

基于STM32的虚拟示波器
仓库地址 https://github.com/shuai132/ScopeMCU ScopeMCU Oscilloscope for MCU MCU: STM32F103C8Tx 需配合ScopeGUI使用 截图说明见wiki 最新版Releases Introduction 用最少的硬件成本,做一个实用的虚拟示波器。 这是硬件部分,基于STM32最小…...

搭建云端vscode-server,使用web ide进行远程开发
使用乌班图系统,搭建自己的网页vs code开发环境github地址:GitHub - coder/code-server: VS Code in the browser安装脚本curl -fsSL https://code-server.dev/install.sh | sh出现deb package has been installed.表示已经正确安装。测试启动2.1修改配置…...

Linux clock子系统及驱动实例
文章目录基本概念CLK子系统时钟API的使用clock驱动实例1、时钟树2、设备树3、驱动实现fixed_clk固定时钟实现factor_clk分频时钟实现gate_clk门控时钟实现基本概念 晶振:晶源振荡器 PLL:Phase lock loop,锁相环。用于提升频率 OSC:…...

GIS数据格式坐标转换(地球坐标WGS84、GCJ-02、火星坐标、百度坐标BD-09、国家大地坐标系CGCS2000)
文章目录前言一、坐标系1.地球坐标 (WGS84)2.国测局坐标系(GCJ-02、火星坐标系)3.百度坐标(BD-09)4.国家大地2000坐标系(CGCS2000)二、百度坐标系(BD-09) 与火星坐标系(GCJ-02)的转换1.核心代码2.转换验证百度地图高德地图腾讯地图三、火星坐标系 (GCJ-02) 与百度坐标系 (BD-09…...
流媒体传输系列文章汇总
流媒体传输系列文章汇总 文章目录流媒体传输系列文章汇总引言流媒体交互协议详解视频封装协议详解流媒体环境搭建其他引言 从去年开始编写有关流媒体传输相关知识的文章,已发表文章22篇,阅读量也超过了10万,为了方便各位阅读,本文…...

“万字“ Java I/O流讲解
Java I/O流讲解 每博一文案 谁让你读了这么多书,又知道了双水村以外还有一个大世界,如果从小你就在这个天地里,日出而作,日落而息。 那你现在就会和众乡亲抱同一理想:经过几年的辛劳,像大哥一样娶个满意的…...
数据库(Spring)事务的四种隔离级别
文章目录Spring(数据库)事务隔离级别分为四种(级别递减)1、Serializable(串行化)2、REPEATABLE READ(可重复读)3、READ COMMITTED(读以提交)4、Read Uncommit…...

RabbitMQ详解(一):RabbitMQ相关概念
RabbitMQ是目前非常热门的一款消息中间件,不管是互联网大厂还是中小企业都在大量使用。作为一名合格的开发者,有必要对RabbitMQ有所了解,本系列是RabbitMQ快速入门文章,主要内容包括RabbitMQ是什么、RabbitMQ核心概念、五种消息模…...

ICLR 2023 | GReTo:以同异配关系重新审视动态时空图聚合
©PaperWeekly 原创 作者 | 周正阳单位 | 中国科学技术大学论文简介动态时空图数据结构在多种不同的学科中均普遍存在,如交通流、空气质量观测、社交网络等,这些观测往往会随着时间而变化,进而引发节点间关联的动态时变特性。本文的主要…...
线程池分享总结
线程池介绍 可以复用线程池的每一个资源 控制资源的总量 为什么要使用线程池 问题一:反复创建线程开销大 问题二:过多的线程会占用太多内存 解决以上两个问题的思路 • 用少量的线程——避免内存占用过多 • 让这部分线程都保持工作,且可…...

AOSP Android11系统源码和内核源码
推荐阅读 商务合作 安全产品 安全服务 2023年招聘 安全培训服务 软件定制服务 Android系统定制服务 安全/软件开发的课程列表 1.下载repo工具 (1).创建bin,并加入到PATH中 mkdir ~/binPATH~/bin:$PATH (2).安装依赖库 sudo apt-get install bison g-mult…...

layui框架学习(6:基础菜单)
菜单是应用系统的必备元素,虽然网页中的导航也能作为菜单使用,但菜单和导航的样式和用途有所不同(不同之处详见参考文献5)。Layui中用不同的预设类定义菜单和导航的样式,同时二者依赖的模块也不一样。本文主要学习和记…...
第十三届蓝桥杯 C++ B组省赛 C 题——刷题统计(AC)
1.刷题统计 1.题目描述 小明决定从下周一开始努力刷题准备蓝桥杯竞赛。他计划周一至周五每天 做 aaa 道题目, 周六和周日每天做 bbb 道题目。请你帮小明计算, 按照计划他将在 第几天实现做题数大于等于 nnn 题? 2.输入格式 输入一行包含三个整数 a,ba,ba,b 和 nnn. 3.输出…...
SkyWalking 10.2.0 SWCK 配置过程
SkyWalking 10.2.0 & SWCK 配置过程 skywalking oap-server & ui 使用Docker安装在K8S集群以外,K8S集群中的微服务使用initContainer按命名空间将skywalking-java-agent注入到业务容器中。 SWCK有整套的解决方案,全安装在K8S群集中。 具体可参…...
树莓派超全系列教程文档--(62)使用rpicam-app通过网络流式传输视频
使用rpicam-app通过网络流式传输视频 使用 rpicam-app 通过网络流式传输视频UDPTCPRTSPlibavGStreamerRTPlibcamerasrc GStreamer 元素 文章来源: http://raspberry.dns8844.cn/documentation 原文网址 使用 rpicam-app 通过网络流式传输视频 本节介绍来自 rpica…...

练习(含atoi的模拟实现,自定义类型等练习)
一、结构体大小的计算及位段 (结构体大小计算及位段 详解请看:自定义类型:结构体进阶-CSDN博客) 1.在32位系统环境,编译选项为4字节对齐,那么sizeof(A)和sizeof(B)是多少? #pragma pack(4)st…...

UE5 学习系列(三)创建和移动物体
这篇博客是该系列的第三篇,是在之前两篇博客的基础上展开,主要介绍如何在操作界面中创建和拖动物体,这篇博客跟随的视频链接如下: B 站视频:s03-创建和移动物体 如果你不打算开之前的博客并且对UE5 比较熟的话按照以…...

Cinnamon修改面板小工具图标
Cinnamon开始菜单-CSDN博客 设置模块都是做好的,比GNOME简单得多! 在 applet.js 里增加 const Settings imports.ui.settings;this.settings new Settings.AppletSettings(this, HTYMenusonichy, instance_id); this.settings.bind(menu-icon, menu…...
如何为服务器生成TLS证书
TLS(Transport Layer Security)证书是确保网络通信安全的重要手段,它通过加密技术保护传输的数据不被窃听和篡改。在服务器上配置TLS证书,可以使用户通过HTTPS协议安全地访问您的网站。本文将详细介绍如何在服务器上生成一个TLS证…...
大模型多显卡多服务器并行计算方法与实践指南
一、分布式训练概述 大规模语言模型的训练通常需要分布式计算技术,以解决单机资源不足的问题。分布式训练主要分为两种模式: 数据并行:将数据分片到不同设备,每个设备拥有完整的模型副本 模型并行:将模型分割到不同设备,每个设备处理部分模型计算 现代大模型训练通常结合…...

《基于Apache Flink的流处理》笔记
思维导图 1-3 章 4-7章 8-11 章 参考资料 源码: https://github.com/streaming-with-flink 博客 https://flink.apache.org/bloghttps://www.ververica.com/blog 聚会及会议 https://flink-forward.orghttps://www.meetup.com/topics/apache-flink https://n…...

OPenCV CUDA模块图像处理-----对图像执行 均值漂移滤波(Mean Shift Filtering)函数meanShiftFiltering()
操作系统:ubuntu22.04 OpenCV版本:OpenCV4.9 IDE:Visual Studio Code 编程语言:C11 算法描述 在 GPU 上对图像执行 均值漂移滤波(Mean Shift Filtering),用于图像分割或平滑处理。 该函数将输入图像中的…...

C++使用 new 来创建动态数组
问题: 不能使用变量定义数组大小 原因: 这是因为数组在内存中是连续存储的,编译器需要在编译阶段就确定数组的大小,以便正确地分配内存空间。如果允许使用变量来定义数组的大小,那么编译器就无法在编译时确定数组的大…...