PDA

View Full Version : Frag shader outputs as function argument strangeness



Dark Photon
05-13-2014, 06:34 AM
This has been working for years in a deferred rendering shader I wrote:


// --- Fragment shader ---

out vec4 my_FragData[4];

void writeGBuffer( out vec4 output[4], ... )
{
...
output[0] = ...;
output[1] = ...;
}

void main( void )
{
...
writeGBuffer( my_FragData, ... );
}


As you can see, nothing special. We're passing the frag shader MRT output into a function and letting it set its values.

One of my coworkers determined that this broke between NVidia drivers 319.76 and 325.08. Question is, are we violating any spec behavior above (I don't think we are), or is this a driver bug?

Interestingly, he found passing a temporary into the function and then copying the temporary to the frag shader output (my_FragData) was sufficient to work around the problem:


void main( void )
{
...
vec4 temp[4];
writeGBuffer( temp, ... );
my_FragData = temp;
}


Also, he found that passing in each frag shader output element separately works too:


void main( void )
{
...
writeGBuffer( my_FragData[0], my_FragData[1], my_FragData[2], my_FragData[3], ... );
}


So the problem in 325.08+ is specifically with passing shader output arrays into functions as arrays. Passing in other arrays works fine. And passing in frag shader outputs individually works fine.

Any spec violations you can see in what the first shader above is doing? Thanks!

Ilian Dinev
05-13-2014, 12:26 PM
Is a bug. The only peculiar thing about function-argument arrays, that might affect your code, is:
Function "out" args are fully copied-out at return. So, if you passed down a 4-element array to an "out", any element that the function didn't write to, will become garbage. Refer to section 6.1.1 "Function Calling Conventions" in the GLSL spec.

Dark Photon
05-13-2014, 08:13 PM
Thanks for the feedback, Ilian.

Had a typo in my first snippet above, where I should have referenced output[] instead of my_FragData[] inside the writeGBuffer() rtn (like the actual code does), but that was probably obvious. Fixed up the source above.