Vulkan忽略GLSL图像格式限定符

问题描述

我有一个计算着色器,它使用imageLoad读取带符号的标准化整数图像。

图像本身(包含正值和负值)被创建为R16G16_SnorM,并由片段着色器在先前的gpass中写入。 绑定到计算着色器中的descriptorsetlayout绑定的imageview也使用相同的R16G16_SnorM格式创建。

一切正常。

昨天,我意识到在计算着色器中我使用了错误的图像格式限定符rg16。 有点困惑(我无法理解它如何读取未签名的归一化值),我更正为rg16_snorm,并且..没有任何改变。

我执行了几次测试(甚至指定了rg16f),并且始终得到相同的结果(正确的[-1,1]签名)。

似乎Vulkan(至少是我的实现)地忽略了任何图像格式限定符,而后退(我想)为绑定到描述符集的imageview格式。

这似乎与有关imageview创建中格式的规范一致

format是VkFormat,描述了用于解释图像中纹理元素的格式和类型

但是然后在附录A(用于SPIR-V的Vulkan环境-“ SPIR-V图像格式和Vulkan格式之间的兼容性”)中,Rg16和Rg16Snorm之间有明显的区别。..

错误还是功能

我正在使用Ubuntu 20.04下的Nvidia 2070 Super

更新

最初的图像写入操作是片段着色器颜色附件输出的结果,因此没有描述符设置布局绑定声明。片段着色器将vec2输出R16G16_SnorM颜色附件,由活动帧缓冲区和renderpass指定。

通过着色器作为图像/图像加载操作然后(正确地,尽管布局限定符不正确)读取生成的图像(在相关障碍之后)。

请注意,验证层已启用且处于静状态。

还请注意,使用rg16rg16frg16_snorm,结果值与随机值相差甚远,并且与期望值(正值和负值)完全匹配。

解决方法

您得到的是未定义的行为。

对图像写入操作进行了验证检查,以防止%dw 2.0 output application/json --- { (abc: payload.XML.ABC) if (payload.XML.ABC?) //abc will be written only if it exists in the payload (whether its value is nil or not) (def: payload.XML.DEF) if (payload.XML.DEF?) //def will be written only if it exists in the payload (whether its value is nil or not) } 的格式(与GLSL中的OpTypeImage格式说明符相同)与后勤layout的格式不兼容。格式:

如果VkImageView的图像格式与OpTypeImage的格式不兼容,则写操作将导致图像存储器的内容变得不确定。

请注意,当它说“兼容”时,并不表示图像视图兼容。意思是"exactly match"。您的VkImageView格式与着色器不完全匹配,因此您的写入内容未定义。 “未定义”可能意味着“就像您指定了正确的格式一样工作。”