[Piglit] [PATCH RFC v3] arb_shader_precision: add tests for floating point precision
Dylan Baker
baker.dylan.c at gmail.com
Fri Nov 21 15:18:25 PST 2014
I have a few nitpicky comments, I didn't look at every example, but most
of them probably apply to all 3 templates.
This requires GL 4.00, so it should require GLSL 400 right? Ian?
If this does require 4.00 then you should also test with fp64 data from
builtin_function_fp64.py
On Friday, November 21, 2014 04:37:05 PM Micah Fedke wrote:
> This generated_tests script creates a suite of tests that measure the
> floating point precision of most GLSL built-ins, according to
> ARB_shader_precision. Test vectors come from builtin_function.py, but
> are filtered down to avoid non-float types.
>
> These tests are reporting precision errors in ceil, cross, mod,
> op-assign-div, op-assign-mult, div, mult, reflect and refract on
> Ivybridge.
>
> ---
>
> Updates since the previous RFC (v2):
>
> Addressed comments from Dylan Baker
> - discarded the procedural string concatenation and implemented Mako templates
> Addressed comments from Chris Forbes (off-list)
> - generated files are now placed in generated_tests/spec/arb_shader_precision/
> - updated the description in the generator script
> Additional fixes
> - the conditional that selects the comparison type (multi-value or
> single-value style) was incorrectly including the single-valued
> distance-float-float in the multi-value branch
>
> Concerns about the utility of the test vectors supplied by builtin_function.py
> still remain. I cannot currently see how to add tests to the test_suite dict
> generated by builtin_function.py in a clean manner - one needs to either hammer
> out each test by hand (which is error prone considering the compounding nature
> of the parameters) or gain access to/copy the private generator functions
> within builtin_function.py. builtin_function.py could be turned into a class,
> or it could be modified to accept operators and/or test vectors from an
> external file, however either option threatens to modify something many tests
> rely on, so discussion on this point is welcome.
>
> Note: I am new to the project and don't have commit access.
>
> generated_tests/CMakeLists.txt | 7 +-
> generated_tests/gen_shader_precision_tests.py | 151 ++++++++++++++++++
> generated_tests/shader_precision_templates/fs.mako | 160 +++++++++++++++++++
> generated_tests/shader_precision_templates/gs.mako | 173 +++++++++++++++++++++
> generated_tests/shader_precision_templates/vs.mako | 169 ++++++++++++++++++++
> 5 files changed, 659 insertions(+), 1 deletion(-)
> create mode 100644 generated_tests/gen_shader_precision_tests.py
> create mode 100644 generated_tests/shader_precision_templates/fs.mako
> create mode 100644 generated_tests/shader_precision_templates/gs.mako
> create mode 100644 generated_tests/shader_precision_templates/vs.mako
>
> diff --git a/generated_tests/CMakeLists.txt b/generated_tests/CMakeLists.txt
> index 6d27b3e..3ccf69c 100644
> --- a/generated_tests/CMakeLists.txt
> +++ b/generated_tests/CMakeLists.txt
> @@ -91,6 +91,10 @@ piglit_make_generated_tests(
> constant_array_size_tests_fp64.list
> gen_constant_array_size_tests_fp64.py
> builtin_function_fp64.py)
> +piglit_make_generated_tests(
> + shader_precision_tests.list
> + gen_shader_precision_tests.py
> + builtin_function.py)
The templates should be added as dependencies, no?
>
> # Add a "gen-tests" target that can be used to generate all the
> # tests without doing any other compilation.
> @@ -113,4 +117,5 @@ add_custom_target(gen-tests ALL
> uniform-initializer_tests.list
> interpolation-qualifier-built-in-variable.list
> builtin_uniform_tests_fp64.list
> - constant_array_size_tests_fp64.list)
> + constant_array_size_tests_fp64.list
> + shader_precision_tests.list)
Stray space?
> diff --git a/generated_tests/gen_shader_precision_tests.py b/generated_tests/gen_shader_precision_tests.py
> new file mode 100644
> index 0000000..c93f811
> --- /dev/null
> +++ b/generated_tests/gen_shader_precision_tests.py
> @@ -0,0 +1,151 @@
> +# coding=utf-8
> +#
> +# Copyright © 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 (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.
> +
This should be formatted as a module docstring. Use triple quotes
instead of # comments
> +# Generate a set of shader_runner tests for overloaded versions of every
> +# built-in function specified in arb_shader_precision, based on the test
> +# vectors computed by builtin_function.py, and structured according to the mako
> +# templates in shader_precision_templates/.
> +#
> +# The vertex, geometry, and fragment shader types are exercised by each test.
> +# In all cases, the inputs to the built-in functions come from uniforms, so
> +# that the effectiveness of the test won't be circumvented by constant folding
> +# in the GLSL compiler.
> +#
> +# The tests operate by invoking the built-in function in the appropriate
> +# shader, calculating any deviance from the expected value (in ulps), comparing
> +# the deviance to a supplied tolerance (according to those specified in
> +# arb_shader_precision), and then outputting the pass/fail result as a solid
> +# rgba color which is then checked using shader_runner's "probe rgba" command.
> +#
> +# For built-in functions whose result type is multi-valued (vec or mat), the
> +# tests calculate the error in ulps for each element separately, but compare
> +# only the largest error value to the tolerance. This accounts for cases where
> +# error varies among the elements of a vec or mat result.
> +#
> +# This program outputs, to stdout, the name of each file it generates.
> +
> +from builtin_function import *
> +import mako.template
> +import os
> +import os.path
> +
> +tolerances = {'pow': 16.0,
> + 'exp': 3.0,
> + 'exp2': 3.0,
> + 'log': 3.0,
> + 'log2': 3.0,
> + 'sqrt': 3.0,
> + 'inversesqrt': 2.0}
> +
> +trig_builtins = ('sin', 'cos', 'tan',
> + 'asin', 'acos', 'atan',
> + 'sinh', 'cosh', 'tanh',
> + 'asinh', 'acosh', 'atanh')
> +
> +def make_indexers(signature):
> + """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 signature.rettype.num_cols == 1:
> + col_indexers = ['']
> + else:
> + col_indexers = ['[{0}]'.format(i) for i in xrange(signature.rettype.num_cols)]
> + if signature.rettype.num_rows == 1:
> + row_indexers = ['']
> + else:
> + row_indexers = ['[{0}]'.format(i) for i in xrange(signature.rettype.num_rows)]
> + return [col_indexer + row_indexer
> + for col_indexer in col_indexers for row_indexer in row_indexers]
> +
> +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_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)
> +
> +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 main():
> + """ Main function """
> +
> + for signature, test_vectors in sorted(test_suite.items()):
use iteritems here.
> + arg_float_check = tuple(
> + arg.base_type == glsl_float for arg in signature.argtypes)
> + # Filter the test vectors down to only those which deal exclusively in float types
> + #and are not trig functions or determinant()
> + indexers = make_indexers(signature)
> + num_elements = signature.rettype.num_cols*signature.rettype.num_rows
> + invocation = signature.template.format( *['arg{0}'.format(i)
> + for i in xrange(len(signature.argtypes))])
> + if signature.rettype.base_type == glsl_float and \
> + arg_float_check and \
> + all(arg_float_check) and \
> + signature.name not in trig_builtins and \
> + signature.name != 'determinant':
Use parens instead of \ here
> + for shader_stage in ('vs', 'fs', 'gs'):
stray extra space?
> + input_filename = 'shader_precision_templates/{0}.mako'.format(shader_stage)
> + template = mako.template.Template(filename=input_filename)
> + output_filename = os.path.join( 'spec', 'arb_shader_precision',
> + '{0}-{1}-{2}.shader_test'.format(
> + shader_stage, signature.name,
> + '-'.join(str(argtype)
> + for argtype in signature.argtypes)))
> + print(output_filename)
> + dirname = os.path.dirname(output_filename)
> + if not os.path.exists(dirname):
> + os.makedirs(dirname)
> + with open(output_filename, 'w') as f:
> + f.write(template.render_unicode( signature=signature,
> + test_vectors=test_vectors,
> + tolerances=tolerances,
> + invocation=invocation,
> + num_elements=num_elements,
> + indexers=indexers,
> + shader_runner_type=shader_runner_type,
> + shader_runner_format=shader_runner_format,
> + column_major_values=column_major_values ))
> +
> +if __name__ == "__main__":
> + main()
> diff --git a/generated_tests/shader_precision_templates/fs.mako b/generated_tests/shader_precision_templates/fs.mako
> new file mode 100644
> index 0000000..cf9ff64
> --- /dev/null
> +++ b/generated_tests/shader_precision_templates/fs.mako
> @@ -0,0 +1,160 @@
> +[require]
> +GLSL >= 3.30
> +
> +[vertex shader]
> +attribute vec4 piglit_vertex;
> +void main()
> +{
> + gl_Position = piglit_vertex;
> +}
> +
> +[fragment shader]
> +% if signature.extension:
> +#extension GL_${signature.extension} : require
> +% endif
> +% for i in xrange(len(signature.argtypes)):
The more pythonic way to handle this would be with enumerate
% for i, arg in enumerate(signature.argtypes):
uniform ${arg} arg${i};
% endfor
> +uniform ${signature.argtypes[i]} arg${i};
> +% endfor
> +uniform float tolerance;
> +uniform ${signature.rettype} expected;
> +
> +void main()
> +{
> + ##
> + ## perform the operation being tested
> + ##
> + ${signature.rettype} result = ${invocation};
> + ##
> + ## compare the result(s) to the expected value(s)
> + ##
> + % if signature.rettype.is_matrix or signature.rettype.is_vector:
> + ##
> + ## build an array of bit-level representations of the floating point results calculated above
> + ##
> + int resultbits[${num_elements}] = int[${num_elements}](\
> + % for i, indexer in enumerate(indexers):
> +floatBitsToInt(result${indexer})\
> + ## handle separators, ala python's .join
> + % if i != len(indexers)-1:
> +, \
> + % endif
Honestly I'd just use a join generator here:
${', '.join('floatBitsToInt(result{})'.format(i) for i in indexers)}
I think this is easier to read than the mako with \ escaping, but it's
just a suggestion.
> + % endfor
> +);
> + ##
> + ## build an array of bit-level representations of the passed-in floating point expected results
> + ##
> + int expectedbits[${num_elements}] = int[${num_elements}](\
> + % for i, indexer in enumerate(indexers):
> +floatBitsToInt(expected${indexer})\
> + ## handle separators, ala python's .join
> + % if i != len(indexers)-1:
> +, \
> + % endif
> + % endfor
> +);
> + ##
> + ## check for differences in the sign bit for each result
> + ##
> + bool signerr = \
> + % for i in range(0, num_elements):
xrange
> +(resultbits[${i}]>>31 != expectedbits[${i}]>>31)\
> + ## handle separators, ala python's .join
> + % if i != num_elements-1:
> + || \
> + % endif
> + % endfor
> +;
> + ##
> + ## calculate the difference between the generated value and the expected value in ulps
> + ##
> + ${signature.rettype} ulps = ${signature.rettype}(\
> + % for i in range(0, num_elements):
xrange instead of range
> + % if signature.name != 'distance':
> +distance(resultbits[${i}],expectedbits[${i}])\
> + % else:
> + ## special case - can't use distance() to test distance()
> +abs(resultbits[${i}] - expectedbits[${i}])\
> + % endif
> + ## handle separators, ala python's .join
> + % if i != num_elements-1:
> +, \
> + % endif
> + % endfor
> +);
> + ##
> + ## find the maximum error in ulps of all the calculations using a nested max() sort
> + ##
> + float max_error = \
> + ## start with the outermost max() if there are more than 2 elements
> + ## (two element arrays, eg. vec2, are handled by the final max() below, only)
> + % if num_elements > 2:
> +max( \
> + % endif
> + ## cat each value to compare, with an additional nested max() up until the final two values
> + % for i, indexer in enumerate(indexers[:len(indexers)-2]):
> +ulps${indexer}, \
> + % if i != len(indexers)-3:
> +max(\
> + % endif
> + ## cat the final, deepest, max comparison
> + % endfor
> +max(ulps${indexers[len(indexers)-2]}, ulps${indexers[len(indexers)-1]})\
> + ## fill in completing parens
> + % for i in range(0, num_elements-2):
xrange
> +)\
> + % endfor
> +;
> + % else:
> + ##
> + ## if there is only a single result value generated, compare it directly
> + ##
> + int resultbits = floatBitsToInt(result);
> + int expectedbits = floatBitsToInt(expected);
> + bool signerr = resultbits>>31 != expectedbits>>31;
> + % if signature.name != 'distance':
> + float ulps = distance(resultbits, expectedbits);
> + % else:
> + float ulps = abs(resultbits - expectedbits);
> + % endif
> + % endif
> + ##
> + ## the test passes if there were no sign errors and the ulps are within tolerance
> + ##
> + gl_FragColor = \
> + % if signature.rettype.is_matrix or signature.rettype.is_vector:
> +!signerr && max_error <= tolerance\
> + % else:
> +!signerr && ulps <= tolerance\
> + % endif
> + ? vec4(0.0, 1.0, 0.0, 1.0) : vec4(1.0, 0.0, 0.0, 1.0);
> +}
> +
> +% if signature.version_introduced >= 140:
> +[vertex data]
> +piglit_vertex/float/2
> +-1.0 -1.0
> + 1.0 -1.0
> + 1.0 1.0
> +-1.0 1.0
> +% endif\
> +
> +[test]
> +% for test_num, test_vector in enumerate(test_vectors):
> + % for i in xrange(len(test_vector.arguments)):
> +uniform ${shader_runner_type(signature.argtypes[i])} arg${i} ${shader_runner_format( column_major_values(test_vector.arguments[i]))}
> + % endfor
> +uniform ${shader_runner_type(signature.rettype)} expected ${shader_runner_format(column_major_values(test_vector.result))}
> +uniform float tolerance \
> + % if signature.name in tolerances:
> +${tolerances[signature.name]}
> + % else:
> +0.0
As a suggestion you could use dict.get here:
${tolerances.get(signature.name, 0.0)}
> + % endif
> + % if signature.version_introduced >= 140:
> +draw arrays GL_TRIANGLE_FAN 0 4
> + % else:
> +draw rect -1 -1 2 2
> + % endif
> +## shader_runner uses a 250x250 window so we must ensure that test_num <= 250.
> +probe rgba ${test_num % 250} 0 0.0 1.0 0.0 1.0
> +% endfor
> diff --git a/generated_tests/shader_precision_templates/gs.mako b/generated_tests/shader_precision_templates/gs.mako
> new file mode 100644
> index 0000000..a87186e
> --- /dev/null
> +++ b/generated_tests/shader_precision_templates/gs.mako
> @@ -0,0 +1,173 @@
> +[require]
> +GLSL >= 3.30
> +
> +[vertex shader]
> +in vec4 piglit_vertex;
> +varying vec4 vertex_to_gs;
> +void main()
> +{
> + vertex_to_gs = piglit_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;
> +% for i in xrange(len(signature.argtypes)):
> +uniform ${signature.argtypes[i]} arg${i};
> +% endfor
> +uniform float tolerance;
> +uniform ${signature.rettype} expected;
> +
> +void main()
> +{
> + vec4 tmp_color;
> + ##
> + ## perform the operation being tested
> + ##
> + ${signature.rettype} result = ${invocation};
> + ##
> + ## compare the result(s) to the expected value(s)
> + ##
> + % if signature.rettype.is_matrix or signature.rettype.is_vector:
> + ##
> + ## build an array of bit-level representations of the floating point results calculated above
> + ##
> + int resultbits[${num_elements}] = int[${num_elements}](\
> + % for i, indexer in enumerate(indexers):
> +floatBitsToInt(result${indexer})\
> + ## handle separators, ala python's .join
> + % if i != len(indexers)-1:
> +, \
> + % endif
> + % endfor
> +);
> + ##
> + ## build an array of bit-level representations of the passed-in floating point expected results
> + ##
> + int expectedbits[${num_elements}] = int[${num_elements}](\
> + % for i, indexer in enumerate(indexers):
> +floatBitsToInt(expected${indexer})\
> + ## handle separators, ala python's .join
> + % if i != len(indexers)-1:
> +, \
> + % endif
> + % endfor
> +);
> + ##
> + ## check for differences in the sign bit for each result
> + ##
> + bool signerr = \
> + % for i in range(0, num_elements):
xrange
> +(resultbits[${i}]>>31 != expectedbits[${i}]>>31)\
> + ## handle separators, ala python's .join
> + % if i != num_elements-1:
> + || \
> + % endif
> + % endfor
> +;
> + ##
> + ## calculate the difference between the generated value and the expected value in ulps
> + ##
> + ${signature.rettype} ulps = ${signature.rettype}(\
> + % for i in range(0, num_elements):
xrange
> + % if signature.name != 'distance':
> +distance(resultbits[${i}],expectedbits[${i}])\
> + % else:
> + ## special case - can't use distance() to test distance()
> +abs(resultbits[${i}] - expectedbits[${i}])\
> + % endif
> + ## handle separators, ala python's .join
> + % if i != num_elements-1:
> +, \
> + % endif
> + % endfor
> +);
> + ##
> + ## find the maximum error in ulps of all the calculations using a nested max() sort
> + ##
> + float max_error = \
> + ## start with the outermost max() if there are more than 2 elements
> + ## (two element arrays, eg. vec2, are handled by the final max() below, only)
> + % if num_elements > 2:
> +max( \
> + % endif
> + ## cat each value to compare, with an additional nested max() up until the final two values
> + % for i, indexer in enumerate(indexers[:len(indexers)-2]):
> +ulps${indexer}, \
> + % if i != len(indexers)-3:
> +max(\
> + % endif
> + ## cat the final, deepest, max comparison
> + % endfor
> +max(ulps${indexers[len(indexers)-2]}, ulps${indexers[len(indexers)-1]})\
> + ## fill in completing parens
> + % for i in range(0, num_elements-2):
xrange
> +)\
> + % endfor
> +;
> + % else:
> + ##
> + ## if there is only a single result value generated, compare it directly
> + ##
> + int resultbits = floatBitsToInt(result);
> + int expectedbits = floatBitsToInt(expected);
> + bool signerr = resultbits>>31 != expectedbits>>31;
> + % if signature.name != 'distance':
> + float ulps = distance(resultbits, expectedbits);
> + % else:
> + float ulps = abs(resultbits - expectedbits);
> + % endif
> + % endif
> + ##
> + ## the test passes if there were no sign errors and the ulps are within tolerance
> + ##
> + tmp_color = \
> + % if signature.rettype.is_matrix or signature.rettype.is_vector:
> +!signerr && max_error <= tolerance\
> + % else:
> +!signerr && ulps <= tolerance\
> + % endif
> + ? vec4(0.0, 1.0, 0.0, 1.0) : vec4(1.0, 0.0, 0.0, 1.0);
> + for (int i = 0; i < 3; i++) {
> + gl_Position = vertex_to_gs[i];
> + color = tmp_color;
> + EmitVertex();
> + }
> +}
> +
> +[fragment shader]
> +varying vec4 color;
> +
> +void main()
> +{
> + gl_FragColor = color;
> +}
> +
> +[vertex data]
> +piglit_vertex/float/2
> +-1.0 -1.0
> + 1.0 -1.0
> + 1.0 1.0
> +-1.0 1.0
> +
> +[test]
> +% for test_num, test_vector in enumerate(test_vectors):
> + % for i in xrange(len(test_vector.arguments)):
> +uniform ${shader_runner_type(signature.argtypes[i])} arg${i} ${shader_runner_format( column_major_values(test_vector.arguments[i]))}
> + % endfor
> +uniform ${shader_runner_type(signature.rettype)} expected ${shader_runner_format(column_major_values(test_vector.result))}
> +uniform float tolerance \
> + % if signature.name in tolerances:
> +${tolerances[signature.name]}
> + % else:
> +0.0
> + % endif
> +draw arrays GL_TRIANGLE_FAN 0 4
> +## shader_runner uses a 250x250 window so we must ensure that test_num <= 250.
> +probe rgba ${test_num % 250} 0 0.0 1.0 0.0 1.0
> +% endfor
> diff --git a/generated_tests/shader_precision_templates/vs.mako b/generated_tests/shader_precision_templates/vs.mako
> new file mode 100644
> index 0000000..40558f9
> --- /dev/null
> +++ b/generated_tests/shader_precision_templates/vs.mako
> @@ -0,0 +1,169 @@
> +[require]
> +GLSL >= 3.30
> +
> +[vertex shader]
> +% if signature.extension:
> +#extension GL_${signature.extension} : require
> +% endif
> +% if signature.version_introduced >= 140:
> +in vec4 piglit_vertex;
> +out vec4 color;
> +% else:
> +attribute vec4 piglit_vertex;
> +varying vec4 color;
> +%endif
> +% for i in xrange(len(signature.argtypes)):
> +uniform ${signature.argtypes[i]} arg${i};
> +% endfor
> +uniform float tolerance;
> +uniform ${signature.rettype} expected;
> +
> +void main()
> +{
> + gl_Position = piglit_vertex;
> + ##
> + ## perform the operation being tested
> + ##
> + ${signature.rettype} result = ${invocation};
> + ##
> + ## compare the result(s) to the expected value(s)
> + ##
> + % if signature.rettype.is_matrix or signature.rettype.is_vector:
> + ##
> + ## build an array of bit-level representations of the floating point results calculated above
> + ##
> + int resultbits[${num_elements}] = int[${num_elements}](\
> + % for i, indexer in enumerate(indexers):
> +floatBitsToInt(result${indexer})\
> + ## handle separators, ala python's .join
> + % if i != len(indexers)-1:
> +, \
> + % endif
> + % endfor
> +);
> + ##
> + ## build an array of bit-level representations of the passed-in floating point expected results
> + ##
> + int expectedbits[${num_elements}] = int[${num_elements}](\
> + % for i, indexer in enumerate(indexers):
> +floatBitsToInt(expected${indexer})\
> + ## handle separators, ala python's .join
> + % if i != len(indexers)-1:
> +, \
> + % endif
> + % endfor
> +);
> + ##
> + ## check for differences in the sign bit for each result
> + ##
> + bool signerr = \
> + % for i in range(0, num_elements):
xrange
> +(resultbits[${i}]>>31 != expectedbits[${i}]>>31)\
> + ## handle separators, ala python's .join
> + % if i != num_elements-1:
> + || \
> + % endif
> + % endfor
> +;
> + ##
> + ## calculate the difference between the generated value and the expected value in ulps
> + ##
> + ${signature.rettype} ulps = ${signature.rettype}(\
> + % for i in range(0, num_elements):
xrange
> + % if signature.name != 'distance':
> +distance(resultbits[${i}],expectedbits[${i}])\
> + % else:
> + ## special case - can't use distance() to test distance()
> +abs(resultbits[${i}] - expectedbits[${i}])\
> + % endif
> + ## handle separators, ala python's .join
> + % if i != num_elements-1:
> +, \
> + % endif
> + % endfor
> +);
> + ##
> + ## find the maximum error in ulps of all the calculations using a nested max() sort
> + ##
> + float max_error = \
> + ## start with the outermost max() if there are more than 2 elements
> + ## (two element arrays, eg. vec2, are handled by the final max() below, only)
> + % if num_elements > 2:
> +max( \
> + % endif
> + ## cat each value to compare, with an additional nested max() up until the final two values
> + % for i, indexer in enumerate(indexers[:len(indexers)-2]):
> +ulps${indexer}, \
> + % if i != len(indexers)-3:
> +max(\
> + % endif
> + ## cat the final, deepest, max comparison
> + % endfor
> +max(ulps${indexers[len(indexers)-2]}, ulps${indexers[len(indexers)-1]})\
> + ## fill in completing parens
> + % for i in range(0, num_elements-2):
xrange
> +)\
> + % endfor
> +;
> + % else:
> + ##
> + ## if there is only a single result value generated, compare it directly
> + ##
> + int resultbits = floatBitsToInt(result);
> + int expectedbits = floatBitsToInt(expected);
> + bool signerr = resultbits>>31 != expectedbits>>31;
> + % if signature.name != 'distance':
> + float ulps = distance(resultbits, expectedbits);
> + % else:
> + float ulps = abs(resultbits - expectedbits);
> + % endif
> + % endif
> + ##
> + ## the test passes if there were no sign errors and the ulps are within tolerance
> + ##
> + color = \
> + % if signature.rettype.is_matrix or signature.rettype.is_vector:
> +!signerr && max_error <= tolerance\
> + % else:
> +!signerr && ulps <= tolerance\
> + % endif
> + ? vec4(0.0, 1.0, 0.0, 1.0) : vec4(1.0, 0.0, 0.0, 1.0);
> +}
> +
> +[fragment shader]
> +varying vec4 color;
> +
> +void main()
> +{
> + gl_FragColor = color;
> +}
> +
> +% if signature.version_introduced >= 140:
> +[vertex data]
> +piglit_vertex/float/2
> +-1.0 -1.0
> + 1.0 -1.0
> + 1.0 1.0
> +-1.0 1.0
> +% endif\
> +
> +[test]
> +% for test_num, test_vector in enumerate(test_vectors):
> + % for i in xrange(len(test_vector.arguments)):
> +uniform ${shader_runner_type(signature.argtypes[i])} arg${i} ${shader_runner_format( column_major_values(test_vector.arguments[i]))}
> + % endfor
> +uniform ${shader_runner_type(signature.rettype)} expected ${shader_runner_format(column_major_values(test_vector.result))}
> +uniform float tolerance \
> + % if signature.name in tolerances:
> +${tolerances[signature.name]}
> + % else:
> +0.0
> + % endif
> + % if signature.version_introduced >= 140:
> +draw arrays GL_TRIANGLE_FAN 0 4
> + % else:
> +draw rect -1 -1 2 2
> + % endif
> +## shader_runner uses a 250x250 window so we must ensure that test_num <= 250.
> +probe rgba ${test_num % 250} 0 0.0 1.0 0.0 1.0
> +% endfor
> --
> 2.1.2
>
> _______________________________________________
> Piglit mailing list
> Piglit at lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/piglit
>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 473 bytes
Desc: This is a digitally signed message part.
URL: <http://lists.freedesktop.org/archives/piglit/attachments/20141121/4b912387/attachment-0001.sig>
More information about the Piglit
mailing list