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