[Piglit] [PATCH V3 7/8] arb_texture_multisample: add new targets to texelFetch

Chris Forbes chrisf at ijw.co.nz
Tue Feb 26 02:18:09 PST 2013


Allows verification of texelFetch with all six flavors of MS sampler.

- Put lod/sample_index in the fourth channel of the texture, so we
    can verify that the correct lod/sample was sampled.
- For multisample targets, render the test pattern rather than uploading
  it. GL won't let us do a direct upload into these texture targets, and
  the alternative (upload to a staging texture; copy to target) is
  even messier.
- Accept sample count as an extra parameter after sampler
- Add existing swizzle option to usage string
- Use smaller formats for multisample tests, to avoid running into some
  hardware limits.

This replaces the earlier arb_texture_multisample-texel-fetch-execution
and arb_texture_multisample-texel-fetch-execution-array tests, and is
much more thorough (it showed Gen7 was still messed up :( !)

V3: - Increase window height so we can test 8x.
    - Don't break the format-based extension checks.

Signed-off-by: Chris Forbes <chrisf at ijw.co.nz>
---
 tests/all.tests                      |   6 +
 tests/texturing/shaders/common.c     |  34 ++++--
 tests/texturing/shaders/common.h     |   2 +
 tests/texturing/shaders/texelFetch.c | 226 +++++++++++++++++++++++++++++++----
 4 files changed, 238 insertions(+), 30 deletions(-)

diff --git a/tests/all.tests b/tests/all.tests
index 5ab0a2d..a041515 100644
--- a/tests/all.tests
+++ b/tests/all.tests
@@ -867,6 +867,12 @@ for sample_count in MSAA_SAMPLE_COUNTS:
     # fb-completeness
     spec['ARB_texture_multisample/fb-completeness/%d' % (sample_count,)] = \
         concurrent_test('arb_texture_multisample-fb-completeness %d' % (sample_count,))
+    # texel-fetch execution
+    for stage in ['vs','fs']:
+        for sampler in samplers_atm:
+                spec['ARB_texture_multisample/texelFetch/%d-%s-%s' % (
+                    sample_count, stage, sampler)] = \
+                    concurrent_test('texelFetch %s %s %d' % (stage, sampler, sample_count))
 add_concurrent_test(arb_texture_multisample, 'arb_texture_multisample-texstate')
 add_concurrent_test(arb_texture_multisample, 'arb_texture_multisample-sample-mask')
 add_concurrent_test(arb_texture_multisample, 'arb_texture_multisample-sample-mask-value')
diff --git a/tests/texturing/shaders/common.c b/tests/texturing/shaders/common.c
index 120e424..0b13d47 100644
--- a/tests/texturing/shaders/common.c
+++ b/tests/texturing/shaders/common.c
@@ -151,10 +151,11 @@ compute_miplevel_info()
 	miplevels = (int) log2f(max_dimension) + 1;
 
 	if (sampler.target == GL_TEXTURE_RECTANGLE ||
-	    sampler.target == GL_TEXTURE_BUFFER ||
-		sampler.target == GL_TEXTURE_2D_MULTISAMPLE ||
-		sampler.target == GL_TEXTURE_2D_MULTISAMPLE_ARRAY)
+	    sampler.target == GL_TEXTURE_BUFFER)
 		miplevels = 1;
+	if (sampler.target == GL_TEXTURE_2D_MULTISAMPLE ||
+		sampler.target == GL_TEXTURE_2D_MULTISAMPLE_ARRAY)
+		miplevels = sample_count;
 
 	/* Compute the size of each miplevel */
 	level_size = malloc(miplevels * sizeof(int *));
@@ -165,7 +166,11 @@ compute_miplevel_info()
 		level_size[l] = malloc(3 * sizeof(int));
 
 		for (i = 0; i < 3 - is_array; i++)
-			level_size[l][i] = max2(level_size[l-1][i] / 2, 1);
+			if (has_samples())
+				/* same size for all sample planes */
+				level_size[l][i] = level_size[l-1][i];
+			else
+				level_size[l][i] = max2(level_size[l-1][i] / 2, 1);
 
 		if (is_array)
 			level_size[l][2] = base_size[2];
@@ -190,6 +195,13 @@ has_slices()
 }
 
 bool
+has_samples()
+{
+    return sampler.target == GL_TEXTURE_2D_MULTISAMPLE ||
+           sampler.target == GL_TEXTURE_2D_MULTISAMPLE_ARRAY;
+}
+
+bool
 is_array_sampler()
 {
 	return sampler.target == GL_TEXTURE_1D_ARRAY ||
@@ -279,15 +291,20 @@ select_sampler(const char *name)
 	sampler.type = samplers[i].type;
 	sampler.target = samplers[i].target;
 
+	/* Use 32bpc sized formats where possible; drop down to 16bpc for
+	 * testing multisample targets to avoid hitting some hardware limits.
+	 * on i965.
+	 */
+
 	if (name[0] == 'i') {
 		sampler.data_type = GL_INT;
 		sampler.format = GL_RGBA_INTEGER;
-		sampler.internal_format = GL_RGBA32I;
+		sampler.internal_format = has_samples() ? GL_RGBA16I : GL_RGBA32I;
 		sampler.return_type = "ivec4";
 	} else if (name[0] == 'u') {
 		sampler.data_type = GL_UNSIGNED_INT;
 		sampler.format = GL_RGBA_INTEGER;
-		sampler.internal_format = GL_RGBA32UI;
+		sampler.internal_format = has_samples() ? GL_RGBA16UI : GL_RGBA32UI;
 		sampler.return_type = "uvec4";
 	} else if (strstr(name, "Shadow")) {
 		/* Shadow Sampler */
@@ -298,7 +315,7 @@ select_sampler(const char *name)
 	} else {
 		sampler.data_type = GL_FLOAT;
 		sampler.format = GL_RGBA;
-		sampler.internal_format = GL_RGBA32F;
+		sampler.internal_format = has_samples() ? GL_RGBA16F : GL_RGBA32F;
 		sampler.return_type = "vec4";
 	}
 
@@ -321,12 +338,15 @@ require_GL_features(enum shader_target test_stage)
 
 	switch (sampler.internal_format) {
 	case GL_RGBA32I:
+	case GL_RGBA16I:
 		piglit_require_extension("GL_EXT_texture_integer");
 		break;
 	case GL_RGBA32UI:
+	case GL_RGBA16UI:
 		piglit_require_gl_version(30);
 		break;
 	case GL_RGBA32F:
+	case GL_RGBA16F:
 		piglit_require_extension("GL_ARB_texture_float");
 		break;
 	}
diff --git a/tests/texturing/shaders/common.h b/tests/texturing/shaders/common.h
index a4e8cd7..878faec 100644
--- a/tests/texturing/shaders/common.h
+++ b/tests/texturing/shaders/common.h
@@ -81,6 +81,7 @@ struct sampler_info
 
 /** Whether or not we're using GL_EXT_texture_swizzle */
 bool swizzling;
+int sample_count;
 extern int shader_version;
 
 /**
@@ -97,6 +98,7 @@ float max2(float x, float y);
 
 bool has_height();
 bool has_slices();
+bool has_samples();
 
 bool is_array_sampler();
 bool is_shadow_sampler();
diff --git a/tests/texturing/shaders/texelFetch.c b/tests/texturing/shaders/texelFetch.c
index 50e91a6..ebfdfe0 100644
--- a/tests/texturing/shaders/texelFetch.c
+++ b/tests/texturing/shaders/texelFetch.c
@@ -84,11 +84,13 @@ PIGLIT_GL_TEST_CONFIG_BEGIN
 	config.supports_gl_core_version = 31;
 
 	config.window_width = 355;
-	config.window_height = 250;
+	config.window_height = 350;
 	config.window_visual = PIGLIT_GL_VISUAL_RGBA | PIGLIT_GL_VISUAL_DOUBLE;
 
 PIGLIT_GL_TEST_CONFIG_END
 
+#define MAX_LOD_OR_SAMPLES  8.0
+
 /** Vertex shader attribute locations */
 const int pos_loc = 0;
 const int texcoord_loc = 1;
@@ -121,7 +123,7 @@ compute_divisors(int lod, float *divisors)
 	divisors[0] = max2(level_size[lod][0] - 1, 1);
 	divisors[1] = max2(level_size[lod][1] - 1, 1);
 	divisors[2] = max2(level_size[lod][2] - 1, 1);
-	divisors[3] = 1.0;
+	divisors[3] = MAX_LOD_OR_SAMPLES;
 
 	if (sampler.data_type != GL_UNSIGNED_INT)
 		divisors[0] = -divisors[0];
@@ -133,6 +135,8 @@ piglit_display()
 	int i, l, z;
 	bool pass = true;
 
+   glViewport(0, 0, piglit_width, piglit_height);
+
 	glClearColor(0.1, 0.1, 0.1, 1.0);
 	glClear(GL_COLOR_BUFFER_BIT);
 
@@ -261,6 +265,150 @@ generate_VBOs()
 	glEnableVertexAttribArray(texcoord_loc);
 }
 
+/* like piglit_draw_rect(), but works in a core context too.
+ * pretty silly and wasteful (binds a throwaway VAO and BO) */
+static void
+draw_rect_core(int x, int y, int w, int h)
+{
+    float verts[4][4];
+    GLuint bo, vao;
+
+    verts[0][0] = x;
+    verts[0][1] = y;
+    verts[0][2] = 0.0;
+    verts[0][3] = 1.0;
+    verts[1][0] = x + w;
+    verts[1][1] = y;
+    verts[1][2] = 0.0;
+    verts[1][3] = 1.0;
+    verts[2][0] = x + w;
+    verts[2][1] = y + h;
+    verts[2][2] = 0.0;
+    verts[2][3] = 1.0;
+    verts[3][0] = x;
+    verts[3][1] = y + h;
+    verts[3][2] = 0.0;
+    verts[3][3] = 1.0;
+
+    glGenVertexArrays(1, &vao);
+    glBindVertexArray(vao);
+
+    glGenBuffers(1, &bo);
+    glBindBuffer(GL_ARRAY_BUFFER, bo);
+    glBufferData(GL_ARRAY_BUFFER, 4 * 4 * sizeof(float),
+            verts, GL_STATIC_DRAW);
+    glVertexAttribPointer(0, 4, GL_FLOAT, false, 0, 0);
+    glEnableVertexAttribArray(0);
+
+    glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
+
+    glBindVertexArray(0);
+    glDeleteBuffers(1, &bo);
+    glDeleteVertexArrays(1, &vao);
+}
+
+/**
+ * Generate the same test pattern as generate_texture() does, but do it in the shader.
+ * This is a silly workaround for not being able to just upload directly.
+ */
+static void
+upload_multisample_data(GLuint tex, int width, int height,
+        int layers, int samples)
+{
+    GLuint oldFBO, FBO;
+    int si;
+    char *fs_code;
+    int vs, fs;
+    int staging_program = 0;
+    int layer_loc = 0;
+    int si_loc = 0;
+
+    glGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, (GLint *) &oldFBO);
+    if (is_array_sampler())
+        glTexImage3DMultisample(sampler.target,
+                samples, sampler.internal_format,
+                width, height, layers, GL_TRUE);
+    else
+        glTexImage2DMultisample(sampler.target,
+                samples, sampler.internal_format,
+                width, height, GL_TRUE);
+    if (!piglit_check_gl_error(GL_NO_ERROR)) {
+        printf("Error creating multisample texture\n");
+        piglit_report_result(PIGLIT_FAIL);
+    }
+
+    vs = piglit_compile_shader_text(GL_VERTEX_SHADER,
+            "#version 130\n"
+            "#extension GL_ARB_explicit_attrib_location: require\n"
+            "layout(location=0) in vec4 pos;\n"
+            "void main() {\n"
+            "   gl_Position = pos;\n"
+            "}\n");
+    asprintf(&fs_code,
+            "#version 130\n"
+            "#extension GL_ARB_explicit_attrib_location: require\n"
+            "#extension GL_ARB_fragment_coord_conventions: require\n"
+            "uniform int layer;\n"
+            "uniform int si;\n"
+            "layout(pixel_center_integer) in vec4 gl_FragCoord;\n"
+            "layout(location=0) out %s o;\n"
+            "void main() {\n"
+            "  o = %s(%sgl_FragCoord.x, gl_FragCoord.y, layer, si);\n"
+            "}\n",
+            sampler.return_type,
+            sampler.return_type,
+            sampler.data_type == GL_UNSIGNED_INT ? "" : "-");
+    fs = piglit_compile_shader_text(GL_FRAGMENT_SHADER, fs_code);
+    if (!fs) {
+        printf("Failed to compile staging program.\n");
+        piglit_report_result(PIGLIT_FAIL);
+    }
+    staging_program = piglit_link_simple_program(vs,fs);
+    if (!piglit_link_check_status(staging_program))
+        piglit_report_result(PIGLIT_FAIL);
+
+    layer_loc = glGetUniformLocation(staging_program, "layer");
+    si_loc = glGetUniformLocation(staging_program, "si");
+
+    glUseProgram(staging_program);
+    if (!piglit_check_gl_error(GL_NO_ERROR)) {
+        printf("glUseProgram failed\n");
+        piglit_report_result(PIGLIT_FAIL);
+    }
+
+    glGenFramebuffers(1, &FBO);
+    glBindFramebuffer(GL_DRAW_FRAMEBUFFER, FBO);
+    glViewport(0, 0, width, height);
+
+    glEnable(GL_SAMPLE_MASK);
+
+    for (si=0; si < samples; si++) {
+        glUniform1i(si_loc, si);
+        glSampleMaski(0, 1<<si);
+
+        if (is_array_sampler()) {
+            int layer;
+            for(layer = 0; layer < layers; layer++) {
+                glFramebufferTextureLayer(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
+                    tex, 0, layer);
+                glUniform1i(layer_loc, layer);
+                draw_rect_core(-1, -1, 2, 2);
+            }
+        }
+        else {
+            glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
+                   sampler.target, tex, 0);
+
+            glUniform1i(layer_loc, 0);
+            draw_rect_core(-1, -1, 2, 2);
+        }
+    }
+
+    glDisable(GL_SAMPLE_MASK);
+
+    glBindFramebuffer(GL_DRAW_FRAMEBUFFER, oldFBO);
+}
+
 /**
  * Create texel data.
  */
@@ -281,18 +429,21 @@ generate_texture()
 
 	glGenTextures(1, &tex);
 	glBindTexture(target, tex);
-	if (sampler.target == GL_TEXTURE_RECTANGLE) {
-		glTexParameteri(target, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
-		glTexParameteri(target, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
-	} else {
-		glTexParameteri(target, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_NEAREST);
-		glTexParameteri(target, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+
+	if (!has_samples()) {
+		if (sampler.target == GL_TEXTURE_RECTANGLE) {
+			glTexParameteri(target, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+			glTexParameteri(target, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+		} else {
+			glTexParameteri(target, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_NEAREST);
+			glTexParameteri(target, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+		}
+		glTexParameteri(target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+		glTexParameteri(target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+		if (swizzling)
+			glTexParameteriv(target, GL_TEXTURE_SWIZZLE_RGBA,
+					 (GLint *) sampler.swizzle);
 	}
-	glTexParameteri(target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
-	glTexParameteri(target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
-	if (swizzling)
-		glTexParameteriv(target, GL_TEXTURE_SWIZZLE_RGBA,
-				 (GLint *) sampler.swizzle);
 
 	expected_colors = calloc(miplevels, sizeof(float **));
 
@@ -321,24 +472,24 @@ generate_texture()
 					f_ptr[0] = nx;
 					f_ptr[1] = y;
 					f_ptr[2] = z;
-					f_ptr[3] = 1.0;
+					f_ptr[3] = l;
 
 					i_ptr[0] = nx;
 					i_ptr[1] = y;
 					i_ptr[2] = z;
-					i_ptr[3] = 1;
+					i_ptr[3] = l;
 
 					u_ptr[0] = nx;
 					u_ptr[1] = y;
 					u_ptr[2] = z;
-					u_ptr[3] = 1;
+					u_ptr[3] = l;
 
 					compute_divisors(l, divisors);
 
 					expected_ptr[0] = f_ptr[0]/divisors[0];
 					expected_ptr[1] = f_ptr[1]/divisors[1];
 					expected_ptr[2] = f_ptr[2]/divisors[2];
-					expected_ptr[3] = 1.0;
+					expected_ptr[3] = f_ptr[3]/divisors[3];
 					swizzle(expected_ptr);
 
 					f_ptr += 4;
@@ -365,8 +516,14 @@ generate_texture()
 			break;
 		}
 
-		upload_miplevel_data(target, l, level_image);
+		if (!has_samples())
+			upload_miplevel_data(target, l, level_image);
 	}
+
+	if (has_samples())
+		upload_multisample_data(tex, level_size[0][0],
+				level_size[0][1], level_size[0][2],
+				sample_count);
 }
 
 /**
@@ -381,9 +538,11 @@ coordinate_size()
 	case GL_TEXTURE_2D:
 	case GL_TEXTURE_1D_ARRAY:
 	case GL_TEXTURE_RECTANGLE:
+	case GL_TEXTURE_2D_MULTISAMPLE:
 		return 2;
 	case GL_TEXTURE_3D:
 	case GL_TEXTURE_2D_ARRAY:
+	case GL_TEXTURE_2D_MULTISAMPLE_ARRAY:
 		return 3;
 	default:
 		assert(!"Should not get here.");
@@ -432,6 +591,7 @@ generate_GLSL(enum shader_target test_stage)
 	case VS:
 		asprintf(&vs_code,
 			 "#version %d\n"
+			 "%s\n"
 			 "#define ivec1 int\n"
 			 "flat out %s color;\n"
 			 "in vec4 pos;\n"
@@ -443,6 +603,7 @@ generate_GLSL(enum shader_target test_stage)
 			 "    gl_Position = pos;\n"
 			 "}\n",
 			 shader_version,
+			 has_samples() ? "#extension GL_ARB_texture_multisample: require" : "",
 			 sampler.return_type, sampler.name,
 			 offset_func,
 			 coordinate_size(),
@@ -475,6 +636,7 @@ generate_GLSL(enum shader_target test_stage)
 			 shader_version);
 		asprintf(&fs_code,
 			 "#version %d\n"
+			 "%s\n"
 			 "#define ivec1 int\n"
 			 "flat in ivec4 tc;\n"
 			 "uniform vec4 divisor;\n"
@@ -485,6 +647,7 @@ generate_GLSL(enum shader_target test_stage)
 			 "    gl_FragColor = color/divisor;\n"
 			 "}\n",
 			 shader_version,
+			 has_samples() ? "#extension GL_ARB_texture_multisample: require" : "",
 			 sampler.name,
 			 offset_func,
 			 coordinate_size(),
@@ -545,6 +708,8 @@ supported_sampler()
 	case GL_TEXTURE_1D_ARRAY:
 	case GL_TEXTURE_2D_ARRAY:
 	case GL_TEXTURE_RECTANGLE:
+	case GL_TEXTURE_2D_MULTISAMPLE:
+	case GL_TEXTURE_2D_MULTISAMPLE_ARRAY:
 		return true;
 	}
 	return false;
@@ -554,7 +719,7 @@ void
 fail_and_show_usage()
 {
 	printf("Usage: texelFetch [140] [offset] <vs|fs> <sampler type> "
-	       "[piglit args...]\n");
+	       "[sample_count] [swizzle] [piglit args...]\n");
 	piglit_report_result(PIGLIT_FAIL);
 }
 
@@ -593,6 +758,21 @@ piglit_init(int argc, char **argv)
 		if (!sampler_found && (sampler_found = select_sampler(argv[i])))
 			continue;
 
+        /* Maybe it's the sample count? */
+        if (sampler_found && has_samples() && !sample_count) {
+            if ((sample_count = atoi(argv[i]))) {
+                /* check it */
+                GLint max_samples;
+                glGetIntegerv(GL_MAX_SAMPLES, &max_samples);
+                if (sample_count > max_samples) {
+                    printf("Sample count of %d not supported, >MAX_SAMPLES\n",
+                            sample_count);
+                    piglit_report_result(PIGLIT_SKIP);
+                }
+            }
+            continue;
+        }
+
 		if (!swizzling && (swizzling = parse_swizzle(argv[i])))
 			continue;
 
@@ -614,14 +794,14 @@ piglit_init(int argc, char **argv)
 	tex_location = glGetUniformLocation(prog, "tex");
 	divisor_loc = glGetUniformLocation(prog, "divisor");
 
-	glUseProgram(prog);
-
-	glUniform1i(tex_location, 0);
-
 	/* Create textures and set miplevel info */
 	set_base_size();
 	compute_miplevel_info();
 	generate_texture();
 
 	generate_VBOs();
+
+	glUseProgram(prog);
+
+	glUniform1i(tex_location, 0);
 }
-- 
1.8.1.4



More information about the Piglit mailing list