3 # Copyright (C) 2014 Intel Corporation
5 # Permission is hereby granted, free of charge, to any person obtaining a
6 # copy of this software and associated documentation files (the "Software"),
7 # to deal in the Software without restriction, including without limitation
8 # the rights to use, copy, modify, merge, publish, distribute, sublicense,
9 # and/or sell copies of the Software, and to permit persons to whom the
10 # Software is furnished to do so, subject to the following conditions:
12 # The above copyright notice and this permission notice (including the next
13 # paragraph) shall be included in all copies or substantial portions of the
16 # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19 # THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21 # FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
25 from mako
.template
import Template
26 from textwrap
import dedent
28 from modules
import utils
31 def gen_header(status
):
33 Generate a GLSL program header.
35 Generate header code for ARB_shader_image_load_store GLSL parser
36 tests that are expected to give status as result.
43 * require_extensions: GL_ARB_shader_image_load_store
47 #extension GL_ARB_shader_image_load_store: require
51 def gen_vector_type(scalar
, dim
):
53 Generate a GLSL vector type name.
55 Generate a GLSL vector type based on the given scalar type with the
56 specified number of dimensions.
64 return ('{0}{1}'.format(vector_types
[scalar
], dim
) if dim
> 1
68 def gen_scalar_args(arity
):
70 Generate image builtin scalar arguments.
72 Returns a generator of well-formed scalar arguments for an image
73 built-in of the given arity having t as argument type.
75 return lambda t
: ', {0}(0)'.format(t
) * arity
78 def gen_vector_args(arity
):
80 Generate image builtin vector arguments.
82 Returns a generator of well-formed arguments for an image built-in
83 of the given arity having a 4-component vector of t as argument
86 return lambda t
: ', {0}(0)'.format(gen_vector_type(t
, 4)) * arity
89 def gen_address_args(dim
):
91 Generate image address arguments.
93 Returns a generator for the coordinate argument of an image
94 built-in expecting an address of the given dimensionality. If
95 fail is True the generated argument will have an arbitrary
96 incorrect dimensionality.
98 return (lambda fail
= False: ', {0}(0)'.format(
99 gen_vector_type('int', dim
if not fail
else dim
% 3 + 1)))
102 def gen_address_args_ms(dim
):
103 """Generate multisample image address arguments."""
104 return (lambda fail
= False:
105 gen_address_args(dim
)() + (', 0' if not fail
else ''))
108 def product(ps
, *qss
):
110 Generate the cartesian product of a number of lists of dictionaries.
112 Each generated element will be the union of some combination of
113 elements from the iterable arguments. The resulting value of each
114 'name' item will be the concatenation of names of the respective
115 element combination separated with dashes.
117 for q
in (product(*qss
) if qss
else [{}]):
120 r
['name'] = '-'.join(s
['name'] for s
in (p
, q
) if s
.get('name'))
124 def gen(name
, src
, tests
):
126 Expand a source template for the provided list of test definitions.
128 Generate a GLSL parser test for each of the elements of the
129 'tests' iterable, each of them should be a dictionary of
130 definitions that will be used as environment to render the source
133 The file name of each test will be the concatenation of the 'name'
134 argument with the 'name' item from the respective test dictionary.
136 template
= Template(dedent(src
))
138 for t
in product([{'name': name
}], tests
):
139 filename
= os
.path
.join('spec',
140 'ARB_shader_image_load_store',
142 '{0}.{1}'.format(t
['name'],
146 dirname
= os
.path
.dirname(filename
)
147 utils
.safe_makedirs(dirname
)
149 with
open(filename
, 'w') as f
:
150 f
.write(template
.render(header
= gen_header
, **t
))
154 {'shader_stage': 'frag'},
155 {'shader_stage': 'vert'}
159 image_atomic_builtins
= [
161 'name': 'atomic-add',
162 'image_builtin': 'imageAtomicAdd',
163 'image_args': gen_scalar_args(1)
166 'name': 'atomic-min',
167 'image_builtin': 'imageAtomicMin',
168 'image_args': gen_scalar_args(1)
171 'name': 'atomic-max',
172 'image_builtin': 'imageAtomicMax',
173 'image_args': gen_scalar_args(1)
176 'name': 'atomic-and',
177 'image_builtin': 'imageAtomicAnd',
178 'image_args': gen_scalar_args(1)
182 'image_builtin': 'imageAtomicOr',
183 'image_args': gen_scalar_args(1)
186 'name': 'atomic-xor',
187 'image_builtin': 'imageAtomicXor',
188 'image_args': gen_scalar_args(1)
191 'name': 'atomic-exchange',
192 'image_builtin': 'imageAtomicExchange',
193 'image_args': gen_scalar_args(1)
196 'name': 'atomic-comp-swap',
197 'image_builtin': 'imageAtomicCompSwap',
198 'image_args': gen_scalar_args(2)
203 image_load_builtin
= [
206 'image_builtin': 'imageLoad',
207 'image_args': gen_vector_args(0)
212 image_store_builtin
= [
215 'image_builtin': 'imageStore',
216 'image_args': gen_vector_args(1)
224 'image_type': 'image1D',
225 'image_addr': gen_address_args(1)
229 'image_type': 'image2D',
230 'image_addr': gen_address_args(2)
234 'image_type': 'image3D',
235 'image_addr': gen_address_args(3)
239 'image_type': 'image2DRect',
240 'image_addr': gen_address_args(2)
244 'image_type': 'imageCube',
245 'image_addr': gen_address_args(3)
249 'image_type': 'imageBuffer',
250 'image_addr': gen_address_args(1)
254 'image_type': 'image1DArray',
255 'image_addr': gen_address_args(2)
259 'image_type': 'image2DArray',
260 'image_addr': gen_address_args(3)
263 'name': 'cube-array',
264 'image_type': 'imageCubeArray',
265 'image_addr': gen_address_args(3)
269 'image_type': 'image2DMS',
270 'image_addr': gen_address_args_ms(2)
273 'name': '2d-ms-array',
274 'image_type': 'image2DMSArray',
275 'image_addr': gen_address_args_ms(3)
283 # Test the early_fragment_tests layout qualifier.
285 gen('early-fragment-tests', """\
286 ${header('pass' if shader_stage == 'frag' and hunk == 'in' else 'fail')}
288 * From the ARB_shader_image_load_store spec:
290 * "Fragment shaders also allow the following layout qualifier on 'in'
291 * only (not with variable declarations):
293 * layout-qualifier-id
294 * early_fragment_tests"
296 layout(early_fragment_tests) ${hunk};
301 """, product(shader_stages
, [
302 {'name': 'in', 'hunk': 'in'},
303 {'name': 'out', 'hunk': 'out'},
304 {'name': 'uniform', 'hunk': 'uniform uint u'},
305 {'name': 'in-var', 'hunk': 'in float f'},
306 {'name': 'uniform-buffer', 'hunk': 'uniform b { image2D img; }'}
310 # Test image declarations.
312 gen('declaration-allowed', """\
315 * From the ARB_shader_image_load_store spec:
317 * "[Images] can only be declared as function parameters or uniform
320 layout(rgba32f) uniform ${image_type} img;
321 layout(rgba32ui) uniform u${image_type} uimg;
322 layout(rgba32i) uniform i${image_type} iimg;
324 void f(${image_type} arg,
333 """, product(image_types
, shader_stages
))
335 gen('declaration-global', """\
338 * From the ARB_shader_image_load_store spec:
340 * "[Images] can only be declared as function parameters or uniform
343 layout(rgba32f) ${qualifier} image2D img;
348 """, product(shader_stages
, [
349 {'name': 'const', 'qualifier': 'const'},
350 {'name': 'in', 'qualifier': 'in'},
351 {'name': 'out', 'qualifier': 'out'}
354 gen('declaration-local', """\
357 * From the ARB_shader_image_load_store spec:
359 * "[Images] can only be declared as function parameters or uniform
364 layout(rgba32f) image2D img;
368 gen('declaration-uniform-block', """\
371 * From the ARB_shader_image_load_store spec:
373 * "Sets of uniforms, except for samplers and images, can be grouped
374 * into uniform blocks."
377 layout(rgba32f) image2D img;
385 gen('declaration-argument', """\
388 * From the ARB_shader_image_load_store spec:
390 * "Images cannot be treated as l-values; hence, they cannot be used
391 * as out or inout function parameters, nor can they be assigned
394 void f(${qualifier} image2D y)
401 """, product(shader_stages
, [
402 {'name': 'inout', 'qualifier': 'inout'},
403 {'name': 'out', 'qualifier': 'out'}
406 gen('declaration-initializer', """\
409 * From the ARB_shader_image_load_store spec:
411 * "[Images] cannot be declared with an initializer in a shader."
413 layout(rgba32f) uniform image2D img = 0;
420 gen('declaration-format-qualifier', """\
423 * From the ARB_shader_image_load_store spec:
425 * "It is an error to declare an image variable where the format
426 * qualifier does not match the image variable type."
428 layout(${format}) uniform ${prefix}${image_type} img;
433 """, product(image_types
, shader_stages
, [
441 'format': 'rgba32ui',
445 gen('declaration-format-qualifier-duplicate', """\
448 * From the ARB_shader_image_load_store spec:
450 * "Only one format qualifier may be specified for any image variable
453 layout(rgba32f) layout(rgba32f) uniform image2D img;
460 gen('declaration-format-qualifier-missing', """\
463 * From the ARB_shader_image_load_store spec:
465 * "Uniforms not qualified with "writeonly" must have a format
468 ${qualifier} uniform image2D img;
473 """, product(shader_stages
, [
474 {'name': 'writeonly',
475 'qualifier': 'writeonly',
478 'qualifier': 'readonly',
480 {'name': 'readwrite',
485 gen('declaration-memory-qualifier-sampler', """\
488 * From the ARB_shader_image_load_store spec:
490 * "Only variables declared as image types [...] can be qualified
491 * with a memory qualifier. "
493 ${qualifier} uniform sampler2D s;
498 """, product(shader_stages
, [
499 {'name': 'readonly', 'qualifier': 'readonly'},
500 {'name': 'writeonly', 'qualifier': 'writeonly'},
501 {'name': 'coherent', 'qualifier': 'coherent'},
502 {'name': 'volatile', 'qualifier': 'volatile'},
503 {'name': 'restrict', 'qualifier': 'restrict'}
507 # Test expressions involving images.
509 gen('expression-allowed', """\
512 * From the ARB_shader_image_load_store spec:
514 * "Except for array indexing, structure field selection, and
515 * parentheses, images are not allowed to be operands in
518 layout(rgba32f) uniform ${image_type} imgs[2];
525 color = y + imageLoad((imgs[1]) ${image_addr()});
527 """, product(image_types
[:1], shader_stages
))
529 gen('expression', """\
532 * From the ARB_shader_image_load_store spec:
534 * "Except for array indexing, structure field selection, and
535 * parentheses, images are not allowed to be operands in
538 layout(rgba32f) uniform image2D img;
544 """, product(shader_stages
, [
545 {'name': 'arithmetic-1', 'expression': '-img'},
546 {'name': 'arithmetic-2', 'expression': 'img + img'},
547 {'name': 'arithmetic-3', 'expression': 'img - img'},
548 {'name': 'arithmetic-4', 'expression': 'img * img'},
549 {'name': 'arithmetic-5', 'expression': 'img / img'},
550 {'name': 'arithmetic-6', 'expression': '++img'},
551 {'name': 'arithmetic-7', 'expression': '--img'},
552 {'name': 'arithmetic-8', 'expression': 'img++'},
553 {'name': 'arithmetic-9', 'expression': 'img--'},
554 {'name': 'assignment-1', 'expression': 'img ^= img'},
555 {'name': 'assignment-2', 'expression': 'img |= img'},
556 {'name': 'assignment-3', 'expression': 'img = img'},
557 {'name': 'assignment-4', 'expression': 'img += img'},
558 {'name': 'assignment-5', 'expression': 'img -= img'},
559 {'name': 'assignment-6', 'expression': 'img *= img'},
560 {'name': 'assignment-7', 'expression': 'img /= img'},
561 {'name': 'assignment-8', 'expression': 'img %= img'},
562 {'name': 'assignment-9', 'expression': 'img <<= img'},
563 {'name': 'assignment-10', 'expression': 'img >>= img'},
564 {'name': 'assignment-11', 'expression': 'img &= img'},
565 {'name': 'binary-1', 'expression': '~img'},
566 {'name': 'binary-2', 'expression': 'img << img'},
567 {'name': 'binary-3', 'expression': 'img >> img'},
568 {'name': 'binary-4', 'expression': 'img & img'},
569 {'name': 'binary-5', 'expression': 'img | img'},
570 {'name': 'binary-6', 'expression': 'img ^ img'},
571 {'name': 'conversion-1', 'expression': 'float(img)'},
572 {'name': 'conversion-2', 'expression': 'uint(img)'},
573 {'name': 'conversion-3', 'expression': 'bool(img)'},
574 {'name': 'conversion-4', 'expression': 'image1D(img)'},
575 {'name': 'field-selection', 'expression': 'img.x'},
576 {'name': 'function-call', 'expression': 'img()'},
577 {'name': 'logical-1', 'expression': '!img'},
578 {'name': 'logical-2', 'expression': 'img && img'},
579 {'name': 'logical-3', 'expression': 'img || img'},
580 {'name': 'logical-4', 'expression': 'img ^^ img'},
581 {'name': 'relational-1', 'expression': 'img == img'},
582 {'name': 'relational-2', 'expression': 'img != img'},
583 {'name': 'relational-3', 'expression': 'img < img'},
584 {'name': 'relational-4', 'expression': 'img > img'},
585 {'name': 'relational-5', 'expression': 'img <= img'},
586 {'name': 'relational-6', 'expression': 'img >= img'},
587 {'name': 'selection', 'expression': 'true ? img : img'},
588 {'name': 'subscript', 'expression': 'img[0]'}
592 # Test passing of image variables in function calls.
594 gen('call-argument-qualifiers', """\
597 * From the ARB_shader_image_load_store spec:
599 * "The values of image variables qualified with 'coherent',
600 * 'volatile', 'restrict', 'readonly', or 'writeonly' may not be
601 * passed to functions whose formal parameters lack such
602 * qualifiers. [...] It is legal to have additional qualifiers on a
603 * formal parameter, but not to have fewer."
605 layout(rgba32f) ${actual_qualifier} uniform image2D x;
607 void f(${formal_qualifier} image2D y)
615 """, product(shader_stages
, [
616 {'name': 'allowed-volatile',
617 'actual_qualifier': 'volatile',
618 'formal_qualifier': 'volatile coherent',
620 {'name': 'allowed-coherent',
621 'actual_qualifier': 'coherent',
622 'formal_qualifier': 'volatile coherent',
624 {'name': 'allowed-restrict',
625 'actual_qualifier': 'restrict',
626 'formal_qualifier': 'volatile restrict',
628 {'name': 'allowed-readonly',
629 'actual_qualifier': 'readonly',
630 'formal_qualifier': 'restrict readonly',
632 {'name': 'allowed-writeonly',
633 'actual_qualifier': 'writeonly',
634 'formal_qualifier': 'volatile writeonly',
636 {'name': 'disallowed-volatile',
637 'actual_qualifier': 'volatile',
638 'formal_qualifier': '',
640 {'name': 'disallowed-coherent',
641 'actual_qualifier': 'coherent',
642 'formal_qualifier': 'restrict',
644 {'name': 'disallowed-restrict',
645 'actual_qualifier': 'restrict',
646 'formal_qualifier': '',
648 {'name': 'disallowed-readonly',
649 'actual_qualifier': 'readonly',
650 'formal_qualifier': 'restrict writeonly',
652 {'name': 'disallowed-writeonly',
653 'actual_qualifier': 'writeonly',
654 'formal_qualifier': 'volatile readonly',
658 gen('call-argument-type', """\
659 ${header('pass' if image_type == 'image2D' else 'fail')}
661 * From the ARB_shader_image_load_store spec:
663 * "As function parameters, images may only be passed to [arguments]
666 layout(rgba32f) uniform image2D x;
668 void f(${image_type} y)
676 """, product(image_types
, shader_stages
))
679 # Test the language built-in constants and functions.
681 gen('builtin-constants', """\
684 * Check that the builtin constants defined by the extension
691 color.x = gl_MaxImageUnits +
692 gl_MaxCombinedImageUnitsAndFragmentOutputs +
694 gl_MaxVertexImageUniforms +
695 gl_MaxGeometryImageUniforms +
696 gl_MaxFragmentImageUniforms +
697 gl_MaxCombinedImageUniforms;
701 gen('builtin-image-argument-mismatch', """\
704 * From the ARB_shader_image_load_store spec:
706 * "Atomic memory operations are supported on only [...]: an image
707 * variable with signed integer components (iimage*) format qualifier
708 * of 'r32i', or an image variable with unsigned integer components
709 * (uimage*) and format qualifier of 'r32ui'."
711 * Call an atomic built-in with a floating point image data type.
713 layout(r32f) uniform ${image_type} img;
717 ${image_builtin}(img ${image_addr()} ${image_args('float')});
719 """, product(image_atomic_builtins
, image_types
[:1], shader_stages
))
721 gen('builtin-data-argument-mismatch', """\
724 * Call a signed integer atomic built-in with a mismatching
725 * argument data type.
727 layout(r32i) uniform i${image_type} img;
731 ${image_builtin}(img ${image_addr()} ${image_args('uint')});
733 """, product(image_store_builtin
+ image_atomic_builtins
,
734 image_types
[:1], shader_stages
))
736 gen('builtin-address-argument-mismatch', """\
739 * From the ARB_shader_image_load_store spec:
741 * "The 'IMAGE_INFO' placeholder is replaced by one of the following
743 * gimage1D image, int coord
744 * gimage2D image, ivec2 coord
745 * gimage3D image, ivec3 coord
746 * gimage2DRect image, ivec2 coord
747 * gimageCube image, ivec3 coord
748 * gimageBuffer image, int coord
749 * gimage1DArray image, ivec2 coord
750 * gimage2DArray image, ivec3 coord
751 * gimageCubeArray image, ivec3 coord
752 * gimage2DMS image, ivec2 coord, int sample
753 * gimage2DMSArray image, ivec3 coord, int sample"
755 * Pass an argument as address coordinate that doesn't match the
756 * dimensionality of the specified image.
758 layout(r32i) uniform i${image_type} img;
762 ${image_builtin}(img ${image_addr(fail = True)} ${image_args('int')});
764 """, product(image_load_builtin
+ image_store_builtin
+ image_atomic_builtins
,
765 image_types
, shader_stages
))
767 gen('builtin-qualifier-mismatch-readonly', """\
770 * From the ARB_shader_image_load_store spec:
772 * "It is an error to pass an image variable qualified with 'readonly'
773 * to imageStore() or other built-in functions that modify image
776 * Call a built-in function on a readonly qualified image.
778 layout(r32i) readonly uniform i${image_type} img;
782 ${image_builtin}(img ${image_addr()} ${image_args('int')});
784 """, product(image_store_builtin
+ image_atomic_builtins
,
785 image_types
[:1], shader_stages
))
787 gen('builtin-qualifier-mismatch-writeonly', """\
790 * From the ARB_shader_image_load_store spec:
792 * "It is an error to pass an image variable qualified with 'writeonly'
793 * to imageLoad() or other built-in functions that read image
796 * Call a built-in function on a writeonly qualified image.
798 layout(r32i) writeonly uniform i${image_type} img;
802 ${image_builtin}(img ${image_addr()} ${image_args('int')});
804 """, product(image_load_builtin
+ image_atomic_builtins
,
805 image_types
[:1], shader_stages
))
807 gen('builtin-memory-barrier', """\
816 if __name__
== '__main__':