Vulkan 从整数解包 uvec4

Vulkan unpack uvec4 from integer

提问人:alagris 提问时间:8/14/2021 更新时间:8/14/2021 访问量:674

问:

我观察到一些奇怪的行为。我有一个无符号的 32 位整数数组。 我使用一个整数对 4 个值进行编码,每个值的大小为 1 个字节。然后我想将这样的缓冲区传递给顶点着色器

layout (location = 0) in uvec4 coords;

为了实现这一点,我使用 with set to .我已经定义了这样一个方便的结构VkVertexInputAttributeDescriptionformatVK_FORMAT_R8G8B8A8_UINT

struct PackedUVec4{
   unsigned char x;
   unsigned char y;
   unsigned char z;
   unsigned char w;
};

然后我构建我的缓冲区,然后将该缓冲区发送到 GPU。但是,我观察到的是字节的顺序被交换了。例如,如果我有PackedUVec4[]

layout (location = 0) in uvec4 coords;
void main(){
   debugPrintfEXT("%v4d", coords);
}

它似乎打印了正确的输出。但是,如果将格式更改为并尝试运行VK_FORMAT_R32_UINT

layout (location = 0) in uint coords;
void main(){
    uint w = coords & 255u;
    uint z = coords/256 & 255u;
    uint y = coords/(256*256) & 255u;
    uint x = coords/(256*256*256) & 255u;
    debugPrintfEXT("%v4d", uvec4(x,y,z,w));
}

我以相反的顺序获取字节。向量类型是否使用不同的字节序?

glsl 字节 vulkan vec

评论

0赞 Nicol Bolas 8/14/2021
我不明白这个问题。您认识到多字节整数中字节的逻辑顺序与内存中这些字节的寻址顺序(即:字节序)之间存在区别。但是,当多字节整数中字节的逻辑顺序与您的寻址顺序不匹配时,您不知道这意味着什么?
0赞 alagris 8/14/2021
我的意思是,我认为 GPU 应该使用与我的 CPU 相同的字节序。我正在尝试在 GPU 上进行一些位移,但我经常遇到错误,因为字节顺序与我预期的不同。但是我在 Vulkan 文档中找不到任何关于此的内容。如何可靠地预测 GPU 上的字节序?由于这个问题,我有点担心我当前的代码会在不同的机器上完全崩溃。
0赞 Nicol Bolas 8/14/2021
"我认为 GPU 应该使用与我的 CPU 相同的字节序。确实如此。问题是没有。您反转了 CPU 上数据的字节序。也就是说,您的代码对数据的实际字节序感到困惑。“但我在 Vulkan 文档中找不到任何关于此的内容。”您可以转到 PDF 并搜索“endian”并找到它。

答:

2赞 Nicol Bolas 8/14/2021 #1

问题不在于 Vulkan,而在于你的代码对正在发生的事情的解释。发送和接收。

回想一下,字节序是关于多字节值中字节的逻辑位置与多字节值中字节的相对地址之间的(潜在)差异。在 little endian 中,如果将一个四字节的值写入内存,则第一个字节将是该值中最低有效字节。

字节序适用于读取和写入,但仅在将多字节值作为多字节值读取/写入时。您不是多字节值;它是一个包含具有特定布局的字节的结构。因此,如果写入 的组件,则无论 CPU 的字节序如何,您都是在写入该结构的第一个字节。PackedUVec4xPackedUVec4

当您告诉 Vulkan 将此数据作为单个 4 字节值 () 读取时,它会按照 CPU 的字节序定义进行读取。但是您的代码没有按照 CPU 的字节序生成该数据;它根据 .所以内存中的第一个字节是 。如果 GPU 将这 4 个字节读取为小字节序 4 字节值,则第一个字节将映射到 4 字节值的最低有效字节。VK_FORMAT_R32_UINTPackedUVec4x

但是手动解码数据的代码解码错误。它期望最低有效字节为 。w

如果您希望您的代码与字节序无关,那么您需要 GPU 按照存储在内存中的顺序将数据读取为 4 个单独的字节。这就是所代表的。如果您希望 GPU 将其读取为单个 32 位整数内基于字节序的排序,则需要由 CPU 以这种方式写入它。VK_FORMAT_R8G8B8A8_UINT