0
votes

I wrote a very simple compute shader that reads a uniform buffer with size of exactly 1KB bound to descriptor set and goes through it as an array of 256 uint(s), then for each element, doubles the value and writes the result in another storage buffer bound to descriptor set (and also defined in shader of course):

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

The input data, is provided through the uniform buffer, whose memory is allocated, and written to, before running the shader. I simply overwrite each byte with the value of 3:

memset(*mappedMemory, 3, 1024);

The result values written by shader into the storage buffer is strange, a quarter of data seems to be correct, the result, filled with 0s: enter image description here

I checked several points in the code where a size or offset is provided to Vulkan functions and all of them are 1024 (1KB) and 0, respectively.

I guess this could be because how Vulkan compute shader reads data from uniform buffer memories, and std140 data layout could be the source of this issue, but, to the best of my knowledge, the tutorials/specifications doesn't mention anything in-between offset requirements!

1

1 Answers

1
votes

You have forgotten how std140 layout works. Elements in arrays of basic types are always 16 bytes in size. So your uint values[256]; is really a uvec4 values[256];.

You should use a uvec4 values[64]; array, and index it like this:

outputBuffer.values[i] = inputBuffer.values[i / 4][i % 4] * 2;