[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