Bug 92909

Summary: [SNB] Offset/alignment issue with layout std140 and vec3
Product: Mesa Reporter: Dimitri Sabadie <dimitri.sabadie>
Component: Drivers/DRI/i965Assignee: Intel 3D Bugs Mailing List <intel-3d-bugs>
Status: RESOLVED FIXED QA Contact: Intel 3D Bugs Mailing List <intel-3d-bugs>
Severity: normal    
Priority: medium CC: lemody, slomo
Version: 11.0   
Hardware: x86-64 (AMD64)   
OS: Linux (All)   
Whiteboard:
i915 platform: i915 features:
Bug Depends on:    
Bug Blocks: 93185    
Attachments: source code with compilation line (first line)
application
issue in 10.4.7, IVB
no issue in 18.2.0 IVB

Description Dimitri Sabadie 2015-11-11 22:42:42 UTC
Created attachment 119574 [details]
source code with compilation line (first line)

When trying to compile an OpenGL 3.2 program to demonstrate the use of UBO (Uniform Buffer Objects), I got astonished my program worked on nvidia but not on i915. I spent days trying to fix my code, but I was eventually advised to submit a driver bug here.

The problem is there when trying to send three colors to fulfill a triangle (red, green and blue). I attached the code so that you can run it and test it; it’s rather small.

So, the shader defines a uniform block as:

struct Color {
  vec3 rgb;
  float k;
};

The rule 3 and rule 9 of the gl32 specs state that the scalar (float) should be aligned on a 4 bytes and that the vec3 should be aligned on 16 bytes. The vec3 rgb field is already aligned on 16 bytes (because its offset is 0) and the float k is already aligned as well (because its offset is 12, which is a multiple of 4). So no padding is needed and the structure’s size is 16 bytes. Though, I guess the driver tries to do different things on the GLSL side and I get wrong values for k (though the vec3 works, like, if I don’t use k in the fragment shader output, I get a correct behavior).
Comment 1 Kenneth Graunke 2015-11-11 22:57:03 UTC
Tracked this down.

The vec4 backend's UBO loading code is broken for indirect offsets that are not vec4 aligned (multiples of 16 bytes).  Notably, the scalar backend shifts right by 2 (bytes / 4 -> DWords), while the vector backend shifts right by 4 (bytes / 4 -> DWords, DWords / 4 -> vec4 blocks).  It tries to load a vec4, then swizzle the result...based on const_offset.  But we don't have any swizzling to compensate for offset % 16 != 0.

The app's second UBO load uses offsets of 12 and 44, which are not vec4-aligned, so it hits this bug.

Unfortunately, the fix isn't terribly simple.  One option is to try and add that swizzling...but this means having to do indirect addressing.  Another is to convert the vec4 backend to use DWord aligned surfaces, which is a pretty big change as well.
Comment 2 Kenneth Graunke 2015-11-12 00:17:28 UTC
If anyone on the team is feeling inspired to fix this, feel free - I'm not likely to get to it immediately.
Comment 3 Kenneth Graunke 2015-11-12 00:34:41 UTC
FWIW, the reporter is using Haswell (hence the vec4 backend).
Comment 4 Tapani Pälli 2015-11-12 06:34:08 UTC
maybe this is the same issue we have with CTS UBO tests on HSW (bug #92113)
Comment 5 Matt Turner 2015-11-12 18:57:48 UTC
Jason's got work-in-progress code that he says will fix this on everything but Sandybridge.
Comment 6 Jason Ekstrand 2015-12-10 22:09:43 UTC
This should now be fixed on IVB and later.
Comment 7 Denis 2018-06-25 12:18:34 UTC
Hello! This issue can be closed as fixed.
I verified it on IVB and SKL CPU's.
In the attachment you may find small app, which displays the issue on mesa-10.4.7, and works fine with mesa-18.2.0 from git.
Comment 8 Denis 2018-06-25 12:19:02 UTC
Created attachment 140315 [details]
application
Comment 9 Denis 2018-06-25 12:19:47 UTC
Created attachment 140316 [details]
issue in 10.4.7, IVB
Comment 10 Denis 2018-06-25 12:20:09 UTC
Created attachment 140317 [details]
no issue in 18.2.0 IVB

Use of freedesktop.org services, including Bugzilla, is subject to our Code of Conduct. How we collect and use information is described in our Privacy Policy.