[Cc'ing original test author/reviewer...]
On Mon, May 22, 2017 at 2:55 PM, Lyude <ly...@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 <ly...@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@lists.freedesktop.org > https://lists.freedesktop.org/mailman/listinfo/piglit _______________________________________________ Piglit mailing list Piglit@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/piglit