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 `VariablePointerFeatures.variablePointers` and 38`VariablePointerFeatures.variablePointersStorageBuffer`. 39 40Extensions can be enabled with the `DEVICE_EXTENSION` and `INSTANCE_EXTENSION` 41commands. 42 43```groovy 44DEVICE_EXTENSION VK_KHR_get_physical_device_properties2 45INSTANCE_EXTENSION VK_KHR_storage_buffer_storage_class 46``` 47 48### Setting Engine Configuration 49 50In some instances there is extra data we want to provide to an engine for 51configuration purposes. The `SET ENGINE_DATA` command allows that for the given 52set of data types. 53 54#### Engine Data Variables 55 * `fence_timeout_ms` - value must be a single uint32 in milliseconds. 56 57```groovy 58SET ENGINE_DATA {engine data variable} {value}* 59``` 60 61### Shaders 62 63#### Shader Type 64 * `vertex` 65 * `fragment` 66 * `geometry` 67 * `tessellation_evaluation` 68 * `tessellation_control` 69 * `compute` 70 * `multi` 71 72The compute pipeline can only contain compute shaders. The graphics pipeline 73can not contain compute shaders, and must contain a vertex shader and a fragment 74shader. 75 76The provided `multi` shader can only be used with `SPIRV-ASM` and `SPIRV-HEX` 77and allows for providing multiple shaders in a single module (so the `vertex` 78and `fragment` shaders can be provided together.) 79 80Note, `SPIRV-ASM` and `SPIRV-HEX` can also be used with each of the other shader 81types, but in that case must only provide a single shader type in the module. 82 83#### Shader Format 84 * `GLSL` (with glslang) 85 * `HLSL` (with dxc or glslang if dxc disabled) -- future 86 * `SPIRV-ASM` (with spirv-as) 87 * `SPIRV-HEX` (decoded straight to SPIR-V) 88 * `OPENCL-C` (with clspv) 89 90```groovy 91# Creates a passthrough vertex shader. The shader passes the vec4 at input 92# location 0 through to the `gl_Position`. 93SHADER vertex {shader_name} PASSTHROUGH 94 95# Creates a shader of |shader_type| with the given |shader_name|. The shader 96# will be of |shader_format|. The shader should then be inlined before the 97# |END| tag. 98SHADER {shader_type} {shader_name} {shader_format} 99... 100END 101``` 102 103### Buffers 104 105An AmberScript buffer represents a set of contiguous bits. This can be used for 106either image buffers or, what the target API would refer to as a buffer. 107 108#### Data Types 109 * `int8` 110 * `int16` 111 * `int32` 112 * `int64` 113 * `uint8` 114 * `uint16` 115 * `uint32` 116 * `uint64` 117 * `float` 118 * `double` 119 * vec[2,3,4]{type} 120 * mat[2,3,4]x[2,3,4]{type} (mat<columns>x<rows>) 121 * Any of the `Image Formats` listed below. 122 123Sized arrays and structures are not currently representable. 124 125```groovy 126# Filling the buffer with a given set of data. The values must be 127# of |type| data. The data can be provided as the type or as a hex value. 128# Buffers are STD430 by default. 129BUFFER {name} DATA_TYPE {type} {STD140 | STD430} DATA 130_value_+ 131END 132 133# Defines a buffer which is filled with data as specified by the `initializer`. 134BUFFER {name} DATA_TYPE {type} {STD140 | STD430} SIZE _size_in_items_ \ 135 {initializer} 136 137# Creates a buffer which will store the given `FORMAT` of data. These 138# buffers are used as image and depth buffers in the `PIPELINE` commands. 139# The buffer will be sized based on the `RENDER_SIZE` of the `PIPELINE`. 140BUFFER {name} FORMAT {format_string} 141``` 142 143#### Buffer Initializers 144 145```groovy 146# Fill the buffer with a single value. 147FILL _value_ 148 149# Fill the buffer with an increasing value from |start| increasing by |inc|. 150# Floating point data uses floating point addition to generate increasing 151# values. Likewise, integer data uses integer addition to generate increasing 152# values. 153SERIES_FROM _start_ INC_BY _inc_ 154``` 155 156#### Buffer Copy 157 158```groovy 159# Copies all data, values and memory from |buffer_from| to |buffer_to|. 160# Both buffers must be declared, and of the same data type. 161# Buffers used as copy destination can be used only as copy destination, and as 162# argument to an EXPECT command. 163COPY {buffer_from} TO {buffer_to} 164``` 165 166### Pipelines 167 168#### Pipeline type 169 * `compute` 170 * `graphics` 171 172```groovy 173# The PIPELINE command creates a pipeline. This can be either compute or 174# graphics. Shaders are attached to the pipeline at pipeline creation time. 175PIPELINE {pipeline_type} {pipeline_name} 176... 177END 178 179# Create a pipeline and inherit from a previously declared pipeline. 180DERIVE_PIPELINE {pipeline_name} FROM {parent_pipeline} 181... 182END 183``` 184 185### Pipeline Content 186 187The following commands are all specified within the `PIPELINE` command. 188```groovy 189 # Attach the shader provided by |name_of_shader| to the pipeline and set 190 # the entry point to be |name|. The provided shader for ATTACH must _not_ be 191 # a 'multi' shader. 192 ATTACH {name_of_shader} ENTRY_POINT {name} 193 194 # Attach the shader provided by |name_of_shader| to the pipeline and set 195 # the entry point to be 'main'. The provided shader for ATTACH must _not_ be 196 # a 'multi' shader. 197 ATTACH {name_of_shader} 198 199 # Attach a 'multi' shader to the pipeline of |shader_type| and use the entry 200 # point with |name|. The provided shader _must_ be a 'multi' shader. 201 ATTACH {name_of_multi_shader} TYPE {shader_type} ENTRY_POINT {name} 202 203 # Attach specialized shader. Specialization can be specified multiple times. 204 # Specialization values must be a 32-bit type. Shader type and entry point 205 # must be specified prior to specializing the shader. 206 ATTACH {name_of_shader} SPECIALIZE 1 AS uint32 4 207 ATTACH {name_of_shader} SPECIALIZE 1 AS uint32 4 SPECIALIZE 4 AS float 1.0 208``` 209 210```groovy 211 # Set the SPIRV-Tools optimization passes to use for a given shader. The 212 # default is to run no optimization passes. 213 SHADER_OPTIMIZATION {shader_name} 214 {optimization_name}+ 215 END 216``` 217 218```groovy 219 # Set the compile options used to compile the given shader. Options are parsed 220 # the same as on the command line. Currently, only supported for OPENCL-C shaders. 221 COMPILE_OPTIONS {shader_name} 222 {option}+ 223 END 224``` 225 226```groovy 227 # Set the size of the render buffers. |width| and |height| are integers and 228 # default to 250x250. 229 FRAMEBUFFER_SIZE _width_ _height_ 230``` 231 232### Pipeline Buffers 233 234#### Buffer Types 235 * `uniform` 236 * `storage` 237 238TODO(dsinclair): Sync the BufferTypes with the list of Vulkan Descriptor types. 239 240A `pipeline` can have buffers bound. This includes buffers to contain image 241attachment content, depth/stencil content, uniform buffers, etc. 242 243```groovy 244 # Attach |buffer_name| as an output color attachment at location |idx|. 245 # The provided buffer must be a `FORMAT` buffer. If no color attachments are 246 # provided a single attachment with format `B8G8R8A8_UNORM` will be created 247 # for graphics pipelines. 248 BIND BUFFER {buffer_name} AS color LOCATION _idx_ 249 250 # Attach |buffer_name| as the depth/stencil buffer. The provided buffer must 251 # be a `FORMAT` buffer. If no depth/stencil buffer is specified a default 252 # buffer of format `D32_SFLOAT_S8_UINT` will be created for graphics 253 # pipelines. 254 BIND BUFFER {buffer_name} AS depth_stencil 255 256 # Attach |buffer_name| as the push_constant buffer. There can be only one 257 # push constant buffer attached to a pipeline. 258 BIND BUFFER <buffer_name> AS push_constant 259 260 # Bind the buffer of the given |buffer_type| at the given descriptor set 261 # and binding. The buffer will use a start index of 0. 262 BIND BUFFER {buffer_name} AS {buffer_type} DESCRIPTOR_SET _id_ \ 263 BINDING _id_ 264 265 # Bind the sampler at the given descriptor set and binding. 266 BIND SAMPLER {sampler_name} DESCRIPTOR_SET _id_ BINDING _id_ 267 268 # Bind OpenCL argument buffer by name. Specifying the buffer type is optional. 269 # Amber will set the type as appropriate for the argument buffer. All uses 270 # of the buffer must have a consistent |buffer_type| across all pipelines. 271 BIND BUFFER {buffer_name} [AS {buffer_type}] KERNEL ARG_NAME _name_ 272 273 # Bind OpenCL argument buffer by argument ordinal. Arguments use 0-based 274 # numbering. Specifying the buffer type is optional. Amber will set the 275 # type as appropriate for the argument buffer. All uses of the buffer 276 # must have a consistent |buffer_type| across all pipelines. 277 BIND BUFFER {buffer_name} [AS {buffer_type}] KERNEL ARG_NUMBER _number_ 278``` 279 280```groovy 281 # Set |buffer_name| as the vertex data at location |val|. 282 VERTEX_DATA {buffer_name} LOCATION _val_ 283 284 # Set |buffer_name| as the index data to use for `INDEXED` draw commands. 285 INDEX_DATA {buffer_name} 286``` 287 288#### OpenCL Plain-Old-Data Arguments 289OpenCL kernels can have plain-old-data (pod or pod_ubo in the desriptor map) 290arguments set their data via this command. Amber will generate the appropriate 291buffers for the pipeline populated with the specified data. 292 293```groovy 294 # Set argument |name| to |data_type| with value |val|. 295 SET KERNEL ARG_NAME _name_ AS {data_type} _val_ 296 297 # Set argument |number| to |data_type| with value |val|. 298 # Arguments use 0-based numbering. 299 SET KERNEL ARG_NUMBER _number_ AS {data_type} _val_ 300``` 301 302#### Topologies 303 * `point_list` 304 * `line_list` 305 * `line_list_with_adjacency` 306 * `line_strip` 307 * `line_strip_with_adjacency` 308 * `triangle_list` 309 * `triangle_list_with_adjacency` 310 * `triangle_strip` 311 * `triangle_strip_with_adjacency` 312 * `triangle_fan` 313 * `patch_list` 314 315### Run a pipeline. 316 317When running a `DRAW_ARRAY` command, you must attach the vertex data to the 318`PIPELINE` with the `VERTEX_DATA` command. 319 320To run an indexed draw, attach the index data to the `PIPELINE` with an 321`INDEX_DATA` command. 322 323For the commands which take a `START_IDX` and a `COUNT` they can be left off the 324command (although, `START_IDX` is required if `COUNT` is provided). The default 325value for `START_IDX` is 0. The default value for `COUNT` is the item count of 326vertex buffer minus the `START_IDX`. 327 328```groovy 329# Run the given |pipeline_name| which must be a `compute` pipeline. The 330# pipeline will be run with the given number of workgroups in the |x|, |y|, |z| 331# dimensions. Each of the x, y and z values must be a uint32. 332RUN {pipeline_name} _x_ _y_ _z_ 333 334# Run the given |pipeline_name| which must be a `graphics` pipeline. The 335# rectangle at |x|, |y|, |width|x|height| will be rendered. Ignores VERTEX_DATA 336# and INDEX_DATA on the given pipeline. 337RUN {pipeline_name} \ 338 DRAW_RECT POS _x_in_pixels_ _y_in_pixels_ \ 339 SIZE _width_in_pixels_ _height_in_pixels_ 340``` 341 342```groovy 343# Run the |pipeline_name| which must be a `graphics` pipeline. The vertex 344# data must be attached to the pipeline. A start index of 0 will be used 345# and a count of the number of elements in the vertex buffer. 346RUN {pipeline_name} DRAW_ARRAY AS {topology} 347 348# Run the |pipeline_name| which must be a `graphics` pipeline. The vertex 349# data must be attached to the pipeline. A start index of |value| will be used 350# and a count of the number of items from |value| to the end of the vertex 351# buffer. 352RUN {pipeline_name} DRAW_ARRAY AS {topology} START_IDX _value_ 353 354# Run the |pipeline_name| which must be a `graphics` pipeline. The vertex 355# data must be attached to the pipeline. A start index of |value| will be used 356# and a count |count_value| will be used. 357RUN {pipeline_name} DRAW_ARRAY AS {topology} START_IDX _value_ \ 358 COUNT _count_value_ 359``` 360 361```groovy 362# Run the |pipeline_name| which must be a `graphics` pipeline. The vertex 363# data and index data must be attached to the pipeline. The vertices will be 364# drawn using the given |topology|. A start index of 0 will be used and the 365# count will be determined by the size of the index data buffer. 366RUN {pipeline_name} DRAW_ARRAY AS {topology} INDEXED 367 368# Run the |pipeline_name| which must be a `graphics` pipeline. The vertex 369# data and index data must be attached to the pipeline. The vertices will be 370# drawn using the given |topology|. A start index of |value| will be used and 371# the count will be determined by the size of the index data buffer. 372RUN {pipeline_name} DRAW_ARRAY AS {topology} INDEXED START_IDX _value_ 373 374# Run the |pipeline_name| which must be a `graphics` pipeline. The vertex 375# data and index data must be attached to the pipeline. The vertices will be 376# drawn using the given |topology|. A start index of |value| will be used and 377# the count of |count_value| items will be processed. 378RUN {pipeline_name} DRAW_ARRAY AS {topology} INDEXED \ 379 START_IDX _value_ COUNT _count_value_ 380``` 381 382### Repeating commands 383 384```groovy 385# It is sometimes useful to run a given draw command multiple times. This can be 386# to detect deterministic rendering or other features. 387REPEAT {count} 388{command}+ 389END 390``` 391 392The commands which can be used inside a `REPEAT` block are: 393 * `CLEAR` 394 * `CLEAR_COLOR` 395 * `COPY` 396 * `EXPECT` 397 * `RUN` 398 399### Commands 400 401```groovy 402# Sets the clear color to use for |pipeline| which must be a graphics 403# pipeline. The colors are integers from 0 - 255. 404CLEAR_COLOR {pipeline} _r (0 - 255)_ _g (0 - 255)_ _b (0 - 255)_ _a (0 - 255)_ 405 406# Instructs the |pipeline| which must be a graphics pipeline to execute the 407# clear command. 408CLEAR {pipeline} 409``` 410 411### Expectations 412 413#### Comparators 414 * `EQ` 415 * `NE` 416 * `LT` 417 * `LE` 418 * `GT` 419 * `GE` 420 * `EQ_RGB` 421 * `EQ_RGBA` 422 * `EQ_BUFFER` 423 * `RMSE_BUFFER` 424 * `EQ_HISTOGRAM_EMD_BUFFER` 425 426```groovy 427# Checks that |buffer_name| at |x| has the given |value|s when compared 428# with the given |comparator|. 429EXPECT {buffer_name} IDX _x_ {comparator} _value_+ 430 431# Checks that |buffer_name| at |x| has values within |tolerance| of |value| 432# The |tolerance| can be specified as 1-4 float values separated by spaces. 433# The tolerances may be given as a percentage by placing a '%' symbol after 434# the value. If less tolerance values are provided then are needed for a given 435# data component the default tolerance will be applied. 436EXPECT {buffer_name} IDX _x_ TOLERANCE _tolerance_{1,4} EQ _value_+ 437 438# Checks that |buffer_name| at |x|, |y| for |width|x|height| pixels has the 439# given |r|, |g|, |b| values. Each r, g, b value is an integer from 0-255. 440EXPECT {buffer_name} IDX _x_in_pixels_ _y_in_pixels_ \ 441 SIZE _width_in_pixels_ _height_in_pixels_ \ 442 EQ_RGB _r (0 - 255)_ _g (0 - 255)_ _b (0 - 255)_ 443 444# Checks that |buffer_name| at |x|, |y| for |width|x|height| pixels has the 445# given |r|, |g|, |b|, |a| values. Each r, g, b, a value is an integer 446# from 0-255. 447EXPECT {buffer_name} IDX _x_in_pixels_ _y_in_pixels_ \ 448 SIZE _width_in_pixels_ _height_in_pixels_ \ 449 EQ_RGBA _r (0 - 255)_ _g (0 - 255)_ _b (0 - 255)_ _a (0 - 255)_ 450 451# Checks that |buffer_1| contents are equal to those of |buffer_2| 452EXPECT {buffer_1} EQ_BUFFER {buffer_2} 453 454# Checks that the Root Mean Square Error when comparing |buffer_1| to 455# |buffer_2| is less than or equal to |tolerance|. Note, |tolerance| is a 456# unit-less number. 457EXPECT {buffer_1} RMSE_BUFFER {buffer_2} TOLERANCE _value_ 458 459# Checks that the Earth Mover's Distance when comparing histograms of 460# |buffer_1| to |buffer_2| is less than or equal to |tolerance|. 461# Note, |tolerance| is a unit-less number. 462EXPECT {buffer_1} EQ_HISTOGRAM_EMD_BUFFER {buffer_2} TOLERANCE _value_ 463``` 464 465## Examples 466 467### Compute Shader 468 469```groovy 470#!amber 471# Simple amber compute shader. 472 473SHADER compute kComputeShader GLSL 474#version 450 475 476layout(binding = 3) buffer block { 477 vec2 values[]; 478}; 479 480void main() { 481 values[gl_WorkGroupID.x + gl_WorkGroupID.y * gl_NumWorkGroups.x] = 482 gl_WorkGroupID.xy; 483} 484END # shader 485 486BUFFER kComputeBuffer DATA_TYPE vec2<int32> SIZE 524288 FILL 0 487 488PIPELINE compute kComputePipeline 489 ATTACH kComputeShader 490 BIND BUFFER kComputeBuffer AS storage DESCRIPTOR_SET 0 BINDING 3 491END # pipeline 492 493RUN kComputePipeline 256 256 1 494 495# Four corners 496EXPECT kComputeBuffer IDX 0 EQ 0 0 497EXPECT kComputeBuffer IDX 2040 EQ 255 0 498EXPECT kComputeBuffer IDX 522240 EQ 0 255 499EXPECT kComputeBuffer IDX 524280 EQ 255 255 500 501# Center 502EXPECT kComputeBuffer IDX 263168 EQ 128 128 503``` 504 505### Entry Points 506 507```groovy 508#!amber 509 510SHADER vertex kVertexShader PASSTHROUGH 511 512SHADER fragment kFragmentShader SPIRV-ASM 513 OpCapability Shader 514 %1 = OpExtInstImport "GLSL.std.450" 515 OpMemoryModel Logical GLSL450 516 517; two entrypoints 518 OpEntryPoint Fragment %red "red" %color 519 OpEntryPoint Fragment %green "green" %color 520 521 OpExecutionMode %red OriginUpperLeft 522 OpExecutionMode %green OriginUpperLeft 523 OpSource GLSL 430 524 OpName %red "red" 525 OpDecorate %color Location 0 526 %void = OpTypeVoid 527 %3 = OpTypeFunction %void 528 %float = OpTypeFloat 32 529 %v4float = OpTypeVector %float 4 530%_ptr_Output_v4float = OpTypePointer Output %v4float 531 %color = OpVariable %_ptr_Output_v4float Output 532 %float_1 = OpConstant %float 1 533 %float_0 = OpConstant %float 0 534 %red_color = OpConstantComposite %v4float %float_1 %float_0 %float_0 %float_1 535%green_color = OpConstantComposite %v4float %float_0 %float_1 %float_0 %float_1 536 537; this entrypoint outputs a red color 538 %red = OpFunction %void None %3 539 %5 = OpLabel 540 OpStore %color %red_color 541 OpReturn 542 OpFunctionEnd 543 544; this entrypoint outputs a green color 545 %green = OpFunction %void None %3 546 %6 = OpLabel 547 OpStore %color %green_color 548 OpReturn 549 OpFunctionEnd 550END # shader 551 552BUFFER kImgBuffer FORMAT R8G8B8A8_UINT 553 554PIPELINE graphics kRedPipeline 555 ATTACH kVertexShader ENTRY_POINT main 556 SHADER_OPTIMIZATION kVertexShader 557 --eliminate-dead-branches 558 --merge-return 559 --eliminate-dead-code-aggressive 560 END 561 ATTACH kFragmentShader ENTRY_POINT red 562 563 FRAMEBUFFER_SIZE 256 256 564 BIND BUFFER kImgBuffer AS color LOCATION 0 565END # pipeline 566 567PIPELINE graphics kGreenPipeline 568 ATTACH kVertexShader 569 ATTACH kFragmentShader ENTRY_POINT green 570 571 FRAMEBUFFER_SIZE 256 256 572 BIND BUFFER kImgBuffer AS color LOCATION 0 573END # pipeline 574 575RUN kRedPipeline DRAW_RECT POS 0 0 SIZE 256 256 576RUN kGreenPipeline DRAW_RECT POS 128 128 SIZE 256 256 577 578EXPECT kImgBuffer IDX 0 0 SIZE 127 127 EQ_RGB 255 0 0 579EXPECT kImgBuffer IDX 128 128 SIZE 128 128 EQ_RGB 0 255 0 580``` 581 582### Buffers 583 584```groovy 585#!amber 586 587SHADER vertex kVertexShader GLSL 588 #version 430 589 590 layout(location = 0) in vec4 position; 591 layout(location = 1) in vec4 color_in; 592 layout(location = 0) out vec4 color_out; 593 594 void main() { 595 gl_Position = position; 596 color_out = color_in; 597 } 598END # shader 599 600SHADER fragment kFragmentShader GLSL 601 #version 430 602 603 layout(location = 0) in vec4 color_in; 604 layout(location = 0) out vec4 color_out; 605 606 void main() { 607 color_out = color_in; 608 } 609END # shader 610 611BUFFER kPosData DATA_TYPE vec2<int32> DATA 612# Top-left 613-1 -1 614 0 -1 615-1 0 616 0 0 617# Top-right 618 0 -1 619 1 -1 620 0 0 621 1 0 622# Bottom-left 623-1 0 624 0 0 625-1 1 626 0 1 627# Bottom-right 628 0 0 629 1 0 630 0 1 631 1 1 632END 633 634BUFFER kColorData DATA_TYPE uint32 DATA 635# red 6360xff0000ff 6370xff0000ff 6380xff0000ff 6390xff0000ff 640 641# green 6420xff00ff00 6430xff00ff00 6440xff00ff00 6450xff00ff00 646 647# blue 6480xffff0000 6490xffff0000 6500xffff0000 6510xffff0000 652 653# purple 6540xff800080 6550xff800080 6560xff800080 6570xff800080 658END 659 660BUFFER kIndices DATA_TYPE int32 DATA 6610 1 2 2 1 3 6624 5 6 6 5 7 6638 9 10 10 9 11 66412 13 14 14 13 15 665END 666 667PIPELINE graphics kGraphicsPipeline 668 ATTACH kVertexShader 669 ATTACH kFragmentShader 670 671 VERTEX_DATA kPosData LOCATION 0 672 VERTEX_DATA kColorData LOCATION 1 673 INDEX_DATA kIndices 674END # pipeline 675 676CLEAR_COLOR kGraphicsPipeline 255 0 0 255 677CLEAR kGraphicsPipeline 678 679RUN kGraphicsPipeline DRAW_ARRAY AS triangle_list START_IDX 0 COUNT 24 680``` 681 682### OpenCL-C Shaders 683 684```groovy 685SHADER compute my_shader OPENCL-C 686kernel void line(const int* in, global int* out, int m, int b) { 687 *out = *in * m + b; 688} 689END 690 691BUFFER in_buf DATA_TYPE int32 DATA 4 END 692BUFFER out_buf DATA_TYPE int32 DATA 0 END 693 694PIPELINE compute my_pipeline 695 ATTACH my_shader ENTRY_POINT line 696 COMPILE_OPTIONS 697 -cluster-pod-kernel-args 698 -pod-ubo 699 -constant-args-ubo 700 -max-ubo-size=128 701 END 702 BIND BUFFER in_buf KERNEL ARG_NAME in 703 BIND BUFFER out_buf KERNEL ARG_NAME out 704 SET KERNEL ARG_NAME m AS int32 3 705 SET KERNEL ARG_NAME b AS int32 1 706END 707 708RUN my_pipeline 1 1 1 709 710EXPECT out_buf EQ IDX 0 EQ 13 711``` 712 713### Image Formats 714 * `A1R5G5B5_UNORM_PACK16` 715 * `A2B10G10R10_SINT_PACK32` 716 * `A2B10G10R10_SNORM_PACK32` 717 * `A2B10G10R10_SSCALED_PACK32` 718 * `A2B10G10R10_UINT_PACK32` 719 * `A2B10G10R10_UNORM_PACK32` 720 * `A2B10G10R10_USCALED_PACK32` 721 * `A2R10G10B10_SINT_PACK32` 722 * `A2R10G10B10_SNORM_PACK32` 723 * `A2R10G10B10_SSCALED_PACK32` 724 * `A2R10G10B10_UINT_PACK32` 725 * `A2R10G10B10_UNORM_PACK32` 726 * `A2R10G10B10_USCALED_PACK32` 727 * `A8B8G8R8_SINT_PACK32` 728 * `A8B8G8R8_SNORM_PACK32` 729 * `A8B8G8R8_SRGB_PACK32` 730 * `A8B8G8R8_SSCALED_PACK32` 731 * `A8B8G8R8_UINT_PACK32` 732 * `A8B8G8R8_UNORM_PACK32` 733 * `A8B8G8R8_USCALED_PACK32` 734 * `B10G11R11_UFLOAT_PACK32` 735 * `B4G4R4A4_UNORM_PACK16` 736 * `B5G5R5A1_UNORM_PACK16` 737 * `B5G6R5_UNORM_PACK16` 738 * `B8G8R8A8_SINT` 739 * `B8G8R8A8_SNORM` 740 * `B8G8R8A8_SRGB` 741 * `B8G8R8A8_SSCALED` 742 * `B8G8R8A8_UINT` 743 * `B8G8R8A8_UNORM` 744 * `B8G8R8A8_USCALED` 745 * `B8G8R8_SINT` 746 * `B8G8R8_SNORM` 747 * `B8G8R8_SRGB` 748 * `B8G8R8_SSCALED` 749 * `B8G8R8_UINT` 750 * `B8G8R8_UNORM` 751 * `B8G8R8_USCALED` 752 * `D16_UNORM` 753 * `D16_UNORM_S8_UINT` 754 * `D24_UNORM_S8_UINT` 755 * `D32_SFLOAT` 756 * `D32_SFLOAT_S8_UINT` 757 * `R16G16B16A16_SFLOAT` 758 * `R16G16B16A16_SINT` 759 * `R16G16B16A16_SNORM` 760 * `R16G16B16A16_SSCALED` 761 * `R16G16B16A16_UINT` 762 * `R16G16B16A16_UNORM` 763 * `R16G16B16A16_USCALED` 764 * `R16G16B16_SFLOAT` 765 * `R16G16B16_SINT` 766 * `R16G16B16_SNORM` 767 * `R16G16B16_SSCALED` 768 * `R16G16B16_UINT` 769 * `R16G16B16_UNORM` 770 * `R16G16B16_USCALED` 771 * `R16G16_SFLOAT` 772 * `R16G16_SINT` 773 * `R16G16_SNORM` 774 * `R16G16_SSCALED` 775 * `R16G16_UINT` 776 * `R16G16_UNORM` 777 * `R16G16_USCALED` 778 * `R16_SFLOAT` 779 * `R16_SINT` 780 * `R16_SNORM` 781 * `R16_SSCALED` 782 * `R16_UINT` 783 * `R16_UNORM` 784 * `R16_USCALED` 785 * `R32G32B32A32_SFLOAT` 786 * `R32G32B32A32_SINT` 787 * `R32G32B32A32_UINT` 788 * `R32G32B32_SFLOAT` 789 * `R32G32B32_SINT` 790 * `R32G32B32_UINT` 791 * `R32G32_SFLOAT` 792 * `R32G32_SINT` 793 * `R32G32_UINT` 794 * `R32_SFLOAT` 795 * `R32_SINT` 796 * `R32_UINT` 797 * `R4G4B4A4_UNORM_PACK16` 798 * `R4G4_UNORM_PACK8` 799 * `R5G5B5A1_UNORM_PACK16` 800 * `R5G6B5_UNORM_PACK16` 801 * `R64G64B64A64_SFLOAT` 802 * `R64G64B64A64_SINT` 803 * `R64G64B64A64_UINT` 804 * `R64G64B64_SFLOAT` 805 * `R64G64B64_SINT` 806 * `R64G64B64_UINT` 807 * `R64G64_SFLOAT` 808 * `R64G64_SINT` 809 * `R64G64_UINT` 810 * `R64_SFLOAT` 811 * `R64_SINT` 812 * `R64_UINT` 813 * `R8G8B8A8_SINT` 814 * `R8G8B8A8_SNORM` 815 * `R8G8B8A8_SRGB` 816 * `R8G8B8A8_SSCALED` 817 * `R8G8B8A8_UINT` 818 * `R8G8B8A8_UNORM` 819 * `R8G8B8A8_USCALED` 820 * `R8G8B8_SINT` 821 * `R8G8B8_SNORM` 822 * `R8G8B8_SRGB` 823 * `R8G8B8_SSCALED` 824 * `R8G8B8_UINT` 825 * `R8G8B8_UNORM` 826 * `R8G8B8_USCALED` 827 * `R8G8_SINT` 828 * `R8G8_SNORM` 829 * `R8G8_SRGB` 830 * `R8G8_SSCALED` 831 * `R8G8_UINT` 832 * `R8G8_UNORM` 833 * `R8G8_USCALED` 834 * `R8_SINT` 835 * `R8_SNORM` 836 * `R8_SRGB` 837 * `R8_SSCALED` 838 * `R8_UINT` 839 * `R8_UNORM` 840 * `R8_USCALED` 841 * `S8_UINT` 842 * `X8_D24_UNORM_PACK32` 843