[Piglit] [PATCH] arb_texture_multisample: add test to check sample positions v2

Paul Berry stereotype441 at gmail.com
Mon Apr 8 15:06:14 PDT 2013


On 6 April 2013 16:19, Christoph Bumiller <christoph.bumiller at speed.at>wrote:

> From: Christoph Bumiller <e0425955 at student.tuwien.ac.at>
>
> v2: Removed dependency on TextureBarrierNV and ARB_tfb_2, added
> comments.
> ---
>  .../spec/arb_texture_multisample/CMakeLists.gl.txt |    1 +
>  .../spec/arb_texture_multisample/sample-position.c |  236
> ++++++++++++++++++++
>  2 files changed, 237 insertions(+), 0 deletions(-)
>  create mode 100644 tests/spec/arb_texture_multisample/sample-position.c
>
> diff --git a/tests/spec/arb_texture_multisample/CMakeLists.gl.txt
> b/tests/spec/arb_texture_multisample/CMakeLists.gl.txt
> index 1339d62..642418f 100644
> --- a/tests/spec/arb_texture_multisample/CMakeLists.gl.txt
> +++ b/tests/spec/arb_texture_multisample/CMakeLists.gl.txt
> @@ -18,5 +18,6 @@ piglit_add_executable
> (arb_texture_multisample-sample-mask sample-mask.c)
>  piglit_add_executable (arb_texture_multisample-sample-mask-value
> sample-mask-value.c)
>  piglit_add_executable (arb_texture_multisample-sample-mask-execution
> sample-mask-execution.c)
>  piglit_add_executable (arb_texture_multisample-negative-max-samples
> negative-max-samples.c)
> +piglit_add_executable (arb_texture_multisample-sample-position
> sample-position.c)
>
>  # vim: ft=cmake:
> diff --git a/tests/spec/arb_texture_multisample/sample-position.c
> b/tests/spec/arb_texture_multisample/sample-position.c
> new file mode 100644
> index 0000000..fed9f27
> --- /dev/null
> +++ b/tests/spec/arb_texture_multisample/sample-position.c
> @@ -0,0 +1,236 @@
> +/*
> + * Copyright © The Piglit Project 2013
> + *
> + * Permission is hereby granted, free of charge, to any person obtaining a
> + * copy of this software and associated documentation files (the
> "Software"),
> + * to deal in the Software without restriction, including without
> limitation
> + * the rights to use, copy, modify, merge, publish, distribute,
> sublicense,
> + * and/or sell copies of the Software, and to permit persons to whom the
> + * Software is furnished to do so, subject to the following conditions:
> + *
> + * The above copyright notice and this permission notice (including the
> next
> + * paragraph) shall be included in all copies or substantial portions of
> the
> + * Software.
> + *
> + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
> EXPRESS OR
> + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
> MERCHANTABILITY,
> + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT
> SHALL
> + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
> OTHER
> + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
> + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
> + * DEALINGS IN THE SOFTWARE.
> + *
> + * Authors: Christoph Bumiller
> + */
> +#include "piglit-util-gl-common.h"
> +
> +/* File: sample-position.c
> + *
> + * Tests whether the sample positions reported by the driver via
> + * glGetMultisamplefv correspond to the actually positions used when
> rendering.
> + *
> + * This test draws creates a 1x1 multisample texture and renders a
> triangle
> + * covering all of the render target starting at a specific x/y offset
> from
> + * the left/bottom to test the x/y coordinate.
> + * After each such draw, the value of all the samples is recorded into a
> buffer
> + * via transform feedback, and the offset is increased slightly.
> + * In the end, the buffer is mapped to check if the correct samples were
> + * covered.
> + */
> +
> +PIGLIT_GL_TEST_CONFIG_BEGIN
> +
> +    config.supports_gl_compat_version = 30;
> +    config.window_visual = PIGLIT_GL_VISUAL_RGB;
> +
> +PIGLIT_GL_TEST_CONFIG_END
> +
> +#define NUM_STEPS   32
> +#define MAX_SAMPLES 32
> +
> +static GLuint tfb;
> +static GLuint buf;
> +static GLuint tex;
> +static GLuint fbo;
> +static GLuint prog;
> +
> +static int samples = 0;
> +
> +enum piglit_result
> +piglit_display(void)
> +{
> +       float mspos[MAX_SAMPLES][2];
> +       float *res;
> +       const float inc = 2.0f / (float)NUM_STEPS;
> +       GLint u;
> +       unsigned int i, s;
> +       enum piglit_result result = PIGLIT_PASS;
> +
> +       glUseProgram(prog);
> +
> +       u = glGetUniformLocation(prog, "pos");
> +
> +       glBindFramebuffer(GL_FRAMEBUFFER, fbo);
> +       for (i = 0; i < samples; ++i)
> +               glGetMultisamplefv(GL_SAMPLE_POSITION, i, &mspos[i][0]);
> +
> +       glActiveTexture(GL_TEXTURE0);
> +       glUniform1i(glGetUniformLocation(prog, "tex"), 0);
> +
> +       glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
> +
> +       /* render triangles from x = -1 + i*increment to test coverage at
> x */
> +       for (i = 0; i < NUM_STEPS; ++i) {
> +               /* clear and draw to MS texture */
> +               glBindFramebuffer(GL_FRAMEBUFFER, fbo);
> +               glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, 0);
> +               glClear(GL_COLOR_BUFFER_BIT);
> +               /* set bottom left vertex (others generated via
> gl_VertexID) */
> +               glUniform2f(u, -1.0f + inc * (float)i, -1.0f);
> +               glDrawArrays(GL_TRIANGLES, 0, 3);
>

The use of gl_VertexID to generate the other vertices seems unnecessarily
obscure.  How about just making pos a vertex attribute and doing something
like this?

GLfloat x = -1.0 + inc * i;
GLfloat y = -1.0;
GLfloat pos[3][2] = { { x, y }, { x + 2, y }, { x, y + 2 } };
glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, pos);
glEnableVertexAttribArray(0);


> +
> +               /* bind MS texture as texture to record samples */
> +               glBindFramebuffer(GL_FRAMEBUFFER, 0);
> +               glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, tex);
> +               glBindBufferRange(GL_TRANSFORM_FEEDBACK_BUFFER, 0, buf,
> +                                 MAX_SAMPLES * sizeof(float) * i,
> +                                 MAX_SAMPLES * sizeof(float));
> +               glBeginTransformFeedback(GL_POINTS);
> +               glDrawArrays(GL_POINTS, 0, 1);
> +               glEndTransformFeedback();
> +       }
> +       /* render triangles from y = -1 + i*increment to test coverage at
> y */
> +       for (i = 0; i < NUM_STEPS; ++i) {
> +               /* clear and draw to MS texture */
> +               glBindFramebuffer(GL_FRAMEBUFFER, fbo);
> +               glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, 0);
> +               glClear(GL_COLOR_BUFFER_BIT);
> +               /* set bottom left vertex (others generated via
> gl_VertexID) */
> +               glUniform2f(u, -1.0f, -1.0f + inc * (float)i);
> +               glDrawArrays(GL_TRIANGLES, 0, 3);
> +
> +               /* bind MS texture as texture to record samples */
> +               glBindFramebuffer(GL_FRAMEBUFFER, 0);
> +               glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, tex);
> +               glBindBufferRange(GL_TRANSFORM_FEEDBACK_BUFFER, 0, buf,
> +                                 MAX_SAMPLES * sizeof(float) * (i +
> NUM_STEPS),
> +                                 MAX_SAMPLES * sizeof(float));
> +               glBeginTransformFeedback(GL_POINTS);
> +               glDrawArrays(GL_POINTS, 0, 1);
> +               glEndTransformFeedback();
> +       }
>

The contents of this loop are almost identical to the contents of the loop
above.  Can we put the loop contents in a function so that we don't have to
duplicate code?


> +
> +       res = glMapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, GL_READ_ONLY);
> +
> +       for (i = 0; i < NUM_STEPS; ++i) {
> +               float p = (float)i / (float)NUM_STEPS; /* x/y offset */
> +
> +               int base_x = i * MAX_SAMPLES;
> +               int base_y = i * MAX_SAMPLES + NUM_STEPS * MAX_SAMPLES;
> +#if 0
> +               fprintf(stderr, "x >= %f:", p);
> +               for (s = 0; s < samples; ++s)
> +                       if (res[base_x + s] == 1.0f)
> +                               fprintf(stderr, " %u", s);
> +               fprintf(stderr, "\n");
> +               fprintf(stderr, "y >= %f:", p);
> +               for (s = 0; s < samples; ++s)
> +                       if (res[base_y + s] == 1.0f)
> +                               fprintf(stderr, " %u", s);
> +               fprintf(stderr, "\n");
> +#endif
> +               /* See which samples are covered at this x/y offset and if
> it
> +                * matches what we expect from GL_SAMPLE_POSITION.
> +                */
> +               for (s = 0; s < samples; ++s) {
> +                       if ((p >  mspos[s][0] && res[base_x + s] == 1.0f)
> ||
> +                           (p <= mspos[s][0] && res[base_x + s] != 1.0f))
> {
> +                               result = PIGLIT_FAIL;
> +                               fprintf(stderr, "sample %i x position (%f,
> %f) "
> +                                       "incorrect !\n",s,
> +                                       mspos[s][0], mspos[s][1]);
> +                       }
> +                       if ((p >  mspos[s][1] && res[base_y + s] == 1.0f)
> ||
> +                           (p <= mspos[s][1] && res[base_y + s] != 1.0f))
> {
> +                               result = PIGLIT_FAIL;
> +                               fprintf(stderr, "sample %i y position (%f,
> %f) "
> +                                       "incorrect !\n",s,
> +                                       mspos[s][0], mspos[s][1]);
> +                       }
> +               }
>

Can we modify the test so that it also prints out what sample position was
observed?  Without this information it's really difficult to investigate
failures.


> +       }
> +       glUnmapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER);
> +
> +       return result;
> +}
> +
> +static const char *vsSource = "#version 130 \n"
> +       "#extension GL_ARB_texture_multisample : require\n"
> +       "uniform sampler2DMS tex; \n"
> +       "uniform vec2 pos; \n"
> +       "out float sample[32]; \n" /* 32 == MAX_SAMPLES */
> +       "void main() { \n"
> +       "   int v = int(gl_VertexID); \n" /* if I can't have immediate
> mode ... */
> +       "   int i; \n"
> +       "   gl_Position.xy = pos + 8.0 * vec2(float(v & 1), float(v & 2));
> \n"
> +       "   gl_Position.zw = vec2(0.0, 1.0); \n"
> +       "   for (i = 0; i < 32; ++i) \n"
> +       "      sample[i] = texelFetch(tex, ivec2(0, 0), i).g; \n"
> +       "} \n";
>

I found this program difficult to follow because it is used twice to do two
completely independent things:

- once to generate triangles (which are written to the multisample texture).
- once to read data back from the multisample texture.

Can we split it into two separate programs?


> +
> +static const char *fsSource = "#version 130 \n"
> +       "void main() { \n"
> +       "   gl_FragColor = vec4(0.0, 1.0, 0.0, 1.0); \n"
> +       "} \n";
> +
> +void
> +piglit_init(int argc, char **argv)
> +{
> +       static const char *varyings[] = { "sample" };
> +       GLuint vs, fs;
> +       GLuint max_samples;
> +
> +       piglit_require_extension("GL_ARB_texture_multisample");
> +       piglit_require_extension("GL_EXT_transform_feedback");
> +
> +       if (argc < 2) {
> +               fprintf(stderr, "texelFetch <sample_count>\n");
>

I don't think you mean "texelFetch" here.  I usually do something like:

fprintf(stderr, "%s <sample_count>\n", argv[0]);


> +               exit(0);
>

I would be a little more comfortable with exit(1), so that just in case
someone tries to automate this test they'll be more likely to notice if
there's an error.

Alternatively, you could just use "piglit_report_result(PIGLIT_FAIL);"


> +       }
> +       samples = strtoul(argv[1], NULL, 0);
> +
> +       glGetIntegerv(GL_MAX_SAMPLES, (GLint *)&max_samples);
> +       if (samples > max_samples)
> +               piglit_report_result(PIGLIT_SKIP);
> +
> +       vs = piglit_compile_shader_text(GL_VERTEX_SHADER, vsSource);
> +       fs = piglit_compile_shader_text(GL_FRAGMENT_SHADER, fsSource);
> +       prog = piglit_link_simple_program(vs, fs);
> +
> +       glGenTransformFeedbacks(1, &tfb);
> +       glBindTransformFeedback(GL_TRANSFORM_FEEDBACK, tfb);
>

The two lines above require ARB_transform_feedback2, but it looks like you
aren't using any transform_feedback2 functionality.  Can we drop these two
lines (and the "tfb" global)?


> +       glTransformFeedbackVaryings(prog, 1, varyings,
> GL_INTERLEAVED_ATTRIBS);
> +       glLinkProgram(prog);
> +       glGenBuffers(1, &buf);
> +       glBindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, buf);
> +       glBufferData(GL_TRANSFORM_FEEDBACK_BUFFER,
> +                    MAX_SAMPLES * sizeof(float) * NUM_STEPS * 2, NULL,
> +                    GL_STREAM_DRAW);
> +
> +       glGenTextures(1, &tex);
> +       glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, tex);
> +       glTexImage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, samples,
> +                               GL_RGBA8,
> +                               1, 1, GL_TRUE);
> +       glGenFramebuffers(1, &fbo);
> +       glBindFramebuffer(GL_FRAMEBUFFER, fbo);
> +       glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
> +                              GL_TEXTURE_2D_MULTISAMPLE, tex, 0);
> +
> +       assert(glCheckFramebufferStatus(GL_FRAMEBUFFER) ==
> GL_FRAMEBUFFER_COMPLETE);
> +
> +       glViewport(0, 0, 1, 1);
> +
> +       if (!piglit_check_gl_error(GL_NO_ERROR))
> +               piglit_report_result(PIGLIT_FAIL);
> +}
> --
> 1.7.3.4
>
> _______________________________________________
> Piglit mailing list
> Piglit at lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/piglit
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.freedesktop.org/archives/piglit/attachments/20130408/f4e96d3a/attachment-0001.html>


More information about the Piglit mailing list