1# coding=utf-8
2# Copyright (c) 2015 Intel Corporation
3
4# Permission is hereby granted, free of charge, to any person obtaining a copy
5# of this software and associated documentation files (the "Software"), to deal
6# in the Software without restriction, including without limitation the rights
7# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8# copies of the Software, and to permit persons to whom the Software is
9# furnished to do so, subject to the following conditions:
10
11# The above copyright notice and this permission notice shall be included in
12# all copies or substantial portions of the Software.
13
14# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
20# SOFTWARE.
21
22"""Generate tests for glsl 1.10 and 1.20 variable index reads."""
23
24import os
25import itertools
26
27from templates import template_dir
28from modules.utils import lazy_property, safe_makedirs
29
30TEMPLATES = template_dir(os.path.basename(os.path.splitext(__file__)[0]))
31FS_TEMPLATE = TEMPLATES.get_template('fs.shader_test.mako')
32VS_TEMPLATE = TEMPLATES.get_template('vs.shader_test.mako')
33DIRNAME = os.path.join('spec', 'glsl-{}', 'execution', 'variable-indexing')
34
35
36class TestParams(object):
37    """Parameters for a single test.
38
39    This is all of the non-formatting logic of the test. Each property is
40    wrapped with a lazy_property decorator, which means the data is cached
41    after it is calculated once.
42
43    """
44    def __init__(self, matrix_dim, array_dim, mode, index_value, col,
45                 expect_type, glsl_version):
46        self.matrix_dim = matrix_dim
47        self.array_dim = array_dim
48        self.mode = mode
49        self.index_value = index_value
50        self.__col = col
51        self.expect_type = expect_type
52
53        assert glsl_version in [110, 120]
54        self.glsl_version = glsl_version
55
56    @lazy_property
57    def idx(self):
58        if self.array_dim != 0:
59            return '[{}]'.format(self.index_value)
60        else:
61            return ''
62
63    @lazy_property
64    def cxr_type(self):
65        return 'mat{0}x{0}'.format(self.matrix_dim)
66
67    @lazy_property
68    def base_type(self):
69        if self.glsl_version == 120:
70            return self.cxr_type
71        else:
72            return 'mat{}'.format(self.matrix_dim)
73
74    @lazy_property
75    def type(self):
76        if self.array_dim != 0 and self.glsl_version == 120:
77            return '{}[{}]'.format(self.base_type, self.array_dim)
78        else:
79            return self.base_type
80
81    @lazy_property
82    def dim(self):
83        if self.array_dim != 0 and self.glsl_version == 110:
84            return '[{}]'.format(self.array_dim)
85        else:
86            # XXX: should this be an error?
87            return ''
88
89    @lazy_property
90    def row(self):
91        if self.expect_type == 'float':
92            return '[row]'
93        else:
94            # XXX: Should this be an error?
95            return ''
96
97    @lazy_property
98    def col(self):
99        return '[{}]'.format(self.__col)
100
101    @lazy_property
102    def test_sizes(self):
103        if self.array_dim == 0:
104            return [1]
105        elif self.index_value == 'index':
106            return list(range(1, 1 + self.array_dim))
107        else:
108            return [2]
109
110    @lazy_property
111    def test_columns(self):
112        if self.col == '[col]':
113            return list(range(1, 1 + self.matrix_dim))
114        else:
115            return [2]
116
117    @lazy_property
118    def test_rows(self):
119        if self.expect_type == 'float':
120            return list(range(1, 1 + self.matrix_dim))
121        else:
122            return [1]
123
124    @lazy_property
125    def test_array_dim(self):
126        if (self.mode == 'uniform' and
127                self.glsl_version == 110 and
128                self.array_dim != 0 and
129                self.index_value != 'index'):
130            return self.index_value + 1
131        else:
132            return self.array_dim
133
134    @lazy_property
135    def varying_comps(self):
136        if self.array_dim != 0:
137            return 4 + self.matrix_dim**2 * self.array_dim
138        else:
139            return 4 + self.matrix_dim**2
140
141    @lazy_property
142    def formated_version(self):
143        return '{:.2f}'.format(float(self.glsl_version) / 100)
144
145
146def make_fs(name, params):
147    """Generate a fragment shader test."""
148    dirname = DIRNAME.format(params.formated_version)
149    safe_makedirs(dirname)
150    with open(os.path.join(dirname, name), 'w') as f:
151        f.write(FS_TEMPLATE.render_unicode(params=params))
152    print(name)
153
154
155def make_vs(name, params):
156    """Generate a vertex shader test."""
157    dirname = DIRNAME.format(params.formated_version)
158    safe_makedirs(dirname)
159    with open(os.path.join(dirname, name), 'w') as f:
160        f.write(VS_TEMPLATE.render_unicode(params=params))
161    print(name)
162
163
164def main():
165    """Generate the tests."""
166    modes = ['temp', 'uniform', 'varying']
167    array_dims = [0, 3]
168    matrix_dims = [2, 3, 4]
169    glsl_versions = [110, 120]
170    cols = [1, 'col']
171    stages = ['fs', 'vs']
172    iter_ = itertools.product(stages, modes, array_dims, matrix_dims,
173                              glsl_versions, cols)
174    for stage, mode, array_dim, matrix_dim, glsl_version, col in iter_:
175        if stage == 'vs':
176            func = make_vs
177        else:
178            func = make_fs
179
180        for expect in ['float', 'vec{}'.format(matrix_dim)]:
181            if array_dim != 0:
182                arr = 'array-'
183                idx_text = 'index-'
184
185                func(
186                    '{stage}-{mode}-{arr}mat{matrix_dim}-{col}{row}rd.shader_test'.format(
187                        stage=stage,
188                        mode=mode,
189                        arr=arr,
190                        matrix_dim=matrix_dim,
191                        col='col-' if col == 'col' else '',
192                        row='row-' if expect == 'float' else ''),
193                    TestParams(matrix_dim, array_dim, mode, 1, col, expect,
194                               glsl_version))
195            else:
196                arr = ''
197                idx_text = ''
198
199            func(
200                '{stage}-{mode}-{arr}mat{matrix_dim}-{idx_text}{col}{row}rd.shader_test'.format(
201                    stage=stage,
202                    mode=mode,
203                    arr=arr,
204                    matrix_dim=matrix_dim,
205                    idx_text=idx_text,
206                    col='col-' if col == 'col' else '',
207                    row='row-' if expect == 'float' else ''),
208                TestParams(matrix_dim, array_dim, mode, 'index', col, expect,
209                           glsl_version))
210
211
212if __name__ == '__main__':
213    main()
214