繁体   English   中英

无论如何将 VkDescriptorImageInfo 设置为 null 或有某种方式使用 VkWriteDescriptorSet 跳过而不会抱怨 vulkan

[英]Is there anyway to set the VkDescriptorImageInfo to null or have some way of skipping using a VkWriteDescriptorSet without vulkan complaining

我将使用的一些网格并不总是有 DiffuseMap 或 SpecularMap。 当我尝试加载没有漫反射和镜面反射 map 的东西时,程序崩溃,因为 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

验证层:无法在尚未分配的 VkDescriptorSet 0x0[] 上调用 vkUpdateDescriptorSets()。

这就是基本代码现在的样子。 这是定义描述符集的区域,以便更容易看到正在发生的事情:

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()));
}

}

在 Vulkan 1.2 之前,Vulkan 无法识别描述符为“空”的可能性。 创建描述符集时,描述符(大部分)未初始化。 有一个带有未初始化描述符的集合是可以的,只要消耗它的管道不静态使用描述符。 由于您可能正在尝试对具有漫反射贴图的对象和没有它们的对象使用相同的管道,因此您的着色器根据您提供的变量从图像中读取。 那代表 static 使用了描述符,所以你需要一个图像。

处理这个问题的典型方法是创建一个合理格式的小图像并将其填充到描述符中。 您可以将相同的图像用于您想要使用的任何“空”纹理。

Vulkan 1.2,作为提升到核心的VK_EXT_descriptor_indexing扩展的一部分,允许部分绑定描述符的可能性。 基本上,如果descriptorBindingPartiallyBound特性可用并且被请求,那么您可以使用VK_DESCRIPTOR_BINDING_PARTIALLY_BOUND_BIT位分配一个描述符集。 这意味着只要不动态使用描述符,就可以保留未定义的描述符。

所以你根本不会为那个描述符写一个值。

当然,这需要 1.2(或上述扩展),以及请求该功能。

您不太正确,由于某种原因,组合图像采样器仍然需要有效的采样器,不仅如此,还必须启用 nullDescriptor 功能。 我遇到了完全相同的问题。 没有人说过的是,部分绑定的描述符与稀疏绑定的描述符不同,所以它基本上意味着如果 X<N,y 可以从 N 中绑定 X 个描述符,但所有这些 X 必须是有效的,规范在这方面非常薄,并且没有好的例子。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM