[Piglit] [PATCH v5 2/3] arb_shader_precision: add framework for calculating tolerances for complex functions
Dylan Baker
baker.dylan.c at gmail.com
Mon Apr 6 17:02:28 PDT 2015
On Mon, Apr 06, 2015 at 05:00:33PM -0500, Micah Fedke wrote:
> Ilia,
>
> All comments thus far addressed here:
> http://cgit.collabora.com/git/user/fedke.m/piglit.git/log/?h=complex_tolerances_straight_comments1
>
> Yeah, Mako is really hard to read. I couldn't find much for Mako style
> guides online, but I tried to keep a common indent scheme for all Mako
> (%) lines. Lines of content, however, have to be indented according to
> how they will appear after rendering the template, which makes the
> template look very messy.
Have a look at filters and blocks. You can make code look *much* better
with a few simple filter functions.
>
>
> -mf
>
> On 04/03/2015 04:31 PM, Ilia Mirkin wrote:
> > On Fri, Apr 3, 2015 at 5:00 PM, Micah Fedke <micah.fedke at collabora.co.uk> wrote:
> >> - update mako templates to support vectors of tolerances
> >>
> >> ---
> >> generated_tests/gen_shader_precision_tests.py | 138 +++++++++++++++++----
> >> .../templates/gen_shader_precision_tests/fs.mako | 62 +++++----
> >> .../templates/gen_shader_precision_tests/gs.mako | 55 ++++----
> >> .../templates/gen_shader_precision_tests/vs.mako | 55 ++++----
> >> 4 files changed, 217 insertions(+), 93 deletions(-)
> >>
> >> diff --git a/generated_tests/gen_shader_precision_tests.py b/generated_tests/gen_shader_precision_tests.py
> >> index 6c011a3..bef1459 100644
> >> --- a/generated_tests/gen_shader_precision_tests.py
> >> +++ b/generated_tests/gen_shader_precision_tests.py
> >> @@ -25,7 +25,7 @@
> >> """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/.
> >> + templates in templates/gen_shader_precision_tests.
> >>
> >> 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
> >> @@ -43,20 +43,26 @@
> >> 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 updates the tolerance values in the test vectors with tolerances
> >> + sourced from the GLSL spec (v4.5) and adds a few new tests as well.
> >> +
> >> This program outputs, to stdout, the name of each file it generates.
> >> """
> >>
> >> from __future__ import print_function, division, absolute_import
> >> from builtin_function import *
> >> -import os
> >> +import os
> >> import numpy
> >> +import struct
> >>
> >> import six
> >> from six.moves import range
> >>
> >> from templates import template_file
> >>
> >> -tolerances = {'pow': 16.0,
> >> +
> >> +
> >> +tolerances = {'pow': 16.0,
> >> 'exp': 3.0,
> >> 'exp2': 3.0,
> >> 'log': 3.0,
> >> @@ -67,14 +73,87 @@ tolerances = {'pow': 16.0,
> >> 'op-assign-div': 2.5,
> >> }
> >>
> >> -trig_builtins = ('sin', 'cos', 'tan',
> >> - 'asin', 'acos', 'atan',
> >> - 'sinh', 'cosh', 'tanh',
> >> - 'asinh', 'acosh', 'atanh')
> >> +shader_precision_spec_fns = ('op-add', 'op-assign-add',
> >> + 'op-sub', 'op-assign-sub',
> >> + 'op-mult', 'op-assign-mult',
> >> + 'op-div', 'op-assign-div',
> >> + 'degrees', 'radians',
> >> + 'pow',
> >> + 'exp',
> >> + 'exp2',
> >> + 'log', 'log2',
> >> + 'sqrt', 'inversesqrt')
> >>
> >> def _is_sequence(arg):
> >> return isinstance(arg, (collections.Sequence, numpy.ndarray))
> >>
> >> +# The precision for log and log2 from the GLSL spec:
> >> +# 3 ULP outside the range [0.5, 2.0].
> >> +# Absolute error < 2^-21 inside the range [0.5, 2.0].
> >> +def _log_tol(arg):
> >> + if arg < 0.5 or arg > 2.0:
> >> + return 3.0
> >> + elif arg >= 0.5 and arg < 1.0:
> >> + # in the range [0.5, 1.0), one ulp is 5.960464478e-08,
> >> + # so 2^-21 is 8 ulps
> >> + return 8.0
> >> + else:
> >> + # in the range [1.0, 2.0), one ulp is 1.192092896e-07,
> >> + # so 2^-21 is 4 ulps
> >> + return 4.0
> >> +
> >> +# The precision for exp and exp2 from the GLSL spec:
> >> +# (3 + 2 * |x|) ULP.
> >> +def _exp_tol(arg):
> >> + return 3.0 + 2.0 * abs(arg)
> >> +
> >> +def _gen_tolerance(name, rettype, args, expected):
> >> + ret = []
> >> + compcnt = rettype.num_cols * rettype.num_rows
> >> +
> >> + for j in range(rettype.num_cols):
> >> + for i in range(rettype.num_rows):
> >> + # The precision for add, sub and mult from the GLSL spec:
> >> + # Correctly rounded.
> >> + if name in ('op-add', 'op-assign-add', 'op-sub', 'op-assign-sub', 'op-mult', 'op-assign-mult'):
> >> + ret.append(0.0)
> >> + # The precision for division from the GLSL spec:
> >> + # 2.5 ULP for b in the range [2^-126, 2^126].
> >> + elif name in ('op-div', 'op-assign-div'):
> >> + divisor = args[1][i] if _is_sequence(args[1]) else args[1]
> >> + if (divisor >= pow(2,-126) and divisor <= pow(2,126)) or \
> >> + (divisor <= -pow(2,-126) and divisor >= -pow(2,126)):
> >> + ret.append(2.5)
> >> + else:
> >> + return -1.0
> >
> > Please stick this logic into a function. (BTW, what does a -1
> > tolerance mean here? Can you just assert? Also this function is
> > supposed to return an array... not a integer.)
> >
> > Then this whole function can be expressed as a table of like
> >
> > foo = {
> > 'op-add': (lambda args, i, j: 0),
> > 'exp': (lambda args, i, j: _exp_tol(args[j][i] if ... ) ),
> >
> > etc.
> >
> >> + # The precision for degrees and radians from the GLSL spec:
> >> + # Inherited from division
> >> + # denominator (pi or 180, respectively) is always within [2^-126, 2^126]
> >> + elif name in ('degrees', 'radians'):
> >> + ret.append(2.5)
> >> + # The precision for pow from the GLSL spec:
> >> + # Inherited from exp2 (x * log2 (y)).
> >> + elif name is 'pow':
> >> + x = args[0][i] if _is_sequence(args[0]) else args[0]
> >> + y = args[1][i] if _is_sequence(args[1]) else args[1]
> >> + ret.append(_exp_tol(x * _log_tol(y)))
> >> + elif name in ('exp', 'exp2'):
> >> + ret.append(_exp_tol(args[j][i] if compcnt > 1 else args[0]))
> >> + elif name in ('log', 'log2'):
> >> + ret.append(_log_tol(args[j][i] if compcnt > 1 else args[0]))
> >> + # The precision for sqrt from the GLSL spec:
> >> + # Inherited from 1.0 / inversesqrt().
> >> + elif name is 'sqrt':
> >> + ret.append(2.5)
> >> + # The precision for inversesqrt from the GLSL spec:
> >> + # 2 ULP.
> >> + elif name is 'inversesqrt':
> >> + ret.append(2.0)
> >> + else:
> >
> > assert False
> >
> >> + return -1.0
> >> +
> >> + return ret
> >> +
> >> 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,
> >> @@ -88,7 +167,7 @@ def make_indexers(signature):
> >> row_indexers = ['']
> >> else:
> >> row_indexers = ['[{0}]'.format(i) for i in range(signature.rettype.num_rows)]
> >> - return [col_indexer + row_indexer
> >> + return [col_indexer + row_indexer
> >> for col_indexer in col_indexers for row_indexer in row_indexers]
> >>
> >> def shader_runner_type(glsl_type):
> >> @@ -116,7 +195,7 @@ def shader_runner_format(values):
> >> retval = ''
> >> for x in values:
> >> assert isinstance(x, (float, np.float32))
> >> - retval+=' {0:1.8e}'.format(x)
> >> + retval += ' {0:1.8e}'.format(x)
> >> else:
> >> assert isinstance(values, (float, np.float32))
> >> retval = '{0:1.8e}'.format(values)
> >> @@ -128,34 +207,45 @@ def main():
> >> """ Main function """
> >>
> >> for signature, test_vectors in sorted(six.iteritems(test_suite)):
> >
> > Can't say I understand why these have to be sorted...
> >
> >> - 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 range(len(signature.argtypes))])
> >> + arg_float_check = tuple(arg.base_type == glsl_float for arg in signature.argtypes)
> >> + arg_mat_check = tuple(arg.is_matrix for arg in signature.argtypes)
> >> + # Filter the test vectors down to only those which deal exclusively in
> >> + # non-matrix float types and are specified in the spec
> >> if (signature.rettype.base_type == glsl_float and
> >> arg_float_check and
> >> all(arg_float_check) and
> >
> > Why are you checking whether arg_float_check is empty explicitly? When
> > would it be empty?
> >
> >> - signature.name not in trig_builtins and
> >> - signature.name != 'determinant'):
> >> + signature.name in shader_precision_spec_fns and
> >> + arg_mat_check and
> >> + (not True in arg_mat_check)):
> >
> > True not in arg_mat_check. Or even better, any(arg_mat_check). Which
> > you can do above as
> >
> > any(arg.is_matrix for arg in ... )
> >
> >> + # replace the tolerances in each test_vector with
> >> + # our own tolerances specified in ulps
> >> + refined_test_vectors = []
> >> + complex_tol_type = signature.rettype
> >> + for test_vector in test_vectors:
> >> + tolerance = _gen_tolerance(signature.name, signature.rettype, test_vector.arguments, test_vector.result)
> >> + if tolerance != -1.0:
> >
> > Is this still needed? Can it return -1 in a real situation?
> >
> >> + refined_test_vectors.append(TestVector(test_vector.arguments, test_vector.result, tolerance))
> >> + # Then generate the shader_test scripts
> >> for shader_stage in ('vs', 'fs', 'gs'):
> >> template = template_file('gen_shader_precision_tests', '{0}.mako'.format(shader_stage))
> >> output_filename = os.path.join( 'spec', 'arb_shader_precision',
> >> '{0}-{1}-{2}.shader_test'.format(
> >> - shader_stage, signature.name,
> >> - '-'.join(str(argtype)
> >> + 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)
> >> + 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 range(len(signature.argtypes))])
> >> with open(output_filename, 'w') as f:
> >> - f.write(template.render_unicode( signature=signature,
> >> - test_vectors=test_vectors,
> >> - tolerances=tolerances,
> >> + f.write(template.render_unicode( signature=signature,
> >> + is_complex_tolerance=_is_sequence(tolerance),
> >> + complex_tol_type=signature.rettype,
> >> + test_vectors=refined_test_vectors,
> >> invocation=invocation,
> >> num_elements=num_elements,
> >> indexers=indexers,
> >> diff --git a/generated_tests/templates/gen_shader_precision_tests/fs.mako b/generated_tests/templates/gen_shader_precision_tests/fs.mako
> >> index 19ec737..7e97b7e 100644
> >> --- a/generated_tests/templates/gen_shader_precision_tests/fs.mako
> >> +++ b/generated_tests/templates/gen_shader_precision_tests/fs.mako
> >> @@ -4,12 +4,7 @@
> >> [require]
> >> GLSL >= 4.00
> >>
> >> -[vertex shader]
> >> -in vec4 piglit_vertex;
> >> -void main()
> >> -{
> >> - gl_Position = piglit_vertex;
> >> -}
> >> +[vertex shader passthrough]
> >>
> >> [fragment shader]
> >> #extension GL_ARB_shader_precision : require
> >> @@ -19,7 +14,11 @@ void main()
> >> % for i, arg in enumerate(signature.argtypes):
> >> uniform ${arg} arg${i};
> >> % endfor
> >> +% if is_complex_tolerance and complex_tol_type.name != 'float':
> >> +uniform ${complex_tol_type} tolerance;
> >> +% else:
> >> uniform float tolerance;
> >> +% endif
> >
> > Uhm... I'm confused. Why not just always feed the type in here and kill the if?
> >
> >> uniform ${signature.rettype} expected;
> >>
> >
> > Bleh. Not your fault, but the diff below is totally unreadable. I'll
> > have to pull it up in some other format. But I think the above
> > comments should be enough for now.
> >
> >> void main()
> >> @@ -56,29 +55,34 @@ ${' || '.join('(resultbits[{0}]>>31 != expectedbits[{0}]>>31)'.format(i) for i i
> >> ${signature.rettype} ulps = ${signature.rettype}(\
> >> ${', '.join('abs(resultbits[{0}] - expectedbits[{0}])'.format(i) for i in range(0, num_elements))}\
> >> );
> >> - ##
> >> - ## find the maximum error in ulps of all the calculations using a nested max() sort
> >> - ##
> >> + % if is_complex_tolerance and complex_tol_type.name != 'float':
> >> + ## compare vecs directly, use a boolean version of the rettype
> >> + b${signature.rettype} calcerr = greaterThan(ulps, tolerance);
> >> + % else:
> >> + ##
> >> + ## 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:
> >> + ## 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]):
> >> + % 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:
> >> + % if i != len(indexers)-3:
> >> max(\
> >> - % endif
> >> - ## cat the final, deepest, max comparison
> >> - % endfor
> >> + % 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):
> >> + ## fill in completing parens
> >> + % for i in range(0, num_elements-2):
> >> )\
> >> - % endfor
> >> + % endfor
> >> ;
> >> + %endif
> >> % else:
> >> ##
> >> ## if there is only a single result value generated, compare it directly
> >> @@ -86,18 +90,18 @@ max(ulps${indexers[len(indexers)-2]}, ulps${indexers[len(indexers)-1]})\
> >> 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:
> >> + % if is_complex_tolerance and complex_tol_type.name != 'float':
> >> +!signerr && !any(calcerr)\
> >> + % else:
> >> !signerr && max_error <= tolerance\
> >> + % endif
> >> % else:
> >> !signerr && ulps <= tolerance\
> >> % endif
> >> @@ -117,8 +121,12 @@ piglit_vertex/float/2
> >> 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))}
> >> +% if is_complex_tolerance and complex_tol_type.name != 'float':
> >> +uniform ${shader_runner_type(complex_tol_type)} tolerance \
> >> +% else:
> >> uniform float tolerance \
> >> -${tolerances.get(signature.name, 0.0)}
> >> +% endif
> >> +${shader_runner_format(test_vector.tolerance)}
> >> 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
> >> diff --git a/generated_tests/templates/gen_shader_precision_tests/gs.mako b/generated_tests/templates/gen_shader_precision_tests/gs.mako
> >> index de4a3c8..3a76e9b 100644
> >> --- a/generated_tests/templates/gen_shader_precision_tests/gs.mako
> >> +++ b/generated_tests/templates/gen_shader_precision_tests/gs.mako
> >> @@ -24,7 +24,11 @@ flat out vec4 color;
> >> % for i, arg in enumerate(signature.argtypes):
> >> uniform ${arg} arg${i};
> >> % endfor
> >> +% if is_complex_tolerance and complex_tol_type.name != 'float':
> >> +uniform ${complex_tol_type} tolerance;
> >> +% else:
> >> uniform float tolerance;
> >> +% endif
> >> uniform ${signature.rettype} expected;
> >>
> >> void main()
> >> @@ -62,29 +66,34 @@ ${' || '.join('(resultbits[{0}]>>31 != expectedbits[{0}]>>31)'.format(i) for i i
> >> ${signature.rettype} ulps = ${signature.rettype}(\
> >> ${', '.join('abs(resultbits[{0}] - expectedbits[{0}])'.format(i) for i in range(0, num_elements))}\
> >> );
> >> - ##
> >> - ## find the maximum error in ulps of all the calculations using a nested max() sort
> >> - ##
> >> + % if is_complex_tolerance and complex_tol_type.name != 'float':
> >> + ## compare vecs directly, use a boolean version of the rettype
> >> + b${signature.rettype} calcerr = greaterThan(ulps, tolerance);
> >> + % else:
> >> + ##
> >> + ## 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:
> >> + ## 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]):
> >> + % 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:
> >> + % if i != len(indexers)-3:
> >> max(\
> >> - % endif
> >> - ## cat the final, deepest, max comparison
> >> - % endfor
> >> + % 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):
> >> + ## fill in completing parens
> >> + % for i in range(0, num_elements-2):
> >> )\
> >> - % endfor
> >> + % endfor
> >> ;
> >> + %endif
> >> % else:
> >> ##
> >> ## if there is only a single result value generated, compare it directly
> >> @@ -92,18 +101,18 @@ max(ulps${indexers[len(indexers)-2]}, ulps${indexers[len(indexers)-1]})\
> >> 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:
> >> + % if is_complex_tolerance and complex_tol_type.name != 'float':
> >> +!signerr && !any(calcerr)\
> >> + % else:
> >> !signerr && max_error <= tolerance\
> >> + % endif
> >> % else:
> >> !signerr && ulps <= tolerance\
> >> % endif
> >> @@ -136,8 +145,12 @@ piglit_vertex/float/2
> >> 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))}
> >> +% if is_complex_tolerance and complex_tol_type.name != 'float':
> >> +uniform ${shader_runner_type(complex_tol_type)} tolerance \
> >> +% else:
> >> uniform float tolerance \
> >> -${tolerances.get(signature.name, 0.0)}
> >> +% endif
> >> +${shader_runner_format(test_vector.tolerance)}
> >> 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
> >> diff --git a/generated_tests/templates/gen_shader_precision_tests/vs.mako b/generated_tests/templates/gen_shader_precision_tests/vs.mako
> >> index 8d8fad6..d64effd 100644
> >> --- a/generated_tests/templates/gen_shader_precision_tests/vs.mako
> >> +++ b/generated_tests/templates/gen_shader_precision_tests/vs.mako
> >> @@ -14,7 +14,11 @@ flat out vec4 color;
> >> % for i, arg in enumerate(signature.argtypes):
> >> uniform ${arg} arg${i};
> >> % endfor
> >> +% if is_complex_tolerance and complex_tol_type.name != 'float':
> >> +uniform ${complex_tol_type} tolerance;
> >> +% else:
> >> uniform float tolerance;
> >> +% endif
> >> uniform ${signature.rettype} expected;
> >>
> >> void main()
> >> @@ -52,29 +56,34 @@ ${' || '.join('(resultbits[{0}]>>31 != expectedbits[{0}]>>31)'.format(i) for i i
> >> ${signature.rettype} ulps = ${signature.rettype}(\
> >> ${', '.join('abs(resultbits[{0}] - expectedbits[{0}])'.format(i) for i in range(0, num_elements))}\
> >> );
> >> - ##
> >> - ## find the maximum error in ulps of all the calculations using a nested max() sort
> >> - ##
> >> + % if is_complex_tolerance and complex_tol_type.name != 'float':
> >> + ## compare vecs directly, use a boolean version of the rettype
> >> + b${signature.rettype} calcerr = greaterThan(ulps, tolerance);
> >> + % else:
> >> + ##
> >> + ## 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:
> >> + ## 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]):
> >> + % 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:
> >> + % if i != len(indexers)-3:
> >> max(\
> >> - % endif
> >> - ## cat the final, deepest, max comparison
> >> - % endfor
> >> + % 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):
> >> + ## fill in completing parens
> >> + % for i in range(0, num_elements-2):
> >> )\
> >> - % endfor
> >> + % endfor
> >> ;
> >> + %endif
> >> % else:
> >> ##
> >> ## if there is only a single result value generated, compare it directly
> >> @@ -82,18 +91,18 @@ max(ulps${indexers[len(indexers)-2]}, ulps${indexers[len(indexers)-1]})\
> >> 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:
> >> + % if is_complex_tolerance and complex_tol_type.name != 'float':
> >> +!signerr && !any(calcerr)\
> >> + % else:
> >> !signerr && max_error <= tolerance\
> >> + % endif
> >> % else:
> >> !signerr && ulps <= tolerance\
> >> % endif
> >> @@ -121,8 +130,12 @@ piglit_vertex/float/2
> >> 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))}
> >> +% if is_complex_tolerance and complex_tol_type.name != 'float':
> >> +uniform ${shader_runner_type(complex_tol_type)} tolerance \
> >> +% else:
> >> uniform float tolerance \
> >> -${tolerances.get(signature.name, 0.0)}
> >> +% endif
> >> +${shader_runner_format(test_vector.tolerance)}
> >> 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
> >> --
> >> 2.3.5
> >>
> >> _______________________________________________
> >> Piglit mailing list
> >> Piglit at lists.freedesktop.org
> >> http://lists.freedesktop.org/mailman/listinfo/piglit
>
> --
>
> Micah Fedke
> Collabora Ltd.
> +44 1223 362967
> https://www.collabora.com/
> https://twitter.com/collaboraltd
> _______________________________________________
> 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: Digital signature
URL: <http://lists.freedesktop.org/archives/piglit/attachments/20150406/b51eaec5/attachment-0001.sig>
More information about the Piglit
mailing list