[Piglit] [PATCH 2/2] arb_post_depth_coverage: Make multisampling test more robust

Ilia Mirkin imirkin at alum.mit.edu
Mon May 22 22:15:46 UTC 2017


[Cc'ing original test author/reviewer...]

On Mon, May 22, 2017 at 2:55 PM, Lyude <lyude at redhat.com> wrote:
> The multisampling test we currently have is not very useful. If you
> modify the vertex shader it uses that enables ARB_post_depth_coverage
> such that the lines enabling said extension are commented out, you will
> notice that the test still "passes" with flying colors. While this makes
> sure that ARB_post_depth_coverage doesn't break anything, it also
> doesn't actually make sure that the extension even works.
>
> I've tried fixing the original test, but honestly no matter how long I
> look at it I still can't even start to understand how this was really
> supposed to work in the first place (why exactly are we using depth
> stenciling?). Since imirkin didn't have much more luck then I did with
> figuring it out, we decided to just write a new and improved test.
>
> So, write a new depth test that actually can't pass unless
> ARB_post_depth_coverage is functional and changes the behavior of
> gl_SampleMaskIn[] properly.
>
> Also, as a sidenote to save people from confusion, this test no longer
> passes on i965:
>
> (0, 0) expected 0x2 in ssbo, got 0x3
> (0, 0) expected 0xe in ssbo, got 0xf
> (0, 0) expected 0xfe in ssbo, got 0xff
> (0, 0) expected 0xfffe in ssbo, got 0xffff
>
> That output only can occur if gl_SampleMaskIn[] actually doesn't do
> anything, since enabling the extension should be unsetting the coverage
> bit for the first sample. So GL_ARB_post_depth_coverage in i965 is
> actually broken, not the test (this test passes 100% on the nvidia
> blob).
>
> Signed-off-by: Lyude <lyude at redhat.com>
> ---
>  tests/spec/arb_post_depth_coverage/multisampling.c | 349 ++++++++-------------
>  1 file changed, 133 insertions(+), 216 deletions(-)
>
> diff --git a/tests/spec/arb_post_depth_coverage/multisampling.c b/tests/spec/arb_post_depth_coverage/multisampling.c
> index f90208d..af23b3e 100644
> --- a/tests/spec/arb_post_depth_coverage/multisampling.c
> +++ b/tests/spec/arb_post_depth_coverage/multisampling.c
> @@ -1,5 +1,5 @@
>  /*
> - * Copyright (c) 2015 Intel Corporation.
> + * Copyright (c) 2017 Red Hat Inc.
>   *
>   * Permission is hereby granted, free of charge, to any person obtaining a
>   * copy of this software and associated documentation files (the "Software"),
> @@ -24,9 +24,15 @@
>  #include "piglit-util-gl.h"
>
>  /*
> - * A test to check whether the right values are written to gl_SampleMaskIn
> - * when ARB_post_depth_coverage and multisampling are enabled. Tests at
> - * 2, 4, 8, 16 sample rates.
> + * A test to check that when ARB_post_depth_coverage is enabled, the values in
> + * gl_SampleMaskIn accurately reflect the results of the depth test being run
> + * before the respective fragment shader invocation. As well, we also check to
> + * make sure that when the extension is disabled, the values in
> + * gl_SampleMaskIn do not reflect the results of the depth test in each
> + * respective fragment shader invocation.
> + * For good measure, we test this behavior at sample rates of 2, 4, 8, and 16
> + * (if the GPU does not support a high enough sample rate to test all of these
> + * rates, we skip the ones we can't test).
>   */
>
>  PIGLIT_GL_TEST_CONFIG_BEGIN
> @@ -38,24 +44,21 @@ PIGLIT_GL_TEST_CONFIG_BEGIN
>                 PIGLIT_GL_VISUAL_DOUBLE;
>  PIGLIT_GL_TEST_CONFIG_END
>
> -static GLuint prog1, prog2, vao, ssbo, tex_color, tex_depth, fbo;
> -static GLint *sample_mask;
> +GLint prog1, prog2, prog3;
>
>  static const char *vs_text =
>         "#version 430\n"
> -       "in vec4 pos_in;\n"
> -       "void main()\n"
> -       "{\n"
> -       "       gl_Position = pos_in;\n"
> +       "in vec4 piglit_vertex;\n"
> +       "void main() {\n"
> +       "       gl_Position = piglit_vertex;\n"
>         "}\n";
>
>  static const char *fs_text1 =
>         "#version 430\n"
>         "out vec4 color;\n"
> -       "void main()\n"
> -       "{\n"
> -       "  gl_FragDepth = 0.5f;\n"
> -       "       color = vec4(0.0, 1.0, 0.0, 1.0);\n"
> +       "void main() {\n"
> +       "       color = vec4(1.0, 0.0, 0.0, 1.0);\n"
> +       "       gl_SampleMask[0] = 1;\n"
>         "}\n";
>
>  static const char *fs_text2 =
> @@ -67,149 +70,111 @@ static const char *fs_text2 =
>         "layout(std430, binding = 0) buffer MaskOutput {\n"
>         "       int data[];\n"
>         "} mask_output;\n"
> -       "layout(location = 1) uniform int width;\n"
> -       "layout(location = 2) uniform int samples;\n"
> -       "void main()\n"
> -       "{\n"
> -       "       int index = int(gl_FragCoord.y) * width + int(gl_FragCoord.x);\n"
> -       "       atomicAdd(mask_output.data[index], bitCount(gl_SampleMaskIn[0]));\n"
> -       "       color = vec4(1.0, 0.0, 0.0, 1.0);\n"
> +       "void main() {\n"
> +       "       int index = int(gl_FragCoord.y) * 160 + int(gl_FragCoord.x);\n"
> +       "       atomicOr(mask_output.data[index], gl_SampleMaskIn[0]);\n"
> +       "       color = vec4(0.0, 1.0, 0.0, 1.0);\n"
>         "}\n";
>
> -static GLuint
> -make_shader_program1(void)
> -{
> -       GLuint prog;
> -
> -       prog = piglit_build_simple_program(vs_text, fs_text1);
> -       glUseProgram(prog);
> -
> -       glBindAttribLocation(prog, 0, "pos_in");
> -
> -       glLinkProgram(prog);
> -
> -       if (!piglit_check_gl_error(GL_NO_ERROR)) {
> -               piglit_report_result(PIGLIT_FAIL);
> -       }
> -
> -       return prog;
> -}
> +static const char *fs_text3 =
> +       "#version 430\n"
> +       "out vec4 color;\n"
> +       "layout(early_fragment_tests) in;\n"
> +       "layout(std430, binding = 0) buffer MaskOutput {\n"
> +       "       int data[];\n"
> +       "} mask_output;\n"
> +       "void main() {\n"
> +       "       int index = int(gl_FragCoord.y) * 160 + int(gl_FragCoord.x);\n"
> +       "       atomicOr(mask_output.data[index], gl_SampleMaskIn[0]);\n"
> +       "       color = vec4(0.0, 1.0, 0.0, 1.0);\n"
> +       "}\n";
>
> -static GLuint
> -make_shader_program2(void)
> +static inline bool
> +draw_and_check_sample_mask(GLint prog, int sample_count, int ssbo_value)
>  {
> -       GLuint prog;
> -
> -       prog = piglit_build_simple_program(vs_text, fs_text2);
> -       glUseProgram(prog);
> +       const size_t sample_mask_size = piglit_width * piglit_height;
> +       GLint *sample_mask = calloc(sizeof(GLint), sample_mask_size);
> +       GLuint fbo, tex_color, tex_depth, ssbo;
> +       int i;
> +       bool ret = true;
>
> -       glBindAttribLocation(prog, 0, "pos_in");
> -
> -       glLinkProgram(prog);
> +       glGenFramebuffers(1, &fbo);
> +       glBindFramebuffer(GL_FRAMEBUFFER, fbo);
>
> -       if (!piglit_check_gl_error(GL_NO_ERROR)) {
> -               piglit_report_result(PIGLIT_FAIL);
> -       }
> +       /* Create new textures */
> +       glGenTextures(1, &tex_color);
> +       glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, tex_color);
> +       glTexImage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, sample_count,
> +                               GL_RGBA32F, piglit_width, piglit_height,
> +                               false);
> +       glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
> +                              GL_TEXTURE_2D_MULTISAMPLE, tex_color, 0);
>
> -       return prog;
> -}
> +       glGenTextures(1, &tex_depth);
> +       glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, tex_depth);
> +       glTexImage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, sample_count,
> +                               GL_DEPTH_COMPONENT24,
> +                               piglit_width, piglit_height, false);
> +       glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT,
> +                              GL_TEXTURE_2D_MULTISAMPLE, tex_depth, 0);
>
> -static GLuint
> -make_ssbo(void)
> -{
> -       GLuint ssbo;
> +       /* Setup the ssbo */
>         glGenBuffers(1, &ssbo);
>         glBindBuffer(GL_SHADER_STORAGE_BUFFER, ssbo);
> +       glBufferData(GL_SHADER_STORAGE_BUFFER,
> +                    sample_mask_size * sizeof(GLint),
> +                    sample_mask, GL_DYNAMIC_DRAW);
> +       glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, ssbo);
> +
> +       glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
>
>         if (!piglit_check_gl_error(GL_NO_ERROR)) {
> -               piglit_report_result(PIGLIT_FAIL);
> +               ret = false;
> +               goto finish;
>         }
>
> -       return ssbo;
> -}
> +       /* Draw a rectangle that covers the entire depth texture, but only in
> +        * the first sample.
> +        */
> +       glUseProgram(prog1);
> +       piglit_draw_rect_z(0.25, -1.0, -1.0, 4.0, 4.0);
>
> -static GLuint
> -make_fbo(void)
> -{
> -       GLuint fbo;
> -       glGenFramebuffers(1, &fbo);
> -       glBindFramebuffer(GL_FRAMEBUFFER, fbo );
> -       glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, tex_color);
> -       glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
> -               GL_TEXTURE_2D_MULTISAMPLE, tex_color, 0);
> -       glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, tex_depth);
> -       glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT,
> -               GL_TEXTURE_2D_MULTISAMPLE, tex_depth, 0);
> -       glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, 0);
> -
> -       return fbo;
> -}
> -
> -static GLuint
> -make_texture_color(void)
> -{
> -       GLuint tex;
> -
> -       glGenTextures(1, &tex);
> -       glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, tex);
> -       glTexImage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, 2,
> -               GL_RGBA32F, piglit_width, piglit_height, false);
> -       glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, 0);
> -
> -       return tex;
> -}
> -
> -static GLuint
> -make_texture_depth(void)
> -{
> -       GLuint tex;
> -
> -       glGenTextures(1, &tex);
> -       glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, tex);
> -       glTexImage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, 2,
> -               GL_DEPTH24_STENCIL8, piglit_width, piglit_height, false);
> -       glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, 0);
> -
> -       return tex;
> -}
> -
> -static GLuint
> -make_vao(void)
> -{
> -       static const float pos_tc[12][2] = {
> -               { -1.0, -1.0 },
> -               {  0.0, -1.0 },
> -               {  0.0,  1.0 },
> -               {  0.0,  1.0 },
> -               { -1.0,  1.0 },
> -               { -1.0, -1.0 },
> -               { -1.0, -1.0 },
> -               {  1.0, -1.0 },
> -               {  1.0,  1.0 },
> -               {  1.0,  1.0 },
> -               { -1.0,  1.0 },
> -               { -1.0, -1.0 }
> -       };
> -       const int stride = sizeof(pos_tc[0]);
> -       GLuint vbo, vao;
> -
> -       glGenVertexArrays(1, &vao);
> -       glBindVertexArray(vao);
> -
> -       glGenBuffers(1, &vbo);
> -       glBindBuffer(GL_ARRAY_BUFFER, vbo);
> -       glBufferData(GL_ARRAY_BUFFER, sizeof(pos_tc), pos_tc, GL_STATIC_DRAW);
> -       piglit_check_gl_error(GL_NO_ERROR);
> +       /* Now draw another rectangle that inhabits all of the samples, and
> +        * see which ones are covered in gl_SampleMaskIn when the fragment
> +        * shader is executed.
> +        */
> +       glUseProgram(prog);
> +       piglit_draw_rect_z(0.5, -1.0, -1.0, 4.0, 4.0);
> +
> +       glGetBufferSubData(GL_SHADER_STORAGE_BUFFER, 0,
> +                          sample_mask_size * sizeof(GLint), sample_mask);
> +       for (i = 0; i < sample_mask_size; i++) {
> +               if (sample_mask[i] != ssbo_value) {
> +                       fprintf(stderr,
> +                               "(%d, %d) expected 0x%x in ssbo, got 0x%x\n",
> +                               i % 160, i / 160, ssbo_value, sample_mask[i]);
> +                       ret = false;
> +                       break;
> +               }
> +       }
>
> -       glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, stride, (void *) 0);
> +       glBindFramebuffer(GL_READ_FRAMEBUFFER, fbo);
> +       glBindFramebuffer(GL_DRAW_FRAMEBUFFER, piglit_winsys_fbo);
> +       glBlitFramebuffer(0, 0, piglit_width, piglit_height,
> +                         0, 0, piglit_width, piglit_height,
> +                         GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT,
> +                         GL_NEAREST);
> +       glBindFramebuffer(GL_FRAMEBUFFER, piglit_winsys_fbo);
>
> -       glEnableVertexAttribArray(0);
> +       piglit_present_results();
>
> -       if (!piglit_check_gl_error(GL_NO_ERROR)) {
> -               piglit_report_result(PIGLIT_FAIL);
> -       }
> +finish:
> +       glDeleteTextures(2, (GLuint[2]) { tex_color, tex_depth });
> +       glDeleteBuffers(1, &ssbo);
> +       glDeleteFramebuffers(1, &fbo);
> +       free(sample_mask);
>
> -       return vbo;
> +       return ret;
>  }
>
>  void
> @@ -218,96 +183,48 @@ piglit_init(int argc, char **argv)
>         piglit_require_extension("GL_ARB_post_depth_coverage");
>
>         glEnable(GL_DEPTH_TEST);
> -       glEnable(GL_STENCIL_TEST);
>         glEnable(GL_MULTISAMPLE);
> -       glClearColor(0.0, 0.0, 0.0, 1.0);
> +       glClearColor(0.2, 0.2, 0.2, 0.2);
>
> -       prog1 = make_shader_program1();
> -       prog2 = make_shader_program2();
> -       vao = make_vao();
> -       ssbo = make_ssbo();
> -       tex_color = make_texture_color();
> -       tex_depth = make_texture_depth();
> -       fbo = make_fbo();
> +       prog1 = piglit_build_simple_program(vs_text, fs_text1);
> +       prog2 = piglit_build_simple_program(vs_text, fs_text2);
> +       prog3 = piglit_build_simple_program(vs_text, fs_text3);
>  }
>
> -
>  enum piglit_result
>  piglit_display(void)
>  {
> -       int samples[4] = { 2, 4, 8, 16 };
> -       int max_samples;
> +       const int samples[] = {2, 4, 8, 16};
> +       int max_sample_count, mask, i, j;
>         bool pass = true;
> -       int i, j, k;
>
> +       glGetIntegerv(GL_MAX_SAMPLES, &max_sample_count);
>         glViewport(0, 0, piglit_width, piglit_height);
> -       glGetIntegerv(GL_MAX_SAMPLES, &max_samples);
> -
> -       for (j = 0; j < 4 && samples[j] <= max_samples; j++) {
> -               sample_mask = (GLint*) calloc (piglit_width * piglit_height,
> -                       sizeof(GLint));
> -               glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(GLint) * piglit_width *
> -                       piglit_height, &sample_mask[0], GL_DYNAMIC_DRAW);
> -               glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, ssbo);
> -
> -               glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fbo);
> -               glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, tex_color);
> -               glTexImage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, samples[j],
> -                       GL_RGBA8, piglit_width, piglit_height, false);
> -               glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, tex_depth);
> -               glTexImage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, samples[j],
> -                       GL_DEPTH24_STENCIL8, piglit_width, piglit_height, false);
> -
> -               glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT |
> -                       GL_STENCIL_BUFFER_BIT);
>
> -               glUseProgram(prog1);
> -               glStencilFunc(GL_ALWAYS, 1, 0xFF);
> -               glStencilOp(GL_REPLACE, GL_REPLACE, GL_REPLACE);
> -               glDrawArrays(GL_TRIANGLES, 0, 6);
> -
> -               glUseProgram(prog2);
> -               glStencilFunc(GL_NOTEQUAL, 1, 0xFF);
> -               glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
> -               glUniform1i(1, piglit_width);
> -               glUniform1i(2, samples[j]);
> -               glDrawArrays(GL_TRIANGLES, 6, 6);
> -
> -               glGetBufferSubData(GL_SHADER_STORAGE_BUFFER, 0, sizeof(GLint) *
> -                       piglit_width * piglit_height, sample_mask);
> -
> -               for (i = 0; i < piglit_width; i++) {
> -                       for (k = 0; k < piglit_height; k++) {
> -                               if (i >= piglit_width / 2) {
> -                                       if (sample_mask[piglit_width * k + i] != samples[j]) {
> -                                               pass = false;
> -                                               break;
> -                                       }
> -                               } else {
> -                                       if (sample_mask[piglit_width * k + i] != 0) {
> -                                               pass = false;
> -                                               break;
> -                                       }
> -                               }
> -                       }
> -
> -                       if (!pass)
> -                               break;
> -               }
> -
> -               glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
> -               glBindFramebuffer(GL_READ_FRAMEBUFFER, fbo);
> -               glDrawBuffer(GL_BACK);
> -               glBlitFramebuffer(0, 0, piglit_width, piglit_height, 0, 0, piglit_width,
> -                       piglit_height, GL_COLOR_BUFFER_BIT, GL_NEAREST);
> -
> -               piglit_present_results();
> -               free(sample_mask);
> -               if (!pass)
> -                       break;
> +       for (i = 0;
> +            i < ARRAY_SIZE(samples) && samples[i] <= max_sample_count;
> +            i++)
> +       {
> +               for (j = 0, mask = 0; j < samples[i]; j++)
> +                       mask |= (1 << j);
> +
> +               /* With post depth coverage, the depth test will be run on
> +                * each sample before the fragment shader's invocation. As a
> +                * result, sample 0 should fail the depth test and
> +                * gl_SampleMaskIn[0] should indicate that all samples but 0
> +                * are covered by the fragment shader.
> +                */
> +               if (!draw_and_check_sample_mask(prog2, samples[i], mask & ~1))
> +                       pass = false;
> +
> +               /* Without post depth coverage, the depth test will not have
> +                * been run by the time that the fragment shader is invoked,
> +                * and thus gl_SampleMaskIn[0] will indicate that all samples
> +                * are covered by the fragment shader.
> +                */
> +               if (!draw_and_check_sample_mask(prog3, samples[i], mask))
> +                       pass = false;
>         }
>
> -       pass = piglit_check_gl_error(GL_NO_ERROR) && pass;
> -
>         return pass ? PIGLIT_PASS : PIGLIT_FAIL;
>  }
> --
> 2.9.4
>
> _______________________________________________
> Piglit mailing list
> Piglit at lists.freedesktop.org
> https://lists.freedesktop.org/mailman/listinfo/piglit


More information about the Piglit mailing list