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