Vulkan API — урок 51. Обновление дескрипторов

Для получения шейдером изображения через объект sampler нам понадобится дескриптор (descriptor). Ранее в уроках uniform buffers дескрипторы уже встречались, сейчас же посмотрим с новый тип дескрискриптора: combined image sampler. Необходимо изменить следующие дескрипторы: макета (layout), пула (pool) и набора (set).

Перейдем к функции createDescriptorSetLayout и добавим VkDescriptorSetLayoutBinding для создания комбинированного дескриптора sampler’а изображения. По сути просто добавим еще одну связь:

VkDescriptorSetLayoutBinding samplerLayoutBinding = {};
samplerLayoutBinding.binding = 1;
samplerLayoutBinding.descriptorCount = 1;
samplerLayoutBinding.descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
samplerLayoutBinding.pImmutableSamplers = nullptr;
samplerLayoutBinding.stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT;

std::array<VkDescriptorSetLayoutBinding, 2> bindings = {uboLayoutBinding, samplerLayoutBinding};
VkDescriptorSetLayoutCreateInfo layoutInfo = {};
layoutInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO;
layoutInfo.bindingCount = bindings.size();
layoutInfo.pBindings = bindings.data();

Стоит убедиться, что установлен флаг stageFlags для указания намерения использовать комбинированный дескриптор в fragment shader. Вот где цвет фрагмента будет определяться. Можно использовать выборку из текстуры в vertex shader, например для динамической искажения сетки вершин с помощью карты высот (правда на .ру вики толком ничего и не написано).

После этого придется дорабатывать пул дескрипторов, он тоже должен быть комбинированным. Теперь редактируем функцию createDescriptorPool, добавляем VkDescriptorPoolSize:

std::array<VkDescriptorPoolSize, 2> poolSizes = {};
poolSizes[0].type = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
poolSizes[0].descriptorCount = 1;
poolSizes[1].type = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
poolSizes[1].descriptorCount = 1;

VkDescriptorPoolCreateInfo poolInfo = {};
poolInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO;
poolInfo.poolSizeCount = poolSizes.size();
poolInfo.pPoolSizes = poolSizes.data();
poolInfo.maxSets = 1;

И последний шаг в процессе связывания реального изображения и sampler – доработать набор дескрипторов, изменения функции createDescriptorSet:

VkDescriptorImageInfo imageInfo = {};
imageInfo.imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
imageInfo.imageView = textureImageView;
imageInfo.sampler = textureSampler;

Ресурсы для комбинированной структуры sampler’а изображения должны быть указаны в структуре VkDescriptorImageInfo, аналогично ресурсам дескриптора uniform buffer, указанным в струтуре VkDescriptorBufferInfo. Это место, где объекты из предыдущих уроков собираются вместе.

std::array<VkWriteDescriptorSet, 2> descriptorWrites = {};

descriptorWrites[0].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
descriptorWrites[0].dstSet = descriptorSet;
descriptorWrites[0].dstBinding = 0;
descriptorWrites[0].dstArrayElement = 0;
descriptorWrites[0].descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
descriptorWrites[0].descriptorCount = 1;
descriptorWrites[0].pBufferInfo = &bufferInfo;

descriptorWrites[1].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
descriptorWrites[1].dstSet = descriptorSet;
descriptorWrites[1].dstBinding = 1;
descriptorWrites[1].dstArrayElement = 0;
descriptorWrites[1].descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
descriptorWrites[1].descriptorCount = 1;
descriptorWrites[1].pImageInfo = &imageInfo;

vkUpdateDescriptorSets(device, descriptorWrites.size(), descriptorWrites.data(), 0, nullptr);

Теперь теперь шейдеры могут использовать дескриптор.

Main Admin

Добавить комментарий

Ваш e-mail не будет опубликован. Обязательные поля помечены *