[Mesa-dev] MaxAnisotropy with GL_NEAREST on i965

Submitted by Cody Northrop on May 22, 2014, 9:45 p.m.

Details

Message ID CAP90KKe9SHg8=DdWjgm+Cw0AqEBYEgdydWyuJ3X3-vR2UHJfQQ@mail.gmail.com
State New
Headers show

Not browsing as part of any series.

Commit Message

Cody Northrop May 22, 2014, 9:45 p.m.
Greetings,

I ran into a problem with how Mesa on i965 handles MaxAnisotropy.

The app I'm looking at sets sampler state min and mag filters to GL_NEAREST,
but also sets GL_TEXTURE_MAX_ANISOTROPY_EXT, like so:

     glSamplerParameteri(pointSampler, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
     glSamplerParameteri(pointSampler, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
     glSamplerParameteri(pointSampler, GL_TEXTURE_MAX_ANISOTROPY_EXT, 8);

On Nvidia closed source and Intel closed source drivers, MaxAnisotropy is
ignored and unfiltered texture results are returned.  In this case, solid
red.

Using Haswell with Mesa, MaxAnisotropy trumps GL_NEAREST, and the texels
are filtered, returning almost greyscale values.  See
gen7_update_sampler_state().

According to the extension, both behaviors are allowed:

    http://www.opengl.org/registry/specs/EXT/texture_filter_anisotropic.txt

    Implementations are free to use the specified minification and
    magnification filter to select a particular anisotropic texture
    filtering scheme.  For example, a NEAREST filter with a maximum
    degree of anisotropy of two could be treated as a 2-tap filter that
    accounts for the direction of anisotropy.  Implementations are also
    permitted to ignore the minification or magnification filter and
    implement the highest quality of anisotropic filtering possible.

So no one is at fault here, it's just different.  What's the policy for
ambiguities like this?  Should i965 match other vendors?  Or emit a warning
that requested filter mode is being overridden?

Below are modifications to a piglit test that show the problem.  I couldn't
find any existing tests for EXT_texture_filter_anisotropic.  The changes
fill a single LOD texture with interleaved colors, then expects a single
unfiltered red color back, but i965 returns greenish brown.

Thanks,

-Cody



 piglit_display(void)
 {
@@ -119,6 +160,73 @@ piglit_display(void)
        };
        bool pass;

+       static GLubyte redColors[][4] = {
+               {255,   0,   0, 255},
+               {255,   0,   0, 255},
+               {255,   0,   0, 255},
+               {255,   0,   0, 255},
+               {255,   0,   0, 255},
+               {255,   0,   0, 255},
+               {255,   0,   0, 255},
+               {255,   0,   0, 255},
+               {255,   0,   0, 255},
+               {255,   0,   0, 255}
+       };
+
+       static GLubyte greenColors[][4] = {
+               {  0, 255,   0, 255},
+               {  0, 255,   0, 255},
+               {  0, 255,   0, 255},
+               {  0, 255,   0, 255},
+               {  0, 255,   0, 255},
+               {  0, 255,   0, 255},
+               {  0, 255,   0, 255},
+               {  0, 255,   0, 255},
+               {  0, 255,   0, 255},
+               {  0, 255,   0, 255}
+       };
+
+       static GLubyte blueColors[][4] = {
+               {  0,   0, 255, 255},
+               {  0,   0, 255, 255},
+               {  0,   0, 255, 255},
+               {  0,   0, 255, 255},
+               {  0,   0, 255, 255},
+               {  0,   0, 255, 255},
+               {  0,   0, 255, 255},
+               {  0,   0, 255, 255},
+               {  0,   0, 255, 255},
+               {  0,   0, 255, 255}
+       };
+
+       GLuint interleavedTex;
+       GLuint pointSampler;
+       GLint width = 128, height = 64, levels = 1;
+       GLint level = 0;
+
+       GLubyte *interleavedBuf = create_interleaved_image(width, height,
redColors[level], greenColors[level], blueColors[level]);
+
+       glGenTextures(1, &interleavedTex);
+       glBindTexture(GL_TEXTURE_2D, interleavedTex);
+       glTexStorage2D(GL_TEXTURE_2D, levels, GL_RGBA8, width, height);
+       piglit_check_gl_error(GL_NO_ERROR);
+       glTexSubImage2D(GL_TEXTURE_2D, level, 0, 0, width, height, GL_RGBA,
GL_UNSIGNED_BYTE, interleavedBuf);
+       glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+       glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+       glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, level);
+       glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, level);
+
+       glGenSamplers(1, &pointSampler);
+       glSamplerParameteri(pointSampler, GL_TEXTURE_MIN_FILTER,
GL_NEAREST);
+       glSamplerParameteri(pointSampler, GL_TEXTURE_MAG_FILTER,
GL_NEAREST);
+
+       // setting MaxAnisotropy causes GL_NEAREST to be ignored
+       glSamplerParameteri(pointSampler, GL_TEXTURE_MAX_ANISOTROPY_EXT, 8);
+
+       glActiveTexture(GL_TEXTURE10);
+       glBindTexture(GL_TEXTURE_2D, interleavedTex);
+       glBindSampler(10, pointSampler);
+
        glClearColor(0.1f, 0.1f, 0.1f, 0.1f);
        glClear(GL_COLOR_BUFFER_BIT);

Patch hide | download patch | download mbox

diff --git
a/tests/spec/arb_separate_shader_objects/rendezvous_by_location.c
b/tests/spec/arb_separate_shader_objects/rendezvous_by_location.c
index 4193ea5..7e83890 100644
--- a/tests/spec/arb_separate_shader_objects/rendezvous_by_location.c
+++ b/tests/spec/arb_separate_shader_objects/rendezvous_by_location.c
@@ -95,6 +95,7 @@  static const char *fs_code_same_location_order_template =
        "#version %d\n"
        "#extension GL_ARB_separate_shader_objects: require\n"
        "#extension GL_ARB_explicit_attrib_location: enable\n"
+       "#extension GL_ARB_shading_language_420pack: require\n"
        "\n"
        "#if __VERSION__ >= 130\n"
        "layout(location = 0) out vec4 out_color;\n"
@@ -104,13 +105,53 @@  static const char
*fs_code_same_location_order_template =
        "\n"
        "layout(location = 2) in vec3 b; /* should get vec3(0, 0, 1) */\n"
        "layout(location = 3) in vec3 a; /* should get vec3(1, 0, 0) */\n"
+       "layout(binding = 10) uniform sampler2D interleavedTexture;\n"
        "\n"
        "void main()\n"
        "{\n"
-       "    out_color = vec4(cross(b, a), 1);\n"
+       "    out_color = texture2D(interleavedTexture, vec2(0.0, 0.0));\n"
        "}\n"
        ;

+/**
+ * Create a an image with 3 interleaved colors.
+ */
+static GLubyte *
+create_interleaved_image(GLint w, GLint h, const GLubyte red[4], const
GLubyte green[4], const GLubyte blue[4])
+{
+       GLubyte *buf = (GLubyte *) malloc(w * h * 4);
+       int i;
+       for (i = 0; i < w * h; i++) {
+
+               switch(i % 3) {
+               case 0:
+                       buf[i*4+0] = red[0];
+                       buf[i*4+1] = red[1];
+                       buf[i*4+2] = red[2];
+                       buf[i*4+3] = red[3];
+                       break;
+
+               case 1:
+                       buf[i*4+0] = green[0];
+                       buf[i*4+1] = green[1];
+                       buf[i*4+2] = green[2];
+                       buf[i*4+3] = green[3];
+                       break;
+
+               case 2:
+                       buf[i*4+0] = blue[0];
+                       buf[i*4+1] = blue[1];
+                       buf[i*4+2] = blue[2];
+                       buf[i*4+3] = blue[3];
+                       break;
+
+               default:
+                       break;
+               }
+       }
+       return buf;
+}
+
 enum piglit_result

Comments

On 05/22/2014 02:45 PM, Cody Northrop wrote:
> Greetings,
> 
> I ran into a problem with how Mesa on i965 handles MaxAnisotropy.
> 
> The app I'm looking at sets sampler state min and mag filters to
> GL_NEAREST, but also sets GL_TEXTURE_MAX_ANISOTROPY_EXT, like so:
> 
>      glSamplerParameteri(pointSampler, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
>      glSamplerParameteri(pointSampler, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
>      glSamplerParameteri(pointSampler, GL_TEXTURE_MAX_ANISOTROPY_EXT, 8);
> 
> On Nvidia closed source and Intel closed source drivers, MaxAnisotropy
> is ignored and unfiltered texture results are returned.  In this case,
> solid red.
> 
> Using Haswell with Mesa, MaxAnisotropy trumps GL_NEAREST, and the texels
> are filtered, returning almost greyscale values.  See
> gen7_update_sampler_state().
> 
> According to the extension, both behaviors are allowed:
> 
>     http://www.opengl.org/registry/specs/EXT/texture_filter_anisotropic.txt
> 
>     Implementations are free to use the specified minification and
>     magnification filter to select a particular anisotropic texture
>     filtering scheme.  For example, a NEAREST filter with a maximum
>     degree of anisotropy of two could be treated as a 2-tap filter that
>     accounts for the direction of anisotropy.  Implementations are also
>     permitted to ignore the minification or magnification filter and
>     implement the highest quality of anisotropic filtering possible.
> 
> So no one is at fault here, it's just different.  What's the policy for
> ambiguities like this?  Should i965 match other vendors?  Or emit a
> warning that requested filter mode is being overridden? 

There are a lot of places in the spec that are explicitly undefined.  We
have a couple different strategies for dealing with those.  When we
notice (and I don't think we ever noticed this particular case):

A. Pick the easiest behavior that some other vendor also does.

B. If all other vendors do the same thing, do that and submit a spec bug.

For "other vendors" we generally just look at the other vendors
available on Linux: AMD and NVIDIA.  We may also look at the Intel
Windows driver and Apple.

Do you know what AMD does in this case?

> Below are modifications to a piglit test that show the problem.  I
> couldn't find any existing tests for EXT_texture_filter_anisotropic. 
> The changes fill a single LOD texture with interleaved colors, then
> expects a single unfiltered red color back, but i965 returns greenish brown.

If we're going to decide that one behavior is correct, we should have a
test for it.  However, that test should be able to run on as many GPUs
that Mesa supports as possible.  It should be pretty easy to make a test
that just uses OpenGL 1.2 + GL_EXT_texture_filter_anisotropic.

It is not at all surprising that there are no tests for this extension.
 Any new tests added should go in tests/spec/ext_texture_filter_anisotropic.

> Thanks,
> 
> -Cody
> 
> 
> 
> diff --git
> a/tests/spec/arb_separate_shader_objects/rendezvous_by_location.c
> b/tests/spec/arb_separate_shader_objects/rendezvous_by_location.c
> index 4193ea5..7e83890 100644
> --- a/tests/spec/arb_separate_shader_objects/rendezvous_by_location.c
> +++ b/tests/spec/arb_separate_shader_objects/rendezvous_by_location.c
> @@ -95,6 +95,7 @@ static const char *fs_code_same_location_order_template =
>         "#version %d\n"
>         "#extension GL_ARB_separate_shader_objects: require\n"
>         "#extension GL_ARB_explicit_attrib_location: enable\n"
> +       "#extension GL_ARB_shading_language_420pack: require\n"
>         "\n"
>         "#if __VERSION__ >= 130\n"
>         "layout(location = 0) out vec4 out_color;\n"
> @@ -104,13 +105,53 @@ static const char
> *fs_code_same_location_order_template =
>         "\n"
>         "layout(location = 2) in vec3 b; /* should get vec3(0, 0, 1) */\n"
>         "layout(location = 3) in vec3 a; /* should get vec3(1, 0, 0) */\n"
> +       "layout(binding = 10) uniform sampler2D interleavedTexture;\n"
>         "\n"
>         "void main()\n"
>         "{\n"
> -       "    out_color = vec4(cross(b, a), 1);\n"
> +       "    out_color = texture2D(interleavedTexture, vec2(0.0, 0.0));\n"
>         "}\n"
>         ;
>  
> +/**
> + * Create a an image with 3 interleaved colors.
> + */
> +static GLubyte *
> +create_interleaved_image(GLint w, GLint h, const GLubyte red[4], const
> GLubyte green[4], const GLubyte blue[4])
> +{
> +       GLubyte *buf = (GLubyte *) malloc(w * h * 4);
> +       int i;
> +       for (i = 0; i < w * h; i++) {
> +
> +               switch(i % 3) {
> +               case 0:
> +                       buf[i*4+0] = red[0];
> +                       buf[i*4+1] = red[1];
> +                       buf[i*4+2] = red[2];
> +                       buf[i*4+3] = red[3];
> +                       break;
> +
> +               case 1:
> +                       buf[i*4+0] = green[0];
> +                       buf[i*4+1] = green[1];
> +                       buf[i*4+2] = green[2];
> +                       buf[i*4+3] = green[3];
> +                       break;
> +
> +               case 2:
> +                       buf[i*4+0] = blue[0];
> +                       buf[i*4+1] = blue[1];
> +                       buf[i*4+2] = blue[2];
> +                       buf[i*4+3] = blue[3];
> +                       break;
> +
> +               default:
> +                       break;
> +               }
> +       }
> +       return buf;
> +}
> +
>  enum piglit_result
>  piglit_display(void)
>  {
> @@ -119,6 +160,73 @@ piglit_display(void)
>         };
>         bool pass;
>  
> +       static GLubyte redColors[][4] = {
> +               {255,   0,   0, 255},
> +               {255,   0,   0, 255},
> +               {255,   0,   0, 255},
> +               {255,   0,   0, 255},
> +               {255,   0,   0, 255},
> +               {255,   0,   0, 255},
> +               {255,   0,   0, 255},
> +               {255,   0,   0, 255},
> +               {255,   0,   0, 255},
> +               {255,   0,   0, 255}
> +       };
> +
> +       static GLubyte greenColors[][4] = {
> +               {  0, 255,   0, 255},
> +               {  0, 255,   0, 255},
> +               {  0, 255,   0, 255},
> +               {  0, 255,   0, 255},
> +               {  0, 255,   0, 255},
> +               {  0, 255,   0, 255},
> +               {  0, 255,   0, 255},
> +               {  0, 255,   0, 255},
> +               {  0, 255,   0, 255},
> +               {  0, 255,   0, 255}
> +       };
> +
> +       static GLubyte blueColors[][4] = {
> +               {  0,   0, 255, 255},
> +               {  0,   0, 255, 255},
> +               {  0,   0, 255, 255},
> +               {  0,   0, 255, 255},
> +               {  0,   0, 255, 255},
> +               {  0,   0, 255, 255},
> +               {  0,   0, 255, 255},
> +               {  0,   0, 255, 255},
> +               {  0,   0, 255, 255},
> +               {  0,   0, 255, 255}
> +       };
> +
> +       GLuint interleavedTex;
> +       GLuint pointSampler;
> +       GLint width = 128, height = 64, levels = 1;
> +       GLint level = 0;
> +
> +       GLubyte *interleavedBuf = create_interleaved_image(width,
> height, redColors[level], greenColors[level], blueColors[level]);
> +
> +       glGenTextures(1, &interleavedTex);
> +       glBindTexture(GL_TEXTURE_2D, interleavedTex);
> +       glTexStorage2D(GL_TEXTURE_2D, levels, GL_RGBA8, width, height);
> +       piglit_check_gl_error(GL_NO_ERROR);
> +       glTexSubImage2D(GL_TEXTURE_2D, level, 0, 0, width, height,
> GL_RGBA, GL_UNSIGNED_BYTE, interleavedBuf);
> +       glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
> +       glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
> +       glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, level);
> +       glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, level);
> +
> +       glGenSamplers(1, &pointSampler);
> +       glSamplerParameteri(pointSampler, GL_TEXTURE_MIN_FILTER,
> GL_NEAREST);
> +       glSamplerParameteri(pointSampler, GL_TEXTURE_MAG_FILTER,
> GL_NEAREST);
> +
> +       // setting MaxAnisotropy causes GL_NEAREST to be ignored
> +       glSamplerParameteri(pointSampler, GL_TEXTURE_MAX_ANISOTROPY_EXT, 8);
> +
> +       glActiveTexture(GL_TEXTURE10);
> +       glBindTexture(GL_TEXTURE_2D, interleavedTex);
> +       glBindSampler(10, pointSampler);
> +
>         glClearColor(0.1f, 0.1f, 0.1f, 0.1f);
>         glClear(GL_COLOR_BUFFER_BIT);
> 
> 
> 
> _______________________________________________
> mesa-dev mailing list
> mesa-dev@lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/mesa-dev
>