[Piglit] [PATCH 1/2] arb_shader_bit_encoding: Add test generator.
Ian Romanick
idr at freedesktop.org
Thu Aug 8 11:28:26 PDT 2013
On 08/07/2013 05:52 PM, Matt Turner wrote:
> On Wed, Aug 7, 2013 at 5:36 PM, Ian Romanick <idr at freedesktop.org> wrote:
>> On 08/06/2013 09:40 PM, Matt Turner wrote:
>>>
>>> Generates fragment and vertex shader execution tests for the built-in
>>> functions floatBitsToInt(), floatBitsToUint(), intBitsToFloat(), and
>>> uintBitsToFloat().
>>>
>>> Functions are tested under
>>> GLSL 1.30 + ARB_shader_bit_encoding
>>> GLSL 1.50 + ARB_gpu_shader5
>>> GLSL 4.00
>>
>>
>> Both ARB_shader_bit_encoding and ARB_gpu_shader5 add the same functions.
>> ARB_gpu_shader5 requires GLSL 1.50 (so sayeth the spec), and
>> ARB_shader_bit_encoding has no requirement (but it uses uint, so it must
>> need at least GLSL 1.30). Right?
>
> Yes, exactly. Worth me documenting in the commit message?
It can't hurt.
>> And, of course, ARB_gpu_shader5 is part of GLSL 4.00.
>>
>>
>>> ---
>>> generated_tests/CMakeLists.txt | 4 +
>>> generated_tests/gen_shader_bit_encoding_tests.py | 234
>>> +++++++++++++++++++++++
>>> 2 files changed, 238 insertions(+)
>>> create mode 100644 generated_tests/gen_shader_bit_encoding_tests.py
>>>
>>> diff --git a/generated_tests/CMakeLists.txt
>>> b/generated_tests/CMakeLists.txt
>>> index db3734f..8c0bc02 100644
>>> --- a/generated_tests/CMakeLists.txt
>>> +++ b/generated_tests/CMakeLists.txt
>>> @@ -40,6 +40,9 @@ piglit_make_generated_tests(
>>> texture_query_lod_tests.list
>>> gen_texture_query_lod_tests.py)
>>> piglit_make_generated_tests(
>>> + shader_bit_encoding_tests.list
>>> + gen_shader_bit_encoding_tests.py)
>>> +piglit_make_generated_tests(
>>> uniform-initializer_tests.list
>>> gen_uniform_initializer_tests.py
>>> uniform-initializer-templates/fs-initializer.template
>>> @@ -65,4 +68,5 @@ add_custom_target(gen-tests ALL
>>> interpolation_tests.list
>>> non-lvalue_tests.list
>>> texture_query_lod_tests.list
>>> + shader_bit_encoding_tests.list
>>> uniform-initializer_tests.list)
>>> diff --git a/generated_tests/gen_shader_bit_encoding_tests.py
>>> b/generated_tests/gen_shader_bit_encoding_tests.py
>>> new file mode 100644
>>> index 0000000..a6ff674
>>> --- /dev/null
>>> +++ b/generated_tests/gen_shader_bit_encoding_tests.py
>>> @@ -0,0 +1,234 @@
>>> +#!/usr/bin/env python2
>>> +# coding=utf-8
>>> +#
>>> +# Copyright © 2013 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.
>>> +
>>> +import struct
>>> +import os
>>> +import os.path
>>> +from mako.template import Template
>>> +from textwrap import dedent
>>> +
>>> +def floatBitsToInt(f):
>>> + return struct.unpack('i', struct.pack('f', f))[0]
>>> +
>>> +def floatBitsToUint(f):
>>> + return struct.unpack('I', struct.pack('f', f))[0]
>>> +
>>> +def intBitsToFloat(i):
>>> + return struct.unpack('f', struct.pack('i', i))[0]
>>> +
>>> +def uintBitsToFloat(u):
>>> + return struct.unpack('f', struct.pack('I', u))[0]
>>> +
>>> +def passthrough(f):
>>> + return f
>>> +
>>> +def vec4(f):
>>> + return [f, f, f, f]
>>> +
>>> +test_data = {
>>> + # Interesting floating-point inputs
>>> + 'mixed': (2.0, 9.5, -4.5, -25.0),
>>> + '0.0': vec4( 0.0), # int 0
>>> + '-0.0': vec4(-0.0), # INT_MIN
>>> + '1.0': vec4( 1.0),
>>> + '-1.0': vec4(-1.0),
>>> + 'subnormal smallest': vec4( 1.401298e-45),
>>> + 'subnormal smallest negative': vec4(-1.401298e-45),
>>> + 'subnormal middle': vec4( 5.877472e-39),
>>> + 'subnormal middle negative': vec4(-5.877472e-39),
>>> + 'subnormal largest': vec4( 1.1754942e-38),
>>> + 'subnormal largest negative': vec4(-1.1754942e-38),
>>> + 'normalized smallest': vec4( 1.1754941e-38),
>>> + 'normalized smallest negative': vec4(-1.1754941e-38),
>>> + 'normalized largest': vec4( 3.4028235e+38),
>>> + 'normalized largest negative': vec4(-3.4028235e+38)
>>> +
>>> + # Don't test +inf or -inf, since we don't have a way to pass them via
>>> + # shader_runner [test] sections. Don't test NaN, since it has many
>>> + # representations.
>>
>>
>> Is it worth also testing some cases of 'x ==
>> intBitsToFloat(floatBitsToInt(x))' and similar? This may require doing one
>> of the functions in the vertex shader and the other in the fragment
>> shader...
>
> Not a bad idea. I'm not sure if I can do that in a nice way in this
> generator. I'd like to do that either in a separate generator, or at
> least as a follow-on patch.
Yeah, looking at the structure of this generator, it would probably be
cleaner that way. I await the follow-on. :)
>>> +}
>>> +
>>> +funcs = {
>>> + 'floatBitsToInt': {
>>> + 'in_func': passthrough,
>>> + 'out_func': floatBitsToInt,
>>> + 'input': 'vec4',
>>> + 'output': 'ivec4'
>>> + },
>>> + 'floatBitsToUint': {
>>> + 'in_func': passthrough,
>>> + 'out_func': floatBitsToUint,
>>> + 'input': 'vec4',
>>> + 'output': 'uvec4'
>>> + },
>>> + 'intBitsToFloat': {
>>> + 'in_func': floatBitsToInt,
>>> + 'out_func': passthrough,
>>> + 'input': 'ivec4',
>>> + 'output': 'vec4'
>>> + },
>>> + 'uintBitsToFloat': {
>>> + 'in_func': floatBitsToUint,
>>> + 'out_func': passthrough,
>>> + 'input': 'uvec4',
>>> + 'output': 'vec4'
>>> + }
>>> +}
>>> +
>>> +requirements = {
>>> + 'ARB_shader_bit_encoding': {
>>> + 'version': '1.30',
>>> + 'extension': 'GL_ARB_shader_bit_encoding'
>>> + },
>>> + 'ARB_gpu_shader5': {
>>> + 'version': '1.50',
>>> + 'extension': 'GL_ARB_gpu_shader5'
>>> + },
>>> + 'glsl-4.00': {
>>> + 'version': '4.00',
>>> + 'extension': ''
>>> + }
>>> +}
>>> +
>>> +template = Template(dedent("""\
>>> + [require]
>>> + GLSL >= ${version}
>>> + % for extension in extensions:
>>> + ${extension}
>>> + % endfor
>>> +
>>> + [vertex shader]
>>> + % if execution_stage == 'vs':
>>> + % for extension in extensions:
>>> + #extension ${extension}: enable
>>> + % endfor
>>> +
>>> + uniform ${input_type} given;
>>> + uniform ${output_type} expected;
>>> + out vec4 color;
>>> + % endif
>>> +
>>> + in vec4 vertex;
>>> +
>>> + void main() {
>>> + gl_Position = vertex;
>>> +
>>> + % if execution_stage == 'vs':
>>> + color = vec4(0.0, 1.0, 0.0, 1.0);
>>> +
>>> + if (expected.x != ${func}(given.x))
>>> + color.r = 1.0;
>>> + if (expected.xy != ${func}(given.xy))
>>> + color.r = 1.0;
>>> + if (expected.xyz != ${func}(given.xyz))
>>> + color.r = 1.0;
>>> + if (expected != ${func}(given))
>>> + color.r = 1.0;
>>> + % endif
>>> + }
>>> +
>>> + [fragment shader]
>>> + % if execution_stage == 'fs':
>>> + % for extension in extensions:
>>> + #extension ${extension}: enable
>>> + % endfor
>>> +
>>> + uniform ${input_type} given;
>>> + uniform ${output_type} expected;
>>> + % else:
>>> + in vec4 color;
>>> + % endif
>>> +
>>> + out vec4 frag_color;
>>> +
>>> + void main() {
>>> + % if execution_stage == 'fs':
>>> + frag_color = vec4(0.0, 1.0, 0.0, 1.0);
>>> +
>>> + if (expected.x != ${func}(given.x))
>>> + frag_color.r = 1.0;
>>> + if (expected.xy != ${func}(given.xy))
>>> + frag_color.r = 1.0;
>>> + if (expected.xyz != ${func}(given.xyz))
>>> + frag_color.r = 1.0;
>>> + if (expected != ${func}(given))
>>> + frag_color.r = 1.0;
>>> + % else:
>>> + frag_color = color;
>>> + % endif
>>> + }
>>> +
>>> + [vertex data]
>>> + vertex/float/2
>>> + -1.0 -1.0
>>> + 1.0 -1.0
>>> + 1.0 1.0
>>> + -1.0 1.0
>>> +
>>> + [test]
>>> + % for name, data in test_data.iteritems():
>>> +
>>> + # ${name}
>>> + uniform ${input_type} given ${' '.join(str(in_func(d)) for d in
>>> data)}
>>> + uniform ${output_type} expected ${' '.join(str(out_func(d)) for d in
>>> data)}
>>> + draw arrays GL_TRIANGLE_FAN 0 4
>>> + probe all rgba 0.0 1.0 0.0 1.0
>>
>>
>> Why do this instead of just 'draw rect -1 -1 2 2'?
>
> Copy-n-paste. That is better. Thanks.
Okay. With that,
Reviewed-by: Ian Romanick <ian.d.romanick at intel.com>
>>> + % endfor
>>> +"""))
>>> +
>>> +for api, requirement in requirements.iteritems():
>>> + version = requirement['version']
>>> + extensions = [requirement['extension']] if requirement['extension']
>>> else []
>>> +
>>> + for func, attrib in funcs.iteritems():
>>> + in_func = attrib['in_func']
>>> + out_func = attrib['out_func']
>>> + input_type = attrib['input']
>>> + output_type = attrib['output']
>>> +
>>> + for execution_stage in ('vs', 'fs'):
>>> + file_extension = 'frag' if execution_stage == 'fs' else
>>> 'vert'
>>> + filename = os.path.join('spec',
>>> + api,
>>> + 'execution',
>>> + 'built-in-functions',
>>> +
>>> "{0}-{1}.shader_test".format(execution_stage,
>>> + func))
>>> + print filename
>>> +
>>> + dirname = os.path.dirname(filename)
>>> + if not os.path.exists(dirname):
>>> + os.makedirs(dirname)
>>> +
>>> + f = open(filename, 'w')
>>> + f.write(template.render(version=version,
>>> + extensions=extensions,
>>> + execution_stage=execution_stage,
>>> + func=func,
>>> + in_func=in_func,
>>> + out_func=out_func,
>>> + input_type=input_type,
>>> + output_type=output_type,
>>> + test_data=test_data))
>>> + f.close()
>>>
More information about the Piglit
mailing list