4 # Copyright © 2014 The Piglit Project
6 # Permission is hereby granted, free of charge, to any person obtaining a
7 # copy of this software and associated documentation files (the "Software"),
8 # to deal in the Software without restriction, including without limitation
9 # the rights to use, copy, modify, merge, publish, distribute, sublicense,
10 # and/or sell copies of the Software, and to permit persons to whom the
11 # Software is furnished to do so, subject to the following conditions:
13 # The above copyright notice and this permission notice (including the next
14 # paragraph) shall be included in all copies or substantial portions of the
17 # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
20 # THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
22 # FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
23 # DEALINGS IN THE SOFTWARE.
25 """Test passing variables from the tessellation control shader to the
26 tessellation evaluation shader.
28 For every combination of varying type as scalar and as two element array and
29 per-vertex or per-patch varying create a test that that passes said variable
30 between the tessellation shader stages.
32 Copy a uniform value to the varying in the tessellation control shader and
33 compare the varying to the same uniform in the tessellation evaluation
35 If the values are equal draw the screen green, red otherwise.
37 Draw for tessellated quads. Each should cover one quarter of the screen.
39 This script outputs, to stdout, the name of each file it generates.
50 def __init__(self
, type_name
, array
, patch_in
, name
):
53 type_name -- varying type to test (e.g.: vec4, mat3x2, int, ...)
54 array -- number of array elements to test, None for no array
55 patch_in -- true for per-patch varying, false for per-vertex varying
56 name -- name of the variable to test
59 self
.var_name
= name
or 'var'
60 self
.use_block
= 0 if patch_in
else 1
62 if self
.var_name
== 'gl_Position':
63 self
.var_type
= 'vec4'
66 elif self
.var_name
== 'gl_PointSize':
67 self
.var_type
= 'float'
70 elif self
.var_name
== 'gl_ClipDistance':
71 self
.var_type
= 'float'
75 self
.var_type
= type_name
76 self
.var_array
= array
77 self
.patch_in
= patch_in
80 self
.interface_name
= 'gl_PerVertex'
81 self
.interface_tcs_instance
= 'gl_out'
82 self
.interface_tes_instance
= 'gl_in'
84 self
.interface_name
= 'tc2te_interface'
85 self
.interface_tcs_instance
= '' if self
.patch_in
else 'tc2te'
86 self
.interface_tes_instance
= '' if self
.patch_in
else 'tc2te'
89 self
.var_type_full
= self
.var_type
+ '[{0}]'.format(self
.var_array
)
91 self
.var_type_full
= self
.var_type
94 self
.interface_prefix
= 'patch '
95 self
.interface_postfix
= ''
97 self
.interface_prefix
= ''
98 self
.interface_postfix
= '[]'
102 return self
.var_name
.startswith('gl_')
105 def tcs_var_ref(self
):
106 return '[gl_InvocationID].' + self
.var_name
if self
.interface_tcs_instance
else self
.var_name
109 def tes_var_ref(self
):
110 return '[i].' + self
.var_name
if self
.interface_tes_instance
else self
.var_name
113 def tcs_reference_index(self
):
114 return 'gl_PrimitiveID' if self
.patch_in
else 'gl_PrimitiveID * vertices_in + gl_InvocationID'
117 def tes_reference_index(self
):
118 return 'gl_PrimitiveID' if self
.patch_in
else 'gl_PrimitiveID * vertices_in + i'
121 def reference_size(self
):
122 return 4 if self
.patch_in
else 12
125 def uniform_string(self
):
126 """Returns string for loading uniform data by the shader_runner."""
127 data
= self
.test_data()
130 for i
in range(self
.reference_size
):
131 for j
in range(self
.var_array
):
132 uniforms
+= 'uniform {0} reference[{1}].v[{2}] {3}\n'.format(
133 self
.var_type
, i
, j
, data
[i
*j
])
135 for i
in range(self
.reference_size
):
136 uniforms
+= 'uniform {0} reference[{1}].v {2}\n'.format(
144 def components(self
):
145 """Returns the number of scalar components of the used data type."""
148 if self
.var_type
.startswith('mat'):
149 if 'x' in self
.var_type
:
150 n
*= int(self
.var_type
[-1])
151 n
*= int(self
.var_type
[-3])
153 n
*= int(self
.var_type
[-1])
154 n
*= int(self
.var_type
[-1])
155 elif 'vec' in self
.var_type
:
156 n
*= int(self
.var_type
[-1])
161 """Returns random but deterministic data as a list of strings.
163 n strings are returned containing c random values, each.
164 Where n is the number of vertices times the array length and
165 c is the number of components in the tested scalar data type.
170 n
= self
.var_array
* self
.reference_size
172 n
= self
.reference_size
174 if self
.var_type
.startswith('i'):
175 rand
= lambda: random
.randint(-0x80000000, 0x7fffffff)
176 elif self
.var_type
.startswith('u'):
177 rand
= lambda: random
.randint(0, 0xffffffff)
179 rand
= lambda: ((-1 + 2 * random
.randint(0, 1)) *
180 random
.randint(0, 2**23-1) *
181 2.0**(random
.randint(-126, 127)))
183 c
= self
.components()
187 ret
.append(" ".join(str(rand()) for _
in range(c
)))
192 """Returns the file name (including path) for the test."""
196 name
= self
.var_type
+ '_{0}'.format(self
.var_array
)
200 name
= 'patch-' + name
201 return os
.path
.join('spec',
202 'arb_tessellation_shader',
205 'tes-input-{0}.shader_test'.format(name
))
208 """Generates and writes the test to disc."""
209 test
= textwrap
.dedent("""\
211 # {generator_command}
212 # Test tessellation evaluation shader inputs
215 GL_ARB_tessellation_shader
220 gl_Position = vec4(0);
223 [tessellation control shader]
224 #extension GL_ARB_tessellation_shader : require
225 layout(vertices = 3) out;
228 {self.var_type_full} v;
232 {self.interface_prefix}out {self.interface_name} {{
233 {self.var_type_full} {self.var_name};
234 }} {self.interface_tcs_instance}{self.interface_postfix};
236 {self.interface_prefix}out {self.var_type_full} {self.var_name};
241 const int vertices_in = 3;
242 {self.interface_tcs_instance}{self.tcs_var_ref} = reference[{self.tcs_reference_index}].v;
243 gl_TessLevelOuter = float[4](1.0, 1.0, 1.0, 1.0);
244 gl_TessLevelInner = float[2](1.0, 1.0);
247 [tessellation evaluation shader]
248 #extension GL_ARB_tessellation_shader : require
252 {self.var_type_full} v;
256 {self.interface_prefix}in {self.interface_name} {{
257 {self.var_type_full} {self.var_name};
258 }} {self.interface_tes_instance}{self.interface_postfix};
260 {self.interface_prefix}in {self.var_type_full} {self.var_name};
267 const int vertices_in = 3;
268 const vec4 red = vec4(1, 0, 0, 1);
269 const vec4 green = vec4(0, 1, 0, 1);
271 for (int i = 0; i < vertices_in; ++i)
272 if ({self.interface_tes_instance}{self.tes_var_ref} != reference[{self.tes_reference_index}].v)
274 vec2[3] position = vec2[3](
275 vec2(float(gl_PrimitiveID / 2) - 1.0, float(gl_PrimitiveID % 2) - 1.0),
276 vec2(float(gl_PrimitiveID / 2) - 0.0, float(gl_PrimitiveID % 2) - 1.0),
277 vec2(float(gl_PrimitiveID / 2) - 1.0, float(gl_PrimitiveID % 2) - 0.0)
279 gl_Position = vec4(position[0]
280 + (position[1] - position[0]) * gl_TessCoord[0]
281 + (position[2] - position[0]) * gl_TessCoord[1], 0.0, 1.0);
292 frag_color = vert_color;
296 {self.uniform_string}
297 draw arrays GL_PATCHES 0 12
298 relative probe rgb (0.25, 0.25) (0.0, 1.0, 0.0)
299 relative probe rgb (0.75, 0.25) (0.0, 1.0, 0.0)
300 relative probe rgb (0.25, 0.75) (0.0, 1.0, 0.0)
301 relative probe rgb (0.75, 0.75) (0.0, 1.0, 0.0)
304 test
= test
.format(self
=self
, generator_command
="generated_tests/gen_tes_input_tests.py")
306 filename
= self
.filename()
307 dirname
= os
.path
.dirname(filename
)
308 if not os
.path
.exists(dirname
):
310 with
open(filename
, 'w') as f
:
315 for type_name
in ['float', 'vec2', 'vec3', 'vec4',
316 'mat2', 'mat3', 'mat4',
317 'mat2x3', 'mat2x4', 'mat3x2',
318 'mat3x4', 'mat4x2', 'mat4x3',
319 'int', 'ivec2', 'ivec3', 'ivec4',
320 'uint', 'uvec2', 'uvec3', 'uvec4']:
321 for array
in [None, 2]:
322 for patch_in
in [True, False]:
323 yield Test(type_name
, array
, patch_in
, name
=None)
324 for var
in ['gl_Position', 'gl_PointSize', 'gl_ClipDistance']:
325 yield Test(type_name
=None, array
=None, patch_in
=False, name
=var
)
329 for test
in all_tests():
331 print(test
.filename())
334 if __name__
== '__main__':