[Piglit] [PATCH 1/2] Add a new textureLod test case, similar to texelFetch. GLSL textureLod and textureLodOffset functions available in VS, GS, FS

Steve Miller dervishx at gmail.com
Mon Sep 16 10:26:29 PDT 2013


From: Kenneth Graunke <kenneth at whitecape.org>

>From GLSL Spec 1.50 Section 8.7 (Texture Lookup Functions):
     "Texture lookup functions are available to vertex, geometry, and fragment
      shaders."

Test sampler types avaiable for texture lookup functions in vertex, geometry, and fragment shading stages of the pipeline:
     For each pixel we want to display, generate a single texel and color it
     according to a texture lookup during the chose stage of the pipeline.
     The color is unique to its eventual position on screen.

Sampler types tested: sampler1D/2D/3D, sampler1D/2DArray

not tested: samplerCube, sampler1D/2DShadow, sampler1DArrayShadow

Credit for this test goes to Kenneth Graunke <kenneth at whitecape.org>

Fixed up by Steve Miller <dervishx at gmail.com>
---
 tests/all.tests                           |   8 +
 tests/texturing/shaders/CMakeLists.gl.txt |   1 +
 tests/texturing/shaders/texelFetch.c      |   2 +-
 tests/texturing/shaders/textureLod.c      | 715 ++++++++++++++++++++++++++++++
 4 files changed, 725 insertions(+), 1 deletion(-)
 create mode 100644 tests/texturing/shaders/textureLod.c

diff --git a/tests/all.tests b/tests/all.tests
index dc36841..d06ec00 100644
--- a/tests/all.tests
+++ b/tests/all.tests
@@ -876,6 +876,14 @@ for stage in ['vs', 'gs', 'fs']:
                 'texelFetch {0} {1}sampler2DArray b0r1'.format(
                         stage, type))
 
+    # textureLod():
+    # XXX: samplerCube
+    for sampler in ['sampler1D', 'sampler2D', 'sampler3D', 'sampler1DArray', 'sampler2DArray', 'isampler1D', 'isampler2D', 'isampler3D', 'isampler1DArray', 'isampler2DArray', 'usampler1D', 'usampler2D', 'usampler3D', 'usampler1DArray', 'usampler2DArray']:
+        profile.test_list['glsl-1.30/execution/textureLod/' + stage + '-textureLod-' + sampler] = PlainExecTest(['textureLod', stage, sampler, '-auto', '-fbo'])
+    # textureLod() with EXT_texture_swizzle mode "b0r1":
+    for type in ['i', 'u', '']:
+        profile.test_list['glsl-1.30/execution/textureLod/' + stage + '-textureLod-' + type + 'sampler2DArray-swizzle'] = PlainExecTest(['textureLod', stage, type + 'sampler2DArray', 'b0r1', '-auto', '-fbo'])
+
 add_plain_test(spec['glsl-1.30']['execution'], 'fs-texelFetch-2D')
 add_plain_test(spec['glsl-1.30']['execution'], 'fs-texelFetchOffset-2D')
 add_shader_test_dir(spec['glsl-1.30']['execution'],
diff --git a/tests/texturing/shaders/CMakeLists.gl.txt b/tests/texturing/shaders/CMakeLists.gl.txt
index 7210c1c..272bbf6 100644
--- a/tests/texturing/shaders/CMakeLists.gl.txt
+++ b/tests/texturing/shaders/CMakeLists.gl.txt
@@ -12,3 +12,4 @@ link_libraries (
 
 piglit_add_executable (textureSize textureSize.c common.c)
 piglit_add_executable (texelFetch texelFetch.c common.c)
+piglit_add_executable (textureLod textureLod.c common.c)
diff --git a/tests/texturing/shaders/texelFetch.c b/tests/texturing/shaders/texelFetch.c
index badaac7..d10a5d6 100644
--- a/tests/texturing/shaders/texelFetch.c
+++ b/tests/texturing/shaders/texelFetch.c
@@ -759,7 +759,7 @@ generate_GLSL(enum shader_target test_stage)
 void
 set_base_size()
 {
-	base_size[0] = 65;
+    base_size[0] = 65;
 	base_size[1] = has_height() ? 32 : 1;
 	base_size[2] = has_slices() ?  5 : 1;
 }
diff --git a/tests/texturing/shaders/textureLod.c b/tests/texturing/shaders/textureLod.c
new file mode 100644
index 0000000..1cd4ad9
--- /dev/null
+++ b/tests/texturing/shaders/textureLod.c
@@ -0,0 +1,715 @@
+/*
+ * 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 textureLod.c
+ *
+ * Tests the GLSL 1.30+ textureLod() built-in function.
+ *
+ * The "textureLod" binary takes two arguments: shader stage and sampler type.
+ *
+ * For example:
+ * ./bin/textureLod fs sampler1DArray
+ * ./bin/textureLod usampler3D vs
+ *
+ * The test covers:
+ * - All pipeline stages (VS, GS, FS)
+ * - Integer and floating point texture formats
+ * - Sampler dimensionality (1D, 2D, 3D, 1DArray, 2DArray)
+ * - Mipmapping
+ * - Non-power-of-two textures
+ *
+ * Draws a series of "rectangles" which display each miplevel and array slice,
+ * at full size.  They are layed out as follows:
+ *
+ * miplevel 3 +          +          +          +          +
+ *
+ * miplevel 2 +-+        +-+        +-+        +-+        +-+
+ *            +-+        +-+        +-+        +-+        +-+
+ *
+ * miplevel 1 +---+      +---+      +---+      +---+      +---+
+ *            |   |      |   |      |   |      |   |      |   |
+ *            +---+      +---+      +---+      +---+      +---+
+ *
+ *            +------+   +------+   +------+   +------+   +------+
+ * miplevel 0 |      |   |      |   |      |   |      |   |      |
+ *            |      |   |      |   |      |   |      |   |      |
+ *            +------+   +------+   +------+   +------+   +------+
+ *            slice #0   slice #1   slice #2   slice #3   slice #4
+ *
+ * Normally, we could draw each rectangle as a single quad (or two triangles),
+ * interpolate the texture coordinates across the primitive, and let the
+ * fragment shader look up the color values from the texture.
+ *
+ * However, this fails miserably for vertex shader texturing: a quad only has
+ * four vertices, which means we could only fetch/display at most 4 texels.
+ * If we used a simple RGBW checkerboard, as in other Piglit tests, this would
+ * only tell us that we sampled somewhere in the right 1/4 of the texture.
+ *
+ * Instead, we take a clever approach: draw each "rectangle" via a series of
+ * 1-pixel wide GL_POINT primitives.  This gives us one vertex per pixel; by
+ * drawing the texture at full size, each pixel and vertex also correspond to
+ * exactly one texel.  So every texel is sampled and verified for correctness.
+ *
+ * In other words: "One pixel, one texel, one vertex."
+ *
+ * For convenience, we take the same approach for fragment shader testing
+ * as well, since it allows us to reuse the same VBO setup and drawing code.
+ */
+#include "common.h"
+
+void
+parse_args(int argc, char **argv);
+
+static enum shader_target test_stage = UNKNOWN;
+
+PIGLIT_GL_TEST_CONFIG_BEGIN
+
+	parse_args(argc, argv);
+	if (test_stage == GS) {
+		config.supports_gl_compat_version = 32;
+		config.supports_gl_core_version = 32;
+	} else {
+		config.supports_gl_compat_version = 10;
+		config.supports_gl_core_version = 31;
+	}
+
+	config.window_width = 355;
+	config.window_height = 350;
+	config.window_visual = PIGLIT_GL_VISUAL_RGBA | PIGLIT_GL_VISUAL_DOUBLE;
+
+PIGLIT_GL_TEST_CONFIG_END
+
+/** Vertex shader attribute locations */
+const int pos_loc = 0;
+const int texcoord_loc = 1;
+
+/** Whether we're testing textureLodOffset() instead of textureLod(). */
+static bool test_offset = false;
+const int fetch_x_offset = 7;
+const int fetch_y_offset = -8;
+const int fetch_z_offset = 4;
+const char *fetch_1d_arg = ", int(7)";
+const char *fetch_2d_arg = ", ivec2(7, -8)";
+const char *fetch_3d_arg = ", ivec3(7, -8, 4)";
+
+/** Uniform locations */
+int divisor_loc;
+
+/**
+ * Expected color data for each rectangle drawn, indexed by miplevel and slice.
+ * For example, expected_colors[1][3] contains the data for miplevel 1 slice 3.
+ */
+float ***expected_colors;
+
+/**
+ * Return the divisors necessary to scale the unnormalized texture data to
+ * a floating point color value in the range [0, 1].
+ */
+static void
+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;
+
+	if (sampler.data_type != GL_UNSIGNED_INT)
+		divisors[0] = -divisors[0];
+}
+
+enum piglit_result
+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);
+
+	glPointSize(1.0);
+
+	i = 0;
+	for (l = 0; l < miplevels; ++l) {
+		for (z = 0; z < level_size[l][2]; z++) {
+			/* Draw the "rectangle" for this miplevel/slice. */
+			int points = level_size[l][0] * level_size[l][1];
+			float divisors[4];
+
+			compute_divisors(l, divisors);
+			swizzle(divisors);
+			glUniform4fv(divisor_loc, 1, divisors);
+
+			glDrawArrays(GL_POINTS, i, points);
+
+			i += points;
+
+			/* Compare results against reference image. */
+			pass &= piglit_probe_image_rgba(5+(5+base_size[0]) * z,
+							5+(5+base_size[1]) * l,
+							level_size[l][0],
+							level_size[l][1],
+							expected_colors[l][z]);
+		}
+	}
+
+	piglit_present_results();
+
+	return pass ? PIGLIT_PASS : PIGLIT_FAIL;
+}
+
+/**
+ * Generate two VBOs for our vertex attributes:
+ * 1. Pixel position (in window coordinates).
+ * 2. Texture coordinates.
+ *
+ * The VBOs contain the data for every rectangle being drawn (as opposed to
+ * creating and binding a separate VBO per miplevel/slice.)
+ */
+void
+generate_VBOs()
+{
+	int x, y, z, l;
+	GLuint pos_vbo, tc_vbo;
+	float *pos, *pos_data;
+	float *tc, *tc_data;
+	bool array_1D = sampler.target == GL_TEXTURE_1D_ARRAY;
+	int num_texels = 0;
+
+	/* Calculate the # of texels a.k.a. size of the VBOs */
+	for (l = 0; l < miplevels; l++) {
+		num_texels += level_size[l][0] * level_size[l][1] * level_size[l][2];
+	}
+
+	pos = pos_data = malloc(num_texels * 4 * sizeof(float));
+	tc = tc_data = malloc(num_texels * 4 * sizeof(int));
+
+	for (l = 0; l < miplevels; l++) {
+		for (z = 0; z < level_size[l][2]; z++) {
+			for (y = 0; y < level_size[l][1]; y++) {
+				for (x = 0; x < level_size[l][0]; x++) {
+					/* Assign pixel positions: */
+					pos[0] = 5.5 + (5 + base_size[0])*z + x;
+					pos[1] = 5.5 + (5 + base_size[1])*l + y;
+					pos[2] = 0.0;
+					pos[3] = 1.0;
+
+					pos[0] = -1.0 + 2.0 * (pos[0] /
+							       piglit_width);
+					pos[1] = -1.0 + 2.0 * (pos[1] /
+							       piglit_height);
+
+					pos += 4;
+
+					/* Assign texture coordinates:
+					 * 1D:      x _ _ l
+					 * 2D:      x y _ l
+					 * 3D:      x y z l
+					 * 1DArray: x z _ l
+					 * 2DArray: x y z l
+					 */
+					if (sampler.target == GL_TEXTURE_RECTANGLE) {
+						tc[0] = x;
+						tc[1] = y;
+						tc[2] = z;
+					} else {
+                        tc[0] = (float) x / ((float) level_size[l][0] - 1);
+                        tc[1] = array_1D ? z : (float) y / ((float) level_size[l][1] -1);
+						if (sampler.target == GL_TEXTURE_3D)
+                            tc[2] = (float) z / ((float) level_size[l][2] - 1);
+						else
+							tc[2] = z;
+
+                        if (test_offset) {
+                           tc[0] -= (float) fetch_x_offset / ((float) level_size[l][0]);
+                           if (sampler.target != GL_TEXTURE_1D_ARRAY)
+                                tc[1] -= (float) fetch_y_offset / ((float) level_size[l][1]);
+                           if (sampler.target != GL_TEXTURE_2D_ARRAY)
+                                tc[2] -= (float) fetch_z_offset / ((float) level_size[l][2]);
+                        }
+					}
+
+
+					tc[3] = l;
+					tc += 4;
+				}
+			}
+		}
+	}
+
+	if (piglit_get_gl_version() >= 31) {
+		GLuint vao;
+		glGenVertexArrays(1, &vao);
+		glBindVertexArray(vao);
+	}
+
+	/* Create VBO for pixel positions in NDC: */
+	glGenBuffers(1, &pos_vbo);
+	glBindBuffer(GL_ARRAY_BUFFER, pos_vbo);
+	glBufferData(GL_ARRAY_BUFFER,
+		     num_texels * 4 * sizeof(float),
+		     pos_data, GL_STATIC_DRAW);
+	glVertexAttribPointer(pos_loc, 4, GL_FLOAT, false, 0, 0);
+	glEnableVertexAttribArray(pos_loc);
+
+	/* Create VBO for texture coordinates: */
+	glGenBuffers(1, &tc_vbo);
+	glBindBuffer(GL_ARRAY_BUFFER, tc_vbo);
+	glBufferData(GL_ARRAY_BUFFER,
+		     num_texels * 4 * sizeof(float),
+		     tc_data, GL_STATIC_DRAW);
+	glVertexAttribPointer(texcoord_loc, 4, GL_FLOAT, false, 0, 0);
+	glEnableVertexAttribArray(texcoord_loc);
+}
+
+/**
+ * Create texel data.
+ */
+void
+generate_texture()
+{
+	int l, x, y, z;
+	unsigned *u_level, *u_ptr;
+	int      *i_level, *i_ptr;
+	float    *f_level, *f_ptr;
+	float    *expected_ptr;
+	void *level_image;
+	float divisors[4];
+	GLuint tex;
+	GLenum target = sampler.target;
+
+	glActiveTexture(GL_TEXTURE0);
+
+	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);
+	}
+	glTexParameteri(target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+	glTexParameteri(target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+	glTexParameteri(target, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);
+	if (swizzling)
+		glTexParameteriv(target, GL_TEXTURE_SWIZZLE_RGBA,
+				 (GLint *) sampler.swizzle);
+
+	expected_colors = calloc(miplevels, sizeof(float **));
+
+	for (l = 0; l < miplevels; l++) {
+		expected_colors[l] = calloc(level_size[l][2], sizeof(float **));
+
+		i_ptr = i_level =
+			malloc(level_size[l][0] * level_size[l][1] *
+			       level_size[l][2] * 4 * sizeof(int));
+
+		u_ptr = u_level =
+			malloc(level_size[l][0] * level_size[l][1] *
+			       level_size[l][2] * 4 * sizeof(unsigned));
+
+		f_ptr = f_level =
+			malloc(level_size[l][0] * level_size[l][1] *
+			       level_size[l][2] * 4 * sizeof(float));
+
+		for (z = 0; z < level_size[l][2]; z++) {
+			expected_ptr = expected_colors[l][z] =
+				malloc(level_size[l][0] * level_size[l][1] *
+				       level_size[l][2] * 4 * sizeof(float));
+			for (y = 0; y < level_size[l][1]; y++) {
+				for (x = 0; x < level_size[l][0]; x++) {
+					int nx = sampler.data_type == GL_UNSIGNED_INT ?  x : -x;
+					f_ptr[0] = nx;
+					f_ptr[1] = y;
+					f_ptr[2] = z;
+                    f_ptr[3] = 1.0;
+
+					i_ptr[0] = nx;
+					i_ptr[1] = y;
+					i_ptr[2] = z;
+                    i_ptr[3] = 1;
+
+					u_ptr[0] = nx;
+					u_ptr[1] = y;
+					u_ptr[2] = z;
+                    u_ptr[3] = 1;
+
+					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;
+					swizzle(expected_ptr);
+
+					f_ptr += 4;
+					i_ptr += 4;
+					u_ptr += 4;
+					expected_ptr += 4;
+				}
+			}
+		}
+
+		switch (sampler.data_type) {
+		case GL_FLOAT:
+			level_image = f_level;
+			break;
+		case GL_UNSIGNED_INT:
+			level_image = u_level;
+			break;
+		case GL_INT:
+			level_image = i_level;
+			break;
+		default:
+			assert(!"Unexpected data type");
+			level_image = NULL;
+			break;
+		}
+
+		upload_miplevel_data(target, l, level_image);
+	}
+
+}
+
+/**
+ * How many components are in the coordinate?
+ */
+static int
+coordinate_size()
+{
+	switch (sampler.target) {
+	case GL_TEXTURE_1D:
+		return 1;
+	case GL_TEXTURE_2D:
+	case GL_TEXTURE_1D_ARRAY:
+    case GL_TEXTURE_RECTANGLE:
+		return 2;
+	case GL_TEXTURE_3D:
+	case GL_TEXTURE_2D_ARRAY:
+		return 3;
+	default:
+		assert(!"Should not get here.");
+		return 0;
+	}
+}
+
+/**
+ * Generate, compile, and link the GLSL shaders.
+ */
+int
+generate_GLSL(enum shader_target test_stage)
+{
+	int vs, gs, fs, prog;
+
+	static char *vs_code;
+	static char *gs_code = NULL;
+	static char *fs_code;
+
+    const char *offset_func, *offset_arg;
+
+    if (test_offset) {
+        offset_func = "Offset";
+        switch (sampler.target) {
+        case GL_TEXTURE_1D:
+        case GL_TEXTURE_1D_ARRAY:
+            offset_arg = fetch_1d_arg;
+            break;
+        case GL_TEXTURE_2D:
+        case GL_TEXTURE_2D_ARRAY:
+        case GL_TEXTURE_RECTANGLE:
+            offset_arg = fetch_2d_arg;
+            break;
+        case GL_TEXTURE_3D:
+            offset_arg = fetch_3d_arg;
+            break;
+        default:
+            assert(!"Unexpected target texture");
+            offset_arg = "";
+            break;
+        }
+    } else {
+        offset_func = "";
+        offset_arg = "";
+    }
+
+	switch (test_stage) {
+	case VS:
+		asprintf(&vs_code,
+			 "#version %d\n"
+			 "#define vec1 float\n"
+			 "flat out %s color;\n"
+			 "in vec4 pos;\n"
+			 "in vec4 texcoord;\n"
+			 "uniform %s tex;\n"
+			 "void main()\n"
+             "{\n"
+             "    color = textureLod%s(tex, vec%d(texcoord),\n"
+             "                       texcoord.w%s);\n"
+             "    gl_Position = pos;\n"
+             "}\n",
+             shader_version,
+             sampler.return_type, sampler.name, offset_func,
+                 coordinate_size(), offset_arg);
+		asprintf(&fs_code,
+			 "#version %d\n"
+			 "flat in %s color;\n"
+			 "uniform vec4 divisor;\n"
+			 "void main()\n"
+			 "{\n"
+			 "    gl_FragColor = vec4(color)/divisor;\n"
+			 "}\n",
+			 shader_version,
+			 sampler.return_type);
+		break;
+    case GS:
+        asprintf(&vs_code,
+             "#version %d\n"
+             "in vec4 pos;\n"
+             "in vec4 texcoord;\n"
+             "flat out vec4 texcoord_to_gs;\n"
+             "out vec4 pos_to_gs;\n"
+             "void main()\n"
+             "{\n"
+             "    texcoord_to_gs = texcoord;\n"
+             "    pos_to_gs = pos;\n"
+             "}\n",
+             shader_version);
+        asprintf(&gs_code,
+             "#version %d\n"
+             "%s\n"
+             "#define vec1 float\n"
+             "layout(points) in;\n"
+             "layout(points, max_vertices = 1) out;\n"
+             "flat out %s color;\n"
+             "flat in vec4 texcoord_to_gs[1];\n"
+             "in vec4 pos_to_gs[1];\n"
+             "uniform %s tex;\n"
+             "void main()\n"
+             "{\n"
+             "    vec4 texcoord = texcoord_to_gs[0];\n"
+             "    color = textureLod%s(tex, vec%d(texcoord)%s%s);\n"
+             "    gl_Position = pos_to_gs[0];\n"
+             "    EmitVertex();\n"
+             "}\n",
+             shader_version,
+             has_samples() ? "#extension GL_ARB_texture_multisample: require" : "",
+             sampler.return_type, sampler.name,
+             offset_func,
+             coordinate_size(),
+             ((sampler.target == GL_TEXTURE_RECTANGLE) ?
+              "" : ", texcoord.w"),
+             offset_arg);
+        asprintf(&fs_code,
+             "#version %d\n"
+             "flat in %s color;\n"
+             "uniform vec4 divisor;\n"
+             "void main()\n"
+             "{\n"
+             "    gl_FragColor = vec4(color)/divisor;\n"
+             "}\n",
+             shader_version,
+             sampler.return_type);
+        break;
+	case FS:
+		asprintf(&vs_code,
+			 "#version %d\n"
+			 "in vec4 pos;\n"
+			 "in vec4 texcoord;\n"
+			 "flat out vec4 tc;\n"
+			 "void main()\n"
+			 "{\n"
+			 "    tc = texcoord;\n"
+			 "    gl_Position = pos;\n"
+			 "}\n",
+			 shader_version);
+		asprintf(&fs_code,
+			 "#version %d\n"
+			 "#define vec1 float\n"
+			 "flat in vec4 tc;\n"
+			 "uniform vec4 divisor;\n"
+			 "uniform %s tex;\n"
+			 "void main()\n"
+			 "{\n"
+             "    vec4 color = textureLod%s(tex, vec%d(tc), tc.w%s);\n"
+			 "    gl_FragColor = color/divisor;\n"
+			 "}\n",
+			 shader_version,
+             sampler.name, offset_func, coordinate_size(), offset_arg);
+		break;
+	default:
+		assert(!"Should not get here.");
+		break;
+	}
+
+	vs = piglit_compile_shader_text(GL_VERTEX_SHADER, vs_code);
+	if (!vs) {
+		printf("VS code:\n%s", vs_code);
+		piglit_report_result(PIGLIT_FAIL);
+	}
+	if (gs_code) {
+		gs = piglit_compile_shader_text(GL_GEOMETRY_SHADER, gs_code);
+		if (!gs) {
+			printf("GS code:\n%s", gs_code);
+			piglit_report_result(PIGLIT_FAIL);
+		}
+	}
+	fs = piglit_compile_shader_text(GL_FRAGMENT_SHADER, fs_code);
+	if (!fs) {
+		printf("FS code:\n%s", fs_code);
+		piglit_report_result(PIGLIT_FAIL);
+	}
+	prog = glCreateProgram();
+	glAttachShader(prog, vs);
+	if (gs_code)
+		glAttachShader(prog, gs);
+	glAttachShader(prog, fs);
+
+	glBindAttribLocation(prog, pos_loc, "pos");
+	glBindAttribLocation(prog, texcoord_loc, "texcoord");
+
+	glLinkProgram(prog);
+	if (!piglit_link_check_status(prog))
+		piglit_report_result(PIGLIT_FAIL);
+
+	return prog;
+}
+
+/**
+ * Set the size of the texture's base level.
+ */
+void
+set_base_size()
+{
+    base_size[0] = 65;
+	base_size[1] = has_height() ? 32 : 1;
+	base_size[2] = has_slices() ?  5 : 1;
+}
+
+/**
+ * Is this sampler supported by textureLod?
+ */
+static bool
+supported_sampler()
+{
+	switch (sampler.target) {
+	case GL_TEXTURE_1D:
+	case GL_TEXTURE_2D:
+	case GL_TEXTURE_3D:
+	case GL_TEXTURE_1D_ARRAY:
+	case GL_TEXTURE_2D_ARRAY:
+	case GL_TEXTURE_RECTANGLE:
+		return true;
+	}
+	return false;
+}
+
+void
+fail_and_show_usage()
+{
+	printf("Usage: textureLod [140] <vs|gs|fs> <sampler type> "
+	       "[swizzle] [piglit args...]\n");
+	piglit_report_result(PIGLIT_FAIL);
+}
+
+void
+parse_args(int argc, char **argv)
+{
+	int i;
+	bool sampler_found = false;
+
+	for (i = 1; i < argc; i++) {
+		if (test_stage == UNKNOWN) {
+			/* Maybe it's the shader stage? */
+			if (strcmp(argv[i], "vs") == 0) {
+				test_stage = VS;
+				continue;
+			} else if (strcmp(argv[i], "gs") == 0) {
+				test_stage = GS;
+				continue;
+			} else if (strcmp(argv[i], "fs") == 0) {
+				test_stage = FS;
+				continue;
+			}
+		}
+
+		if (strcmp(argv[i], "140") == 0) {
+			shader_version = 140;
+			continue;
+		}
+
+		if (strcmp(argv[i], "offset") == 0) {
+			test_offset = true;
+			continue;
+		}
+
+		/* Maybe it's the sampler type? */
+		if (!sampler_found && (sampler_found = select_sampler(argv[i])))
+			continue;
+
+		if (!swizzling && (swizzling = parse_swizzle(argv[i])))
+			continue;
+
+		fail_and_show_usage();
+	}
+
+	if (test_stage == UNKNOWN || !sampler_found)
+		fail_and_show_usage();
+
+	if (test_stage == GS && shader_version < 150)
+		shader_version = 150;
+}
+
+
+void
+piglit_init(int argc, char **argv)
+{
+	int prog;
+	int tex_location;
+
+	if (!supported_sampler()) {
+		printf("%s unsupported\n", sampler.name);
+		piglit_report_result(PIGLIT_FAIL);
+	}
+
+	require_GL_features(test_stage);
+
+	prog = generate_GLSL(test_stage);
+
+	tex_location = glGetUniformLocation(prog, "tex");
+	divisor_loc = glGetUniformLocation(prog, "divisor");
+
+	/* Create textures and set miplevel info */
+	set_base_size();
+	compute_miplevel_info();
+	generate_texture();
+
+	generate_VBOs();
+
+	glUseProgram(prog);
+
+	glUniform1i(tex_location, 0);
+}
-- 
1.8.3.1



More information about the Piglit mailing list