vulakn教程--Drawing a Triangle--Pipeline--Render passes
2016-09-15 21:29
926 查看
原文链接 : vulkan-tutorial
现在我们来填充这个结构 :
因为我们不使用multiSampling ,所以这里samples 取值 _1_BIT 。
stencil..Op应用于stencil data ,这里我们不需要关心。
在
我们将在文理(texture)部分再详细讲解这部分,现在仅需要明确的是image 在每个后续的操作中都要转变成特定的
每一个
pInputAttachments: 从着色器中读取的 attachment
pResolveAttachments: multiple color attachment
pDepthStencilAttachment: depth and stencil data 的attachment
pPreserveAttachments: 不被Subpass 使用,但出于某种原因需要保存
不知道你的思绪是否有点混乱,让我们来理清一下。创建Render Pass 需要Subpass 和Attachment, 现在就简单的理解为Render Pass 包含Subpass 数组和 Attachment数组吧。Render Pass的工作需要Subpass 来完成, 每一个Subpass 可以操作多个Attachment ,怎么从Attachment数组中表示哪些attachment会被某个Subpass处理呢,所以我们需要一个VkAttachmentReference来描述attachment在Attachment数组中的小标和处理时的layout。
着色器阶段: 我们定义了 Shader module, 这是可编程部分。
配置固定功能状态(fixed-function state): Pipeline 所需要的input assembly, rasterizer, viewport and color blending 配置, 这是不可编程部分。
Pipeline layout: 主要是Uniform 变量,这些变量可以在绘画阶段动态改变。
Render pass : Attachment 的定义以及他们的使用。
现在已经到了本章的最终阶段 ->创建
Vulkan允许我们从已有的Pipeline派生新的Pipeline, 它们有很多相似点会使新Pipeline的创建花费更少。这里我们没有已存在的Pipeline。
让我们来看看这个函数:
它允许我们传入多个
原文源码 : source code
Render Pass
在创建Pipeline之前我们必须告诉
Vulkan在渲染时要使用的
FrameBuffer附件(
attachments),需要定义使用color buffer 以及 depth buffer attachments的数量,要使用多少个采样(samples)以及应该如何处理采样的内容。所有这些信息都可以填写在Render Pass里。
Attachment description
在我们的应用里只使用了一个color buffer attachment,我们用Swap Chain里的一个
image来表示这个
buffer。先来看一下需要用到的结构:
typedef struct VkAttachmentDescription { VkAttachmentDescriptionFlags flags; VkFormat format; VkSampleCountFlagBits samples; VkAttachmentLoadOp loadOp; VkAttachmentStoreOp storeOp; VkAttachmentLoadOp stencilLoadOp; VkAttachmentStoreOp stencilStoreOp; VkImageLayout initialLayout; VkImageLayout finalLayout; } VkAttachmentDescription;
// subpass 执行前对color或depth attachment内容做何种处理 typedef enum VkAttachmentLoadOp { VK_ATTACHMENT_LOAD_OP_LOAD = 0, //±£´æÒÑÓеÄÄÚÈÝ VK_ATTACHMENT_LOAD_OP_CLEAR = 1, //Çå¿Õ VK_ATTACHMENT_LOAD_OP_DONT_CARE = 2, // ²»ÔÚºõ } VkAttachmentLoadOp;
// subpass 执行后做何种处理 typedef enum VkAttachmentStoreOp { VK_ATTACHMENT_STORE_OP_STORE = 0, //保存 VK_ATTACHMENT_STORE_OP_DONT_CARE = 1, // } VkAttachmentStoreOp;
现在我们来填充这个结构 :
VkAttachmentDescription colorAttachment = {}; colorAttachment.format = swapChainImageFormat; colorAttachment.samples = VK_SAMPLE_COUNT_1_BIT;
因为我们不使用multiSampling ,所以这里samples 取值 _1_BIT 。
colorAttachment.loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR; colorAttachment.storeOp = VK_ATTACHMENT_STORE_OP_STORE;
loadOp和
storeO表示渲染前和渲染后要做的动作,在我们的例子中,写入新片原(fragment)之前先清空FrameBuffer,使FrameBuffer变为黑色。我们想让渲染后的三角形显示到屏幕上,所以这里我们将
storeOp设置为保存。
colorAttachment.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE; colorAttachment.stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
stencil..Op应用于stencil data ,这里我们不需要关心。
colorAttachment.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; colorAttachment.finalLayout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR;
在
Vulkan中,用具有特定像素格式的
VkImage表示纹理(texture)和
FrameBuffer,而像素在内存中的布局(
layout)随着我们使用Image 的目的不同是可以改变的。一些常见的
layout有:
VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL: Images 用作 color attachment
VK_IMAGE_LAYOUT_PRESENT_SRC_KHR: 表示一个要被显示的swap chain image源
VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL: images 作为内存拷贝操作的目的
我们将在文理(texture)部分再详细讲解这部分,现在仅需要明确的是image 在每个后续的操作中都要转变成特定的
layout。
initial / finalLaout表示渲染前后image的layout,
VK_IMAGE_LAYOUT_UNDEFINED表示我们不在乎之前的layout,而
VK_IMAGE_LAYOUT_PRESENT_SRC_KHR表示在渲染后,使用Swpa Chain 时,image 处于可显示的
layout。
Subpasses and attachment references
一个Render Pass 由一系列的subPass组成,并由
subpass处理随后的渲染操作,代表渲染的一个阶段,渲染命令存储在一个Render Pass的诸多
subpass中,一个subpass的动作取决于上一个subpass 的处理结果,如果我们把它们打包成一个Render Pass ,Vulkan 能够为我们重新排序它们的执行顺序,节省内存带宽,从而可能获取更好的性能。
每一个
Subpass引用一个或多个我们在前一节用
VkAttachmentDescription描述的attachment(s) ,每一个引用用
VkAttachmentReference描述:
VkAttachmentReference colorAttachmentRef = {}; colorAttachmentRef.attachment = 0; colorAttachmentRef.layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
attachment表示此
VkAttachmentReference代表哪一个
attachment,它的值是一个索引(index),这里我们只有一个
VkAttachmentDescription,所以索引是0, 同时这个attachment 和Frame Shader 里的:
layout(location = 0) out vec4 outColor相对应。
layout表示subpass 在执行时希望此atatchment具有的layout,Vulkan将自动为我们完成attachment的转换。我们想使用color buffer attachment,
VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL选项还会做些优化。
Subpass本身用
VkSubpassDescription表示:
VkSubpassDescription subPass = {}; subPass.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS;
pipelineBindPoint表示要绑定的Pipeline类型,这里只支持两种类型:计算(compute)和图形(graphics),这里我们选择图形Pipeline。 然后我们告诉
subpass它所引用的
attachment:
subPass.colorAttachmentCount = 1; subPass.pColorAttachments = &colorAttachmentRef;
Subpass还可以引用的
attachment有:
pInputAttachments: 从着色器中读取的 attachment
pResolveAttachments: multiple color attachment
pDepthStencilAttachment: depth and stencil data 的attachment
pPreserveAttachments: 不被Subpass 使用,但出于某种原因需要保存
Create Render pass
Attachment 和 Subpass 都已经声明好了,现在开始创建Render Pass:VDeleter<VkRenderPass> renderPass {device, vkDestroyRenderPass}; VkRenderPassCreateInfo renderPassInfo = {}; renderPassInfo.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO; renderPassInfo.attachmentCount = 1; renderPassInfo.pAttachments = &colorAttachment; renderPassInfo.subpassCount = 1; renderPassInfo.pSubpasses = &subPass; //需要一个VkDevice 参数 即:Logical Device if (vkCreateRenderPass(device, &renderPassInfo, nullptr, &renderPass) != VK_SUCCESS) { throw std::runtime_error("failed to create render pass!"); }
不知道你的思绪是否有点混乱,让我们来理清一下。创建Render Pass 需要Subpass 和Attachment, 现在就简单的理解为Render Pass 包含Subpass 数组和 Attachment数组吧。Render Pass的工作需要Subpass 来完成, 每一个Subpass 可以操作多个Attachment ,怎么从Attachment数组中表示哪些attachment会被某个Subpass处理呢,所以我们需要一个VkAttachmentReference来描述attachment在Attachment数组中的小标和处理时的layout。
Create Pipeline
先回顾一下这一章我们都做了什么:着色器阶段: 我们定义了 Shader module, 这是可编程部分。
配置固定功能状态(fixed-function state): Pipeline 所需要的input assembly, rasterizer, viewport and color blending 配置, 这是不可编程部分。
Pipeline layout: 主要是Uniform 变量,这些变量可以在绘画阶段动态改变。
Render pass : Attachment 的定义以及他们的使用。
现在已经到了本章的最终阶段 ->创建
Pipeline:
VkGraphicsPipelineCreateInfo pipelineInfo = {}; pipelineInfo.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO; pipelineInfo.stageCount = 2; pipelineInfo.pStages = shaderStages; pipelineInfo.pVertexInputState = &vertexInputInfo; pipelineInfo.pInputAssemblyState = &inputAssembly; pipelineInfo.pViewportState = &viewportState; pipelineInfo.pRasterizationState = &rasterizer; pipelineInfo.pMultisampleState = &multisampling; pipelineInfo.pDepthStencilState = nullptr; // Optional pipelineInfo.pColorBlendState = &colorBlending; pipelineInfo.pDynamicState = nullptr; // Optional pipelineInfo.layout = pipelineLayout; pipelineInfo.renderPass = renderPass; pipelineInfo.subpass = 0; //subpass索引,表示pipeline 将会使用renderPass 里的哪个subpass. pipelineInfo.basePipelineHandle = VK_NULL_HANDLE; pipelineInfo.basePipelineIndex = -1; // Optional
Vulkan允许我们从已有的Pipeline派生新的Pipeline, 它们有很多相似点会使新Pipeline的创建花费更少。这里我们没有已存在的Pipeline。
// 创建Pipeline VDeleter<VkPipeline> graphicsPipeline {device, vkDestroyPipeline}; if (vkCreateGraphicsPipelines(device, VK_NULL_HANDLE, 1, &pipelineInfo, nullptr, &graphicsPipeline) != VK_SUCCESS) { throw std::runtime_error("failed to create graphics pipeline!"); }
让我们来看看这个函数:
VkResult vkCreateGraphicsPipelines( VkDevice device, VkPipelineCache pipelineCache, uint32_t createInfoCount, const VkGraphicsPipelineCreateInfo* pCreateInfos, const VkAllocationCallbacks* pAllocator, VkPipeline* pPipelines);
它允许我们传入多个
createInfo来创建多个Pipeline, 第二个参数
pipelineCache允许存储和重用数据,加速pipeine的创建过程。
原文源码 : source code
相关文章推荐
- vulakn教程--Drawing a Triangle--Pipeline--Introduction
- vulakn教程--Drawing a Triangle--Pipeline--Fixed function
- vulakn教程--Drawing a Triangle--Pipeline--Shader Module
- vulakn教程--Drawing a Triangle--Draw--Framebuffer
- vulakn教程--Drawing a Triangle--Presentation--Window surface
- vulakn教程--Drawing a Triangle--Presentation--SwapChain
- vulakn教程--Drawing a Triangle--Set up--Logical Device
- vulakn教程--Drawing a Triangle--Set up--Instance
- vulakn教程--Drawing a Triangle--Set up--Physical Device and Queue Family
- vulakn教程--Drawing a Triangle--Draw--Render and presentation
- vulakn教程--Drawing a Triangle--Set up--Validation layers
- vulakn教程--Drawing a Triangle--Presentation-- Image views
- vulakn教程--Drawing a Triangle--Draw--CommandBuffer
- DirectX 教程: DirectX Tutorial - Direct3D: Drawing a Triangle
- vulakn教程--Drawing a Triangle--Set up--Base code
- Drawing a triangle - Instance
- Android OpenGL ES 开发教程(11):绘制三角形Triangle
- Android OpenGL ES 开发教程(11):绘制三角形Triangle
- Netty教程-ChannelPipeline
- GStreamer基础教程08——pipeline的快捷访问