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