Vulkan【9】描述符集合佈局和管線佈局(Descriptor Set Layouts and Pipeline Layouts)

描述符集合佈局和管線佈局

本節的代碼是 08-init_pipeline_layout.cpp

在前面的例子中,您創建了一個uniform 緩衝區,但是您沒有告訴着色器該如何使用它。緩衝區包含了MVP轉換的Uiform變量,它只會被頂點着色器使用,但是Vulkan還不知道這一點。

我們通過使用描述符來實現這一點。

描述符和描述符集合

描述符是一個特殊的不透明的着色器變量,着色器使用它以間接的方式訪問緩衝區和圖像資源。它可以被認爲是一個資源的“指針”。Vulkan API允許在繪製操作之間更改這些變量,以便着色器能夠爲每次繪製訪問不同的資源。

在樣例例子中,您只有一個Uniform 緩衝區。但是你可以創建兩個Uniform 緩衝區,每個緩衝區都有一個不同的MVP來給出不同的場景視圖。然後,您可以很容易地改變描述符,以指向任何一個Uniform 緩衝區,以便在MVP矩陣之間來回切換。

描述符集合被稱爲“集合”,因爲它可以引用一組同構資源,可以用相同的佈局綁定(Layout Binding)來描述。

在本例中,您沒有使用紋理,但是使用多個描述符的一種可能方法是用兩個描述符構造一個描述符集合,每個描述符引用一個單獨的紋理。因此,在繪製過程中,兩種紋理都是可用的。然後,命令緩衝區中的命令可以通過指定所需紋理的索引來選擇紋理。

需要注意的是,您只是在“描述”這裏的描述符集合,實際上並沒有真正地分配或創建描述符集合本身,稍後您將在"Descriptor_Set"示例中進行描述。

爲了描述描述符集合,您可以使用描述符集合佈局。

描述符集佈局

描述符集合佈局是用來描述描述符列表裏的內容。
對於每個描述符集合,您還需要一個佈局綁定,您可以使用它來描述每個描述符集合:

VkDescriptorSetLayoutBinding layout_binding = {};
layout_binding.binding = 0;
layout_binding.descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
layout_binding.descriptorCount = 1;
layout_binding.stageFlags = VK_SHADER_STAGE_VERTEX_BIT;
layout_binding.pImmutableSamplers = NULL;
  • 您只有一個描述符集合,所以binding成員的惟一選擇是0。
  • 因爲這個描述符引用了一個Uniform 緩衝區,所以您適當地設置了descriptorType
  • 在這個描述符集合中,您只有一個描述符,它由descriptorCount 成員表示。
  • 您指出,這個Uniform 緩衝區資源將被綁定到shader頂點階段。

當這個描述符集的綁定被定義好之後,我們就可以創建一個描述符集合佈局:

#define NUM_DESCRIPTOR_SETS 1
VkDescriptorSetLayoutCreateInfo descriptor_layout = {};
descriptor_layout.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO;
descriptor_layout.pNext = NULL;
descriptor_layout.bindingCount = 1;
descriptor_layout.pBindings = &layout_binding;
info.desc_layout.resize(NUM_DESCRIPTOR_SETS);
res = vkCreateDescriptorSetLayout(info.device, &descriptor_layout, NULL,
                                  info.desc_layout.data());

管線佈局

管道佈局包含一個描述符集合佈局的列表。它還可以包含一個推送常量範圍的列表,這是將常量傳遞給着色器的另一種方法,在這裏先不涉及。

與描述符集合一樣,您只是定義了佈局。實際的描述符集合的內存分配和填充,會在稍後的uniform 緩衝引用中。

VkPipelineLayoutCreateInfo pPipelineLayoutCreateInfo = {};
pPipelineLayoutCreateInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO;
pPipelineLayoutCreateInfo.pNext = NULL;
pPipelineLayoutCreateInfo.pushConstantRangeCount = 0;
pPipelineLayoutCreateInfo.pPushConstantRanges = NULL;
pPipelineLayoutCreateInfo.setLayoutCount = NUM_DESCRIPTOR_SETS;
pPipelineLayoutCreateInfo.pSetLayouts = info.desc_layout.data();

res = vkCreatePipelineLayout(info.device, &pPipelineLayoutCreateInfo, NULL,
                             &info.pipeline_layout);

稍後您將使用管道佈局來創建圖形管道。

描述符的着色器引用

值得指出的是,着色器明確地引用了着色器語言中的這些描述符。

例如, 在 GLSL裏:

 layout (set=M, binding=N) uniform sampler2D variableNameArray[I];
  • M表示管線佈局中的pSetLayouts
  • N表示M的描述符集合佈局中的pBindings
  • I表示N的描述符集合中描述符的索引

在您將要使用的頂點着色器中,Uniform 緩衝區的佈局代碼看起來像:

layout (std140, binding = 0) uniform bufferVals {
    mat4 mvp;
} myBufferVals;

這將uniform 緩衝區內容映射到myBufferVals結構。“set=M”沒有指定,默認爲0。

“std140”是描述數據如何在統一塊中打包的標準。如果您希望將更多的數據放在一個統一的塊中,您可能希望引用它。更多信息請查看 這個文檔

© Copyright 2016 LunarG, Inc

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章