summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLyude <lyude@redhat.com>2017-05-22 14:55:10 -0400
committerIlia Mirkin <imirkin@alum.mit.edu>2017-07-19 20:41:23 -0400
commit973892687cf5c2f8e2dbe1d22998b82736643787 (patch)
tree2d579c13c90cb023031ec9670cdb0d8b8a2c0b50
parent779548372f0a0bab3a344d0470812faa4ae6d7cc (diff)
arb_post_depth_coverage: Make multisampling test more robust
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. Signed-off-by: Lyude <lyude@redhat.com> Reviewed-by: Ilia Mirkin <imirkin@alum.mit.edu>
-rw-r--r--tests/spec/arb_post_depth_coverage/multisampling.c349
1 files 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 f90208d74..af23b3e93 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;
}