[Piglit] [PATCH 06/12] generated_tests: Test tessellation control shader input.

Chris Forbes chrisf at ijw.co.nz
Wed Sep 17 00:42:19 PDT 2014


for every GLSL variable type, generate two tests. One passes a varying of said
type as a scalar from the vertex to the tessellation control shader and one
that passes a two-element array.
Fill the varying in the vertex shader from a uniform and compare
it against the uniform in the tessellation control shader.

Draw 4 patches, tessellate each into a quad that fills a quarter of the
screen.

Also test core profile built-in varyings.
---
 generated_tests/CMakeLists.txt         |   4 +
 generated_tests/gen_tcs_input_tests.py | 301 +++++++++++++++++++++++++++++++++
 2 files changed, 305 insertions(+)
 create mode 100644 generated_tests/gen_tcs_input_tests.py

diff --git a/generated_tests/CMakeLists.txt b/generated_tests/CMakeLists.txt
index e8129a7..9db23d7 100644
--- a/generated_tests/CMakeLists.txt
+++ b/generated_tests/CMakeLists.txt
@@ -37,6 +37,9 @@ piglit_make_generated_tests(
 	tes_input_tests.list
 	gen_tes_input_tests.py)
 piglit_make_generated_tests(
+	tcs_input_tests.list
+	gen_tcs_input_tests.py)
+piglit_make_generated_tests(
 	interpolation_tests.list
 	gen_interpolation_tests.py)
 piglit_make_generated_tests(
@@ -108,6 +111,7 @@ add_custom_target(gen-tests ALL
 		builtin_cl_math_tests.list
 		builtin_cl_relational_tests.list
 		cl_store_tests.list
+		tcs_input_tests.list
 		tes_input_tests.list
 		interpolation_tests.list
 		non-lvalue_tests.list
diff --git a/generated_tests/gen_tcs_input_tests.py b/generated_tests/gen_tcs_input_tests.py
new file mode 100644
index 0000000..41741aa
--- /dev/null
+++ b/generated_tests/gen_tcs_input_tests.py
@@ -0,0 +1,301 @@
+#!/usr/bin/env python
+# coding=utf-8
+#
+# Copyright © 2014 The Piglit Project
+#
+# 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.
+
+## Test passing variables from the vertex shader to the tessellation control
+# shader.
+#
+# For every varying type create one tests that passes a scalar of that type
+# and one test that passes a two element array.
+# Copy a uniform value to the varying in the vertex shader and compare the
+# varying to the same uniform in the tessellation control shader.
+# If the values are equal draw the screen green, red otherwise.
+#
+# Draw for tessellated quads. Each should cover one quarter of the screen.
+#
+# This script outputs, to stdout, the name of each file it generates.
+
+import os, sys, random
+
+
+class Test(object):
+    def __init__(self, type_name, array, name):
+        """Creates a test.
+
+        type_name -- varying type to test (e.g.: vec4, mat3x2, int, ...)
+        array -- number of array elements to test, None for no array
+        name -- name of the variable to test
+
+        """
+        self.var_name = name or 'var';
+
+        if self.var_name == 'gl_Position':
+            self.var_type = 'vec4'
+            self.var_array = None
+        elif self.var_name == 'gl_PointSize':
+            self.var_type = 'float'
+            self.var_array = None
+        elif self.var_name == 'gl_ClipDistance':
+            self.var_type = 'float'
+            self.var_array = 8
+        else:
+            self.var_type = type_name
+            self.var_array = array
+
+        if self.built_in:
+            self.interface_name = 'gl_PerVertex'
+            self.interface_vs_instance = ''
+            self.interface_tcs_instance = 'gl_in'
+        else:
+            self.interface_name = 'v2tc_interface'
+            self.interface_vs_instance = ''
+            self.interface_tcs_instance = 'v2tc'
+
+        if self.var_array:
+            self.var_type_full = self.var_type + '[{0}]'.format(self.var_array)
+        else:
+            self.var_type_full = self.var_type
+
+    @property
+    def built_in(self):
+        return self.var_name.startswith('gl_')
+
+    @property
+    def vs_var_ref(self):
+        return '.' + self.var_name if self.interface_vs_instance else self.var_name
+
+    @property
+    def tcs_var_ref(self):
+        return '.' + self.var_name if self.interface_tcs_instance else self.var_name
+
+    @property
+    def uniform_string(self):
+        """Returns string for loading uniform data by the shader_runner."""
+        data = self.test_data()
+        uniforms = ''
+        if (self.var_array):
+            for i in range(12):
+                for j in range(self.var_array):
+                    uniforms += 'uniform {0} reference[{1}].v[{2}] {3}\n'.format(
+                            self.var_type, i, j, data[i*j])
+        else:
+            for i in range(12):
+                uniforms += 'uniform {0} reference[{1}].v {2}\n'.format(
+                        self.var_type,
+                        i,
+                        data[i])
+
+        #strip last newline
+        return uniforms[:-1]
+
+    def components(self):
+        """Returns the number of scalar components of the used data type."""
+        n = 1
+
+        if self.var_type.startswith('mat'):
+            if 'x' in self.var_type:
+                n *= int(self.var_type[-1])
+                n *= int(self.var_type[-3])
+            else:
+                n *= int(self.var_type[-1])
+                n *= int(self.var_type[-1])
+        elif 'vec' in self.var_type:
+            n *= int(self.var_type[-1])
+
+        return n
+
+    def test_data(self):
+        """Returns random but deterministic data as a list of strings.
+
+        n strings are returned containing c random values, each.
+        Where n is the number of vertices times the array length and
+        c is the number of components in the tested scalar data type.
+        """
+        random.seed(17)
+
+        if self.var_array:
+            n = self.var_array * 12
+        else:
+            n = 12
+
+        if self.var_type.startswith('i'):
+            rand = lambda : random.randint(-0x80000000, 0x7fffffff)
+        elif self.var_type.startswith('u'):
+            rand = lambda : random.randint(0, 0xffffffff)
+        else:
+            rand = lambda : ((-1 + 2 * random.randint(0, 1)) *
+                             random.randint(0, 2**23-1) *
+                             2.0**(random.randint(-126, 127)))
+
+        c = self.components()
+
+        ret = []
+        for i in range(n):
+            ret.append(" ".join([str(rand()) for _ in range(c)]))
+
+        return ret
+
+    def filename(self):
+        """Returns the file name (including path) for the test."""
+        if (self.built_in):
+            name = self.var_name
+        elif (self.var_array):
+            name = self.var_type + '_{0}'.format(self.var_array)
+        else:
+            name = self.var_type
+        return os.path.join('spec',
+                            'arb_tessellation_shader',
+                            'execution',
+                            'tcs-input',
+                            'tcs-input-{0}.shader_test'.format(name))
+
+    def generate(self):
+        """Generates and writes the test to disc."""
+        test = \
+"""# Test generated by:
+# {generator_command}
+# Test tessellation control shader inputs
+[require]
+GLSL >= 1.50
+GL_ARB_tessellation_shader
+
+[vertex shader]
+uniform struct S0 {{
+	{self.var_type_full} v;
+}} reference[12];
+
+out {self.interface_name} {{
+	{self.var_type_full} {self.var_name};
+}} {self.interface_vs_instance};
+
+void main()
+{{
+	{self.interface_vs_instance}{self.vs_var_ref} = reference[gl_VertexID].v;
+}}
+
+[tessellation control shader]
+#extension GL_ARB_tessellation_shader : require
+layout(vertices = 3) out;
+
+uniform struct S0 {{
+	{self.var_type_full} v;
+}} reference[12];
+
+in {self.interface_name} {{
+	{self.var_type_full} {self.var_name};
+}} {self.interface_tcs_instance}[];
+
+out int pass[];
+
+void main()
+{{
+	const int vertices_in = 3;
+	pass[gl_InvocationID] = 1;
+	for (int i = 0; i < vertices_in; ++i) {{
+		int vertex_ID = gl_PrimitiveID * vertices_in + i;
+		if ({self.interface_tcs_instance}[i]{self.tcs_var_ref} != reference[vertex_ID].v)
+			pass[gl_InvocationID] = 0;
+	}}
+	gl_TessLevelOuter = float[4](1.0, 1.0, 1.0, 1.0);
+	gl_TessLevelInner = float[2](1.0, 1.0);
+}}
+
+[tessellation evaluation shader]
+#extension GL_ARB_tessellation_shader : require
+layout(quads) in;
+
+in int pass[];
+
+out vec4 vert_color;
+
+void main()
+{{
+	const int vertices_in = 3;
+	const vec4 red = vec4(1, 0, 0, 1);
+	const vec4 green = vec4(0, 1, 0, 1);
+	vec2[3] position = vec2[3](
+		vec2(float(gl_PrimitiveID / 2) - 1.0, float(gl_PrimitiveID % 2) - 1.0),
+		vec2(float(gl_PrimitiveID / 2) - 0.0, float(gl_PrimitiveID % 2) - 1.0),
+		vec2(float(gl_PrimitiveID / 2) - 1.0, float(gl_PrimitiveID % 2) - 0.0)
+	);
+	gl_Position = vec4(position[0]
+	            + (position[1] - position[0]) * gl_TessCoord[0]
+	            + (position[2] - position[0]) * gl_TessCoord[1], 0.0, 1.0);
+	vert_color = green;
+	for (int i = 0; i < vertices_in; ++i) {{
+		if (pass[i] == 0)
+			vert_color = red;
+	}}
+}}
+
+[fragment shader]
+
+in vec4 vert_color;
+
+out vec4 frag_color;
+
+void main()
+{{
+	frag_color = vert_color;
+}}
+
+[test]
+{self.uniform_string}
+draw arrays GL_PATCHES 0 12
+relative probe rgb (0.25, 0.25) (0.0, 1.0, 0.0)
+relative probe rgb (0.75, 0.25) (0.0, 1.0, 0.0)
+relative probe rgb (0.25, 0.75) (0.0, 1.0, 0.0)
+relative probe rgb (0.75, 0.75) (0.0, 1.0, 0.0)
+"""
+
+        test = test.format(self = self,
+            generator_command = " ".join(sys.argv))
+
+        filename = self.filename()
+        dirname = os.path.dirname(filename)
+        if not os.path.exists(dirname):
+            os.makedirs(dirname)
+        with open(filename, 'w') as f:
+            f.write(test)
+
+
+def all_tests():
+    for type_name in ['float', 'vec2',  'vec3',  'vec4',
+                      'mat2', 'mat3', 'mat4',
+                      'mat2x3', 'mat2x4', 'mat3x2',
+                      'mat3x4', 'mat4x2', 'mat4x3',
+                      'int', 'ivec2', 'ivec3', 'ivec4',
+                      'uint', 'uvec2', 'uvec3', 'uvec4']:
+        for array in [None, 2]:
+            yield Test(type_name=type_name, array=array, name=None)
+    for var in ['gl_Position', 'gl_PointSize', 'gl_ClipDistance']:
+        yield Test(type_name=None, array=None, name=var);
+
+def main():
+    for test in all_tests():
+        test.generate()
+        print(test.filename())
+
+
+if __name__ == '__main__':
+    main()
-- 
2.1.0



More information about the Piglit mailing list