This patch changes gen_builtin_uniform_tests to use mako to generate tests, rather than direct string concatenation.
Signed-off-by: Dylan Baker <[email protected]> --- generated_tests/CMakeLists.txt | 5 + generated_tests/builtins/glsl_types.py | 21 + generated_tests/gen_builtin_uniform_tests.py | 712 ++------------------- .../gen_builtin_uniform_tests/cs.shader_test.mako | 41 ++ .../gen_builtin_uniform_tests/fs.shader_test.mako | 48 ++ .../gen_builtin_uniform_tests/gs.shader_test.mako | 59 ++ .../templates/gen_builtin_uniform_tests/utils.mako | 211 ++++++ .../gen_builtin_uniform_tests/vs.shader_test.mako | 52 ++ 8 files changed, 505 insertions(+), 644 deletions(-) create mode 100644 generated_tests/templates/gen_builtin_uniform_tests/cs.shader_test.mako create mode 100644 generated_tests/templates/gen_builtin_uniform_tests/fs.shader_test.mako create mode 100644 generated_tests/templates/gen_builtin_uniform_tests/gs.shader_test.mako create mode 100644 generated_tests/templates/gen_builtin_uniform_tests/utils.mako create mode 100644 generated_tests/templates/gen_builtin_uniform_tests/vs.shader_test.mako diff --git a/generated_tests/CMakeLists.txt b/generated_tests/CMakeLists.txt index 98379c5..1f50318 100644 --- a/generated_tests/CMakeLists.txt +++ b/generated_tests/CMakeLists.txt @@ -36,6 +36,11 @@ piglit_make_generated_tests( builtins/glsl_types.py builtins/generators.py builtins/math.py + templates/gen_builtin_uniform_tests/utils.mako + templates/gen_builtin_uniform_tests/vs.shader_test.mako + templates/gen_builtin_uniform_tests/fs.shader_test.mako + templates/gen_builtin_uniform_tests/gs.shader_test.mako + templates/gen_builtin_uniform_tests/cs.shader_test.mako ) piglit_make_generated_tests( constant_array_size_tests.list diff --git a/generated_tests/builtins/glsl_types.py b/generated_tests/builtins/glsl_types.py index 084dcda..038fcd7 100644 --- a/generated_tests/builtins/glsl_types.py +++ b/generated_tests/builtins/glsl_types.py @@ -97,6 +97,27 @@ class GlslBuiltinType(object): """ return self.__version_introduced + @property + def as_shader_runner_uniform(self): + """Return this glsl_type as expected by shader_runner. + + Specifically this is the format expected by shader_runner for it's + uniform command. + + Boolans and vectors are converted to ints, square matricies are + rendered in matNxN, everything else is just self.__str__. + + """ + if self.base_type is GLSL_BOOL: + if self.is_scalar: + return 'int' + else: + return 'ivec{}'.format(self.num_rows) + elif self.is_matrix: + return 'mat{0}x{1}'.format(self.num_cols, self.num_rows) + else: + return str(self) + def __str__(self): return self.__name diff --git a/generated_tests/gen_builtin_uniform_tests.py b/generated_tests/gen_builtin_uniform_tests.py index 4e83bb6..05e16e2 100644 --- a/generated_tests/gen_builtin_uniform_tests.py +++ b/generated_tests/gen_builtin_uniform_tests.py @@ -43,674 +43,98 @@ doesn't generate them. """ -from __future__ import absolute_import -import abc -import optparse +from __future__ import absolute_import, print_function import os -import numpy as np - -from builtins import glsl_types, generators import builtin_function +from builtins import glsl_types +from templates import template_dir +TEMPLATES = template_dir(os.path.basename(os.path.splitext(__file__)[0])) -def compute_offset_and_scale(test_vectors): - """Compute scale and offset values such that for each result in - test_vectors, (result - offset) * scale is in the range [0.25, - 0.75], and scale is less than or equal to 1.0. These values are - used to transform the test vectors so that their outputs can be - stored in gl_FragColor without overflow. - """ - low = min(np.min(tv.result) for tv in test_vectors) - hi = max(np.max(tv.result) for tv in test_vectors) - span = hi - low - center = (hi + low)/2.0 - span *= 2.0 - if span < 1.0: - span = 1.0 - offset = center - span/2.0 - scale = 1.0/span - return offset, scale - - -def shader_runner_format(values): - """Format the given values for use in a shader_runner "uniform" or - "probe rgba" command. Bools are converted to 0's and 1's, and - values are separated by spaces. - """ - transformed_values = [] - for value in values: - if isinstance(value, (bool, np.bool_)): - transformed_values.append(int(value)) - else: - transformed_values.append(value) - return ' '.join(repr(x) for x in transformed_values) - - -def shader_runner_type(glsl_type): - """Return the appropriate type name necessary for binding a - uniform of the given type using shader_runner's "uniform" command. - Boolean values and vectors are converted to ints, and square - matrices are written in "matNxN" form. - """ - if glsl_type.base_type == glsl_types.GLSL_BOOL: - if glsl_type.is_scalar: - return 'int' - else: - return 'ivec{0}'.format(glsl_type.num_rows) - elif glsl_type.is_matrix: - return 'mat{0}x{1}'.format(glsl_type.num_cols, glsl_type.num_rows) - else: - return str(glsl_type) - - -class Comparator(object): - """Base class which abstracts how we compare expected and actual - values. - """ - __metaclass__ = abc.ABCMeta - - def make_additional_declarations(self): - """Return additional declarations, if any, that are needed in - the shader program. - """ - return '' - - @abc.abstractmethod - def make_result_handler(self, invocation, output_var): - """Return the shader code that is needed to produce the result - and store it in output_var. - - invocation is the GLSL code to compute the output of the - built-in function. - """ - - @abc.abstractmethod - def make_result_test(self, test_num, test_vector): - """Return the shader_runner test code that is needed to test a - single test vector. - """ - - def testname_suffix(self): - """Return a string to be used as a suffix on the test name to - distinguish it from tests using other comparators.""" - return '' - - -class BoolComparator(Comparator): - """Comparator that tests functions returning bools and bvecs by - converting them to floats. - - This comparator causes code to be generated in the following form: - - rettype result = func(args); - output_var = vec4(result, 0.0, ...); - """ - def __init__(self, signature): - assert not signature.rettype.is_matrix - self.__signature = signature - self.__padding = 4 - signature.rettype.num_rows - - def make_result_handler(self, invocation, output_var): - statements = ' {0} result = {1};\n'.format( - self.__signature.rettype, invocation) - statements += ' {0} = vec4(result{1});\n'.format( - output_var, ', 0.0' * self.__padding) - return statements - - def convert_to_float(self, value): - """Convert the given vector or scalar value to a list of - floats representing the expected color produced by the test. - """ - value = value*1.0 # convert bools to floats - value = generators.column_major_values(value) - value += [0.0] * self.__padding - return value - - def make_result_test(self, test_num, test_vector, draw): - test = draw - test += 'probe rgba {0} 0 {1}\n'.format( - test_num, - shader_runner_format(self.convert_to_float(test_vector.result))) - return test - - -class BoolIfComparator(Comparator): - """Comparator that tests functions returning bools by evaluating - them inside an if statement. - - This comparator causes code to be generated in the following form: - - if (func(args)) - output_var = vec4(1.0, 1.0, 0.0, 1.0); - else - output_var = vecp(0.0, 0.0, 1.0, 1.0); - """ - def __init__(self, signature): - assert signature.rettype == glsl_types.GLSL_BOOL - self.__padding = 4 - signature.rettype.num_rows - - def make_result_handler(self, invocation, output_var): - statements = ' if({0})\n'.format(invocation) - statements += ' {0} = vec4(1.0, 1.0, 0.0, 1.0);\n'.format( - output_var) - statements += ' else\n' - statements += ' {0} = vec4(0.0, 0.0, 1.0, 1.0);\n'.format( - output_var) - return statements - - def convert_to_float(self, value): - """Convert the given vector or scalar value to a list of - floats representing the expected color produced by the test. - """ - if value: - return [1.0, 1.0, 0.0, 1.0] - else: - return [0.0, 0.0, 1.0, 1.0] - - def make_result_test(self, test_num, test_vector, draw): - test = draw - test += 'probe rgba {0} 0 {1}\n'.format( - test_num, - shader_runner_format(self.convert_to_float(test_vector.result))) - return test - - def testname_suffix(self): - return '-using-if' - - -class IntComparator(Comparator): - """Comparator that tests functions returning ints or ivecs using a - strict equality test. - - This comparator causes code to be generated in the following form: - - rettype result = func(args); - output_var = result == expected ? vec4(0.0, 1.0, 0.0, 1.0) - : vec4(1.0, 0.0, 0.0, 1.0); - """ - def __init__(self, signature): - self.__signature = signature - - def make_additional_declarations(self): - return 'uniform {0} expected;\n'.format(self.__signature.rettype) - - def make_result_handler(self, invocation, output_var): - statements = ' {0} result = {1};\n'.format( - self.__signature.rettype, invocation) - statements += ' {v} = {cond} ? {green} : {red};\n'.format( - v=output_var, cond='result == expected', - green='vec4(0.0, 1.0, 0.0, 1.0)', - red='vec4(1.0, 0.0, 0.0, 1.0)') - return statements - - def make_result_test(self, test_num, test_vector, draw): - test = 'uniform {0} expected {1}\n'.format( - shader_runner_type(self.__signature.rettype), - shader_runner_format(generators.column_major_values( - test_vector.result))) - test += draw - test += 'probe rgba {0} 0 0.0 1.0 0.0 1.0\n'.format(test_num) - return test - - -class FloatComparator(Comparator): - """Comparator that tests functions returning floats or vecs using a - strict equality test. - - This comparator causes code to be generated in the following form: - - rettype result = func(args); - output_var = distance(result, expected) <= tolerance - ? vec4(0.0, 1.0, 0.0, 1.0) : vec4(1.0, 0.0, 0.0, 1.0); - """ - def __init__(self, signature): - self.__signature = signature - - def make_additional_declarations(self): - decls = 'uniform float tolerance;\n' - decls += 'uniform {0} expected;\n'.format(self.__signature.rettype) - return decls - - def make_indexers(self): - """Build a list of strings which index into every possible - value of the result. For example, if the result is a vec2, - then build the indexers ['[0]', '[1]']. - """ - if self.__signature.rettype.num_cols == 1: - col_indexers = [''] - else: - col_indexers = ['[{0}]'.format(i) - for i in xrange(self.__signature.rettype.num_cols)] - if self.__signature.rettype.num_rows == 1: - row_indexers = [''] - else: - row_indexers = ['[{0}]'.format(i) - for i in xrange(self.__signature.rettype.num_rows)] - return [col_indexer + row_indexer - for col_indexer in col_indexers - for row_indexer in row_indexers] - - def make_result_handler(self, invocation, output_var): - statements = ' {0} result = {1};\n'.format( - self.__signature.rettype, invocation) - # Can't use distance when testing itself, or when the rettype - # is a matrix. - if self.__signature.name == 'distance' or \ - self.__signature.rettype.is_matrix: - statements += ' {0} residual = result - expected;\n'.format( - self.__signature.rettype) - statements += ' float error_sq = {0};\n'.format( - ' + '.join( - 'residual{0} * residual{0}'.format(indexer) - for indexer in self.make_indexers())) - condition = 'error_sq <= tolerance * tolerance' - else: - condition = 'distance(result, expected) <= tolerance' - statements += ' {v} = {cond} ? {green} : {red};\n'.format( - v=output_var, cond=condition, green='vec4(0.0, 1.0, 0.0, 1.0)', - red='vec4(1.0, 0.0, 0.0, 1.0)') - return statements - - def make_result_test(self, test_num, test_vector, draw): - test = 'uniform {0} expected {1}\n'.format( - shader_runner_type(self.__signature.rettype), - shader_runner_format(generators.column_major_values( - test_vector.result))) - test += 'uniform float tolerance {0}\n'.format( - shader_runner_format([test_vector.tolerance])) - test += draw - test += 'probe rgba {0} 0 0.0 1.0 0.0 1.0\n'.format(test_num) - return test - - -class ShaderTest(object): - """Class used to build a test of a single built-in. This is an - abstract base class--derived types should override test_prefix(), - make_vertex_shader(), make_fragment_shader(), and other functions - if necessary. - """ - __metaclass__ = abc.ABCMeta - - def __init__(self, signature, test_vectors, use_if): - """Prepare to build a test for a single built-in. signature - is the signature of the built-in (a key from the - glsl_types_function.test_suite dict), and test_vectors is the - list of test vectors for testing the given glsl_types (the - corresponding value from the glsl_types_function.test_suite - dict). - - If use_if is True, then the generated test checks the result - by using it in an if statement--this only works for glsl_typess - returning bool. - """ - self._signature = signature - self._test_vectors = test_vectors - if use_if: - self._comparator = BoolIfComparator(signature) - elif signature.rettype.base_type == glsl_types.GLSL_BOOL: - self._comparator = BoolComparator(signature) - elif signature.rettype.base_type == glsl_types.GLSL_FLOAT: - self._comparator = FloatComparator(signature) - elif signature.rettype.base_type in (glsl_types.GLSL_INT, - glsl_types.GLSL_UINT): - self._comparator = IntComparator(signature) - else: - raise Exception('Unexpected rettype {0}'.format(signature.rettype)) - - def glsl_version(self): - return self._signature.version_introduced - - def draw_command(self): - if self.glsl_version() >= 140: - return 'draw arrays GL_TRIANGLE_FAN 0 4\n' - else: - return 'draw rect -1 -1 2 2\n' - - def make_additional_requirements(self): - """Return a string that should be included in the test's - [require] section. - """ - return '' - - @abc.abstractmethod - def test_prefix(self): - """Return the prefix that should be used in the test file name - to identify the type of test, e.g. "vs" for a vertex shader - test. - """ - - def make_vertex_shader(self): - """Return the vertex shader for this test (or None if this - test doesn't require a vertex shader). No need to - reimplement this function in classes that don't use vertex - shaders. - """ - return None - - def make_geometry_shader(self): - """Return the geometry shader for this test (or None if this - test doesn't require a geometry shader). No need to - reimplement this function in classes that don't use geometry - shaders. - """ - return None - - def make_geometry_layout(self): - """Return the geometry layout for this test (or None if this - test doesn't require a geometry layout section). No need to - reimplement this function in classes that don't use geometry - shaders. - """ - return None - - def make_fragment_shader(self): - """Return the fragment shader for this test (or None if this - test doesn't require a fragment shader). No need to - reimplement this function in classes that don't use fragment - shaders. - """ - return None - - def make_compute_shader(self): - """Return the compute shader for this test (or None if this test - doesn't require a compute shader). No need to reimplement - this function in classes that don't use compute shaders. - """ - return None - - def make_test_shader(self, additional_declarations, prefix_statements, - output_var, suffix_statements): - """Generate the shader code necessary to test the built-in. - additional_declarations is a string containing any - declarations that need to be before the main() function of the - shader. prefix_statements is a string containing any - additional statements than need to be inside the main() - function of the shader, before the built-in function is - called. output_var is the variable that the result of the - built-in function should be assigned to, after conversion to a - vec4. suffix_statements is a string containing any additional - statements that need to be inside the main() funciton of the - shader, after the built-in function is called. - """ - shader = '' - if self._signature.extension: - shader += '#extension GL_{0} : require\n'.format(self._signature.extension) - shader += additional_declarations - for i in xrange(len(self._signature.argtypes)): - shader += 'uniform {0} arg{1};\n'.format( - self._signature.argtypes[i], i) - shader += self._comparator.make_additional_declarations() - shader += '\n' - shader += 'void main()\n' - shader += '{\n' - shader += prefix_statements - invocation = self._signature.template.format( - *['arg{0}'.format(i) - for i in xrange(len(self._signature.argtypes))]) - shader += self._comparator.make_result_handler(invocation, output_var) - shader += suffix_statements - shader += '}\n' - return shader - - def make_test_init(self): - """Generate initialization for the test. - """ - return '' - - def make_test(self): - """Make the complete shader_runner test file, and return it as - a string. - """ - test = self.make_test_init() - for test_num, test_vector in enumerate(self._test_vectors): - for i in xrange(len(test_vector.arguments)): - test += 'uniform {0} arg{1} {2}\n'.format( - shader_runner_type(self._signature.argtypes[i]), - i, - shader_runner_format(generators.column_major_values( - test_vector.arguments[i]))) - # Note: shader_runner uses a 250x250 window so we must - # ensure that test_num <= 250. - test += self._comparator.make_result_test( - test_num % 250, test_vector, self.draw_command()) - return test - - def make_vbo_data(self): - # Starting with GLSL 1.40/GL 3.1, we need to use VBOs and - # vertex shader input bindings for our vertex data instead of - # the piglit drawing utilities and gl_Vertex. - if self.glsl_version() < 140: - return "" - vbo = '[vertex data]\n' - vbo += 'vertex/float/2\n' - vbo += '-1.0 -1.0\n' - vbo += ' 1.0 -1.0\n' - vbo += ' 1.0 1.0\n' - vbo += '-1.0 1.0\n' - vbo += '\n' - return vbo - def filename(self): - argtype_names = '-'.join( - str(argtype) for argtype in self._signature.argtypes) - if self._signature.extension: - subdir = self._signature.extension.lower() - else: - subdir = 'glsl-{0:1.2f}'.format(float(self.glsl_version()) / 100) - return os.path.join( - 'spec', subdir, 'execution', 'built-in-functions', - '{0}-{1}-{2}{3}.shader_test'.format( - self.test_prefix(), self._signature.name, argtype_names, - self._comparator.testname_suffix())) +def _select_comparator(signature, use_if): + """Select the apropriate comparison function.""" + if use_if: + return 'boolif' + elif signature.rettype.base_type == glsl_types.GLSL_BOOL: + return 'bool' + elif signature.rettype.base_type == glsl_types.GLSL_FLOAT: + return 'float' + elif signature.rettype.base_type in (glsl_types.GLSL_INT, + glsl_types.GLSL_UINT): + return 'int' - def generate_shader_test(self): - """Generate the test and write it to the output file.""" - shader_test = '[require]\n' - shader_test += 'GLSL >= {0:1.2f}\n'.format( - float(self.glsl_version()) / 100) - shader_test += self.make_additional_requirements() - shader_test += '\n' - vs = self.make_vertex_shader() - if vs: - shader_test += '[vertex shader]\n' - shader_test += vs - shader_test += '\n' - gs = self.make_geometry_shader() - if gs: - shader_test += '[geometry shader]\n' - shader_test += gs - shader_test += '\n' - gl = self.make_geometry_layout() - if gl: - shader_test += '[geometry layout]\n' - shader_test += gl - shader_test += '\n' - fs = self.make_fragment_shader() - if fs: - shader_test += '[fragment shader]\n' - shader_test += fs - shader_test += '\n' - cs = self.make_compute_shader() - if cs: - shader_test += '[compute shader]\n' - shader_test += cs - shader_test += '\n' - if vs: - shader_test += self.make_vbo_data() - shader_test += '[test]\n' - shader_test += self.make_test() - 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(shader_test) +def _get_glsl_version(signature, stage): + """Set the apropriate version. -class VertexShaderTest(ShaderTest): - """Derived class for tests that exercise the built-in in a vertex - shader. - """ - def test_prefix(self): - return 'vs' - - def make_vertex_shader(self): - if self.glsl_version() >= 140: - return self.make_test_shader( - 'in vec4 vertex;\n' + - 'out vec4 color;\n', - ' gl_Position = vertex;\n', - 'color', '') - else: - return self.make_test_shader( - 'varying vec4 color;\n', - ' gl_Position = gl_Vertex;\n', - 'color', '') - - def make_fragment_shader(self): - shader = '''varying vec4 color; + normally signature introduced is the correct value, but for some stages + that isn't correct. -void main() -{ - gl_FragColor = color; -} -''' - return shader - - -class GeometryShaderTest(ShaderTest): - """Derived class for tests that exercise the built-in in a - geometry shader. """ - def test_prefix(self): - return 'gs' - - def glsl_version(self): - return max(150, ShaderTest.glsl_version(self)) - - def make_vertex_shader(self): - shader = '' - shader += "in vec4 vertex;\n" - shader += "out vec4 vertex_to_gs;\n" - - shader += "void main()\n" - shader += "{\n" - shader += " vertex_to_gs = vertex;\n" - shader += "}\n" - - return shader - - def make_geometry_shader(self): - additional_declarations = '' - additional_declarations += 'layout(triangles) in;\n' - additional_declarations \ - += 'layout(triangle_strip, max_vertices = 3) out;\n' - additional_declarations += 'in vec4 vertex_to_gs[3];\n' - additional_declarations += 'out vec4 color;\n' - return self.make_test_shader( - additional_declarations, - ' vec4 tmp_color;\n', - 'tmp_color', - ' for (int i = 0; i < 3; i++) {\n' - ' gl_Position = vertex_to_gs[i];\n' - ' color = tmp_color;\n' - ' EmitVertex();\n' - ' }\n') - - def make_fragment_shader(self): - shader = '''varying vec4 color; - -void main() -{ - gl_FragColor = color; -} -''' - return shader - - -class FragmentShaderTest(ShaderTest): - """Derived class for tests that exercise the built-in in a - fragment shader. - """ - def test_prefix(self): - return 'fs' - - def make_vertex_shader(self): - shader = "" - if self.glsl_version() >= 140: - shader += "in vec4 vertex;\n" - - shader += "void main()\n" - shader += "{\n" - if self.glsl_version() >= 140: - shader += " gl_Position = vertex;\n" - else: - shader += " gl_Position = gl_Vertex;\n" - shader += "}\n" - - return shader + if stage == 'gs': + return max(150, signature.version_introduced) + elif stage == 'cs': + return max(430, signature.version_introduced) + return signature.version_introduced + + +def _filename(signature, version, use_if, stage): + """Generate the filename.""" + argtype_names = '-'.join(str(s) for s in signature.argtypes) + if signature.extension: + subdir = signature.extension.lower() + else: + subdir = 'glsl-{0:1.2f}'.format(float(version) / 100) + return os.path.join( + 'spec', subdir, 'execution', 'built-in-functions', + '{0}-{1}-{2}{3}.shader_test'.format( + stage, signature.name, argtype_names, + '-using-if' if use_if else '')) - def make_fragment_shader(self): - return self.make_test_shader('', '', 'gl_FragColor', '') +def _get_draw(stage, version): + """get the draw function.""" + if stage == 'cs': + return 'compute 1 1 1\n' + if version >= 140: + return 'draw arrays GL_TRIANGLE_FAN 0 4\n' + else: + return 'draw rect -1 -1 2 2\n' -class ComputeShaderTest(ShaderTest): - """Derived class for tests that exercise the built-in in a - compute shader. - """ - def test_prefix(self): - return 'cs' - def glsl_version(self): - return max(430, ShaderTest.glsl_version(self)) +def generate(signature, vectors, use_if, stage): + """Create a test with the given inputs.""" + template = TEMPLATES.get_template('{}.shader_test.mako'.format(stage)) + version = _get_glsl_version(signature, stage) + filename = _filename(signature, version, use_if, stage) - def make_compute_shader(self): - additional_declarations = 'writeonly uniform image2D tex;\n' - additional_declarations += 'layout(local_size_x = 16, local_size_y = 16) in;\n' - return self.make_test_shader( - additional_declarations, - ' vec4 tmp_color;\n', - 'tmp_color', - ' ivec2 coord = ivec2(gl_GlobalInvocationID.xy);\n' - ' imageStore(tex, coord, tmp_color);\n') + if not os.path.exists(os.path.dirname(filename)): + os.makedirs(os.path.dirname(filename)) - def make_test_init(self): - return '''uniform int tex 0 -texture rgbw 0 (16, 16) -image texture 0 -fb tex 2d 0 -''' + print(filename) + with open(filename, 'w') as f: + f.write(template.render( + draw=_get_draw(stage, version), + comparator=_select_comparator(signature, use_if), + signature=signature, + vectors=vectors, + glsl_version=version)) - def draw_command(self): - return 'compute 1 1 1\n' def all_tests(): - for use_if in [False, True]: - for signature, test_vectors in sorted(builtin_function.test_suite.items()): - if use_if and signature.rettype != glsl_types.GLSL_BOOL: - continue - yield VertexShaderTest(signature, test_vectors, use_if) - yield GeometryShaderTest(signature, test_vectors, use_if) - yield FragmentShaderTest(signature, test_vectors, use_if) - yield ComputeShaderTest(signature, test_vectors, use_if) + for signature, test_vectors in builtin_function.test_suite.iteritems(): + yield signature, test_vectors, False + if signature.rettype == glsl_types.GLSL_BOOL: + yield signature, test_vectors, True def main(): - desc = 'Generate shader tests that test built-in functions using uniforms' - usage = 'usage: %prog [-h] [--names-only]' - parser = optparse.OptionParser(description=desc, usage=usage) - parser.add_option( - '--names-only', - dest='names_only', - action='store_true', - help="Don't output files, just generate a list of filenames to stdout") - options, args = parser.parse_args() - for test in all_tests(): - if not options.names_only: - test.generate_shader_test() - print test.filename() + for sig, vecs, use_if in all_tests(): + for stage in ['vs', 'fs', 'gs', 'cs']: + generate(sig, vecs, use_if, stage) if __name__ == '__main__': diff --git a/generated_tests/templates/gen_builtin_uniform_tests/cs.shader_test.mako b/generated_tests/templates/gen_builtin_uniform_tests/cs.shader_test.mako new file mode 100644 index 0000000..60b4df1 --- /dev/null +++ b/generated_tests/templates/gen_builtin_uniform_tests/cs.shader_test.mako @@ -0,0 +1,41 @@ +## Copyright (C) 2014 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 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. +## +## Create a vertex shader test. +## +<%namespace name="utils" file="utils.mako"/> + +[require] +GLSL >= ${'{:1.2f}'.format(float(glsl_version) / 100)} + +[compute shader] +% if signature.extension: +#extension GL_${signature.extension} : require +% endif +writeonly uniform image2D tex; +layout(local_size_x = 16, local_size_y = 16) in; +${utils.make_shader(signature, comparator, 'tmp_color', prefix=['vec4 tmp_color;'], suffix=['ivec2 coord = ivec2(gl_GlobalInvocationID.xy);', 'imageStore(tex, coord, tmp_color);'], extension=False)} + +[test] +uniform int tex 0 +texture rgbw 0 (16, 16) +image texture 0 +fb tex 2d 0 +${utils.make_test(vectors, signature, draw, comparator)} diff --git a/generated_tests/templates/gen_builtin_uniform_tests/fs.shader_test.mako b/generated_tests/templates/gen_builtin_uniform_tests/fs.shader_test.mako new file mode 100644 index 0000000..75935f1 --- /dev/null +++ b/generated_tests/templates/gen_builtin_uniform_tests/fs.shader_test.mako @@ -0,0 +1,48 @@ +## Copyright (C) 2014 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 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. +## +## Create a vertex shader test. +## +<%namespace name="utils" file="utils.mako"/> + +[require] +GLSL >= ${'{:1.2f}'.format(float(glsl_version) / 100)} + +[vertex shader] +% if glsl_version >= 140: +in vec4 vertex; +% endif + +void main() +{ +% if glsl_version >= 140: + gl_Position = vertex; +% else: + gl_Position = gl_Vertex; +% endif +} + +[fragment shader] +${utils.make_shader(signature, comparator, 'gl_FragColor')} + +${utils.make_vertex_data(glsl_version)} + +[test] +${utils.make_test(vectors, signature, draw, comparator)} diff --git a/generated_tests/templates/gen_builtin_uniform_tests/gs.shader_test.mako b/generated_tests/templates/gen_builtin_uniform_tests/gs.shader_test.mako new file mode 100644 index 0000000..81ed1b8 --- /dev/null +++ b/generated_tests/templates/gen_builtin_uniform_tests/gs.shader_test.mako @@ -0,0 +1,59 @@ +## Copyright (C) 2014 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 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. +## +## Create a vertex shader test. +## +<%namespace name="utils" file="utils.mako"/> + +[require] +GLSL >= ${'{:1.2f}'.format(float(glsl_version) / 100)} + +[vertex shader] +in vec4 vertex; +out vec4 vertex_to_gs; + +void main() +{ + vertex_to_gs = vertex; +} + +[geometry shader] +% if signature.extension: +#extension GL_${signature.extension} : require +% endif +layout(triangles) in; +layout(triangle_strip, max_vertices = 3) out; +in vec4 vertex_to_gs[3]; +out vec4 color; + +${utils.make_shader(signature, comparator, 'tmp_color', prefix=['vec4 tmp_color;'], suffix=['for (int i = 0; i < 3; i++) {', 'gl_Position = vertex_to_gs[i];', 'color = tmp_color;', 'EmitVertex();', '}'], extension=False)} + +[fragment shader] +varying vec4 color; + +void main() +{ + gl_FragColor = color; +} + +${utils.make_vertex_data(glsl_version)} + +[test] +${utils.make_test(vectors, signature, draw, comparator)} diff --git a/generated_tests/templates/gen_builtin_uniform_tests/utils.mako b/generated_tests/templates/gen_builtin_uniform_tests/utils.mako new file mode 100644 index 0000000..742a703 --- /dev/null +++ b/generated_tests/templates/gen_builtin_uniform_tests/utils.mako @@ -0,0 +1,211 @@ +## Copyright (C) 2014 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 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. + +## Provides shared helper function written in mako for generating tests. +## +## These function are shared across the different shader stages, and allow +## for clear focuses templates for each stage without the need to to +## reimplement the same functionality multiple times + +<%! + # Ideally this would all be in a python module, but I can't figure out + # how to get a mako template to import a python module that isn't already + # in the sys.path, the normal sys.path.append trick doesn't seem to work + + import numpy as np + + + def column_major_values(value): + """Ripped straight out of builtins.generators.""" + if isinstance(value, np.ndarray): + return list(np.reshape(value, -1, 'F')) + else: + return [value] + + + def shader_runner_format(values): + """Transform a list of values for shader_runner 'uniform' and 'probe'. + + Shader_runner requires that bools be converted to 0 or 1 and seperated by + spaces. This function produces a string formatted as such + + """ + def gen(): + for value in values: + if isinstance(value, (bool, np.bool_)): + yield int(value) + else: + yield value + + return ' '.join(repr(x) for x in gen()) + + + def bool_to_float(value, signature): + v = column_major_values(value * 1.0) + v.extend([0.0] * (4 - signature.rettype.num_rows)) + return v + + + def make_indexer(signature): + if signature.rettype.num_cols == 1: + col_indexers = [''] + else: + col_indexers = ['[{}]'.format(i) for i in xrange(signature.rettype.num_cols)] + + if signature.rettype.num_rows == 1: + row_indexers = [''] + else: + row_indexers = ['[{}]'.format(i) for i in xrange(signature.rettype.num_rows)] + + return [c + r for c in col_indexers for r in row_indexers] + + + def invocation(signature): + return signature.template.format( + *['arg{0}'.format(i)for i in xrange(len(signature.argtypes))]) +%> + +<%def name="make_test(vectors, signature, draw, comparator)" filter='trim'> + ## XXX: make test init needs to be handled by the individual generators + % for n, vector in enumerate(vectors): + % for i in xrange(len(vector.arguments)): + uniform ${signature.argtypes[i].as_shader_runner_uniform} arg${i} ${shader_runner_format(column_major_values(vector.arguments[i]))} + % endfor + + % if comparator == 'boolif': + ${test_bool_if(n, vector, draw, signature)} + % elif comparator == 'bool': + ${test_bool(n, vector, draw, signature)} + % elif comparator == 'int': + ${test_int(n, vector, draw, signature)} + % elif comparator == 'float': + ${test_float(n, vector, draw, signature)} + % endif + % endfor +</%def> + +<%def name="test_bool(test_num, vector, draw, signature)" filter='trim'> + ${draw} + probe rgba ${test_num % 250} 0 ${shader_runner_format(bool_to_float(vector.result, signature))} +</%def> + +<%def name="test_bool_if(test_num, vector, draw, signature)" filter='trim'> + ${draw} + probe rgba ${test_num % 250} 0 ${shader_runner_format([1.0, 1.0, 0.0, 1.0] if vector.result else [0.0, 0.0, 1.0, 1.0])} +</%def> + +<%def name="test_int(test_num, vector, draw, signature)" filter='trim'> + uniform ${signature.rettype.as_shader_runner_uniform} expected ${shader_runner_format(column_major_values(vector.result))} + ${draw} + probe rgba ${test_num % 250} 0 0.0 1.0 0.0 1.0 +</%def> + +<%def name="test_float(test_num, vector, draw, signature)" filter='trim'> + uniform ${signature.rettype.as_shader_runner_uniform} expected ${shader_runner_format(column_major_values(vector.result))} + uniform float tolerance ${shader_runner_format([vector.tolerance])} + ${draw} + probe rgba ${test_num % 250} 0 0.0 1.0 0.0 1.0 +</%def> + +## XXX: original signature (additional_declarations, prefix_statements, output_var, suffix_statement) +## additional_declarations -> declarations (originally string, now list) +## prefix_statements -> prefix +## suffix_statements -> suffix +## output_var -> output +## TODO: Kill declarations, just handle those in the individual templates +## TODO: convert prefix and suffix to lists +<%def name="make_shader(signature, comparator, output, prefix=[], suffix=[], extension=True)" filter='trim'> + % if extension and signature.extension: + #extension GL_${signature.extension} : require + % endif + + % for i in xrange(len(signature.argtypes)): + uniform ${signature.argtypes[i]} arg${i}; + % endfor + + % if comparator == 'int': + uniform ${signature.rettype} expected; + % elif comparator == 'float': + uniform float tolerance; + uniform ${signature.rettype} expected; + % endif + + void main() + { + % for line in prefix: + ${line} + % endfor + % if comparator == 'boolif': + ${result_bool_if(output, signature)} + % elif comparator == 'bool': + ${result_bool(output, signature)} + % elif comparator == 'int': + ${result_int(output, signature)} + % elif comparator == 'float': + ${result_float(output, signature)} + % endif + % for line in suffix: + ${line} + % endfor + } +</%def> + +<%def name="result_bool(output, signature)" filter='trim'> + ${signature.rettype} result = ${invocation(signature)}; + % if signature.rettype.num_rows != 4: + ${output} = vec4(result, ${', '.join(['0.0'] * (4 - signature.rettype.num_rows))}); + % else: + ${output} = vec4(result); + % endif +</%def> + +<%def name="result_bool_if(output, signature)" filter='trim'> + if (${invocation(signature)}) + ${output} = vec4(1.0, 1.0, 0.0, 1.0); + else + ${output} = vec4(0.0, 0.0, 1.0, 1.0); +</%def> + +<%def name="result_int(output, signature)" filter='trim'> + ${signature.rettype} result = ${invocation(signature)}; + ${output} = result == expected ? vec4(0.0, 1.0, 0.0, 1.0) : vec4(1.0, 0.0, 0.0, 1.0); +</%def> + +<%def name="result_float(output, signature)" filter='trim'> + ${signature.rettype} result = ${invocation(signature)}; + % if signature.name == 'distance' or signature.rettype.is_matrix: + ${signature.rettype} residual = result - expected; + float error_sq = ${' + '.join('residual{0} * residual{0}'.format(i) for i in make_indexer(signature))}; + ${output} = error_sq <= tolerance * tolerance ? vec4(0.0, 1.0, 0.0, 1.0) : vec4(1.0, 0.0, 0.0, 1.0); + % else: + ${output} = distance(result, expected) <= tolerance ? vec4(0.0, 1.0, 0.0, 1.0) : vec4(1.0, 0.0, 0.0, 1.0); + % endif +</%def> + +<%def name="make_vertex_data(glsl_version)" filter='trim'> + % if glsl_version >= 140: + [vertex data] + vertex/float/2 + -1.0 -1.0 + 1.0 -1.0 + 1.0 1.0 + -1.0 1.0 + % endif +</%def> diff --git a/generated_tests/templates/gen_builtin_uniform_tests/vs.shader_test.mako b/generated_tests/templates/gen_builtin_uniform_tests/vs.shader_test.mako new file mode 100644 index 0000000..c03cd06 --- /dev/null +++ b/generated_tests/templates/gen_builtin_uniform_tests/vs.shader_test.mako @@ -0,0 +1,52 @@ +## Copyright (C) 2014 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 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. +## +## Create a vertex shader test. +## +<%namespace name="utils" file="utils.mako"/> + +[require] +GLSL >= ${'{:1.2f}'.format(float(glsl_version) / 100)} + +[vertex shader] +% if signature.extension: +#extension GL_${signature.extension} : require +% endif +% if glsl_version >= 140: + in vec4 vertex; + out vec4 color; + ${utils.make_shader(signature, comparator, 'color', prefix=['gl_Position = vertex;'], extension=False)} +% else: + varying vec4 color; + ${utils.make_shader(signature, comparator, 'color', prefix=['gl_Position = gl_Vertex;'], extension=False)} +% endif + +[fragment shader] +varying vec4 color; + +void main() +{ + gl_FragColor = color; +} + +${utils.make_vertex_data(glsl_version)} + +[test] +${utils.make_test(vectors, signature, draw, comparator)} -- 2.2.0 _______________________________________________ Piglit mailing list [email protected] http://lists.freedesktop.org/mailman/listinfo/piglit
