gen_shader_bit_encoding_tests.py 6.12 KB
Newer Older
1 2
# coding=utf-8
#
3
# Copyright © 2013, 2014 Intel Corporation
4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
#
# 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.

24
from __future__ import print_function
25 26
import struct
import os
27
from operator import neg
28 29

from templates import template_file
30
from modules import utils
31 32 33 34

TEMPLATE = template_file(os.path.basename(os.path.splitext(__file__)[0]),
                         'template.shader_test.mako')

35

36
def floatBitsToInt(f):  # pylint: disable=invalid-name
37 38
    return struct.unpack('i', struct.pack('f', f))[0]

39 40

def floatBitsToUint(f):  # pylint: disable=invalid-name
41 42
    return struct.unpack('I', struct.pack('f', f))[0]

43 44

def intBitsToFloat(i):  # pylint: disable=invalid-name
45 46
    return struct.unpack('f', struct.pack('i', i))[0]

47 48

def uintBitsToFloat(u):  # pylint: disable=invalid-name
49 50
    return struct.unpack('f', struct.pack('I', u))[0]

51

52
def neg_abs(num):
53
    return neg(abs(num))
54

55

56 57 58
def vec4(f):
    return [f, f, f, f]

59 60
# pylint: disable=bad-whitespace
TEST_DATA = {
61 62
    # Interesting floating-point inputs
    'mixed':                        (2.0, 9.5, -4.5, -25.0),
63 64
    '0.0':                          vec4( 0.0),  # int 0
    '-0.0':                         vec4(-0.0),  # INT_MIN
65 66 67 68 69
    '1.0':                          vec4( 1.0),
    '-1.0':                         vec4(-1.0),
    'normalized smallest':          vec4( 1.1754944e-38),
    'normalized smallest negative': vec4(-1.1754944e-38),
    'normalized largest':           vec4( 3.4028235e+38),
70
    'normalized largest negative':  vec4(-3.4028235e+38),
71 72 73 74 75 76

    # 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. Don't test subnormal values, since hardware might
    # flush them to zero.
}
77
# pylint: enable=bad-whitespace
78 79 80 81 82 83

# in_func: Function to convert floating-point data in test_data (above) into
#          input (given) data to pass the shader.
# out_func: Function to convert floating-point data in test_data (above) into
#           output (expected) data to pass the shader.

84
FUNCS = {
85
    'floatBitsToInt': {
86
        'in_func':  lambda x: x,
87 88 89 90 91
        'out_func': floatBitsToInt,
        'input':    'vec4',
        'output':   'ivec4'
    },
    'floatBitsToUint': {
92
        'in_func':  lambda x: x,
93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110
        'out_func': floatBitsToUint,
        'input':    'vec4',
        'output':   'uvec4'
    },
    'intBitsToFloat': {
        'in_func':  floatBitsToInt,
        'out_func': intBitsToFloat,
        'input':    'ivec4',
        'output':   'vec4'
    },
    'uintBitsToFloat': {
        'in_func':  floatBitsToUint,
        'out_func': uintBitsToFloat,
        'input':    'uvec4',
        'output':   'vec4'
    }
}

111
MODIFIER_FUNCS = {
112
    '':            lambda x: x,
113 114
    'abs':         abs,
    'neg':         neg,
115
    'neg_abs':     neg_abs,
116 117
}

118
REQUIREMENTS = {
119 120 121 122 123 124 125 126
    'ARB_shader_bit_encoding': {
        'version': '1.30',
        'extension': 'GL_ARB_shader_bit_encoding'
    },
    'ARB_gpu_shader5': {
        'version': '1.50',
        'extension': 'GL_ARB_gpu_shader5'
    },
127 128
    'glsl-3.30': {
        'version': '3.30',
129 130 131 132 133
        'extension': ''
    }
}


134 135
def main():
    """main function."""
136
    # pylint: disable=line-too-long
137
    for api, requirement in REQUIREMENTS.iteritems():
138 139 140
        version = requirement['version']
        extensions = [requirement['extension']] if requirement['extension'] else []

141 142
        dirname = os.path.join('spec', api.lower(), 'execution',
                               'built-in-functions')
143
        utils.safe_makedirs(dirname)
144

145
        for func, attrib in FUNCS.iteritems():
146
            for execution_stage in ('vs', 'fs'):
147
                for in_modifier_func, modifier_func in MODIFIER_FUNCS.iteritems():
148 149 150 151 152 153
                    # Modifying the sign of an unsigned number doesn't make sense.
                    if func == 'uintBitsToFloat' and in_modifier_func != '':
                        continue

                    modifier_name = '-' + in_modifier_func if in_modifier_func != '' else ''
                    filename = os.path.join(
154
                        dirname,
155 156
                        "{0}-{1}{2}.shader_test".format(execution_stage, func,
                                                        modifier_name))
157
                    print(filename)
158 159 160 161 162 163

                    if in_modifier_func == 'neg':
                        in_modifier_func = '-'
                    elif in_modifier_func == 'neg_abs':
                        in_modifier_func = '-abs'

164 165 166 167 168 169 170 171
                    with open(filename, 'w') as f:
                        f.write(TEMPLATE.render(
                            version=version,
                            extensions=extensions,
                            execution_stage=execution_stage,
                            func=func,
                            modifier_func=modifier_func,
                            in_modifier_func=in_modifier_func,
172 173 174 175
                            in_func=attrib['in_func'],
                            out_func=attrib['out_func'],
                            input_type=attrib['input'],
                            output_type=attrib['output'],
176
                            test_data=TEST_DATA))
177 178 179 180


if __name__ == '__main__':
    main()