Есть ли способ установить для VkDescriptorImageInfo значение null или иметь какой-либо способ пропустить с помощью VkWriteDescriptorSet без жалоб вулкана - PullRequest
3 голосов
/ 09 мая 2020

Некоторые из me sh, которые я буду использовать, не всегда имеют DiffuseMap или SpecularMap. Когда я пытаюсь загрузить что-то без диффузной и зеркальной карты, программа вылетает, потому что в DiffuseMap.ImageView / SpecularMap.ImageView ничего нет, потому что он ни на что не указывает. Если я попытаюсь установить для imageview / sample значение VK_NULL_HANDLE, программа выдаст мне это и выйдет из строя на vkUpdateDescriptorSets:

Validation Layer: Invalid VkImageView Object 0x0. The Vulkan spec states: If descriptorType is VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, or VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT, the imageView and imageLayout members of each element of pImageInfo must be a valid VkImageView and VkImageLayout, respectively (https://www.khronos.org/registry/vulkan/specs/1.1-extensions/html/vkspec.html#VUID-VkWriteDescriptorSet-descriptorType-00326)

Затем, если я просто попробую установить привязку на null, я получу следующее:

Validation Layer: vkUpdateDescriptorSets: required parameter pDescriptorWrites[2].dstSet specified as VK_NULL_HANDLE

Уровень проверки: Невозможно вызвать vkUpdateDescriptorSets () для VkDescriptorSet 0x0 [], который не был выделен.

Вот как сейчас выглядит базовый код. Это область, которая определяет наборы дескрипторов, чтобы было легче увидеть, что происходит:

void Mesh::CreateDescriptorSets(VulkanRenderer& Renderer)
{
    BaseMesh::CreateDescriptorSets(Renderer, *GetDescriptorSetLayout(Renderer));

VkDescriptorImageInfo DiffuseMap = {};
DiffuseMap.imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
DiffuseMap.imageView = TextureList[0].textureImageView;
DiffuseMap.sampler = TextureList[0].textureSampler;

VkDescriptorImageInfo SpecularMap = {};
SpecularMap.imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
SpecularMap.imageView = TextureList[1].textureImageView;
SpecularMap.sampler = TextureList[1].textureSampler;

for (size_t i = 0; i < GetSwapChainImageCount(Renderer); i++)
{
    VkDescriptorBufferInfo PositionInfo = {};
    PositionInfo.buffer = uniformBuffers[i];
    PositionInfo.offset = 0;
    PositionInfo.range = sizeof(UniformBufferObject);

    VkDescriptorBufferInfo AmbiantLightInfo = {};
    AmbiantLightInfo.buffer = AmbientLightUniformBuffers[i];
    AmbiantLightInfo.offset = 0;
    AmbiantLightInfo.range = sizeof(AmbientLightUniformBuffer);

    VkDescriptorBufferInfo LightInfo = {};
    LightInfo.buffer = LighterUniformBuffers[i];
    LightInfo.offset = 0;
    LightInfo.range = sizeof(Lighter);

    std::array<WriteDescriptorSetInfo, 5>  WriteDescriptorInfo = {};

    WriteDescriptorInfo[0].DstBinding = 0;
    WriteDescriptorInfo[0].DstSet = descriptorSets[i];
    WriteDescriptorInfo[0].DescriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
    WriteDescriptorInfo[0].DescriptorBufferInfo = PositionInfo;

    WriteDescriptorInfo[1].DstBinding = 1;
    WriteDescriptorInfo[1].DstSet = descriptorSets[i];
    WriteDescriptorInfo[1].DescriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
    WriteDescriptorInfo[1].DescriptorImageInfo = DiffuseMap;

    WriteDescriptorInfo[2].DstBinding = 2;
    WriteDescriptorInfo[2].DstSet = descriptorSets[i];
    WriteDescriptorInfo[2].DescriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
    WriteDescriptorInfo[2].DescriptorImageInfo = SpecularMap;

    WriteDescriptorInfo[3].DstBinding = 3;
    WriteDescriptorInfo[3].DstSet = descriptorSets[i];
    WriteDescriptorInfo[3].DescriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
    WriteDescriptorInfo[3].DescriptorBufferInfo = AmbiantLightInfo;

    WriteDescriptorInfo[4].DstBinding = 4;
    WriteDescriptorInfo[4].DstSet = descriptorSets[i];
    WriteDescriptorInfo[4].DescriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
    WriteDescriptorInfo[4].DescriptorBufferInfo = LightInfo;

    Mesh::CreateDescriptorSetsData(Renderer, std::vector<WriteDescriptorSetInfo>(WriteDescriptorInfo.begin(), WriteDescriptorInfo.end()));
}

}

1 Ответ

2 голосов
/ 09 мая 2020

До Vulkan 1.2 Vulkan не распознавал возможность того, что дескриптор «пустой». Когда создается набор дескрипторов, дескрипторы (в основном) не инициализируются. Это нормально иметь набор с неинициализированным дескриптором, если конвейер, который его потребляет, не использует статически дескриптор. Поскольку вы, вероятно, пытаетесь использовать один и тот же конвейер для объектов с диффузными картами и объектов без них, ваш шейдер читает из изображения на основе указанной вами переменной. Это представляет собой статическое c использование дескриптора, поэтому вам нужно там изображение.

Типичный способ справиться с этим - создать крошечное изображение разумного формата и вставить его в дескриптор. Вы можете использовать одно и то же изображение практически для любой "нулевой" текстуры, которую хотите использовать.

Vulkan 1.2, как часть VK_EXT_descriptor_indexing расширения, продвинутого в ядро, допускает возможность частичного связывания дескрипторы. В основном, если функция descriptorBindingPartiallyBound доступна и запрошена, вы можете выделить набор дескрипторов с помощью бита VK_DESCRIPTOR_BINDING_PARTIALLY_BOUND_BIT. Это означает, что можно оставить дескриптор неопределенным, если он не используется динамически.

Таким образом, вы просто не стали бы записывать значение для этого дескриптора.

Конечно, для этого требуется 1.2 (или вышеупомянутое расширение), а также запрос функции.

...