• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1# AmberScript
2 * DRAFT
3
4This document defines the script input language for the Amber system. The format
5is based on the Talvos format, VkRunner format, and VkScript proposed format.
6
7## Specification
8All amber scripts must start with `#!amber` as the first line. Comments are
9specified by a # character and continue to the end of the line, except in
10inlined shader source code, where AmberScript comments are not
11possible. Keywords are case sensitive. All names are made up of ASCII
12characters, and delimited by whitespace.
13
14TODO(dneto): What characters are valid in a name?
15
16### Number literals
17
18Literal numbers are normally presented in decimal form.  They are interpreted
19as integers or floating point depending on context: a command parameter is
20predefined as either integral or floating point, or the data type is
21user-specified (such as for buffer data).
22
23Hex values: Whenever an integer is expected, you may use a hexadecimal number,
24which is the characters `0x` followed by hexadecimal digits.
25
26### Requesting features
27
28If specific device features are required you can use the `DEVICE_FEATURE`
29command to enable them.
30
31```groovy
32DEVICE_FEATURE vertexPipelineStoresAndAtomics
33DEVICE_FEATURE VariablePointerFeatures.variablePointersStorageBuffer
34```
35
36Currently each of the items in `VkPhysicalDeviceFeatures` are recognized along
37with:
38 * `VariablePointerFeatures.variablePointers`
39 * `VariablePointerFeatures.variablePointersStorageBuffer`
40 * `Float16Int8Features.shaderFloat16`
41 * `Float16Int8Features.shaderInt8`
42 * `Storage8BitFeatures.storageBuffer8BitAccess`
43 * `Storage8BitFeatures.uniformAndStorageBuffer8BitAccess`
44 * `Storage8BitFeatures.storagePushConstant8`
45 * `Storage16BitFeatures.storageBuffer16BitAccess`
46 * `Storage16BitFeatures.uniformAndStorageBuffer16BitAccess`
47 * `Storage16BitFeatures.storagePushConstant16`
48 * `Storage16BitFeatures.storageInputOutput16`
49 * `SubgroupSizeControl.subgroupSizeControl`
50 * `SubgroupSizeControl.computeFullSubgroups`
51 * `SubgroupSupportedOperations.basic`
52 * `SubgroupSupportedOperations.vote`
53 * `SubgroupSupportedOperations.arithmetic`
54 * `SubgroupSupportedOperations.ballot`
55 * `SubgroupSupportedOperations.shuffle`
56 * `SubgroupSupportedOperations.shuffleRelative`
57 * `SubgroupSupportedOperations.clustered`
58 * `SubgroupSupportedOperations.quad`
59 * `SubgroupSupportedStages.vertex`
60 * `SubgroupSupportedStages.tessellationControl`
61 * `SubgroupSupportedStages.tessellationEvaluation`
62 * `SubgroupSupportedStages.geometry`
63 * `SubgroupSupportedStages.fragment`
64 * `SubgroupSupportedStages.compute`
65 * `RayTracingPipelineFeaturesKHR.rayTracingPipeline`
66 * `AccelerationStructureFeaturesKHR.accelerationStructure`
67 * `BufferDeviceAddressFeatures.bufferDeviceAddress`
68
69Extensions can be enabled with the `DEVICE_EXTENSION` and `INSTANCE_EXTENSION`
70commands.
71
72```groovy
73DEVICE_EXTENSION VK_KHR_get_physical_device_properties2
74INSTANCE_EXTENSION VK_KHR_storage_buffer_storage_class
75```
76
77### Setting Engine Configuration
78
79In some instances there is extra data we want to provide to an engine for
80configuration purposes. The `SET ENGINE_DATA` command allows that for the given
81set of data types.
82
83#### Engine Data Variables
84  * `fence_timeout_ms`  - value must be a single uint32 in milliseconds.
85
86```groovy
87SET ENGINE_DATA {engine data variable} {value}*
88```
89
90### Virtual File Store
91
92Each amber script contains a virtual file system that can store files of textual
93data. This lets you bundle multiple source files into a single, hermetic amber
94script file.
95
96Virtual files are declared using the `VIRTUAL_FILE` command:
97
98```groovy
99VIRTUAL_FILE {path}
100 {file-content}
101END
102```
103
104Paths must be unique.
105
106Shaders can directly reference these virtual files for their source. \
107HLSL shaders that `#include` other `.hlsl` files will first check the virtual
108file system, before falling back to the standard file system.
109
110### Shaders
111
112Shader programs are declared using the `SHADER` command. \
113Shaders can be declared as `PASSTHROUGH`, with inlined source or using source
114from a `VIRTUAL_FILE` or from a `FILE` in the file system.
115
116Pass-through shader:
117
118```groovy
119# Creates a passthrough vertex shader. The shader passes the vec4 at input
120# location 0 through to the `gl_Position`.
121SHADER vertex {shader_name} PASSTHROUGH
122```
123
124Shader using inlined source:
125
126```groovy
127# Creates a shader of |shader_type| with the given |shader_name|. The shader
128# will be of |shader_format|. The shader source then follows and is terminated
129# with the |END| tag.
130SHADER {shader_type} {shader_name} {shader_format} [ TARGET_ENV {target_env} ]
131{shader_source}
132END
133```
134
135Shader using source from `VIRTUAL_FILE` or `FILE`:
136
137```groovy
138# Creates a shader of |shader_type| with the given |shader_name|. The shader
139# will be of |shader_format|. The shader will use the virtual file with |path|.
140SHADER {shader_type} {shader_name} {shader_format} [ TARGET_ENV {target_env} ] ( VIRTUAL_FILE | FILE ) {path}
141```
142
143`{shader_name}` is used to identify the shader to attach to `PIPELINE`s,
144
145`{shader_type}` and `{shader_format}` are described below:
146
147#### Shader Type
148 * `vertex`
149 * `fragment`
150 * `geometry`
151 * `tessellation_evaluation`
152 * `tessellation_control`
153 * `compute`
154 * `ray_generation`
155 * `any_hit`
156 * `closest_hit`
157 * `miss`
158 * `intersection`
159 * `callable`
160 * `multi`
161
162The compute pipeline can only contain compute shaders. The graphics pipeline
163can not contain compute shaders, and must contain a vertex shader and a fragment
164shader. Ray tracing pipeline can contain only shaders of ray tracing types:
165ray generation, any hit, closest hit, miss, intersection, and callable shaders.
166
167The provided `multi` shader can only be used with `SPIRV-ASM`, `SPIRV-HEX`, and
168`SPIRV-BIN` and allows for providing multiple shaders in a single module (so the
169`vertex` and `fragment` shaders can be provided together.)
170
171Note, `SPIRV-ASM`, `SPIRV-HEX`, and `SPIRV-BIN` can also be used with each of
172the other shader types, but in that case must only provide a single shader type
173in the module.
174
175#### Shader Format
176 * `GLSL`  (with glslang)
177 * `HLSL`  (with dxc or glslang if dxc disabled)
178 * `SPIRV-ASM` (with spirv-as; specifying `TARGET_ENV` is _highly recommended_
179    in this case, as explained below)
180 * `SPIRV-HEX` (decoded straight to SPIR-V)
181 * `SPIRV-BIN` (read as binary SPIR-V, only with `FILE`)
182 * `OPENCL-C` (with clspv)
183
184### Target environment
185
186Specifying `TARGET_ENV` is optional and can be used to select a target
187SPIR-V environment. For example:
188
189 * `spv1.0`
190 * `spv1.5`
191 * `vulkan1.0`
192 * `vulkan1.2`
193
194Check the help text of the corresponding tool (e.g. spirv-as, glslangValidator)
195for the full list. The `SPIRV-HEX` and `SPIRV-BIN` shader formats are not
196affected by the target environment.
197
198The specified target environment for the shader overrides the default (`spv1.0`)
199or the one specified on the command line.
200
201Specifying the target environment when using the `SPIRV-ASM` shader format
202is _highly recommended_, otherwise the SPIR-V version of the final SPIR-V binary
203shader passed to the graphics device might not be what you expect.
204Typically, SPIR-V assembly text will contain a comment near the beginning similar
205to `; Version: 1.0` but this is _ignored_ by the spirv-as assembler.
206Thus, you should specify the equivalent target environment (e.g. `spv1.0`)
207in the `SHADER` command.
208
209Specifying the target environment for other shader formats depends on whether
210you want to vary the final SPIR-V shader binary based on the target environment
211specified on the command line. For example, you could write one AmberScript file
212that contains a GLSL shader without specifying a target environment.
213You could then run the AmberScript file several times with different
214target environments specified on the command line
215(`spv1.0`, `spv1.1`, `spv1.2`, etc.) to test the different SPIR-V shader variants.
216
217### Buffers
218
219An AmberScript buffer represents a set of contiguous bits. This can be used for
220either image buffers or, what the target API would refer to as a buffer.
221
222#### Data Types
223 * `int8`
224 * `int16`
225 * `int32`
226 * `int64`
227 * `uint8`
228 * `uint16`
229 * `uint32`
230 * `uint64`
231 * `float16`
232 * `float`
233 * `double`
234 * vec[2,3,4]{type}
235 * mat[2,3,4]x[2,3,4]{type}  (mat<columns>x<rows>)
236 * Any of the `Image Formats` listed below.
237 * For any of the non-Image Formats types above appending '[]' will treat the
238    data as an array. e.g. int8[], vec2<float>[]
239
240Sized arrays and structures are not currently representable.
241
242```groovy
243# Filling the buffer with a given initializer. Initializer data must be
244# of |type|. Buffers are STD430 by default.
245BUFFER {name} DATA_TYPE {type} {STD140 | STD430} {initializer}
246
247# Defines a buffer which is filled with data as specified by the `initializer`.
248BUFFER {name} DATA_TYPE {type} {STD140 | STD430} SIZE _size_in_items_ \
249    {initializer}
250
251# Deprecated
252# Defines a buffer with width and height and filled by data as specified by the
253# `initializer`.
254BUFFER {name} DATA_TYPE {type} {STD140 | STD430} WIDTH {w} HEIGHT {h} \
255  {initializer}
256
257# Defines a buffer which is filled with binary data from a file specified
258# by `FILE`.
259BUFFER {name} DATA_TYPE {type} {STD140 | STD430} SIZE _size_in_items_ \
260    FILE BINARY {file_name}
261
262# Defines a buffer which is filled with text data parsed from a file specified
263# by `FILE`.
264BUFFER {name} DATA_TYPE {type} {STD140 | STD430} SIZE _size_in_items_ \
265    FILE TEXT {file_name}
266
267# Creates a buffer which will store the given `FORMAT` of data. These
268# buffers are used as image and depth buffers in the `PIPELINE` commands.
269# The buffer will be sized based on the `RENDER_SIZE` of the `PIPELINE`.
270# For multisampled images use value greater than one for `SAMPLES`. Allowed
271# sample counts are 1, 2, 4, 8, 16, 32, and 64. Note that Amber doesn't
272# preserve multisampled images across pipelines.
273BUFFER {name} FORMAT {format_string} \
274    [ MIP_LEVELS _mip_levels_ (default 1) ] \
275    [ SAMPLES _samples_ (default 1) ]
276
277# Load buffer data from a PNG image with file name specified by `FILE`.
278# The file path is relative to the script file being run. Format specified
279# by `FORMAT` must match the image format.
280BUFFER {name} FORMAT {format_string} FILE PNG {file_name.png}
281```
282
283#### Images
284
285An AmberScript image is a specialized buffer that specifies image-specific
286attributes.
287
288##### Dimensionality
289 * `DIM_1D` -- A 1-dimensional image
290 * `DIM_2D` -- A 2-dimensional image
291 * `DIM_3D` -- A 3-dimensional image
292
293```groovy
294# Specify an image buffer with a format. HEIGHT is necessary for DIM_2D and
295# DIM_3D. DEPTH is necessary for DIM_3D.
296IMAGE {name} FORMAT {format_string} [ MIP_LEVELS _mip_levels_ (default 1) ] \
297    [ SAMPLES _samples_ (default 1) ] \
298    {dimensionality} \
299    WIDTH {w} [ HEIGHT {h} [ DEPTH {d} ] ] \
300    {initializer}
301
302# Specify an image buffer with a data type. HEIGHT is necessary for DIM_2D and
303# DIM_3D. DEPTH is necessary for DIM_3D.
304IMAGE {name} DATA_TYPE {type} {dimensionality} \
305    WIDTH {w} [ HEIGHT {h} [ DEPTH {d} ] ] \
306    {intializer}
307```
308
309#### Buffer Initializers
310
311```groovy
312# Filling the buffer with a given set of data. The values must be
313# of the correct type. The data can be provided as the type or as a hex
314# value.
315DATA
316_value_+
317END
318
319```groovy
320# Fill the buffer with a single value.
321FILL _value_
322
323# Fill the buffer with an increasing value from |start| increasing by |inc|.
324# Floating point data uses floating point addition to generate increasing
325# values. Likewise, integer data uses integer addition to generate increasing
326# values.
327SERIES_FROM _start_ INC_BY _inc_
328```
329
330#### Buffer Copy
331
332```groovy
333# Copies all data, values and memory from |buffer_from| to |buffer_to|.
334# Both buffers must be declared, and of the same data type.
335# Buffers used as copy destination can be used only as copy destination, and as
336# argument to an EXPECT command.
337COPY {buffer_from} TO {buffer_to}
338```
339
340### Samplers
341
342Samplers are used for sampling buffers that are bound to a pipeline as
343sampled image or combined image sampler.
344
345#### Filter types
346 * `nearest`
347 * `linear`
348
349#### Address modes
350 * `repeat`
351 * `mirrored_repeat`
352 * `clamp_to_edge`
353 * `clamp_to_border`
354 * `mirrored_clamp_to_edge`
355
356#### Border colors
357 * `float_transparent_black`
358 * `int_transparent_black`
359 * `float_opaque_black`
360 * `int_opaque_black`
361 * `float_opaque_white`
362 * `int_opaque_white`
363
364#### Compare operations
365* `never`
366* `less`
367* `equal`
368* `less_or_equal`
369* `greater`
370* `not_equal`
371* `greater_or_equal`
372* `always`
373
374```groovy
375
376# Creates a sampler with |name|. |compare_enable| is either on or off.
377SAMPLER {name} \
378    [ MAG_FILTER {filter_type} (default nearest) ] \
379    [ MIN_FILTER {filter_type} (default nearest) ] \
380    [ ADDRESS_MODE_U {address_mode} (default repeat) ] \
381    [ ADDRESS_MODE_V {address_mode} (default repeat) ] \
382    [ ADDRESS_MODE_W {address_mode} (default repeat) ] \
383    [ BORDER_COLOR {border_color} (default float_transparent_black) ] \
384    [ MIN_LOD _val_ (default 0.0) ] \
385    [ MAX_LOD _val_ (default 1.0) ] \
386    [ NORMALIZED_COORDS | UNNORMALIZED_COORDS (default NORMALIZED_COORDS) ] \
387    [ COMPARE _compare_enable_ (default off) ] \
388    [ COMPARE_OP _compare_op_ (default never) ]
389```
390
391Note: unnormalized coordinates will override MIN\_LOD and MAX\_LOD to 0.0.
392
393#### OpenCL Literal Samplers
394
395Literal constant samplers defined in the OpenCL program are automatically
396generated and bound to the pipeline in Amber.
397
398Note: currently the border color is always transparent black.
399
400Note: the addressing mode is used for all coordinates currently. Arrayed images
401should use `clamp_to_edge` for the array index.
402
403### Acceleration Structures
404
405Acceleration structures are used to enumerate geometries to describe a scene.
406There are two kinds of acceleration structures:
407 * Bottom level
408 * Top level
409
410#### Bottom Level
411
412Bottom level acceleration structures consists of a set of geometries.
413Each bottom level acceleration structure can consists either of triangle or
414axis aligned bounding box (AABB) geometries. It is prohibited to mix triangle
415geometries and AABBs inside same bottom level acceleration structures.
416
417A bottom level acceleration structure consisting of triangle geometries is defined as:
418
419```groovy
420  # Bottom level acceleration structure consisting of triangles
421  ACCELERATION_STRUCTURE BOTTOM_LEVEL {name_of_bottom_level_acceleration_structure}
422    {GEOMETRY TRIANGLES
423      [FLAGS <geometry_flags>]
424      {x0 y0 z0
425       x1 y1 z1
426       x2 y2 z2}+
427    END}+
428  END
429```
430
431A bottom level acceleration structure consisting of axis aligned bounding boxes is defined as:
432
433```groovy
434  # Bottom level acceleration structure consisting of AABBs
435  ACCELERATION_STRUCTURE BOTTOM_LEVEL {name_of_bottom_level_acceleration_structure}
436    {GEOMETRY AABBS
437      [FLAGS <geometry_flags>]
438      {x0 y0 z0 x1 y1 z1}+
439    END}+
440  END
441```
442
443Each coordinate |x{n}|, |y{n}|, and |z{n}| should be floating point values.
444
445FLAGS is a space separated list of following geometry flags:
446 * OPAQUE
447 * NO_DUPLICATE_ANY_HIT
448
449#### Top Level
450
451Top level acceleration structures consists of a set of instances of bottom
452level acceleration structures.
453
454```groovy
455  # Acceleration structure with instance defined in one line
456  ACCELERATION_STRUCTURE TOP_LEVEL {name_of_top_level_acceleration_structure}
457    {BLAS_INSTANCE USE {name_of_bottom_level_acceleration_structure}}+
458  END
459
460  # Acceleration structure with instance defined in multiple lines
461  ACCELERATION_STRUCTURE TOP_LEVEL {name_of_top_level_acceleration_structure}
462    {BOTTOM_LEVEL_INSTANCE {name_of_bottom_level_acceleration_structure}
463      [INDEX {index}]
464      [OFFSET {offset}]
465      [FLAGS {flags}]
466      [MASK {mask}]
467      [TRANSFORM \
468        {transform} \
469      END]
470    END}+
471  END
472```
473
474The value of |index| should be an integer in range of [0..16,777,215] is a 24-bit user-specified
475index value accessible to ray shaders in the InstanceCustomIndexKHR built-in.
476
477The value of |offset| should be an integer in range of [0..16,777,215] is a 24-bit offset used
478in calculating the hit shader binding table index.
479
480The value of |mask| should be an integer in range of [0..255] (may be specified as 0xNN) is an
4818-bit visibility mask for the geometry.
482
483The value of |flags| is space-separated or EOL-separated list of following:
484 * `TRIANGLE_FACING_CULL_DISABLE`
485 * `TRIANGLE_FLIP_FACING`
486 * `FORCE_OPAQUE`
487 * `FORCE_NO_OPAQUE`
488 * `FORCE_OPACITY_MICROMAP_2_STATE`
489 * `DISABLE_OPACITY_MICROMAPS`
490 * <any integer number>
491
492If |flags| is a EOL-separated list it should be ended with END statement.
493If |flags| is a space-separated list it should not be ended with END statement.
494
495The |transform| is 12 space-separated values describing a 3x4 row-major affine transformation matrix applied to
496the acceleration structure.
497
498
499### Pipelines
500
501#### Pipeline type
502 * `compute`
503 * `graphics`
504 * `ray_tracing`
505
506```groovy
507# The PIPELINE command creates a pipeline. This can be either compute,
508# graphics, or ray_tracing. Shaders are attached to the pipeline
509# at pipeline creation time.
510PIPELINE {pipeline_type} {pipeline_name}
511...
512END
513
514# Create a pipeline and inherit from a previously declared pipeline.
515DERIVE_PIPELINE {pipeline_name} FROM {parent_pipeline}
516...
517END
518```
519
520### Pipeline Content
521
522The following commands are all specified within the `PIPELINE` command.
523```groovy
524  # Attach the shader provided by |name_of_shader| to the pipeline with an
525  # entry point name of |name|. The provided shader for ATTACH must _not_ be
526  # a 'multi' shader.
527  ATTACH {name_of_shader} \
528      [ ENTRY_POINT {name} (default "main") ]
529
530  # Attach a 'multi' shader to the pipeline of |shader_type| and use the entry
531  # point with |name|. The provided shader _must_ be a 'multi' shader.
532  ATTACH {name_of_multi_shader} TYPE {shader_type} ENTRY_POINT {name}
533
534  # Attach specialized shader. Specialization can be specified multiple times.
535  # Specialization values must be a 32-bit type. Shader type and entry point
536  # must be specified prior to specializing the shader.
537  ATTACH {name_of_shader} SPECIALIZE _id_ AS uint32 _value_
538  ATTACH {name_of_shader} \
539      SPECIALIZE _id_ AS uint32 _value_ \
540      SPECIALIZE _id_ AS float _value_
541```
542
543```groovy
544  # Set the SPIRV-Tools optimization passes to use for a given shader. The
545  # default is to run no optimization passes.
546  SHADER_OPTIMIZATION {shader_name}
547    {optimization_name}+
548  END
549```
550
551```groovy
552  # Set the compile options used to compile the given shader. Options are parsed
553  # the same as on the command line. Currently, only supported for OPENCL-C shaders.
554  COMPILE_OPTIONS {shader_name}
555    {option}+
556  END
557```
558
559```groovy
560  # Set the polygon mode used for all drawing with the pipeline.
561  # |mode| is fill, line, or point and it defaults to fill.
562  POLYGON_MODE {mode}
563```
564
565```groovy
566  # Set the number of patch control points used by tessellation. The default value is 3.
567  PATCH_CONTROL_POINTS {control_points}
568```
569
570Ray tracing pipelines do not attach shaders directly like compute or graphics pipelines.
571Ray tracing pipelines organize shaders into shader groups in one of four ways
572depending on shader types used:
573
574```groovy
575  # Four possible shader group definitions
576  SHADER_GROUP {group_name_1} {ray_generation_shader_name}
577  SHADER_GROUP {group_name_2} {miss_shader_name}
578  SHADER_GROUP {group_name_3} {call_shader_name}
579  SHADER_GROUP {group_name_4} [closest_hit_shader_name] [any_hit_shader_name] [intersection_shader_name]
580```
581
582Shader group cannot be empty.
583Each group name must be unique within a pipeline. The same shader can be used within one or more
584shader groups. The shader group order is important, further commands as shader code might refer
585them directly. With the shader groups defined, they are then added into shader binding tables:
586
587```groovy
588  # Create shader binding tables and set shader groups into it
589  SHADER_BINDING_TABLE {sbt_name}
590    {group_name_1}
591    [ | {group_name_n}]
592  END
593```
594
595Generally a program needs three shader binding tables:
596 * ray generation shader binding table with one ray generation shader group
597 * miss shader binding table containing one or more miss shader groups
598 * hit shader binding table containing one or more hit shader groups
599
600Shader binding tables for call shaders are optional.
601
602Ray tracing pipelines support pipeline libraries. To declare a pipeline as a pipeline library
603the pipeline should declare itself a library by specifying `LIBRARY` in `FLAGS`:
604
605```groovy
606  # Declare this pipeline as a library
607  FLAGS LIBRARY
608```
609
610or multiline version:
611
612```groovy
613  # Declare this pipeline as a library
614  FLAGS
615    LIBRARY
616  END
617```
618
619Pipeline `FLAGS` can contain:
620
621 * `LIBRARY`
622
623Ray tracing pipeline can include one or more pipeline libraries:
624
625```groovy
626  # Specify list of libraries to use
627  USE_LIBRARY {library_name_1} [{library_name_2} [...]]
628```
629
630Ray tracing pipelines that declare and use pipeline libraries should declare
631the maximum ray payload size and the maximum ray hit attribute size:
632```groovy
633  # Define maximum ray payload size
634  MAX_RAY_PAYLOAD_SIZE <max_ray_payload_size>
635  # Define maximum ray hit attribute size
636  MAX_RAY_HIT_ATTRIBUTE_SIZE <max_ray_hit_attribute_size>
637```
638
639Default for both maximum ray payload size and maximum ray hit attribute size is zero.
640If there is a pipeline which uses a pipeline library then the `MAX_RAY_PAYLOAD_SIZE` and `MAX_RAY_HIT_ATTRIBUTE_SIZE`
641values must be the same between the pipeline and all the pipeline libraries used.
642
643Used libraries must precede shader group `SHADER_GROUP` and shader binding tables
644`SHADER_BINDING_TABLE` declarations. A pipeline can be a library and use other pipelines as a libraries.
645
646Ray tracing pipelines can declare a maximum ray recursion depth:
647
648```groovy
649  # Define maximum ray recursion depth
650  MAX_RAY_RECURSION_DEPTH <max_ray_recursion_depth>
651```
652
653If the MAX_RAY_RECURSION_DEPTH is not specified, then maximum ray recursion depth is set to 1.
654
655If a pipeline library is used within this pipeline (via `USE_LIBRARY` keyword), then the
656shader binding table can use shader groups from any of the used libraries.
657
658#### Compare operations
659 * `never`
660 * `less`
661 * `equal`
662 * `less_or_equal`
663 * `greater`
664 * `not_equal`
665 * `greater_or_equal`
666 * `always`
667
668```groovy
669  # Set depth test settings. All enable options are specified with keywords on and off.
670  # BOUNDS and BIAS values are specified with decimal numbers. |compare_op| is selected
671  # from the list of compare operations above.
672  DEPTH
673    TEST {test_enable}
674    WRITE {write_enable}
675    COMPARE_OP {compare_op}
676    CLAMP {clamp_enable}
677    BOUNDS min {bound_min} max {bounds_max}
678    BIAS constant {bias_constant} clamp {bias_clamp} slope {bias_slope}
679  END
680```
681
682#### Stencil operations
683 * `keep`
684 * `replace`
685 * `increment_and_clamp`
686 * `decrement_and_clamp`
687 * `invert`
688 * `increment_and_wrap`
689 * `decrement_and_wrap`
690
691```groovy
692  # Set stencil test settings. |face| can be front, back, or front_and_back.
693  # |test_enable| is either on or off and affects both faces. |fail_op|, |pass_op|,
694  # and |depth_fail_op| are selected from the stencil operations table above,
695  # and |compare_op| from the compare operations table. |compare_mask|, |write_mask|,
696  # and |reference| are 8bit unsigned integer values (range 0..255).
697  STENCIL {face}
698    TEST {test_enable}
699    FAIL_OP {fail_op}
700    PASS_OP {pass_op}
701    DEPTH_FAIL_OP {depth_fail_op}
702    COMPARE_OP {compare_op}
703    COMPARE_MASK {compare_mask}
704    WRITE_MASK {write_mask}
705    REFERENCE {reference}
706  END
707```
708
709#### Blend factors
710* `zero`
711* `one`
712* `src_color`
713* `one_minus_src_color`
714* `dst_color`
715* `one_minus_dst_color`
716* `src_alpha`
717* `one_minus_src_alpha`
718* `dst_alpha`
719* `one_minus_dst_alpha`
720* `constant_color`
721* `one_minus_constant_color`
722* `constant_alpha`
723* `one_minus_constant_alpha`
724* `src_alpha_saturate`
725* `src1_color`
726* `one_minus_src1_color`
727* `src1_alpha`
728* `one_minus_src1_alpha`
729
730#### Blend operations
731* `add`
732* `substract`
733* `reverse_substract`
734* `min`
735* `max`
736
737The following operations also require VK_EXT_blend_operation_advanced
738when using a Vulkan backend.
739* `zero`
740* `src`
741* `dst`
742* `src_over`
743* `dst_over`
744* `src_in`
745* `dst_in`
746* `src_out`
747* `dst_out`
748* `src_atop`
749* `dst_atop`
750* `xor`
751* `multiply`
752* `screen`
753* `overlay`
754* `darken`
755* `lighten`
756* `color_dodge`
757* `color_burn`
758* `hard_light`
759* `soft_light`
760* `difference`
761* `exclusion`
762* `invert`
763* `invert_rgb`
764* `linear_dodge`
765* `linear_burn`
766* `vivid_light`
767* `linear_light`
768* `pin_light`
769* `hard_mix`
770* `hsl_hue`
771* `hsl_saturation`
772* `hsl_color`
773* `hsl_luminosity`
774* `plus`
775* `plus_clamped`
776* `plus_clamped_alpha`
777* `plus_darker`
778* `minus`
779* `minus_clamped`
780* `contrast`
781* `invert_org`
782* `red`
783* `green`
784* `blue`
785
786```groovy
787  # Enable alpha blending and set blend factors and operations. Available
788  # blend factors and operations are listed above.
789  BLEND
790    SRC_COLOR_FACTOR {src_color_factor}
791    DST_COLOR_FACTOR {dst_color_factor}
792    COLOR_OP {color_op}
793    SRC_ALPHA_FACTOR {src_alpha_factor}
794    DST_ALPHA_FACTOR {dst_alpha_factor}
795    ALPHA_OP {alpha_op}
796  END
797```
798
799```groovy
800  # Set the size of the render buffers. |width| and |height| are integers and
801  # default to 250x250.
802  FRAMEBUFFER_SIZE _width_ _height_
803```
804
805```groovy
806  # Set the viewport size. If no viewport is provided then it defaults to the
807  # whole framebuffer size. Depth range defaults to 0 to 1.
808  VIEWPORT {x} {y} SIZE {width} {height} [MIN_DEPTH {mind}] [MAX_DEPTH {maxd}]
809```
810
811```groovy
812  # Set subgroup size control setting. Require that subgroups must be launched
813  # with all invocations active for given shader. Allow SubgroupSize to vary
814  # for given shader. Require a specific SubgroupSize the for given shader.
815  # |fully_populated_enable| and |varying_size_enable| can be on or off.
816  # |subgroup_size| can be set one of the values below:
817  #  - a power-of-two integer that _must_ be greater or equal to minSubgroupSize
818  #    and be less than or equal to maxSubgroupSize
819  # - MIN to set the required subgroup size to the minSubgroupSize
820  # - MAX to set the required subgroup size to the maxSubgroupSize
821  SUBGROUP {name_of_shader}
822    FULLY_POPULATED {fully_populated_enable}
823    VARYING_SIZE {varying_size_enable}
824    REQUIRED_SIZE {subgroup_size}
825  END
826```
827
828### Pipeline Buffers
829
830#### Buffer Types
831 * `uniform`
832 * `storage`
833 * `uniform_dynamic`
834 * `storage_dynamic`
835 * `uniform_texel_buffer`
836 * `storage_texel_buffer`
837
838TODO(dsinclair): Sync the BufferTypes with the list of Vulkan Descriptor types.
839
840A `pipeline` can have buffers or samplers bound. This includes buffers to
841contain image attachment content, depth/stencil content, uniform buffers, etc.
842
843```groovy
844  # Attach |buffer_name| as an output color attachment at location |idx|.
845  # The provided buffer must be a `FORMAT` buffer. If no color attachments are
846  # provided a single attachment with format `B8G8R8A8_UNORM` will be created
847  # for graphics pipelines. The MIP level will have a base of |level|.
848  BIND BUFFER {buffer_name} AS color LOCATION _idx_ \
849      [ BASE_MIP_LEVEL _level_ (default 0) ]
850
851  # Attach |buffer_name| as the depth/stencil buffer. The provided buffer must
852  # be a `FORMAT` buffer. If no depth/stencil buffer is specified a default
853  # buffer of format `D32_SFLOAT_S8_UINT` will be created for graphics
854  # pipelines.
855  BIND BUFFER {buffer_name} AS depth_stencil
856
857  # Attach |buffer_name| as a multisample resolve target. The order of resolve
858  # target images match with the order of color attachments that have more than
859  # one sample.
860  BIND BUFFER {buffer_name} AS resolve
861
862  # Attach |buffer_name| as the push_constant buffer. There can be only one
863  # push constant buffer attached to a pipeline.
864  BIND BUFFER {buffer_name} AS push_constant
865
866  # Bind OpenCL argument buffer by name. Specifying the buffer type is optional.
867  # Amber will set the type as appropriate for the argument buffer. All uses
868  # of the buffer must have a consistent |buffer_type| across all pipelines.
869  BIND BUFFER {buffer_name} [ AS {buffer_type} (default computed)] \
870      KERNEL ARG_NAME _name_
871
872  # Bind OpenCL argument buffer by argument ordinal. Arguments use 0-based
873  # numbering. Specifying the buffer type is optional. Amber will set the
874  # type as appropriate for the argument buffer. All uses of the buffer
875  # must have a consistent |buffer_type| across all pipelines.
876  BIND BUFFER {buffer_name} [ AS {buffer_type} (default computed)] \
877      KERNEL ARG_NUMBER _number_
878
879  # Bind OpenCL argument sampler by argument name.
880  BIND SAMPLER {sampler_name} KERNEL ARG_NAME _name_
881
882  # Bind OpenCL argument sampler by argument ordinal. Arguments use 0-based
883  # numbering.
884  BIND SAMPLER {sampler_name} KERNEL ARG_NUMBER _number_
885```
886
887All BIND BUFFER and BIND SAMPLER commands below define a descriptor set and binding ID.
888These commands can be replaced with BIND BUFFER_ARRAY and BIND SAMPLER_ARRAY commands.
889In these cases multiple buffer or sampler names need to be provided, separated by spaces.
890This creates a descriptor array of buffers or samplers bound to the same descriptor set
891and binding ID. An array of dynamic offsets should be provided via `OFFSET offset1 offset2 ...`
892when using dynamic buffers with BUFFER_ARRAY. Optional descriptor binding offset(s) and range(s)
893can be defined via `DESCRIPTOR_OFFSET offset1 offset2 ...` and
894`DESCRIPTOR_RANGE range1 range2 ...` when using uniform or storage buffers. Offsets and
895ranges can be used also with dynamic buffers.
896```groovy
897  # Bind the buffer of the given |buffer_type| at the given descriptor set
898  # and binding. The buffer will use a byte offset |descriptor_offset|
899  # with range |range|.
900  BIND {BUFFER | BUFFER_ARRAY} {buffer_name} AS {buffer_type} DESCRIPTOR_SET _id_ \
901       BINDING _id_ [ DESCRIPTOR_OFFSET _descriptor_offset_ (default 0) ] \
902       [ DESCRIPTOR_RANGE _range_ (default -1 == VK_WHOLE_SIZE) ]
903
904  # Attach |buffer_name| as a storage image. The MIP level will have a base
905  # value of |level|.
906  BIND {BUFFER | BUFFER_ARRAY} {buffer_name} AS storage_image \
907      DESCRIPTOR_SET _id_ BINDING _id_ [ BASE_MIP_LEVEL _level_ (default 0) ]
908
909  # Attach |buffer_name| as a sampled image.  The MIP level will have a base
910  # value of |level|.
911  BIND {BUFFER | BUFFER_ARRAY} {buffer_name} AS sampled_image \
912      DESCRIPTOR_SET _id_ BINDING _id_ [ BASE_MIP_LEVEL _level_ (default 0) ]
913
914  # Attach |buffer_name| as a combined image sampler. A sampler |sampler_name|
915  # must also be specified. The MIP level will have a base value of 0.
916  BIND {BUFFER | BUFFER_ARRAY} {buffer_name} AS combined_image_sampler SAMPLER {sampler_name} \
917      DESCRIPTOR_SET _id_ BINDING _id_ [ BASE_MIP_LEVEL _level_ (default 0) ]
918
919  # Bind the sampler at the given descriptor set and binding.
920  BIND {SAMPLER | SAMPLER_ARRAY} {sampler_name} DESCRIPTOR_SET _id_ BINDING _id_
921
922  # Bind |buffer_name| as dynamic uniform/storage buffer at the given descriptor set
923  # and binding. The buffer will use a byte offset |offset| + |descriptor_offset|
924  # with range |range|.
925  BIND {BUFFER | BUFFER_ARRAY} {buffer_name} AS {uniform_dynamic | storage_dynamic} \
926       DESCRIPTOR_SET _id_ BINDING _id_ OFFSET _offset_ \
927       [ DESCRIPTOR_OFFSET _descriptor_offset_ (default 0) ] \
928       [ DESCRIPTOR_RANGE _range_ (default -1 == VK_WHOLE_SIZE) ]
929```
930
931```groovy
932  # Set |buffer_name| as the vertex data at location |val|. RATE defines the
933  # input rate for vertex attribute reading. OFFSET sets the byte offset for the
934  # vertex data within the buffer |buffer_name|, which by default is 0. FORMAT
935  # sets the vertex buffer format, which by default is the format of the buffer
936  # |buffer_name|. STRIDE sets the byte stride, which by default is the stride
937  # of the format (set explicitly via FORMAT or from the format of the buffer
938  # |buffer_name|).
939  VERTEX_DATA {buffer_name} LOCATION _val_ [ RATE { vertex | instance } (default vertex) ] \
940        [ FORMAT {format} ] [ OFFSET {offset} ] [ STRIDE {stride} ]
941
942  # Set |buffer_name| as the index data to use for `INDEXED` draw commands.
943  INDEX_DATA {buffer_name}
944```
945
946Ray tracing pipelines allow bind top level acceleration structures.
947
948```groovy
949  # Bind the top level acceleration structure at the given descriptor set and binding.
950  BIND ACCELERATION_STRUCTURE {tlas_name} DESCRIPTOR_SET _set_id_ BINDING _id_
951```
952
953#### OpenCL Plain-Old-Data Arguments
954OpenCL kernels can have plain-old-data (pod or pod_ubo in the desriptor map)
955arguments set their data via this command. Amber will generate the appropriate
956buffers for the pipeline populated with the specified data.
957
958```groovy
959  # Set argument |name| to |data_type| with value |val|.
960  SET KERNEL ARG_NAME _name_ AS {data_type} _val_
961
962  # Set argument |number| to |data_type| with value |val|.
963  # Arguments use 0-based numbering.
964  SET KERNEL ARG_NUMBER _number_ AS {data_type} _val_
965```
966
967#### Topologies
968 * `POINT_LIST`
969 * `LINE_LIST`
970 * `LINE_LIST_WITH_ADJACENCY`
971 * `LINE_STRIP`
972 * `LINE_STRIP_WITH_ADJACENCY`
973 * `TRIANGLE_LIST`
974 * `TRIANGLE_LIST_WITH_ADJACENCY`
975 * `TRIANGLE_STRIP`
976 * `TRIANGLE_STRIP_WITH_ADJACENCY`
977 * `TRIANGLE_fan`
978 * `PATCH_LIST`
979
980### Run a pipeline.
981
982When running a `DRAW_ARRAY` command, you must attach the vertex data to the
983`PIPELINE` with the `VERTEX_DATA` command.
984
985To run an indexed draw, attach the index data to the `PIPELINE` with an
986`INDEX_DATA` command.
987
988For the commands which take a `START_IDX` and a `COUNT` they can be left off the
989command (although, `START_IDX` is required if `COUNT` is provided). The default
990value for `START_IDX` is 0. The default value for `COUNT` is the item count of
991vertex buffer minus the `START_IDX`. The same applies to `START_INSTANCE`
992(default 0) and `INSTANCE_COUNT` (default 1).
993
994The `TIMED_EXECUTION` is an optional flag that can be passed to the run command.
995This will cause Amber to insert device specific counters to time the execution
996of this pipeline command.
997
998```groovy
999# Run the given |pipeline_name| which must be a `compute` pipeline. The
1000# pipeline will be run with the given number of workgroups in the |x|, |y|, |z|
1001# dimensions. Each of the x, y and z values must be a uint32.
1002RUN [TIMED_EXECUTION] {pipeline_name} _x_ _y_ _z_
1003```
1004
1005```groovy
1006# Run the given |pipeline_name| which must be a `graphics` pipeline. The
1007# rectangle at |x|, |y|, |width|x|height| will be rendered. Ignores VERTEX_DATA
1008# and INDEX_DATA on the given pipeline.
1009RUN [TIMED_EXECUTION] {pipeline_name} \
1010  DRAW_RECT POS _x_in_pixels_ _y_in_pixels_ \
1011  SIZE _width_in_pixels_ _height_in_pixels_
1012```
1013
1014```groovy
1015# Run the given |pipeline_name| which must be a `graphics` pipeline. The
1016# grid at |x|, |y|, |width|x|height|, |columns|x|rows| will be rendered.
1017# Ignores VERTEX_DATA and INDEX_DATA on the given pipeline.
1018# For columns, rows of (5, 4) a total of 5*4=20 rectangles will be drawn.
1019RUN [TIMED_EXECUTION] {pipeline_name} \
1020  DRAW_GRID POS _x_in_pixels_ _y_in_pixels_ \
1021  SIZE _width_in_pixels_ _height_in_pixels_ \
1022  CELLS _columns_of_cells_ _rows_of_cells_
1023```
1024
1025```groovy
1026# Run the |pipeline_name| which must be a `graphics` pipeline. The vertex
1027# data must be attached to the pipeline.
1028
1029# A start index of |value| will be used and the count of |count_value| items
1030# will be processed. The draw is instanced if |inst_count_value| is greater
1031# than one. In case of instanced draw |inst_value| controls the starting
1032# instance ID.
1033RUN [TIMED_EXECUTION] {pipeline_name} DRAW_ARRAY AS {topology} \
1034    [ START_IDX _value_ (default 0) ] \
1035    [ COUNT _count_value_ (default vertex_buffer size - start_idx) ] \
1036    [ START_INSTANCE _inst_value_ (default 0) ] \
1037    [ INSTANCE_COUNT _inst_count_value_ (default 1) ]
1038```
1039
1040```groovy
1041# Run the |pipeline_name| which must be a `graphics` pipeline. The vertex
1042# data and  index data must be attached to the pipeline. The vertices will be
1043# drawn using the given |topology|.
1044#
1045# A start index of |value| will be used and the count of |count_value| items
1046# will be processed. The draw is instanced if |inst_count_value| is greater
1047# than one. In case of instanced draw |inst_value| controls the starting
1048# instance ID.
1049RUN [TIMED_EXECUTION] {pipeline_name} DRAW_ARRAY AS {topology} INDEXED \
1050    [ START_IDX _value_ (default 0) ] \
1051    [ COUNT _count_value_ (default index_buffer size - start_idx) ] \
1052    [ START_INSTANCE _inst_value_ (default 0) ] \
1053    [ INSTANCE_COUNT _inst_count_value_ (default 1) ]
1054```
1055
1056```groovy
1057# Run the |pipeline_name| which must be a `ray tracing` pipeline.
1058# Next four shader binding table names should be specified:
1059# * RAYGEN |ray_gen_sbt_name| - shader binding table containing ray generation shader group
1060# * MISS |miss_sbt_name| - shader binding table containing one or more miss shader groups
1061# * HIT |hit_sbt_name| - shader binding table containing one or more hit shader groups
1062# * CALL |call_sbt_name| - shader binding table containing one or more call shader groups
1063# RAYGEN is required, other shader binding tables (MISS, HIT and CALL) are optional.
1064#
1065# The pipeline will be run with the given ray tracing dimensions |x|, |y|, |z|.
1066# Each of the x, y and z values must be a uint32.
1067RUN [TIMED_EXECUTION] {pipeline_name} \
1068    RAYGEN {ray_gen_sbt_name} \
1069    [MISS {miss_sbt_name}] \
1070    [HIT {hit_sbt_name}] \
1071    [CALL {call_sbt_name}] \
1072     _x_ _y_ _z_
1073```
1074
1075### Repeating commands
1076
1077```groovy
1078# It is sometimes useful to run a given draw command multiple times. This can be
1079# to detect deterministic rendering or other features.
1080REPEAT {count}
1081{command}+
1082END
1083```
1084
1085The commands which can be used inside a `REPEAT` block are:
1086  * `CLEAR`
1087  * `CLEAR_COLOR`
1088  * `CLEAR_DEPTH`
1089  * `CLEAR_STENCIL`
1090  * `COPY`
1091  * `EXPECT`
1092  * `RUN`
1093
1094### Commands
1095
1096```groovy
1097# Sets the clear color to use for |pipeline| which must be a graphics
1098# pipeline. The colors are integers from 0 - 255.  Defaults to (0, 0, 0, 0)
1099CLEAR_COLOR {pipeline} _r (0 - 255)_ _g (0 - 255)_ _b (0 - 255)_ _a (0 - 255)_
1100
1101# Sets the depth clear value to use for |pipeline| which must be a graphics
1102# pipeline. |value| must be a decimal number.
1103CLEAR_DEPTH {pipeline} _value_
1104
1105# Sets the stencil clear value to use for |pipeline| which must be a graphics
1106# pipeline. |value| must be an integer from 0 - 255.
1107CLEAR_STENCIL {pipeline} _value_
1108
1109# Instructs the |pipeline| which must be a graphics pipeline to execute the
1110# clear command.
1111CLEAR {pipeline}
1112```
1113
1114### Expectations
1115
1116#### Comparators
1117 * `EQ`
1118 * `NE`
1119 * `LT`
1120 * `LE`
1121 * `GT`
1122 * `GE`
1123 * `EQ_RGB`
1124 * `EQ_RGBA`
1125 * `EQ_BUFFER`
1126 * `RMSE_BUFFER`
1127 * `EQ_HISTOGRAM_EMD_BUFFER`
1128
1129```groovy
1130# Checks that |buffer_name| at |x| has the given |value|s when compared
1131# with the given |comparator|.
1132EXPECT {buffer_name} IDX _x_ {comparator} _value_+
1133
1134# Checks that |buffer_name| at |x| has values within |tolerance| of |value|
1135# The |tolerance| can be specified as 1-4 float values separated by spaces.
1136# The tolerances may be given as a percentage by placing a '%' symbol after
1137# the value. If less tolerance values are provided then are needed for a given
1138# data component the default tolerance will be applied.
1139EXPECT {buffer_name} IDX _x_ TOLERANCE _tolerance_{1,4} EQ _value_+
1140
1141# Checks that |buffer_name| at |x|, |y| for |width|x|height| pixels has the
1142# given |r|, |g|, |b| values. Each r, g, b value is an integer from 0-255.
1143EXPECT {buffer_name} IDX _x_in_pixels_ _y_in_pixels_ \
1144  SIZE _width_in_pixels_ _height_in_pixels_ \
1145  EQ_RGB _r (0 - 255)_ _g (0 - 255)_ _b (0 - 255)_
1146
1147# Checks that |buffer_name| at |x|, |y| for |width|x|height| pixels has the
1148# given |r|, |g|, |b|, |a| values. Each r, g, b, a value is an integer
1149# from 0-255.
1150EXPECT {buffer_name} IDX _x_in_pixels_ _y_in_pixels_ \
1151  SIZE _width_in_pixels_ _height_in_pixels_ \
1152  EQ_RGBA _r (0 - 255)_ _g (0 - 255)_ _b (0 - 255)_ _a (0 - 255)_
1153
1154# Checks that |buffer_1| contents are equal to those of |buffer_2|
1155EXPECT {buffer_1} EQ_BUFFER {buffer_2}
1156
1157# Checks that the Root Mean Square Error when comparing |buffer_1| to
1158# |buffer_2| is less than or equal to |tolerance|. Note, |tolerance| is a
1159# unit-less number.
1160EXPECT {buffer_1} RMSE_BUFFER {buffer_2} TOLERANCE _value_
1161
1162# Checks that the Earth Mover's Distance when comparing histograms of
1163# |buffer_1| to |buffer_2| is less than or equal to |tolerance|.
1164# Note, |tolerance| is a unit-less number.
1165EXPECT {buffer_1} EQ_HISTOGRAM_EMD_BUFFER {buffer_2} TOLERANCE _value_
1166```
1167
1168## Examples
1169
1170### Compute Shader
1171
1172```groovy
1173#!amber
1174# Simple amber compute shader.
1175
1176SHADER compute kComputeShader GLSL
1177#version 450
1178
1179layout(binding = 3) buffer block {
1180  uvec2 values[];
1181};
1182
1183void main() {
1184  values[gl_WorkGroupID.x + gl_WorkGroupID.y * gl_NumWorkGroups.x] =
1185                gl_WorkGroupID.xy;
1186}
1187END  # shader
1188
1189BUFFER kComputeBuffer DATA_TYPE vec2<int32> SIZE 524288 FILL 0
1190
1191PIPELINE compute kComputePipeline
1192  ATTACH kComputeShader
1193  BIND BUFFER kComputeBuffer AS storage DESCRIPTOR_SET 0 BINDING 3
1194END  # pipeline
1195
1196RUN kComputePipeline 256 256 1
1197
1198# Four corners
1199EXPECT kComputeBuffer IDX 0 EQ 0 0
1200EXPECT kComputeBuffer IDX 2040 EQ 255 0
1201EXPECT kComputeBuffer IDX 522240 EQ 0 255
1202EXPECT kComputeBuffer IDX 524280 EQ 255 255
1203
1204# Center
1205EXPECT kComputeBuffer IDX 263168 EQ 128 128
1206```
1207
1208### Entry Points
1209
1210```groovy
1211#!amber
1212
1213SHADER vertex kVertexShader PASSTHROUGH
1214
1215SHADER fragment kFragmentShader SPIRV-ASM
1216              OpCapability Shader
1217          %1 = OpExtInstImport "GLSL.std.450"
1218               OpMemoryModel Logical GLSL450
1219
1220; two entrypoints
1221               OpEntryPoint Fragment %red "red" %color
1222               OpEntryPoint Fragment %green "green" %color
1223
1224               OpExecutionMode %red OriginUpperLeft
1225               OpExecutionMode %green OriginUpperLeft
1226               OpSource GLSL 430
1227               OpName %red "red"
1228               OpDecorate %color Location 0
1229       %void = OpTypeVoid
1230          %3 = OpTypeFunction %void
1231      %float = OpTypeFloat 32
1232    %v4float = OpTypeVector %float 4
1233%_ptr_Output_v4float = OpTypePointer Output %v4float
1234      %color = OpVariable %_ptr_Output_v4float Output
1235    %float_1 = OpConstant %float 1
1236    %float_0 = OpConstant %float 0
1237  %red_color = OpConstantComposite %v4float %float_1 %float_0 %float_0 %float_1
1238%green_color = OpConstantComposite %v4float %float_0 %float_1 %float_0 %float_1
1239
1240; this entrypoint outputs a red color
1241        %red = OpFunction %void None %3
1242          %5 = OpLabel
1243               OpStore %color %red_color
1244               OpReturn
1245               OpFunctionEnd
1246
1247; this entrypoint outputs a green color
1248      %green = OpFunction %void None %3
1249          %6 = OpLabel
1250               OpStore %color %green_color
1251               OpReturn
1252               OpFunctionEnd
1253END  # shader
1254
1255BUFFER kImgBuffer FORMAT R8G8B8A8_UINT
1256
1257PIPELINE graphics kRedPipeline
1258  ATTACH kVertexShader ENTRY_POINT main
1259  SHADER_OPTIMIZATION kVertexShader
1260    --eliminate-dead-branches
1261    --merge-return
1262    --eliminate-dead-code-aggressive
1263  END
1264  ATTACH kFragmentShader ENTRY_POINT red
1265
1266  FRAMEBUFFER_SIZE 256 256
1267  BIND BUFFER kImgBuffer AS color LOCATION 0
1268END  # pipeline
1269
1270PIPELINE graphics kGreenPipeline
1271  ATTACH kVertexShader
1272  ATTACH kFragmentShader ENTRY_POINT green
1273
1274  FRAMEBUFFER_SIZE 256 256
1275  BIND BUFFER kImgBuffer AS color LOCATION 0
1276END  # pipeline
1277
1278RUN kRedPipeline DRAW_RECT POS 0 0 SIZE 256 256
1279RUN kGreenPipeline DRAW_RECT POS 128 128 SIZE 256 256
1280
1281EXPECT kImgBuffer IDX 0 0 SIZE 127 127 EQ_RGB 255 0 0
1282EXPECT kImgBuffer IDX 128 128 SIZE 128 128 EQ_RGB 0 255 0
1283```
1284
1285### Buffers
1286
1287```groovy
1288#!amber
1289
1290SHADER vertex kVertexShader GLSL
1291  #version 430
1292
1293  layout(location = 0) in vec4 position;
1294  layout(location = 1) in vec4 color_in;
1295  layout(location = 0) out vec4 color_out;
1296
1297  void main() {
1298    gl_Position = position;
1299    color_out = color_in;
1300  }
1301END  # shader
1302
1303SHADER fragment kFragmentShader GLSL
1304  #version 430
1305
1306  layout(location = 0) in vec4 color_in;
1307  layout(location = 0) out vec4 color_out;
1308
1309  void main() {
1310    color_out = color_in;
1311  }
1312END  # shader
1313
1314BUFFER kPosData DATA_TYPE vec2<int32> DATA
1315# Top-left
1316-1 -1  
1317 0 -1  
1318-1  0
1319 0  0
1320# Top-right
1321 0 -1  
1322 1 -1  
1323 0  0
1324 1  0
1325# Bottom-left
1326-1  0
1327 0  0
1328-1  1
1329 0  1
1330# Bottom-right
1331 0  0
1332 1  0
1333 0  1
1334 1  1
1335END
1336
1337BUFFER kColorData DATA_TYPE uint32 DATA
1338# red
13390xff0000ff
13400xff0000ff
13410xff0000ff
13420xff0000ff
1343
1344# green
13450xff00ff00
13460xff00ff00
13470xff00ff00
13480xff00ff00
1349
1350# blue
13510xffff0000
13520xffff0000
13530xffff0000
13540xffff0000
1355
1356# purple
13570xff800080
13580xff800080
13590xff800080
13600xff800080
1361END
1362
1363BUFFER kIndices DATA_TYPE int32 DATA
13640  1  2    2  1  3
13654  5  6    6  5  7
13668  9  10   10 9  11
136712 13 14   14 13 15
1368END
1369
1370PIPELINE graphics kGraphicsPipeline
1371  ATTACH kVertexShader
1372  ATTACH kFragmentShader
1373
1374  VERTEX_DATA kPosData LOCATION 0
1375  VERTEX_DATA kColorData LOCATION 1
1376  INDEX_DATA kIndices
1377END  # pipeline
1378
1379CLEAR_COLOR kGraphicsPipeline 255 0 0 255
1380CLEAR kGraphicsPipeline
1381
1382RUN kGraphicsPipeline DRAW_ARRAY AS TRIANGLE_LIST START_IDX 0 COUNT 24
1383```
1384
1385### OpenCL-C Shaders
1386
1387```groovy
1388SHADER compute my_shader OPENCL-C
1389kernel void line(const int* in, global int* out, int m, int b) {
1390  *out = *in * m + b;
1391}
1392END
1393
1394BUFFER in_buf DATA_TYPE int32 DATA 4 END
1395BUFFER out_buf DATA_TYPE int32 DATA 0 END
1396
1397PIPELINE compute my_pipeline
1398  ATTACH my_shader ENTRY_POINT line
1399  COMPILE_OPTIONS
1400    -cluster-pod-kernel-args
1401    -pod-ubo
1402    -constant-args-ubo
1403    -max-ubo-size=128
1404  END
1405  BIND BUFFER in_buf KERNEL ARG_NAME in
1406  BIND BUFFER out_buf KERNEL ARG_NAME out
1407  SET KERNEL ARG_NAME m AS int32 3
1408  SET KERNEL ARG_NAME b AS int32 1
1409END
1410
1411RUN my_pipeline 1 1 1
1412
1413EXPECT out_buf EQ IDX 0 EQ 13
1414```
1415
1416### Image Formats
1417  * `A1R5G5B5_UNORM_PACK16`
1418  * `A2B10G10R10_SINT_PACK32`
1419  * `A2B10G10R10_SNORM_PACK32`
1420  * `A2B10G10R10_SSCALED_PACK32`
1421  * `A2B10G10R10_UINT_PACK32`
1422  * `A2B10G10R10_UNORM_PACK32`
1423  * `A2B10G10R10_USCALED_PACK32`
1424  * `A2R10G10B10_SINT_PACK32`
1425  * `A2R10G10B10_SNORM_PACK32`
1426  * `A2R10G10B10_SSCALED_PACK32`
1427  * `A2R10G10B10_UINT_PACK32`
1428  * `A2R10G10B10_UNORM_PACK32`
1429  * `A2R10G10B10_USCALED_PACK32`
1430  * `A8B8G8R8_SINT_PACK32`
1431  * `A8B8G8R8_SNORM_PACK32`
1432  * `A8B8G8R8_SRGB_PACK32`
1433  * `A8B8G8R8_SSCALED_PACK32`
1434  * `A8B8G8R8_UINT_PACK32`
1435  * `A8B8G8R8_UNORM_PACK32`
1436  * `A8B8G8R8_USCALED_PACK32`
1437  * `B10G11R11_UFLOAT_PACK32`
1438  * `B4G4R4A4_UNORM_PACK16`
1439  * `B5G5R5A1_UNORM_PACK16`
1440  * `B5G6R5_UNORM_PACK16`
1441  * `B8G8R8A8_SINT`
1442  * `B8G8R8A8_SNORM`
1443  * `B8G8R8A8_SRGB`
1444  * `B8G8R8A8_SSCALED`
1445  * `B8G8R8A8_UINT`
1446  * `B8G8R8A8_UNORM`
1447  * `B8G8R8A8_USCALED`
1448  * `B8G8R8_SINT`
1449  * `B8G8R8_SNORM`
1450  * `B8G8R8_SRGB`
1451  * `B8G8R8_SSCALED`
1452  * `B8G8R8_UINT`
1453  * `B8G8R8_UNORM`
1454  * `B8G8R8_USCALED`
1455  * `D16_UNORM`
1456  * `D16_UNORM_S8_UINT`
1457  * `D24_UNORM_S8_UINT`
1458  * `D32_SFLOAT`
1459  * `D32_SFLOAT_S8_UINT`
1460  * `R16G16B16A16_SFLOAT`
1461  * `R16G16B16A16_SINT`
1462  * `R16G16B16A16_SNORM`
1463  * `R16G16B16A16_SSCALED`
1464  * `R16G16B16A16_UINT`
1465  * `R16G16B16A16_UNORM`
1466  * `R16G16B16A16_USCALED`
1467  * `R16G16B16_SFLOAT`
1468  * `R16G16B16_SINT`
1469  * `R16G16B16_SNORM`
1470  * `R16G16B16_SSCALED`
1471  * `R16G16B16_UINT`
1472  * `R16G16B16_UNORM`
1473  * `R16G16B16_USCALED`
1474  * `R16G16_SFLOAT`
1475  * `R16G16_SINT`
1476  * `R16G16_SNORM`
1477  * `R16G16_SSCALED`
1478  * `R16G16_UINT`
1479  * `R16G16_UNORM`
1480  * `R16G16_USCALED`
1481  * `R16_SFLOAT`
1482  * `R16_SINT`
1483  * `R16_SNORM`
1484  * `R16_SSCALED`
1485  * `R16_UINT`
1486  * `R16_UNORM`
1487  * `R16_USCALED`
1488  * `R32G32B32A32_SFLOAT`
1489  * `R32G32B32A32_SINT`
1490  * `R32G32B32A32_UINT`
1491  * `R32G32B32_SFLOAT`
1492  * `R32G32B32_SINT`
1493  * `R32G32B32_UINT`
1494  * `R32G32_SFLOAT`
1495  * `R32G32_SINT`
1496  * `R32G32_UINT`
1497  * `R32_SFLOAT`
1498  * `R32_SINT`
1499  * `R32_UINT`
1500  * `R4G4B4A4_UNORM_PACK16`
1501  * `R4G4_UNORM_PACK8`
1502  * `R5G5B5A1_UNORM_PACK16`
1503  * `R5G6B5_UNORM_PACK16`
1504  * `R64G64B64A64_SFLOAT`
1505  * `R64G64B64A64_SINT`
1506  * `R64G64B64A64_UINT`
1507  * `R64G64B64_SFLOAT`
1508  * `R64G64B64_SINT`
1509  * `R64G64B64_UINT`
1510  * `R64G64_SFLOAT`
1511  * `R64G64_SINT`
1512  * `R64G64_UINT`
1513  * `R64_SFLOAT`
1514  * `R64_SINT`
1515  * `R64_UINT`
1516  * `R8G8B8A8_SINT`
1517  * `R8G8B8A8_SNORM`
1518  * `R8G8B8A8_SRGB`
1519  * `R8G8B8A8_SSCALED`
1520  * `R8G8B8A8_UINT`
1521  * `R8G8B8A8_UNORM`
1522  * `R8G8B8A8_USCALED`
1523  * `R8G8B8_SINT`
1524  * `R8G8B8_SNORM`
1525  * `R8G8B8_SRGB`
1526  * `R8G8B8_SSCALED`
1527  * `R8G8B8_UINT`
1528  * `R8G8B8_UNORM`
1529  * `R8G8B8_USCALED`
1530  * `R8G8_SINT`
1531  * `R8G8_SNORM`
1532  * `R8G8_SRGB`
1533  * `R8G8_SSCALED`
1534  * `R8G8_UINT`
1535  * `R8G8_UNORM`
1536  * `R8G8_USCALED`
1537  * `R8_SINT`
1538  * `R8_SNORM`
1539  * `R8_SRGB`
1540  * `R8_SSCALED`
1541  * `R8_UINT`
1542  * `R8_UNORM`
1543  * `R8_USCALED`
1544  * `S8_UINT`
1545  * `X8_D24_UNORM_PACK32`
1546