Bug 96765 - BindFragDataLocationIndexed on array fragment shader output.
Summary: BindFragDataLocationIndexed on array fragment shader output.
Status: RESOLVED FIXED
Alias: None
Product: Mesa
Classification: Unclassified
Component: Mesa core (show other bugs)
Version: 11.2
Hardware: Other Linux (All)
: medium normal
Assignee: mesa-dev
QA Contact: mesa-dev
URL:
Whiteboard:
Keywords:
Depends on:
Blocks:
 
Reported: 2016-07-01 17:04 UTC by Corentin Wallez
Modified: 2016-07-08 19:37 UTC (History)
2 users (show)

See Also:
i915 platform:
i915 features:


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Corentin Wallez 2016-07-01 17:04:59 UTC
While trying to make Chromium use the 3.3 core profile of Mesa 11.2, the following bug showed up.

When trying to use an array fragment varying variable as the secondary fragment color (index = 0) the driver seems to decide to set it to another location instead. Causing nothing to be rendered. The same code with non-array variables provides the expected result.

Repro case at https://github.com/Kangz/GLDriverBugs/blob/master/blend_func_extended_array/Main.cpp running it shows that SecondaryFragData[0] is set to location 1 index 0 instead of location 0 index 1.
Comment 1 Ilia Mirkin 2016-07-06 01:19:07 UTC
Are you sure that's correct? It's unclear from the spec that you should be able to set arbitrary array indices' frag data locations/index values. Your test case works with:

diff --git a/blend_func_extended_array/Main.cpp b/blend_func_extended_array/Main.cpp
index 5718d0f..31217ee 100644
--- a/blend_func_extended_array/Main.cpp
+++ b/blend_func_extended_array/Main.cpp
@@ -29,8 +29,8 @@ class BlendFuncExtendedArray : public GLFWApp {
                    })";
 
             mProgram = CompileProgramStuffBeforeLink(vs, fs, [](GLuint program){
-                glBindFragDataLocationIndexed(program, 0, 0, "FragData[0]");
-                glBindFragDataLocationIndexed(program, 0, 1, "SecondaryFragData[0]");
+                glBindFragDataLocationIndexed(program, 0, 0, "FragData");
+                glBindFragDataLocationIndexed(program, 0, 1, "SecondaryFragData");
             });
             std::cout << "Location of FragData, should be 0: " << glGetFragDataLocation(mProgram, "FragData[0]") << std::endl;
             std::cout << "Index of FragData, should be 0: " << glGetFragDataIndex(mProgram, "FragData[0]") << std::endl;


Note that it's still arrays in the glsl.

Does this work with other drivers? If so, which ones?
Comment 2 Corentin Wallez 2016-07-06 14:58:24 UTC
Thanks for taking a look, indeed my understanding was wrong but I found a Khronos bug related to this that doesn't have a formal resolution but indicates that while you can't bind array elements individually, "array[0]" should be equivalent to "array". See https://cvs.khronos.org/bugzilla/show_bug.cgi?id=7829

Unfortunately Chrome has been testing this on few platforms, so far it only tested NVIDIA proprietary (passes), fglrx (doesn't pass). It also fails on the OSX drivers, seemingly for the same reason as for Mesa it seems.

Given all the above, I will fix Chromium's tests to not use indices, can you still consider making the [0] equivalent to no subscript?

Thank you for your time.
Comment 3 Ilia Mirkin 2016-07-06 15:33:26 UTC
(In reply to Corentin Wallez from comment #2)
> Thanks for taking a look, indeed my understanding was wrong but I found a
> Khronos bug related to this that doesn't have a formal resolution but
> indicates that while you can't bind array elements individually, "array[0]"
> should be equivalent to "array". See
> https://cvs.khronos.org/bugzilla/show_bug.cgi?id=7829
> 
> Unfortunately Chrome has been testing this on few platforms, so far it only
> tested NVIDIA proprietary (passes), fglrx (doesn't pass). It also fails on
> the OSX drivers, seemingly for the same reason as for Mesa it seems.
> 
> Given all the above, I will fix Chromium's tests to not use indices, can you
> still consider making the [0] equivalent to no subscript?
> 
> Thank you for your time.

That does seem reasonable. As I'm not one of the cool kids with KHR access, mind letting me know what that bug says about what to do when someone binds both "array" and "array[0]"? Right now we store these in a map, and resolve locations at link time (as per the spec). We don't know what's an array and what's not at bind time.

Also, does the bug make any comments about AoA? i.e.

out vec4 foo[2][2][2]

Should you be able to bind with "foo[0][0][0]"? What about "foo[0][0]" and "foo[0]" in that case? [Perhaps the AoA spec says something about this, I'm not up on all the details myself.]
Comment 4 Corentin Wallez 2016-07-06 17:32:12 UTC
The bug indicates that "array" and "array[0]" are identical so I'd assume that the binding done last takes precedence. I'm not sure about AofA, or if it's even allowed for fragment outputs.

Here's the relevant bit from the bug where a parallel with ARB_program_interface_query is made:

> I think my recommendation would be to adopt language similar to that for GetProgramResourceIndex(), allowing you to drop the "[0]" but not to address individual elements.  I don't think we want you to be able to assign "array[0]" to location 3 and "array[1]" to location 5, for example.

I also tried the changes you mentioned in Comment 1, while it fixes the values queried back from the driver, the triangle is still not being shown. Only making FragColor and SecondaryFragColor to be non-array floats make the triangle appear.
Comment 5 Ilia Mirkin 2016-07-06 18:06:31 UTC
(In reply to Corentin Wallez from comment #4)
> I also tried the changes you mentioned in Comment 1, while it fixes the
> values queried back from the driver, the triangle is still not being shown.
> Only making FragColor and SecondaryFragColor to be non-array floats make the
> triangle appear.

Ah, right you are. I'm used to seeing piglit print a failure message when it didn't work. More investigating is left here.
Comment 6 Ilia Mirkin 2016-07-06 19:52:19 UTC
Oh, actually it should work now with the patch I pushed out last night but failed to mention, since it wasn't addressing the array issue. Double-checked on i965:

https://cgit.freedesktop.org/mesa/mesa/commit/?id=a37e46323c7e18bec4160f2f66847c10b7041dc1

commit a37e46323c7e18bec4160f2f66847c10b7041dc1
Author: Ilia Mirkin <imirkin@alum.mit.edu>
Date:   Fri Jul 1 19:10:36 2016 -0400

    glsl: don't try to lower non-gl builtins as if they were gl_FragData
    
    If a shader has an output array, it will get treated as though it were
    gl_FragData and rewritten into gl_out_FragData instances. We only want
    this to happen on the actual gl_FragData and not everything else.
    
    This is a small part of the problem pointed out by the below bug.
    
    Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=96765
    Signed-off-by: Ilia Mirkin <imirkin@alum.mit.edu>
    Reviewed-by: Marek Olšák <marek.olsak@amd.com>
    Reviewed-by: Kenneth Graunke <kenneth@whitecape.org>
    Cc: "11.2 12.0" <mesa-stable@lists.freedesktop.org>

[BTW, your repo appears to have obtained a bug where you try to do glGetString(GL_EXTENSIONS) and die when it's not there -- you're supposed to use glGetStringi(GL_EXTENSIONS) in core contexts.]
Comment 7 Corentin Wallez 2016-07-06 19:59:13 UTC
Thank you, I'm still figuring out how to test top of tree Mesa and will confirm if that fixes all the failures.

I've fixed the core profile GL_EXTENSIONS bug locally, will push to the repo.
Comment 8 Ilia Mirkin 2016-07-07 00:23:50 UTC
https://patchwork.freedesktop.org/patch/97464/

This patch should also fix it for the [0] names. I chose to implement it as a fallback thing, so if you have foo and foo[0] set, foo will always get picked, no matter which was set first.

If I stripped the [0]'s at bind time, one might run into the issue of a

out vec4 foo;

shader (which, as the spec says, can be added after the binding is done on the program), and someone doing a bind on both foo and foo[0], and it'd be awkward for the foo[0] to win out in that case.
Comment 9 Corentin Wallez 2016-07-08 19:37:40 UTC
Mesa 12.0 with your patch applied fixes all the remaining failures in the relevant Chromium tests.

There's still one failure but it is trying to set FragData[0] = 2 and FragData[1] = 1 which is invalid given the discussion in the Khronos bug tracker. I'll fix this on our side.

Thank you again for fixing this!


bug/show.html.tmpl processed on Mar 30, 2017 at 04:44:52.
(provided by the Example extension).