[Piglit] [PATCH 2/3] Add test to verify the accuracy of multisample scaled blit using a shader program

Anuj Phogat anuj.phogat at gmail.com
Tue Jun 4 18:17:34 PDT 2013


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 extension
   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 don't produce expected
results on other hardware. So, this might not land in upstream piglit.
Test passes with all of the scaling factors between 0.1 to 2.5 on
Intel's i965 drivers. Patches for scaled blitting support on i965 are
out for review on mesa-dev mailing list.

Signed-off-by: Anuj Phogat <anuj.phogat at gmail.com>
---
 .../ext_framebuffer_multisample/CMakeLists.gl.txt  |   1 +
 .../blit-scaled-glsl.cpp                           | 294 +++++++++++++++++++++
 2 files changed, 295 insertions(+)
 create mode 100644 tests/spec/ext_framebuffer_multisample/blit-scaled-glsl.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-glsl common.cpp blit-scaled-glsl.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-glsl.cpp b/tests/spec/ext_framebuffer_multisample/blit-scaled-glsl.cpp
new file mode 100644
index 0000000..b8094ca
--- /dev/null
+++ b/tests/spec/ext_framebuffer_multisample/blit-scaled-glsl.cpp
@@ -0,0 +1,294 @@
+/*
+ * 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-glsl.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. multisample buffer to single sample buffer scaled blit using extension
+ *    EXT_multisample_framebuffer_blit_scaled extension.
+ * 2. multisample buffer to single sample buffer scaled blit implemented
+ *    using glsl shader program.
+ */
+
+#include "common.h"
+
+const int pattern_width = 258; const int pattern_height = 258;
+const float w = pattern_width / 2; const float h = pattern_height / 2;
+int srcX0 = 0;
+int srcY0 = 0;
+int dstX0 = 0;
+int dstY0 = 0;
+
+int num_samples;
+
+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 Fbo multisampled_fbo, singlesampled_fbo;
+GLuint prog, vao, vertex_buf;
+static TestPattern *test_pattern;
+static Test *test = NULL;
+
+static void
+print_usage_and_exit(char *prog_name)
+{
+	printf("Usage: %s <num_samples>\n", prog_name);
+	piglit_report_result(PIGLIT_FAIL);
+}
+
+void
+compile_ms_scaled_blit_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. */
+	static const char *frag =
+		"#version 130\n"
+		"#extension GL_ARB_texture_multisample : require\n"
+		"in vec2 textureCoord;\n"
+		"uniform sampler2DMS msTex;\n"
+		"uniform int samples;\n"
+		"out vec4 out_color;\n"
+		"void main()\n"
+		"{\n"
+		"  vec4 s_0, s_1, s_2, s_3;\n"
+		"  float x_f = fract(textureCoord.x);\n"
+		"  float y_f = fract(textureCoord.y);\n"
+		"  if (samples == 4) {\n"
+		"    s_0 = texelFetch(msTex, ivec2(textureCoord), 0);\n"
+		"    s_1 = texelFetch(msTex, ivec2(textureCoord), 1);\n"
+		"    s_2 = texelFetch(msTex, ivec2(textureCoord), 2);\n"
+		"    s_3 = texelFetch(msTex, ivec2(textureCoord), 3);\n"
+		"  } else {\n"
+		"    s_0 = texelFetch(msTex, ivec2(textureCoord), 4);\n"
+		"    s_0 = s_0 + texelFetch(msTex, ivec2(textureCoord), 5);\n"
+		"    s_0 = s_0 / 2.0;\n"
+		"    s_1 = texelFetch(msTex, ivec2(textureCoord), 2);\n"
+		"    s_1 = s_1 + texelFetch(msTex, ivec2(textureCoord), 6);\n"
+		"    s_1 = s_1 / 2.0;\n"
+		"    s_2 = texelFetch(msTex, ivec2(textureCoord), 0);\n"
+		"    s_2 = s_2 + texelFetch(msTex, ivec2(textureCoord), 7);\n"
+		"    s_2 = s_2 / 2.0;\n"
+		"    s_3 = texelFetch(msTex, ivec2(textureCoord), 1);\n"
+		"    s_3 = s_3 + texelFetch(msTex, ivec2(textureCoord), 3);\n"
+		"    s_3 = s_3 / 2.0;\n"
+		"  }\n"
+		"  vec4 color_x1 =  mix(s_0, s_1, fract(textureCoord.x));\n"
+		"  vec4 color_x2 =  mix(s_2, s_3, fract(textureCoord.x));\n"
+		"  out_color = mix(color_x1, color_x2, fract(textureCoord.y));\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
+do_multisample_scaled_blit(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, 0, 0 },
+		{ -1,  1, 0, h },
+		{  1,  1, w, h },
+		{  1, -1, w, 0 }};
+
+	glActiveTexture(GL_TEXTURE0);
+	glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, src_fbo->color_tex);
+	glUseProgram(prog);
+	glBindVertexArray(vao);
+
+	/* Set up uniforms */
+	glUseProgram(prog);
+	glUniformMatrix4fv(glGetUniformLocation(prog, "proj"), 1, GL_TRUE, &proj[0][0]);
+	glUniform1i(glGetUniformLocation(prog, "msTex"), 0);
+	glUniform1i(glGetUniformLocation(prog, "samples"), samples);
+
+	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));
+	FboConfig msConfig(num_samples, pattern_width, pattern_height);
+	msConfig.attach_texture = true;
+	multisampled_fbo.setup(msConfig);
+
+	test_pattern = new Triangles();
+	test_pattern->compile();
+
+	test = create_test(TEST_TYPE_COLOR, num_samples,
+                           false /*small*/,
+			   true /* combine_depth_stencil */,
+			   pattern_width, pattern_height,
+			   16 /* supersample_factor */);
+
+	compile_ms_scaled_blit_shader();
+	if (!piglit_check_gl_error(GL_NO_ERROR)) {
+		piglit_report_result(PIGLIT_FAIL);
+	}
+}
+
+enum piglit_result
+piglit_display()
+{
+	GLfloat scale;
+	GLint samples;
+	bool pass = true, result = true;
+
+	/* Draw the test pattern into the framebuffer with multisample
+	 * texture attachment.
+	 */
+	glBindFramebuffer(GL_DRAW_FRAMEBUFFER, multisampled_fbo.handle);
+	glGetIntegerv(GL_SAMPLES, &samples);
+	glViewport(0, 0, w, h);
+	glClear(GL_COLOR_BUFFER_BIT);
+	test_pattern->draw(TestPattern::no_projection);
+
+	printf("Left: multisample scaled blit using extension.\n"
+	       "Right: multisample scaled blit using shader program.\n");
+
+        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");
+		glBindFramebuffer(GL_READ_FRAMEBUFFER, multisampled_fbo.handle);
+		glBindFramebuffer(GL_DRAW_FRAMEBUFFER, singlesampled_fbo.handle);
+		glClear(GL_COLOR_BUFFER_BIT);
+		glEnable(GL_SCISSOR_TEST);
+		glScissor(0, 0, pattern_width, pattern_height);
+		glBlitFramebuffer(0, 0, w, h,
+				  dstX0, dstY0, dstX0 + w * scale, dstY0 + h * 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_fbo.handle);
+		glBindFramebuffer(GL_DRAW_FRAMEBUFFER, singlesampled_fbo.handle);
+		glViewport(pattern_width + dstX0, dstY0, w * scale, h * scale);
+		do_multisample_scaled_blit(&multisampled_fbo, samples);
+
+		pass = piglit_check_gl_error(GL_NO_ERROR) && 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);
+
+		result = test->measure_accuracy();
+		pass = result && pass;
+		piglit_present_results();
+		printf("scaling_factor = %f, result = %s\n\n",
+		       scale, result ? "pass" : "fail");
+	}
+	return pass ? PIGLIT_PASS : PIGLIT_FAIL;
+}
-- 
1.8.1.4



More information about the Piglit mailing list