Vulkan 计算着色器只读取部分统一缓冲区
Vulkan compute shader reading only parts of the uniform buffer
我写了一个非常简单的计算着色器,它读取大小正好为 1KB 的统一缓冲区绑定到描述符集,并作为 256 的数组遍历它 uint
(s),然后对于每个元素,将值加倍并将结果写入绑定到描述符集的另一个存储缓冲区(并且也在着色器中定义当然):
#version 450 core
layout (local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
layout(set = 0, binding = 0) uniform InputBuffer
{
uint values[256];
} inputBuffer;
layout(set = 0, binding = 1) buffer OutputBuffer
{
uint values[256];
} outputBuffer;
void main(void)
{
for(int i = 0; i < 256; i++) {
outputBuffer.values[i] = inputBuffer.values[i] * 2;
}
return;
}
输入数据通过统一缓冲区提供,在 运行 着色器之前分配并写入其内存。我只是用 3:
的值覆盖每个字节
memset(*mappedMemory, 3, 1024);
shader写入存储缓冲区的结果值很奇怪,四分之一的数据似乎是正确的,结果,用0s填充:
我检查了代码中为 Vulkan 函数提供大小或偏移量的几个点,它们都是 1024 (1KB) 和 0, 分别.
我想这可能是因为 Vulkan 计算着色器如何从统一缓冲存储器读取数据,而 std140 数据布局可能是这个问题的根源,但据我所知,tutorials/specifications 没有'提及任何介于两者之间的偏移要求!
您忘记了 std140
布局的工作原理。基本类型数组中的元素总是 16 字节大小。所以你的uint values[256];
是真的一个uvec4 values[256];
。
您应该使用 uvec4 values[64];
数组,并像这样对其进行索引:
outputBuffer.values[i] = inputBuffer.values[i / 4][i % 4] * 2;
我写了一个非常简单的计算着色器,它读取大小正好为 1KB 的统一缓冲区绑定到描述符集,并作为 256 的数组遍历它 uint
(s),然后对于每个元素,将值加倍并将结果写入绑定到描述符集的另一个存储缓冲区(并且也在着色器中定义当然):
#version 450 core
layout (local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
layout(set = 0, binding = 0) uniform InputBuffer
{
uint values[256];
} inputBuffer;
layout(set = 0, binding = 1) buffer OutputBuffer
{
uint values[256];
} outputBuffer;
void main(void)
{
for(int i = 0; i < 256; i++) {
outputBuffer.values[i] = inputBuffer.values[i] * 2;
}
return;
}
输入数据通过统一缓冲区提供,在 运行 着色器之前分配并写入其内存。我只是用 3:
的值覆盖每个字节memset(*mappedMemory, 3, 1024);
shader写入存储缓冲区的结果值很奇怪,四分之一的数据似乎是正确的,结果,用0s填充:
我检查了代码中为 Vulkan 函数提供大小或偏移量的几个点,它们都是 1024 (1KB) 和 0, 分别.
我想这可能是因为 Vulkan 计算着色器如何从统一缓冲存储器读取数据,而 std140 数据布局可能是这个问题的根源,但据我所知,tutorials/specifications 没有'提及任何介于两者之间的偏移要求!
您忘记了 std140
布局的工作原理。基本类型数组中的元素总是 16 字节大小。所以你的uint values[256];
是真的一个uvec4 values[256];
。
您应该使用 uvec4 values[64];
数组,并像这样对其进行索引:
outputBuffer.values[i] = inputBuffer.values[i / 4][i % 4] * 2;