Vulkan 从整数中解压 uvec4

Vulkan unpack uvec4 from integer

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

layout (location = 0) in uvec4 coords;

为了实现这一点,我使用 VkVertexInputAttributeDescription 并将 format 设置为 VK_FORMAT_R8G8B8A8_UINT。我已经定义了这样方便的结构

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

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

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

我得到的字节顺序相反。矢量类型是否使用不同的字节顺序?

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

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

字节顺序适用于读写,但当reading/writing多字节值as多字节值时.您的 PackedUVec4 而不是 多字节值;它是一个包含具有 特定 布局的字节的结构。因此,如果您写入 PackedUVec4x 组件,您将写入该结构的第一个字节, 不管 CPU 的 的字节序。

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

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

如果您希望您的代码与端序无关,那么您需要 GPU 将数据读取为 4 个单独的字节,按照存储在内存中的顺序。 VK_FORMAT_R8G8B8A8_UINT 代表什么。如果您希望 GPU 在单个 32 位整数中将其读取为基于字节序的顺序,则需要 written CPU.