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

2023-11-22

我将使用的一些网格并不总是具有 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

验证层:无法对尚未分配的 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 并未认识到描述符为“空”的可能性。创建描述符集时,描述符(大部分)未初始化。拥有一个带有未初始化描述符的集合是可以的,只要消耗它的管道不这样做静态地使用描述符。由于您可能尝试对具有漫反射贴图的对象和没有漫反射贴图的对象使用相同的管道,因此您的着色器根据您提供的变量从图像中读取。这表示描述符的静态使用,因此您需要在那里有一个图像。

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

Vulkan 1.2,作为VK_EXT_描述符_索引扩展提升到核心,允许部分绑定描述符的可能性。基本上,如果descriptorBindingPartiallyBound功能可用且已请求,那么您可以使用以下方法分配描述符集VK_DESCRIPTOR_BINDING_PARTIALLY_BOUND_BIT少量。这意味着只要不动态使用描述符,就可以保留未定义的描述符。

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

当然,这需要 1.2(或前面提到的扩展),以及请求该功能。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

无论如何,是否有将 VkDescriptorImageInfo 设置为 null 或有某种方式跳过使用 VkWriteDescriptorSet 而不会出现 vulkan 抱怨 的相关文章

  • VLC 媒体播放器有 C# 界面吗? [关闭]

    Closed 这个问题正在寻求书籍 工具 软件库等的推荐 不满足堆栈溢出指南 help closed questions 目前不接受答案 是否可以使用 C 控制台应用程序中的包装器从 VLC 播放中当前播放的文件中读取曲目统计信息 时间 标
  • 捕获 .aspx 和 .ascx 页面中的异常

    问题说明了一切 请看以下示例代码 ul li li ul
  • 如何使用 openSSL 函数验证 PEM 证书的密钥长度

    如何验证以这种方式生成的 PEM 证书的密钥长度 openssl genrsa des3 out server key 1024 openssl req new key server key out server csr cp server
  • 关于逻辑/算法的想法以及如何防止线程写入 Sql Server 中的竞争

    我有以下逻辑 public void InQueueTable DataTable Table int incomingRows Table Rows Count if incomingRows gt RowsThreshold async
  • C# 中的 Stack<> 实现

    我最近一直在实现递归目录搜索实现 并且使用堆栈来跟踪路径元素 当我使用 string Join 连接路径元素时 我发现它们被颠倒了 当我调试该方法时 我查看了堆栈 发现堆栈内部数组中的元素本身是相反的 即最近 Push 的元素位于内部数组的
  • strlen() 编译时优化

    前几天我发现你可以找到编译时strlen使用这样的东西 template
  • C# 中一次性对象克隆会导致内存泄漏吗?

    检查这个代码 class someclass IDisposable private Bitmap imageObject public void ImageCrop int X int Y int W int H imageObject
  • 2个对象,完全相同(除了命名空间)c#

    我正在使用第三方的一组网络服务 但遇到了一个小障碍 在我手动创建将每个属性从源复制到目标的方法之前 我想我应该在这里寻求更好的解决方案 我有 2 个对象 一个是 Customer CustomerParty 类型 另一个是 Appointm
  • C# 根据当前日期传递日期时间值

    我正在尝试根据 sql server 中的两个日期获取记录 Select from table where CreatedDate between StartDate and EndDate我通过了5 12 2010 and 5 12 20
  • Unity手游触摸动作不扎实

    我的代码中有一种 错误 我只是找不到它发生的原因以及如何修复它 我是统一的初学者 甚至是统一的手机游戏的初学者 我使用触摸让玩家从一侧移动到另一侧 但问题是我希望玩家在手指从一侧滑动到另一侧时能够平滑移动 但我的代码还会将玩家移动到您点击的
  • Linux 上的 RTLD_LOCAL 和dynamic_cast

    我们有一个由应用程序中的一些共享库构成的插件 我们需要在应用程序运行时更新它 出于性能原因 我们在卸载旧插件之前加载并开始使用新插件 并且只有当所有线程都使用旧插件完成后 我们才卸载它 由于新插件和旧插件的库具有相同的符号 我们dlopen
  • 保证复制省略是否适用于函数参数?

    如果我理解正确的话 从 C 17 开始 这段代码现在要求不进行任何复制 Foo myfunc void return Foo auto foo myfunc no copy 函数参数也是如此吗 下面的代码中的副本会被优化掉吗 Foo myf
  • LinkLabel 无下划线 - Compact Framework

    我正在使用 Microsoft Compact Framework 开发 Windows CE 应用程序 我必须使用 LinkLabel 它必须是白色且没有下划线 因此 在设计器中 我将字体颜色修改为白色 并在字体对话框中取消选中 下划线
  • 在 azure blob 存储中就地创建 zip 文件

    我将文件存储在 Blob 存储帐户内的一个容器中 我需要在第二个容器中创建一个 zip 文件 其中包含第一个容器中的文件 我有一个使用辅助角色和 DotNetZip 工作的解决方案 但由于 zip 文件的大小最终可能达到 1GB 我担心在进
  • MySQL 连接器 C++ 64 位在 Visual Studio 2012 中从源代码构建

    我正在尝试建立mySQL 连接器 C 从源头在视觉工作室2012为了64 bit建筑学 我知道这取决于一些boost头文件和C 连接器 跑步CMake生成一个项目文件 但该项目文件无法编译 因为有一大堆非常令人困惑的错误 这些错误可能与包含
  • 读取依赖步行者输出

    I am having some problems using one of the Dlls in my application and I ran dependency walker on it i am not sure how to
  • 以编程方式创建 Blob 存储容器

    我有一个要求 即在创建公司时 在我的 storageaccount 中创建关联的 blob 存储容器 并将容器名称设置为传入的字符串变量 我已尝试以下操作 public void AddCompanyStorage string subDo
  • 如何获取带有某个属性注释的所有属性?

    我刚刚从 Roslyn 开始 我想找到所有用属性名称 OneToOne 注释的属性 我启动了 SyntaxVisualizer 并能够获取对该节点的引用 但我想知道是否有更简单的方法来实现此目的 这就是我所拥有的 var prop docu
  • 任何人都可以清楚地告诉如何在不使用像 这样的预定义函数的情况下找到带有小数值或小数值的指数吗? [关闭]

    Closed 这个问题需要多问focused help closed questions 目前不接受答案 例如 2 0 5 1 414 所以想要 我是 c 的新手 所以请解释简单的逻辑 如果不是复杂的逻辑也足够了 在数学中 从整数取幂到实数
  • 如何组合两个 lambda [重复]

    这个问题在这里已经有答案了 可能的重复 在 C 中组合两个 lambda 表达式 https stackoverflow com questions 1717444 combining two lamba expressions in c

随机推荐