Is there anyway to set the VkDescriptorImageInfo to null or have some way of skipping using a VkWriteDescriptorSet without vulkan complaining(有没有办法将VkDescriptorImageInfo设置为空,或者有某种方法跳过使用VkWriteDescriptorSet而不会出现Vulkan抱怨)
问题描述
我将使用的一些网格并不总是有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)
然后,如果我只是尝试将绑定设置为空,则会得到以下结果:
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()));
}
}
推荐答案
直到Vulkan1.2,Vulkan才认识到描述符为"空"的可能性。当创建描述符集时,描述符(大部分)未初始化。拥有一个带有未初始化描述符的集合是可以的,只要使用它的管道不会静态地使用描述符。由于您可能会尝试对具有漫反射贴图的对象和不具有漫反射贴图的对象使用相同的管线,因此着色器将根据您提供的变量从图像中读取。表示描述符的静态使用,因此您需要一个图像。
处理此问题的典型方法是创建一个格式合理的微型图像,并将其填充到描述符中。基本上,您可以对要使用的任何"空"纹理使用相同的图像。 作为升级到核心的VK_EXT_descriptor_indexing扩展的一部分,Vulkan 1.2允许部分绑定描述符的可能性。基本上,如果descriptorBindingPartiallyBound
特性可用并被请求,那么您可以使用VK_DESCRIPTOR_BINDING_PARTIALLY_BOUND_BIT
位来分配描述符集。这意味着只要描述符不是动态使用的,就可以不对其进行定义。
因此您根本不会为该描述符写入值。
当然,这需要1.2(或前述扩展),以及请求该功能。
这篇关于有没有办法将VkDescriptorImageInfo设置为空,或者有某种方法跳过使用VkWriteDescriptorSet而不会出现Vulkan抱怨的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持编程学习网!
本文标题为:有没有办法将VkDescriptorImageInfo设置为空,或者有某种方法跳过使用VkWriteDescriptorSet而不会出现Vulkan抱怨
基础教程推荐
- C++,'if' 表达式中的变量声明 2021-01-01
- 设计字符串本地化的最佳方法 2022-01-01
- 运算符重载的基本规则和习语是什么? 2022-10-31
- C++ 标准:取消引用 NULL 指针以获取引用? 2021-01-01
- 您如何将 CreateThread 用于属于类成员的函数? 2021-01-01
- 如何在 C++ 中处理或避免堆栈溢出 2022-01-01
- 什么是T&&(双与号)在 C++11 中是什么意思? 2022-11-04
- 调用std::Package_TASK::Get_Future()时可能出现争用情况 2022-12-17
- 如何定义双括号/双迭代器运算符,类似于向量的向量? 2022-01-01
- C++ 程序在执行 std::string 分配时总是崩溃 2022-01-01