Created attachment 136344 [details]
Test case showing the problem
There is a piglit test called arb_enhanced_layouts-transform-feedback-layout-qualifiers which tests transform feedback with a float array output like this:
layout(xfb_offset = 4) out float x2_out;
It verifies that the two floats in the array are written out to the XFB buffer packed tightly together. This works ok and seems to make sense. I have been trying to get this working with SPIR-V which effectively requires adding an explicit location. If you do this, then I think Mesa ends up assigning a separate location to each element of the array which means there will be three wasted components in each location. This is presumably the correct behaviour. However, this seems to be also affecting the XFB and the second element no longer gets written out.
I was thinking maybe the second would get written out with some padding in-between but this doesn’t seem to be the case. In any case on the proprietary nVidia driver it continues to write the two values out packed together even with an explicit location so I don’t think padding them out would be the correct behaviour.
I think the problem is that the XFB linking code assumes that float arrays are packed into components of a varying location. So for example an array like float will end up generating two XFB outputs, one reading from a vec4 varying and the other from a vec2 varying. This mostly works because lower_packed_varyings usually lowers the varying arrays to floats. However it doesn’t do this if the varying has an explicit location so the generated outputs read from the wrong varyings. It looks like link_varyings only takes into account the types of varyings before the optimisation so it doesn’t know if the varyings have been packed or not. Maybe a way to fix it would be to get it to look out the optimised varyings.
Incidentally for the SPIR-V linker it is already using the nir_variables to determine the XFB outputs so it already has the optimised types and this is easier to fix. (I was previously planning to fix this bug for GLSL and do the same thing for SPIR-V, but now I think fixing it for GLSL is harder).