[Piglit] [PATCH v5 2/3] arb_shader_precision: add framework for calculating tolerances for complex functions

Micah Fedke micah.fedke at collabora.co.uk
Mon Apr 6 15:00:33 PDT 2015


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.


-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


More information about the Piglit mailing list