소개

이전 챕터의 decsriptor 레이아웃은 바인딩할 수 있는 descriptor유형을 설명합니다. 이 챕터에서는 각 VkBuffer 리소스에 대한 descriptor set를 만들어 이를 uniform buffer descriptor에 바인딩하겠습니다.

Descriptor pool

descriptor set는 직접 만들 수 없으며, 명령 버퍼와 같은 풀에서 할당해야 합니다. descriptor set에 해당하는 것을 descriptor pool 이라고 하는 것은 당연합니다. 이를 설정하기 위해 새 함수 createDescriptorPool을 작성합니다.

void initVulkan() {
    ...
    createUniformBuffers();
    createDescriptorPool();
    ...
}

...

void createDescriptorPool() {

}

먼저 VkDescriptorPoolSize 구조체를 사용하여 descriptor set에 포함될 descriptor 유형과 몇 개가 있는지를 설명해야 합니다.

VkDescriptorPoolSize poolSize{};
poolSize.type = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
poolSize.descriptorCount = static_cast<uint32_t>(MAX_FRAMES_IN_FLIGHT);

모든 프레임에 대해 이러한 descriptor 중 하나를 할당합니다. 이 풀 크기 구조는 기본VkDescriptorPoolCreateInfo 에서 참조합니다.

VkDescriptorPoolCreateInfo poolInfo{};
poolInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO;
poolInfo.poolSizeCount = 1;
poolInfo.pPoolSizes = &poolSize;

사용 가능한 최대 descriptor 수 외에도 할당할 수 있는 descriptor set의 최대 수도 지정해야 합니다:

poolInfo.maxSets = static_cast<uint32_t>(MAX_FRAMES_IN_FLIGHT);

구조에는 개별 descriptor set를 해제할 수 있는지 여부를 결정하는 명령 풀과 유사한 선택적 플래그가 있습니다: VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT. descriptor set를 생성한 후에는 건드리지 않을 것이므로 이 플래그는 필요없습니다. flags를 기본 값인 0으로 둘 수 있습니다.

VkDescriptorPool descriptorPool;

...

if (vkCreateDescriptorPool(device, &poolInfo, nullptr, &descriptorPool) != VK_SUCCESS) {
    throw std::runtime_error("failed to create descriptor pool!");
}

descriptor pool에 핸들을 저장할 새 클래스 구성원을 추가하고 vkCraeteDescriptorPool을 호출하여 생성합니다.

Descriptor set

이제 descriptor set 자체를 할당할 수 있습니다. 이를 위해 createDescriptorSets 함수를 추가합니다.

void initVulkan() {
    ...
    createDescriptorPool();
    createDescriptorSets();
    ...
}

...

void createDescriptorSets() {

}

descriptor set은 VkDescriptorSetAllocateInfo 구조체로 설명됩니다. 할당할 descriptor pool와 할당할 descriptor set 수, 그리고 기반으로 할 descriptor 레이아웃을 지정해야 합니다:

std::vector<VkDescriptorSetLayout> layouts(MAX_FRAMES_IN_FLIGHT, descriptorSetLayout);
VkDescriptorSetAllocateInfo allocInfo{};
allocInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO;
allocInfo.descriptorPool = descriptorPool;
allocInfo.descriptorSetCount = static_cast<uint32_t>(MAX_FRAMES_IN_FLIGHT);
allocInfo.pSetLayouts = layouts.data();

우리의 경우 flight 중인 각 프레임에 대해 하나의 descriptor set를 만들고, 모두 동일한 레이아웃을 사용합니다. 불행하게도 다음 함수는 set 수와 일치하는 배열을 기대하기 때문에 레이아웃의 모든 복사본이 필요합니다.