OpenGL/ES, multiple draw buffers, dual source blending and layout assignments
I've seen shader linking errors in the form of
Error: Output fsout_c1 location or component exceeds max allowed.
showing up. The logs showed usage of glBindFragDataLocationIndexed()
, which led to GL_EXT_blend_func_extended. However, in this specific case no dual source blending was done, but it was a FBO with 4 color attachments. The first 2 of the output colors got assigned via glBindFragDataLocationIndexed()
, the other 2 were unassigned. The shader code listed the output variables like this:
out vec4 fsout_c0;
out vec4 fsout_c1;
out vec4 fsout_c2;
out vec4 fsout_c3;
In case there are 2 or more fragment shader outputs, OpenGL/ES requires an explicit layout assignment for all of them (OpenGL/ES 3.2, 14.2.3). With GL_EXT_blend_func_extended in place that is not the case anymore, if the extension is enabled in the shader code:
"If there is more than one fragment output, the location must
be specified for all outputs unless the EXT_blend_func_extended
extension is enabled in which case more than one unassigned fragment
output locations are allowed though they must be assigned to unique
locations assigned with glBindFragDataLocationIndexedEXT prior to
linking."
and
When a program is linked, any varying out variables without
a binding specified through BindFragDataLocationIndexedEXT or
BindFragDataLocationEXT will automatically be bound to fragment
colors and indices by the GL. All such assignments will use color
indices of zero. Such bindings can be queried using the commands
GetFragDataLocation and GetFragDataIndexEXT.
For auto-assignments the extension must be enabled in the shader code, otherwise explicit assignments are necessary for all outputs (if there are 2 or more). If I read this correctly, glBindFragDataLocation{Indexed}()
doesn't count as explicit assignment, i.e. that must happen in the shader code with the layout
specifier.
I've been experimenting with the Nvidia OpenGL/ES layer plus the Qualcomm Adreno driver. I will create a more systematic list and check against that (kind of permuations of the requirements), and how they react to that. However, the way virglrenderer deals with these things currently is not exactly correct when it comes to OpenGL/ES.