[Piglit] [PATCH] EXT_multisampled_render_to_texture: functional test

Magnus Wendt magnus.wendt at intel.com
Wed Dec 16 06:33:47 PST 2015


EXT_multisampled_render_to_texture allows you to bind a singlesampled
texture to the color attachment of a multisampled framebuffer object.
Rendering is multisampled and the multisample data is implicitly
resolved and invalidated when texturing.

The test renders a ground truth image by drawing a slanted textured quad
to a multisampled fbo and resolves it using a blit to a singlesampled
fbo. This is textured onto the left half of the window.
It then renders the same thing into an implicitly resolved fbo and
textures that onto the right half of the screen. The two halfs are
compared. This is repeated for another slant and different clear colors
to check for possible interactions with fast clear.
The test passes if the two methods yeild identical results for all image
pairs.

Signed-off-by: Magnus Wendt <magnus.wendt at intel.com>
---
 tests/all.py                                       |   7 +
 tests/spec/CMakeLists.txt                          |   1 +
 .../CMakeLists.gles3.txt                           |   5 +
 .../CMakeLists.txt                                 |   1 +
 .../ext_multisampled_render_to_texture.c           | 367 +++++++++++++++++++++
 5 files changed, 381 insertions(+)
 create mode 100644 tests/spec/ext_multisampled_render_to_texture/CMakeLists.gles3.txt
 create mode 100644 tests/spec/ext_multisampled_render_to_texture/CMakeLists.txt
 create mode 100644 tests/spec/ext_multisampled_render_to_texture/ext_multisampled_render_to_texture.c

diff --git a/tests/all.py b/tests/all.py
index f61ff15..c17450b 100644
--- a/tests/all.py
+++ b/tests/all.py
@@ -4552,5 +4552,12 @@ with profile.group_manager(
     for sample_count in (str(x) for x in MSAA_SAMPLE_COUNTS):
         g(['ext_shader_samples_identical', sample_count])
 
+# Group EXT_multismapled_render_to_texture
+with profile.group_manager(
+        PiglitGLTest,
+        grouptools.join('spec', 'ext_multisampled_render_to_texture')) as g:
+    for sample_count in (str(x) for x in MSAA_SAMPLE_COUNTS):
+        g(['ext_multisampled_render_to_texture', sample_count])
+
 if platform.system() is 'Windows':
     profile.filter_tests(lambda p, _: not p.startswith('glx'))
diff --git a/tests/spec/CMakeLists.txt b/tests/spec/CMakeLists.txt
index 57ac541..21ec666 100644
--- a/tests/spec/CMakeLists.txt
+++ b/tests/spec/CMakeLists.txt
@@ -75,6 +75,7 @@ add_subdirectory (ext_depth_bounds_test)
 add_subdirectory (ext_fog_coord)
 add_subdirectory (ext_framebuffer_multisample)
 add_subdirectory (ext_framebuffer_multisample_blit_scaled)
+add_subdirectory (ext_multisampled_render_to_texture)
 add_subdirectory (ext_packed_depth_stencil)
 add_subdirectory (ext_packed_float)
 add_subdirectory (ext_shader_samples_identical)
diff --git a/tests/spec/ext_multisampled_render_to_texture/CMakeLists.gles3.txt b/tests/spec/ext_multisampled_render_to_texture/CMakeLists.gles3.txt
new file mode 100644
index 0000000..fbb688c
--- /dev/null
+++ b/tests/spec/ext_multisampled_render_to_texture/CMakeLists.gles3.txt
@@ -0,0 +1,5 @@
+link_libraries(
+	piglitutil_${piglit_target_api}
+	)
+
+piglit_add_executable(ext_multisampled_render_to_texture ext_multisampled_render_to_texture.c)
diff --git a/tests/spec/ext_multisampled_render_to_texture/CMakeLists.txt b/tests/spec/ext_multisampled_render_to_texture/CMakeLists.txt
new file mode 100644
index 0000000..144a306
--- /dev/null
+++ b/tests/spec/ext_multisampled_render_to_texture/CMakeLists.txt
@@ -0,0 +1 @@
+piglit_include_target_api()
diff --git a/tests/spec/ext_multisampled_render_to_texture/ext_multisampled_render_to_texture.c b/tests/spec/ext_multisampled_render_to_texture/ext_multisampled_render_to_texture.c
new file mode 100644
index 0000000..6a7cb02
--- /dev/null
+++ b/tests/spec/ext_multisampled_render_to_texture/ext_multisampled_render_to_texture.c
@@ -0,0 +1,367 @@
+/*
+ * Copyright (c) 2015 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 ext_multisampled_render_to_texture.c
+ * Functional test for EXT_multisampled_render_to_texture.
+ *
+ * The test renders a ground truth image by drawing a slanted textured quad
+ * to a multisampled fbo and resolves it using a blit to a singlesampled fbo.
+ * This is textured onto the left half of the window.
+ * It then renders the same thing into an implicitly resolved fbo and textures
+ * that onto the right half of the screen. The two halfs are compared. This is
+ * repeated for another slant and different clear colors to check for possible
+ * interactions with fast clear.
+ * The test passes if the two methods yeild identical results for all image
+ * pairs.
+ *
+ */
+
+#include "piglit-util-gl.h"
+
+#define TEX_HEIGHT (8)
+#define TEX_WIDTH (8)
+#define FBO_HEIGHT (32)
+#define FBO_WIDTH (32)
+#define FB_HEIGHT (64)
+#define FB_WIDTH (2*FB_HEIGHT)
+
+PIGLIT_GL_TEST_CONFIG_BEGIN
+	/* multisampled FBO used for ground truth req ES 3.0 */
+	config.supports_gl_es_version = 30;
+	config.window_visual = PIGLIT_GL_VISUAL_RGB
+	                     | PIGLIT_GL_VISUAL_DOUBLE
+	                     | PIGLIT_GL_VISUAL_DEPTH;
+	config.window_width  = FB_WIDTH;
+	config.window_height = FB_HEIGHT;
+PIGLIT_GL_TEST_CONFIG_END
+
+#define SOURCE(x) # x
+static const GLchar vshader_src[] = "#version 100\n" SOURCE(
+	attribute vec4 piglit_vertex;
+	attribute vec2 piglit_texcoord;
+	varying vec2 coord_fs;
+
+	void main()
+	{
+		gl_Position =  piglit_vertex;
+		coord_fs = piglit_texcoord;
+	}
+);
+
+static const GLchar fshader_src[] = "#version 100\n" SOURCE(
+	precision highp float;
+	varying vec2 coord_fs;
+	uniform sampler2D tex;
+
+	void main()
+	{
+		gl_FragColor = texture2D(tex, coord_fs);
+	}
+);
+
+static GLuint tex_check;
+
+static struct {
+	GLuint fbo;
+	GLuint color;
+	GLuint depth;
+} fbo_ms, fbo_ss, fbo_impl;
+
+static GLuint basic_tex_prog, tex_loc;
+
+int result = PIGLIT_PASS;
+
+static GLubyte tex_data[TEX_HEIGHT][TEX_WIDTH][3];
+
+static void gen_texdata(void)
+{
+	int x,y;
+	for (y = 0; y < TEX_HEIGHT; ++y) {
+		for (x = 0; x < TEX_WIDTH; ++x) {
+			tex_data[y][x][0] = (GLubyte) (255.0f *
+			                    ((float)x/(float)(TEX_WIDTH-1)));
+			tex_data[y][x][1] = (GLubyte) (255.0f *
+			                    ((float)y/(float)(TEX_HEIGHT-1)));
+			tex_data[y][x][2] = 127;
+		}
+	}
+	for (y = 0; y < TEX_HEIGHT; ++y) {
+		for (x = 0; x < TEX_WIDTH; ++x) {
+			if ((x^y)&1) {
+				tex_data[y][x][0] /= 2;
+				tex_data[y][x][1] /= 2;
+				tex_data[y][x][2] = 64;
+			}
+		}
+	}
+}
+
+enum piglit_result
+piglit_display(void)
+{
+	static GLfloat quad1_verts[4][4] = {
+		{ -0.7,  -0.9, 0, 1 },
+		{  0.9,  -0.7, 0, 1 },
+		{ -0.9,   0.7, 0, 1 },
+		{  0.7,   0.9, 0, 1 },
+	};
+
+	static GLfloat quad2_verts[4][4] = {
+		{ -0.9,  -0.7, 0, 1 },
+		{  0.7,  -0.9, 0, 1 },
+		{ -0.7,   0.9, 0, 1 },
+		{  0.9,   0.7, 0, 1 },
+	};
+
+	static const GLfloat tex_coords[4][2] = {
+		{ 0.0, 0.0 },
+		{ 1.0, 0.0 },
+		{ 0.0, 1.0 },
+		{ 1.0, 1.0 },
+	};
+
+	GLfloat white[] = {1.0, 1.0, 1.0, 1.0};
+	GLfloat gray[] = {0.5, 0.5, 0.5, 0.0};
+
+	/* Run the test in multiple passes with different geometry and
+	 * different clear colors to catch possible interactions with fast
+	 * clear.
+	 */
+	GLfloat *test_config[4][2] = {
+		{ gray,  &quad1_verts[0][0] },
+		{ gray,  &quad2_verts[0][0] },
+		{ white, &quad1_verts[0][0] },
+		{ white, &quad2_verts[0][0] }
+	};
+
+	int i;
+	for (i = 0; i < 4; i++) {
+		GLfloat *clear_color = test_config[i][0];
+		GLfloat *quad_verts  = test_config[i][1];
+
+		glClearColor(clear_color[0], clear_color[1],
+		             clear_color[2], clear_color[3]);
+		glUseProgram(basic_tex_prog);
+		tex_loc = glGetUniformLocation(basic_tex_prog, "tex");
+		glUniform1i(tex_loc, 0);
+
+		/*** Explicit Resolve (ground truth) ***/
+		/* Draw quad into MS renderbuffer */
+		glBindFramebuffer(GL_FRAMEBUFFER, fbo_ms.fbo);
+		glViewport(0, 0, FBO_WIDTH, FBO_HEIGHT);
+		glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+
+		glBindTexture(GL_TEXTURE_2D, tex_check);
+		piglit_draw_rect_from_arrays(quad_verts, tex_coords, false);
+
+		/* Do the explicit multisample resolve */
+		glBindFramebuffer(GL_READ_FRAMEBUFFER, fbo_ms.fbo);
+		glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fbo_ss.fbo);
+		glBlitFramebuffer(0, 0, FBO_WIDTH, FBO_HEIGHT,
+		                  0, 0, FBO_WIDTH, FBO_HEIGHT,
+		                  GL_COLOR_BUFFER_BIT, GL_NEAREST);
+
+		/* draw the result to the left side of the frame buffer */
+		glBindFramebuffer(GL_FRAMEBUFFER, 0);
+		glViewport(0, 0, FB_WIDTH/2, FB_HEIGHT);
+		glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+
+		glBindTexture(GL_TEXTURE_2D, fbo_ss.color);
+		piglit_draw_rect_tex(-1, -1, 2, 2, 0, 0, 1, 1);
+
+		piglit_check_gl_error(GL_NO_ERROR);
+
+		/*** Implicit Resolve ***/
+		/* Draw quad into MSAA texture */
+		glBindFramebuffer(GL_FRAMEBUFFER, fbo_impl.fbo);
+		glViewport(0, 0, FBO_WIDTH, FBO_HEIGHT);
+		glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+
+		glBindTexture(GL_TEXTURE_2D, tex_check);
+		piglit_draw_rect_from_arrays(quad_verts, tex_coords, false);
+
+		/* draw the result to the right side of the frame buffer */
+		glBindFramebuffer(GL_FRAMEBUFFER, 0);
+		glViewport(FB_WIDTH/2, 0, FB_WIDTH/2, FB_HEIGHT);
+
+		glBindTexture(GL_TEXTURE_2D, fbo_impl.color);
+		piglit_draw_rect_tex(-1, -1, 2, 2, 0, 0, 1, 1);
+
+		/*** Compare the results ***/
+		if (!piglit_probe_rect_halves_equal_rgba(0, 0, FB_WIDTH,
+		                                         FB_HEIGHT)) {
+			result = PIGLIT_FAIL;
+			printf("Test failed during pass %d\n", i);
+		}
+
+		piglit_present_results();
+	}
+	return result;
+}
+
+
+void
+piglit_init(int argc, char **argv)
+{
+	int samples = 0, samples_impl = 0, samples_expl = 0;
+
+	GLint max_samples;
+
+	piglit_require_extension("GL_EXT_multisampled_render_to_texture");
+
+	if (argc < 2) {
+		fprintf(stderr, "Usage: %s <sample_count>\n", argv[0]);
+		piglit_report_result(PIGLIT_SKIP);
+	}
+
+	samples = strtoul(argv[1], NULL, 0);
+	glGetIntegerv(GL_MAX_SAMPLES, &max_samples);
+	if (samples > max_samples) {
+		piglit_report_result(PIGLIT_SKIP);
+	}
+
+	/* Create primary texture */
+	gen_texdata();
+	glGenTextures(1, &tex_check);
+	glActiveTexture( GL_TEXTURE0 );
+	glBindTexture(GL_TEXTURE_2D, tex_check);
+	glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, TEX_WIDTH, TEX_HEIGHT, 0,
+	             GL_RGB, GL_UNSIGNED_BYTE, tex_data);
+	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+
+	/* Create multisampled FBO for explicit resolve (ground truth) */
+	glGenFramebuffers(1, &fbo_ms.fbo);
+	glBindFramebuffer(GL_FRAMEBUFFER, fbo_ms.fbo);
+
+	/* depth */
+	glGenRenderbuffers(1, &fbo_ms.depth);
+	glBindRenderbuffer(GL_RENDERBUFFER, fbo_ms.depth);
+	glRenderbufferStorageMultisample(GL_RENDERBUFFER, samples,
+	                                 GL_DEPTH_COMPONENT16,
+	                                 FBO_WIDTH, FBO_HEIGHT);
+	glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT,
+	                          GL_RENDERBUFFER, fbo_ms.depth);
+
+	/* color */
+	glGenRenderbuffers(1, &fbo_ms.color);
+	glBindRenderbuffer(GL_RENDERBUFFER, fbo_ms.color);
+	glRenderbufferStorageMultisample(GL_RENDERBUFFER, samples, GL_RGB8,
+	                                 FBO_WIDTH, FBO_HEIGHT);
+	glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
+	                          GL_RENDERBUFFER, fbo_ms.color);
+
+	if (glCheckFramebufferStatus(GL_FRAMEBUFFER)
+	                          != GL_FRAMEBUFFER_COMPLETE) {
+		printf("Multisampled framebuffer is incomplete");
+		piglit_report_result(PIGLIT_FAIL);
+	}
+
+	glGetRenderbufferParameteriv(GL_RENDERBUFFER, GL_RENDERBUFFER_SAMPLES,
+	                             &samples_expl);
+
+	/* Create singlesampled FBO for explicit resolve (ground truth) */
+	glGenFramebuffers(1, &fbo_ss.fbo);
+	glBindFramebuffer(GL_FRAMEBUFFER, fbo_ss.fbo);
+
+	/* color */
+	glGenTextures(1, &fbo_ss.color);
+	glBindTexture(GL_TEXTURE_2D, fbo_ss.color);
+	glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB8, FBO_WIDTH, FBO_HEIGHT, 0,
+	             GL_RGB, GL_UNSIGNED_BYTE, 0);
+	glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+	glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+	glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+	glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+	glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
+	                       GL_TEXTURE_2D, fbo_ss.color, 0);
+
+	if (glCheckFramebufferStatus(GL_FRAMEBUFFER)
+	                          != GL_FRAMEBUFFER_COMPLETE) {
+		printf("Singlesampled framebuffer is incomplete");
+		piglit_report_result(PIGLIT_FAIL);
+	}
+
+	/* Create FBO for implicit resolve */
+	glGenFramebuffers(1, &fbo_impl.fbo);
+	glBindFramebuffer(GL_FRAMEBUFFER, fbo_impl.fbo);
+
+	/* depth */
+	glGenRenderbuffers(1, &fbo_impl.depth);
+	glBindRenderbuffer(GL_RENDERBUFFER, fbo_impl.depth);
+	glRenderbufferStorageMultisampleEXT(GL_RENDERBUFFER, samples,
+	                                    GL_DEPTH_COMPONENT16,
+	                                    FBO_WIDTH, FBO_HEIGHT);
+	glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT,
+	                          GL_RENDERBUFFER, fbo_impl.depth);
+
+	/* color */
+	glGenTextures(1, &fbo_impl.color);
+	glBindTexture(GL_TEXTURE_2D, fbo_impl.color);
+	glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB8, FBO_WIDTH, FBO_HEIGHT, 0,
+	             GL_RGB, GL_UNSIGNED_BYTE, 0);
+	glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+	glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+	glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+	glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+	glFramebufferTexture2DMultisampleEXT(GL_FRAMEBUFFER,
+	                                     GL_COLOR_ATTACHMENT0,
+	                                     GL_TEXTURE_2D, fbo_impl.color, 0,
+	                                     samples);
+
+	if (glCheckFramebufferStatus(GL_FRAMEBUFFER)
+	                          != GL_FRAMEBUFFER_COMPLETE) {
+		printf("Implicitly resolved multisampled framebuffer is incomplete");
+		piglit_report_result(PIGLIT_FAIL);
+	}
+
+	glGetFramebufferAttachmentParameteriv(GL_FRAMEBUFFER,
+			GL_COLOR_ATTACHMENT0,
+			GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_SAMPLES_EXT,
+			&samples_impl);
+
+	glBindRenderbuffer(GL_RENDERBUFFER, 0);
+	glBindFramebuffer(GL_FRAMEBUFFER, 0);
+
+	glDisable(GL_CULL_FACE);
+	glEnable(GL_DEPTH_TEST);
+
+	/* Test that we get the same number of samples for the two methods */
+
+	if (samples_impl != samples_expl) {
+		printf("samples_expl: %d, samples_impl: %d\n",
+		        samples_expl, samples_impl);
+		piglit_report_result(PIGLIT_FAIL);
+	}
+
+	/* create basic texturing shader */
+	basic_tex_prog = piglit_build_simple_program(vshader_src,
+	                                             fshader_src);
+	glUseProgram(basic_tex_prog);
+
+	if (!piglit_check_gl_error(GL_NO_ERROR)) {
+		piglit_report_result(PIGLIT_FAIL);
+	}
+}
-- 
2.5.0



More information about the Piglit mailing list