指定子过程描述
译者注:示例代码点击此处
在渲染过程中执行的操作被分组为子过程。每个子过程代表渲染命令的一个阶段,其中使用了渲染过程附件的子集(我们在其中渲染或读取数据)。渲染过程使用需要至少一个在我们开始渲染过程时自动启用的子过程。对于每个子过程,我们需要准备一个描述。
做好准备...
为简化每个子过程所需的参数数量,我们使用自定义结构类型,它是Vulkan中定义的VkSubpassDescription结构的简化版本:
struct SubpassParameters {
VkPipelineBindPoint PipelineType;
std::vector<VkAttachmentReference> InputAttachments;
std::vector<VkAttachmentReference> ColorAttachments;
std::vector<VkAttachmentReference> ResolveAttachments;
VkAttachmentReference const * DepthStencilAttachment;
std::vector<uint32_t> PreserveAttachments;
};
成员PipelineType定义将在子过程期间使用的管道类型(图形或计算,但此时仅在渲染过程中支持图形管道)。 InputAttachments是附件的集合,我们将在子过程中读取数据。 ColorAttachments指定将用作颜色附件的所有附件(我们将在子过程中将其渲染到其中)。 ResolveAttachments指定在子过程末尾应解析哪些颜色附件(从多重采样图像更改为非多采样/单采样图像)。 DepthStencilAttachment(如果使用)指定在子过程期间将哪个附件用作深度和/或模板附件。 PreserveAttachments是一组未在子过程中使用但在整个子过程中必须保留其内容的附件。
怎么做...
1.创建一个类型为std::vector<VkSubpassDescription>的变量,命名为subpass_descriptions。 将渲染过程中定义的每个子过程添加到subpass_descriptions向量中,并为其成员使用以下值:
·flags为0
·pipelineBindPoint为VK_PIPELINE_BIND_POINT_GRAPHICS(当前渲染过程中仅支持图形管道)
·inputAttachmentCount为子过程中使用的输入附件数
·pInputAttachments为指向输入附件参数的数组的第一个元素的指针(如果子过程中没有使用输入附件,则为nullptr值); 对pInputAttachments数组的每个成员使用以下值:
·attachment为所有渲染过程附件列表中附件的索引
·layout为给定图像的布局应自动转换到子过程的开头
·colorAttachmentCount 为The number of color attachments used in the subpass
·pColorAttachments为指想包含子过程颜色附件数组的第一个元素的指针(如果子过程中没有使用颜色附件,则为nullptr值);对于数组的每个成员,请指定值4a和4b中所述的值。
·pResolveAttachments为如果要解析任何颜色附件(从多重采样更改为单采样),请指定指向数组第一个元素的指针,其元素数量与pColorAttachments相同。或者如果不需要颜色附件则使用nullptr值。pResolveAttachments数组的每个成员对应于同一索引处的颜色附件,并指定在子过程末尾应解析给定颜色附件的附件; 对于数组的每个成员,使用4a和4b中所述的指定值; 如果不应解析给定的颜色附件,请使用VK_ATTACHMENT_UNUSED值作为附件索引。
·pDepthStencilAttachment如果使用深度/模板附件,则提供指向VkAttachmentReference类型变量的指针(如果子过程中未使用深度/模板附件,则提供nullptr值); 对于此变量的成员,请指定值4a和4b中所述的值。
·preserveAttachmentCount为未使用但应保留其内容的附件数。
·pPreserveAttachments为其中索引的附件的内容应保留在子过程中的数组的第一个元素的指针(如果没有要保留的附件,则为nullptr值)
这个怎么运作...
Vulkan渲染过程必须至少有一个子过程。 子过程参数在VkSubpassDescription元素的数组中定义。 每个这样的元素描述了如何在相应的子过程中使用附件。 输入,颜色,分辨率和保留附件有单独的列表,深度/模板附件有单个条目。 这些成员中的每一个都可以为空(或为空)。 在这种情况下,相应类型的附件不在子过程中使用。
刚才描述的其中一个列表中的每个条目都是对附件描述中为渲染过程指定的所有附件列表的引用(请参阅指定附件描述配方)。 另外,每个条目指定在子通过期间图像应该在其中的布局。 转换为指定布局由驱动程序自动执行。
下面是一个代码示例,它使用SubpassParameters类型的自定义结构来指定子过程定义:
subpass_descriptions.clear();
for( auto & subpass_description : subpass_parameters ) {
subpass_descriptions.push_back( {
0,
subpass_description.PipelineType,
static_cast<uint32_t>(subpass_description.InputAttachments.size()),
subpass_description.InputAttachments.data(),
static_cast<uint32_t>(subpass_description.ColorAttachments.size()),
subpass_description.ColorAttachments.data(),
subpass_description.ResolveAttachments.data(),
subpass_description.DepthStencilAttachment,
static_cast<uint32_t>(subpass_description.PreserveAttachments.size()),
subpass_description.PreserveAttachments.data()
} );
}
以下是定义一个子过程的代码示例,该子过程对应于具有一个颜色附件的示例:深度/模板附件:
VkAttachmentReference depth_stencil_attachment = {
1,
VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL,
};
std::vector<SubpassParameters> subpass_parameters = {
{
VK_PIPELINE_BIND_POINT_GRAPHICS,
{},
{
{
0,
VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL
}
},
{},
&depth_stencil_attachment,
{}
}
};
先,我们为深度/模板附件的描述指定depth_stencil_attachment变量。 对于深度数据,使用附件描述列表中的第二个附件; 这就是我们为其索引指定值1的原因(请参阅指定附件描述描述内容)。 当我们想要渲染到这个附件中时,我们为其布局提供VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL值(如果需要,驱动程序将自动执行转换)。
在示例中,我们只使用一种颜色附件。 它是附件描述列表中的第一个附件,因此我们对其索引使用0值。 当我们渲染成颜色附件时,我们应该为其布局指定VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL值。 最后一件事 - 我们想要渲染几何体,需要使用图形管道。 这是通过为PipelineType成员提供的VK_PIPELINE_BIND_POINT_GRAPHICS值完成的。 由于我们不使用输入附件,并且我们不想解析任何颜色附件,因此它们对应的向量是空的。