[Piglit] [PATCH 1/2] arb_shader_bit_encoding: Add test generator.
Ian Romanick
idr at freedesktop.org
Wed Aug 7 17:36:51 PDT 2013
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?
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...
> +}
> +
> +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'?
> + % 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