[Piglit] [PATCH V2 2/3] Add test to verify the accuracy of multisample scaled blitting
Paul Berry
stereotype441 at gmail.com
Tue Jul 9 16:20:17 PDT 2013
On 2 July 2013 12:20, Anuj Phogat <anuj.phogat at gmail.com> wrote:
> This test verifies the accuracy of scaled blitting on Intel's i965
> drivers by comparing the output images by:
> 1. multisample buffer to single sample buffer scaled blit using
> EXT_multisample_framebuffer_blit_scaled extension.
> 2. multisample buffer to single sample buffer scaled blit implemented
> using glsl shader program.
>
> Note: This test is specific to Intel's implementation of extension
> EXT_multisample_framebuffer_blit_scaled and may not produce expected
> results on other hardware. Test passes with all of the scaling factors
> between 0.1 to 2.5 on Intel's i965 drivers and NVIDIA's proprietary
> linux drivers.
>
It might be nice to reproduce the above paragraph in a comment in the .c
file, just so that if someone comes along later trying to figure out why
the test is failing on their implementation, they won't have to dig through
git history to find the explanation.
>
> V2: Add testing for scaled blitting using multisample framebuffer with
> renderbuffer attachment. This helps verify that mcs_fetch() is
> happening correctly for each sample.
>
> Signed-off-by: Anuj Phogat <anuj.phogat at gmail.com>
> ---
> .../ext_framebuffer_multisample/CMakeLists.gl.txt | 1 +
> .../blit-scaled.cpp | 372 +++++++++++++++++++++
> 2 files changed, 373 insertions(+)
> create mode 100644 tests/spec/ext_framebuffer_multisample/blit-scaled.cpp
>
> diff --git a/tests/spec/ext_framebuffer_multisample/CMakeLists.gl.txt
> b/tests/spec/ext_framebuffer_multisample/CMakeLists.gl.txt
> index 1542b92..b1f837e 100644
> --- a/tests/spec/ext_framebuffer_multisample/CMakeLists.gl.txt
> +++ b/tests/spec/ext_framebuffer_multisample/CMakeLists.gl.txt
> @@ -23,6 +23,7 @@ piglit_add_executable
> (ext_framebuffer_multisample-alpha-to-one-single-sample-bu
> draw-buffers-common.cpp
> alpha-to-one-single-sample-buffer.cpp)
> piglit_add_executable (ext_framebuffer_multisample-bitmap common.cpp
> bitmap.cpp)
> piglit_add_executable (ext_framebuffer_multisample-blit-flipped
> common.cpp blit-flipped.cpp)
> +piglit_add_executable (ext_framebuffer_multisample-blit-scaled common.cpp
> blit-scaled.cpp)
> piglit_add_executable
> (ext_framebuffer_multisample-blit-mismatched-samples common.cpp
> blit-mismatched-samples.cpp)
> piglit_add_executable (ext_framebuffer_multisample-blit-mismatched-sizes
> common.cpp blit-mismatched-sizes.cpp)
> piglit_add_executable
> (ext_framebuffer_multisample-blit-mismatched-formats common.cpp
> blit-mismatched-formats.cpp)
> diff --git a/tests/spec/ext_framebuffer_multisample/blit-scaled.cpp
> b/tests/spec/ext_framebuffer_multisample/blit-scaled.cpp
> new file mode 100644
> index 0000000..4d78a0b
> --- /dev/null
> +++ b/tests/spec/ext_framebuffer_multisample/blit-scaled.cpp
> @@ -0,0 +1,372 @@
> +/*
> + * Copyright © 2013 Intel Corporation
> + *
> + * 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.
> + */
> +
> +/** \file blit-scaled.cpp
> + *
> + * This test verifies the accuracy of scaled blitting from a multisampled
> + * buffer to a single-sampled buffer by comparing the output from
> following
> + * rendering scenarios:
> + * 1. Scaled blit using EXT_multisample_framebuffer_blit_scaled.
> + * 2. Scaled blit using glsl shader program.
> + */
> +
> +#include "common.h"
> +
> +const int pattern_width = 258; const int pattern_height = 258;
> +
> +PIGLIT_GL_TEST_CONFIG_BEGIN
> +
> + config.supports_gl_compat_version = 10;
> +
> + config.window_width = pattern_width * 2;
> + config.window_height = pattern_height;
> + config.window_visual = PIGLIT_GL_VISUAL_DOUBLE |
> PIGLIT_GL_VISUAL_RGBA;
> +
> +PIGLIT_GL_TEST_CONFIG_END
> +
> +static int num_samples;
> +static TestPattern *test_pattern;
> +static unsigned prog, vao, vertex_buf;
> +const float srcX0 = 6, srcY0 = 7, dstX0 = 0, dstY0 = 0;
> +const float srcX1 = pattern_width / 2, srcY1 = pattern_height / 2;
> +static Fbo multisampled_tex, multisampled_fbo, singlesampled_fbo;
> +
> +static void
> +print_usage_and_exit(char *prog_name)
> +{
> + printf("Usage: %s <num_samples>\n", prog_name);
> + piglit_report_result(PIGLIT_FAIL);
> +}
> +
> +void
> +compile_shader(void)
> +{
> + static const char *vert =
> + "#version 130\n"
> + "uniform mat4 proj;\n"
> + "in vec2 pos;\n"
> + "in vec2 texCoord;\n"
> + "out vec2 textureCoord;\n"
> + "void main()\n"
> + "{\n"
> + " gl_Position = proj * vec4(pos, 0.0, 1.0);\n"
> + " textureCoord = texCoord;\n"
> + "}\n";
> + /* Bilinear filtering of samples using shader program */
> + static const char *frag =
> + "#version 130\n"
> + "#extension GL_ARB_texture_multisample : require\n"
> + "in vec2 textureCoord;\n"
> + "uniform sampler2DMS ms_tex;\n"
> + "uniform int samples;\n"
> + "uniform float src_x0;\n"
> + "uniform float src_y0;\n"
> + "uniform float src_x1;\n"
> + "uniform float src_y1;\n"
> + "out vec4 out_color;\n"
> + "void main()\n"
> + "{\n"
> + " float x_f, y_f;\n"
> + " vec4 s_0, s_1, s_2, s_3;\n"
> + " vec2 s_0_coord, s_1_coord, s_2_coord, s_3_coord;\n"
> + " float x_scale = 2.0;\n"
> + " float y_scale = samples / 2.0;\n"
> + " int sample_map[8] = int[8](5 , 2, 4, 6, 0, 3, 7, 1);\n"
> + "\n"
> + " vec2 tex_coord = vec2(textureCoord.x - 1.0 / 4,\n"
> + " textureCoord.y - 1.0 /
> samples);\n"
> + " tex_coord = vec2(x_scale * tex_coord.x,\n"
> + " y_scale * tex_coord.y);\n"
> + "\n"
> + " if((tex_coord.x) < x_scale * src_x0)\n"
> + " tex_coord.x = x_scale * src_x0;\n"
> + " if(tex_coord.x >= x_scale * src_x1 - 1.0)\n"
> + " tex_coord.x = x_scale * src_x1 - 1.0;\n"
> + "\n"
> + " if(tex_coord.y < y_scale * src_y0)\n"
> + " tex_coord.y = y_scale * src_y0;\n"
> + " if(tex_coord.y >= y_scale * src_y1 - 1.0)\n"
> + " tex_coord.y = y_scale * src_y1 - 1.0;\n"
> + "\n"
> + " x_f = fract(tex_coord.x);\n"
> + " y_f = fract(tex_coord.y);\n"
> + "\n"
> + " tex_coord.x = int(tex_coord.x) / x_scale;\n"
> + " tex_coord.y = int(tex_coord.y) / y_scale;\n"
> + "\n"
> + " s_0_coord = tex_coord;\n"
> + " s_1_coord = s_0_coord + vec2(1 / x_scale, 0 /
> y_scale);\n"
> + " s_2_coord = s_0_coord + vec2(0 / x_scale, 1 /
> y_scale);\n"
> + " s_3_coord = s_0_coord + vec2(1 / x_scale, 1 /
> y_scale);\n"
> + "\n"
> + " if (samples == 4) {\n"
> + " s_0 = texelFetch(ms_tex, ivec2(s_0_coord),\n"
> + " int(2 * fract(s_0_coord.x) +\n"
> + " samples * fract(s_0_coord.y)));\n"
> + " s_1 = texelFetch(ms_tex, ivec2(s_1_coord),\n"
> + " int(2 * fract(s_1_coord.x) +\n"
> + " samples * fract(s_1_coord.y)));\n"
> + " s_2 = texelFetch(ms_tex, ivec2(s_2_coord),\n"
> + " int(2 * fract(s_2_coord.x) +\n"
> + " samples * fract(s_2_coord.y)));\n"
> + " s_3 = texelFetch(ms_tex, ivec2(s_3_coord),\n"
> + " int(2 * fract(s_3_coord.x) +\n"
> + " samples * fract(s_3_coord.y)));\n"
> + " } else {\n"
> + " s_0 = texelFetch(ms_tex, ivec2(s_0_coord),\n"
> + " sample_map[int(2 *
> fract(s_0_coord.x) +\n"
> + " samples * fract(s_0_coord.y))]);\n"
> + " s_1 = texelFetch(ms_tex, ivec2(s_1_coord),\n"
> + " sample_map[int(2 *
> fract(s_1_coord.x) +\n"
> + " samples * fract(s_1_coord.y))]);\n"
> + " s_2 = texelFetch(ms_tex, ivec2(s_2_coord),\n"
> + " sample_map[int(2 *
> fract(s_2_coord.x) +\n"
> + " samples * fract(s_2_coord.y))]);\n"
> + " s_3 = texelFetch(ms_tex, ivec2(s_3_coord),\n"
> + " sample_map[int(2 *
> fract(s_3_coord.x) +\n"
> + " samples * fract(s_3_coord.y))]);\n"
> + " }\n"
> + "\n"
> + " vec4 color_x1 = mix(s_0, s_1, x_f);\n"
> + " vec4 color_x2 = mix(s_2, s_3, x_f);\n"
> + " out_color = mix(color_x1, color_x2, y_f);\n"
> + "}\n";
> + /* Compile program */
> + prog = glCreateProgram();
> + GLint vs = piglit_compile_shader_text(GL_VERTEX_SHADER, vert);
> + glAttachShader(prog, vs);
> + piglit_check_gl_error(GL_NO_ERROR);
> + GLint fs = piglit_compile_shader_text(GL_FRAGMENT_SHADER, frag);
> + glAttachShader(prog, fs);
> + glBindAttribLocation(prog, 0, "pos");
> + glBindAttribLocation(prog, 1, "texCoord");
> + glLinkProgram(prog);
> + if (!piglit_link_check_status(prog)) {
> + piglit_report_result(PIGLIT_FAIL);
> + }
> +
> + /* Set up vertex array object */
> + glGenVertexArrays(1, &vao);
> + glBindVertexArray(vao);
> +
> + /* Set up vertex input buffer */
> + glGenBuffers(1, &vertex_buf);
> + glBindBuffer(GL_ARRAY_BUFFER, vertex_buf);
> + glEnableVertexAttribArray(0);
> + glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 4*sizeof(float),
> + (void *) 0);
> + glEnableVertexAttribArray(1);
> + glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 4*sizeof(float),
> + (void *) (2*sizeof(float)));
> +
> + /* Set up element input buffer to tesselate a quad into
> + * triangles
> + */
> + unsigned int indices[6] = { 0, 1, 2, 0, 2, 3 };
> + GLuint element_buf;
> + glGenBuffers(1, &element_buf);
> + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, element_buf);
> + glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices,
> + GL_STATIC_DRAW);
> +}
> +
> +void
> +ms_blit_scaled_glsl(const Fbo *src_fbo, GLint samples)
> +{
> + const float proj[4][4] = {
> + { 1, 0, 0, 0 },
> + { 0, 1, 0, 0 },
> + { 0, 0, 1, 0 },
> + { 0, 0, 0, 1 }};
> +
> + float vertex_data[4][4] = {
> + { -1, -1, srcX0, srcY0 },
> + { -1, 1, srcX0, srcY1 },
> + { 1, 1, srcX1, srcY1 },
> + { 1, -1, srcX1, srcY0 }};
> +
> + glActiveTexture(GL_TEXTURE0);
> + glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, src_fbo->color_tex);
> + glUseProgram(prog);
> + glBindVertexArray(vao);
> +
> + /* Set up uniforms */
> + glUseProgram(prog);
> + glUniform1i(glGetUniformLocation(prog, "ms_tex"), 0);
> + glUniform1i(glGetUniformLocation(prog, "samples"), samples);
> + glUniform1f(glGetUniformLocation(prog, "src_x0"), 0);
> + glUniform1f(glGetUniformLocation(prog, "src_y0"), 0);
> + glUniform1f(glGetUniformLocation(prog, "src_x1"),
> + multisampled_fbo.config.width);
> + glUniform1f(glGetUniformLocation(prog, "src_y1"),
> + multisampled_fbo.config.height);
>
This is confusing because it's a holdover from the old implementation where
we were clipping the texel coordinate to the source rectangle, rather than
to the source framebuffer.
I'd recommend renaming src_x0, src_y0, src_x1, and src_y1 to something like
xmin, ymin, xmax, and ymax since that's what they mean now.
> + glUniformMatrix4fv(glGetUniformLocation(prog, "proj"), 1,
> + GL_TRUE, &proj[0][0]);
> +
> + glBindBuffer(GL_ARRAY_BUFFER, vertex_buf);
> + glBufferData(GL_ARRAY_BUFFER, sizeof(vertex_data), vertex_data,
> + GL_STREAM_DRAW);
> + glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, (void *) 0);
> +}
> +
> +void
> +piglit_init(int argc, char **argv)
> +{
> + if (argc != 2)
> + print_usage_and_exit(argv[0]);
> +
> + /* 1st arg: num_samples */
> + char *endptr = NULL;
> + num_samples = strtol(argv[1], &endptr, 0);
> + if (endptr != argv[1] + strlen(argv[1]))
> + print_usage_and_exit(argv[0]);
> +
> + piglit_require_gl_version(21);
> + piglit_require_extension("GL_ARB_vertex_array_object");
> +
> piglit_require_extension("GL_EXT_framebuffer_multisample_blit_scaled");
> +
> + /* Skip the test if num_samples > GL_MAX_SAMPLES */
> + GLint max_samples;
> + glGetIntegerv(GL_MAX_SAMPLES, &max_samples);
> + if (num_samples == 0 || num_samples > max_samples)
> + piglit_report_result(PIGLIT_SKIP);
> +
> + singlesampled_fbo.setup(FboConfig(0,
> + 2 * pattern_width,
> + pattern_height));
> + /* Create two multisample FBOs with same dimensions and sample
> count
> + * but different color attachment types.
> + */
> + FboConfig msConfig(num_samples, pattern_width, pattern_height);
> + msConfig.attach_texture = true;
> + multisampled_tex.setup(msConfig);
> + msConfig.attach_texture = false;
> + multisampled_fbo.setup(msConfig);
> +
> + test_pattern = new Triangles();
> + test_pattern->compile();
> +
> + compile_shader();
> + if (!piglit_check_gl_error(GL_NO_ERROR)) {
> + piglit_report_result(PIGLIT_FAIL);
> + }
> +}
> +
> +bool test_ms_blit_scaled(Fbo ms_fbo)
> +{
> + GLfloat scale;
> + GLint samples;
> + bool pass = true, result = true;
> +
> + /* Draw the test pattern into the framebuffer with texture
> + * attachment.
> + */
> + glBindFramebuffer(GL_DRAW_FRAMEBUFFER, multisampled_tex.handle);
> + glViewport(0, 0, srcX1, srcY1);
> + glGetIntegerv(GL_SAMPLES, &samples);
> + glClear(GL_COLOR_BUFFER_BIT);
> + test_pattern->draw(TestPattern::no_projection);
> +
> + if(!ms_fbo.config.attach_texture) {
> + /* Blit the framebuffer with multisample texture attachment
> + * into the framebuffer with multisample renderbuffer
> attachment.
> + */
> + glBindFramebuffer(GL_READ_FRAMEBUFFER,
> multisampled_tex.handle);
> + glBindFramebuffer(GL_DRAW_FRAMEBUFFER,
> multisampled_fbo.handle);
> + glClear(GL_COLOR_BUFFER_BIT);
> + glBlitFramebuffer(0, 0,
> + multisampled_tex.config.width,
> + multisampled_tex.config.height,
> + 0, 0,
> + multisampled_tex.config.width,
> + multisampled_tex.config.height,
> + GL_COLOR_BUFFER_BIT, GL_NEAREST);
> + }
> +
> + for(scale = 0.1; scale < 2.5f; scale += 0.1) {
> + glBindFramebuffer(GL_DRAW_FRAMEBUFFER, piglit_winsys_fbo);
> + glClear(GL_COLOR_BUFFER_BIT);
> +
> + /* Do scaled resolve of multisampled_fbo to left half of
> + * singlesampled_fbo.
> + */
> +// printf("ms to ss scaled blit using extension.\n");
>
This commented-out printf should probably go away (as well as the two
commented out printfs below).
> + glBindFramebuffer(GL_READ_FRAMEBUFFER, ms_fbo.handle);
> + glBindFramebuffer(GL_DRAW_FRAMEBUFFER,
> singlesampled_fbo.handle);
> + glClearColor(0.0, 1.0, 0.0, 1.0);
> + glClear(GL_COLOR_BUFFER_BIT);
> + glClearColor(0.0, 0.0, 0.0, 0.0);
> + glEnable(GL_SCISSOR_TEST);
> + glScissor(0, 0, pattern_width, pattern_height);
> + glBlitFramebuffer(srcX0, srcY0,
> + srcX1, srcY1,
> + dstX0, dstY0,
> + dstX0 + srcX1 * scale, dstY0 + srcY1 *
> scale,
> + GL_COLOR_BUFFER_BIT,
> + GL_SCALED_RESOLVE_FASTEST_EXT);
> + glDisable(GL_SCISSOR_TEST);
> +
> + /* Use multisampled texture to draw in to right half of
> scaled
> + * single-sampled buffer using shader program.
> + */
> +// printf("ms to ss scaled blit using shader program.\n");
> + glBindFramebuffer(GL_READ_FRAMEBUFFER,
> multisampled_tex.handle);
> + glBindFramebuffer(GL_DRAW_FRAMEBUFFER,
> singlesampled_fbo.handle);
> + glViewport(pattern_width + dstX0, dstY0, srcX1 * scale,
> srcY1 * scale);
> + ms_blit_scaled_glsl(&multisampled_tex, samples);
> +
> + pass = piglit_check_gl_error(GL_NO_ERROR) && pass;
> + glBindFramebuffer(GL_READ_FRAMEBUFFER,
> singlesampled_fbo.handle);
> + result = piglit_probe_rect_halves_equal_rgba(0, 0,
> + piglit_width,
> + piglit_height);
> + pass = result && pass;
> +
> +// printf("ss non-scaled blit to window system
> framebuffer.\n");
> + glBindFramebuffer(GL_READ_FRAMEBUFFER,
> singlesampled_fbo.handle);
> + glBindFramebuffer(GL_DRAW_FRAMEBUFFER, piglit_winsys_fbo);
> + glBlitFramebuffer(0, 0, 2 * pattern_width, piglit_height,
> + 0, 0, 2 * pattern_width, piglit_height,
> + GL_COLOR_BUFFER_BIT, GL_NEAREST);
> + piglit_present_results();
> + printf("MS attachment = %24s, scale = %f, result = %s\n",
> + ms_fbo.config.attach_texture ?
> + "MULTISAMPLE_TEXTURE" :
> + "MULTISAMPLE_RENDERBUFFER",
> + scale, result ? "pass" : "fail");
> + }
> + return pass;
> +}
> +
> +enum piglit_result
> +piglit_display()
> +{
> + bool pass = true;
> + printf("Left Image: multisample scaled blit using extension.\n"
> + "Right Image: multisample scaled blit using shader
> program.\n");
> + pass = test_ms_blit_scaled(multisampled_tex)
> + && pass;
> + pass = test_ms_blit_scaled(multisampled_fbo)
> + && pass;
> + return pass ? PIGLIT_PASS : PIGLIT_FAIL;
> +}
> --
> 1.8.1.4
>
>
It's unfortunate that this test is so specific to the algorithm we've used
in our implementation, but I can't really think of a suggestion for making
the test more general, so with the above changes, the series is:
Reviewed-by: Paul Berry <stereotype441 at gmail.com>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.freedesktop.org/archives/piglit/attachments/20130709/b0fe8328/attachment-0001.html>
More information about the Piglit
mailing list