glslvulkanssbo

Write SSBO in VS and read from FS


Using Vulkan library I have a vec3[] positions calculated in Vertex shader (hundreds of omni light positions transformed by TBN matrix), which I wish to pass to the fragment shader for reading.

I try to have an SSBO buffer created for this, with VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT flag, since no data will be uploaded to it from client CPU side (only VS writes, then FS reads from it). While the buffer works, I have read/write hazard.

The buffer in shader:

//ssbo for TS omni
layout(set=0, binding=11) coherent buffer OmniPositionsTS
{
    vec3 mOmniPositionsTS[];
};

Instead of SSBO, tried a simple array[16] 'out', consumed as 'in' variable in FS, and it works like a charm, but of course i am very limited with under 32 such in/out attribute, so going back for the SSBO solution:

Does this all mean the fragment shader does not wait for vertex shader to finish writing the SSBO? How come that other shader varying 'out' and 'in' variables do not suffer from this race condition?

Should i invoke memoryBarrier in the vertex shader? Generally, what is the preferred way to pass TBN transformed light positions to fragment shaders?


Solution

  • In accord with the Vulkan memory model, a fragment shader can only rely on the products of execution of the vertex shader invocations needed to generate that particular fragment. That is, if you're rendering a triangle, all of the fragment shaders that are executed as a result of that triangle can freely read data written by the 3 vertex shader invocations which were responsible for generating that triangle.

    Without additional synchronization, all other data written by VS invocations around the triangle cannot be accessed by the FS. And no, a memory barrier in the shader doesn't count. You need a hard execution dependency between the VS invocations generating the data and the FS invocations receiving it. This would generally be some kind of pipeline barrier containing a memory barrier. And that requires the VS invocations generating the data to be in a different draw function call from the FS invocations reading it.