Bug 42435

Summary: Suspected loss of varyings between shaders
Product: Mesa Reporter: Alexander Sabourenkov <screwdriver>
Component: Drivers/Gallium/r600Assignee: Default DRI bug account <dri-devel>
Status: RESOLVED FIXED QA Contact:
Severity: major    
Priority: medium    
Version: git   
Hardware: x86-64 (AMD64)   
OS: Linux (All)   
Whiteboard:
i915 platform: i915 features:
Attachments: Test case and stuff
minimized test case
xterm corruption screenshot
piglit test case for the problem
piglit test case for the problem as a patch
piglit test case for the problem as a patch
[PATCH] r600g: take into account PSIZE output for spi mapping

Description Alexander Sabourenkov 2011-10-31 07:40:48 UTC
Longer description, the test case, screenshots, and core from i965 crash  are in attached archive.

In short:

I try to draw a 2D screenful of point sprites, emulating an ansi-colored terminal. Fragment shader receives texture coordinates for the character, its color and size of graphic in the texture via varyings.

R600g draws a black screen, while llvmpipe and fglrx draw what is supposed to be drawn. i965 crashes. non-llvm swrast fails to set gl_PointSize. R600c also draws a black screen.

Drawing varying values themselves I get bogus values for some of them.

Mesa version: 7.12.0~git20111027.0fbc8d30-0ubuntu0sarvatt~natty
Comment 1 Alexander Sabourenkov 2011-10-31 07:43:44 UTC
Created attachment 52954 [details]
Test case and stuff
Comment 2 Alexander Sabourenkov 2011-10-31 07:50:58 UTC
core did not fit: >3000K size
Comment 3 Alexander Sabourenkov 2011-11-01 02:42:01 UTC
Worked around the issue by moving all texture sampling to fragment shader.
(even works on 965)

Also, just moving sampling outside conditional blocks did not change anything.
Comment 4 Alexander Sabourenkov 2011-11-01 15:27:29 UTC
The workaround did not help r600g. Same black screen. In addition, the non-llvm swrast draws point sprites 60 pixels in size instead of requested 16 (my original shaders get texture sub-image size via varyings too), plus it draws solid-black-textured point sprites as single pixels. r600c (as of Oct 27 git, just before being axed) works though.

Not knowing whether any given black screen is a bug, or legitimate undefined behaviour that just happens to work on some other renderer is driving me mad.

I managed to cut down the test case to bare minimum.

Usage:

./testbed <shaderset> <mesadriver>

shaderset is either "working" or "failing" - loads similarly named shaders.

"working" shader set does texture sampling in fragment shader
"failing" shader set does texture sampling in vertex shader and passes
the color as a varying vec4.

mesadriver is:
hw - default, LIBGL_ALWAYS_SOFTWARE and LIBGL_DRIVERS_PATH unset.
hw-alt - use .so from dri-alternates (x64-86 hardcoded, sorry).
sw - LIBGL_ALWAYS_SOFTWARE=y
sw-alt - as above, but use .so from dri-alternates.

For the Oct 27 git these map to r600g, r600c, swrast, llvmpipe on my box.

Of those:

"failing" llvmpipe - works as intended, vertical colored bars (composed of 16x16 point sprites), one sprite is dark green - left unpainted intentionally.
"working" llvmpipe - same (ok)
"failing" DRI - ok
"working" DRI - ok
"failing" r600g - all sprites black 
"working" r600g - all sprites black 
"failing" old-swrast  - single pixels instead of 16x16, but looks like color is right
"working" old-swrast  - same as "failing"

The hardware is rv770 9440.

I'd say there's a problem with r600g and a different one with old swrast.

There's also intermittent display corruption mainly on areas in xterm redrawn (but not those that get scrolled up) immediately after launching the testcase.
Comment 5 Alexander Sabourenkov 2011-11-01 15:28:43 UTC
Created attachment 53025 [details]
minimized test case
Comment 6 Alexander Sabourenkov 2011-11-01 17:31:52 UTC
Created attachment 53028 [details]
xterm corruption screenshot

xterm corruption screenshot, got it right after I first run those shaders:

#version 120
#line 2 0

uniform float posz;
uniform float width;
attribute vec2 posn;

varying float idx;

void main() { 
    vec2 posn2 = posz*posn;
    idx = posn2.x/width;
    gl_Position = gl_ModelViewProjectionMatrix*vec4(posn2.x, posn2.y, 0.0, 1.0);
    gl_PointSize = posz;
}
#version 120
#line 2 0
uniform sampler2D ansi;

varying float idx;

void main() {
    vec2 pc = gl_PointCoord;
    gl_FragColor = texture2D(ansi, vec2(0.5, 0));
}

 - got grey screen as expected, and then reset fragment shader back to 

#version 120
#line 2 0
uniform sampler2D ansi;

varying float idx;

void main() {
    vec2 pc = gl_PointCoord;
    gl_FragColor = texture2D(ansi, vec2(idx, 0));
}
Comment 7 Alexander Sabourenkov 2011-11-01 17:53:45 UTC
Further reducing shaders I got to this point:

#version 120
#line 2 0

varying float idx;

void main() { 
    vec2 posn2 = posz*posn;
    idx = 0.625;
    gl_Position = gl_ModelViewProjectionMatrix*vec4(128, 128, 0.0, 1.0);
    gl_PointSize = 128;
}

#version 120
#line 2 0
varying float idx;

void main() {
    gl_FragColor = vec4(idx, 0, 0, 1);
}

This is in fact very close to glsl-novertexdata from the piglit.

Which still does not work on r600g and swrast while working ok on r600c and llvmpipe.
Comment 8 Alexander Sabourenkov 2011-11-01 17:54:54 UTC
Created attachment 53029 [details]
piglit test case for the problem
Comment 9 Alexander Sabourenkov 2011-11-01 18:03:56 UTC
Created attachment 53030 [details]
piglit test case for the problem as a patch
Comment 10 Alexander Sabourenkov 2011-11-01 18:40:05 UTC
Created attachment 53031 [details] [review]
piglit test case for the problem as a patch
Comment 11 Alexander Sabourenkov 2011-11-01 18:41:06 UTC
Problem manifests itself only when gl_PointSize is set in the shader. Corrected patch attached.
Comment 12 Vadim Girlin 2011-11-01 21:56:03 UTC
Created attachment 53033 [details] [review]
[PATCH] r600g: take into account PSIZE output for spi mapping

Does this patch help?
Comment 13 Alexander Sabourenkov 2011-11-02 00:41:39 UTC
Yes, thank you.
Comment 14 Claudio Freire 2012-02-25 14:26:24 UTC
I experience a similar situation with Ironlake and Mesa 8.0.1, only with far more complex shaders.

Apparently, in these shaders, all varyings get bogus data on the fragment shader.

The only workaround I can find is passing that data through the built-in varying in gl_TexCoord, although that's quite suboptimal for other drivers so I would prefer not to.

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.