forked from gpuweb/gpuweb
-
Notifications
You must be signed in to change notification settings - Fork 0
/
index.bs
15316 lines (12756 loc) · 606 KB
/
index.bs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
<pre class='metadata'>
Title: WebGPU Shading Language
Shortname: WGSL
Level: None
Status: w3c/ED
Group: webgpu
ED: https://gpuweb.github.io/gpuweb/wgsl/
TR: https://www.w3.org/TR/WGSL/
Repository: gpuweb/gpuweb
Text Macro: INT i32 or u32
Text Macro: UNSIGNEDINTEGRAL u32 or vecN<u32>
Text Macro: SIGNEDINTEGRAL i32 or vecN<i32>
Text Macro: ALLSIGNEDINTEGRAL AbstractInt, i32, vecN<AbstractInt>, or vecN<i32>
Text Macro: INTEGRAL i32, u32, vecN<i32>, or vecN<u32>
Text Macro: FLOATING f32, f16, vecN<f32>, or vecN<f16>
Text Macro: NUMERIC i32, u32, f32, f16, vecN<i32>, vecN<u32>, vecN<f32>, or vecN<f16>
Text Macro: ALLINTEGRALDECL S is AbstractInt, i32, or u32<br>T is S or vecN<S>
Text Macro: ALLFLOATINGDECL S is AbstractFloat, f32, or f16<br>T is S or vecN<S>
Text Macro: ALLNUMERICDECL S is AbstractInt, AbstractFloat, i32, u32, f32, or f16<br>T is S, or vecN<S>
Text Macro: ALLSIGNEDNUMERICDECL S is AbstractInt, AbstractFloat, i32, f32, or f16<br>T is S, or vecN<S>
Ignored Vars: i, c0, e, e1, e2, e3, edge, eN, p, s1, s2, sn, AS, AM, N, newbits, M, C, R, v, Stride, Offset, Align, Extent, T, T1
!Participate: <a href="https://github.com/gpuweb/gpuweb/issues/new?labels=wgsl">File an issue</a> (<a href="https://github.com/gpuweb/gpuweb/issues?q=is%3Aissue+is%3Aopen+label%3Awgsl">open issues</a>)
!Tests: <a href=https://github.com/gpuweb/cts/tree/main/src/webgpu/shader/>WebGPU CTS shader/</a>
Editor: Alan Baker, Google https://www.google.com, alanbaker@google.com, w3cid 129277
Editor: Mehmet Oguz Derin, mehmetoguzderin@mehmetoguzderin.com, w3cid 101130
Editor: David Neto, Google https://www.google.com, dneto@google.com, w3cid 99785
Former Editor: Myles C. Maxfield, Apple Inc., mmaxfield@apple.com, w3cid 77180
Former Editor: dan sinclair, Google https://www.google.com, dsinclair@google.com, w3cid 107549
Abstract: Shading language for WebGPU.
Markup Shorthands: markdown yes
Markup Shorthands: biblio yes
Markup Shorthands: idl yes
Assume Explicit For: yes
</pre>
<style>
tr:nth-child(2n) {
background-color: #b0b0b050;
}
thead {
background-color: #b0b0b050;
font-weight: bold;
}
.nowrap {
white-space:nowrap;
}
.small {
font-size: smaller;
}
div.syntax {
display: block;
page-break-before: avoid;
padding: .5em 1em;
background: var(--def-bg);
border-left: 0.5em solid var(--def-border);
color: var(--def-text);
margin-block-start: 1em;
margin-block-end: 1em;
}
div.syntax > p {
margin-block-start: 0em;
margin-block-end: 0em;
margin-inline-start: 1em;
margin-inline-end: 0em;
color: var(--text);
font-weight: 100;
}
div.syntax > p::first-letter {
letter-spacing: 0.5em;
}
div.syntax > p > a {
margin-inline-start: 0.1em;
margin-inline-end: 0.1em;
font-style: italic;
font-weight: normal;
color: var(--text);
}
div.syntax > p > code {
margin-inline-start: 0.1em;
margin-inline-end: 0.1em;
color: var(--text);
font-style: normal;
font-weight: bold;
}
div.syntax > p > a > code {
margin-inline-start: 0.1em;
margin-inline-end: 0.1em;
color: var(--text);
font-style: normal;
font-weight: bold;
}
[data-dfn-for="syntax"] {
font-style: italic;
font-weight: normal;
color: var(--text);
}
[data-dfn-for="syntax_kw"] {
margin-inline-start: 0.1em;
margin-inline-end: 0.1em;
color: var(--text);
font-style: normal;
font-weight: bold;
}
[data-dfn-for="syntax_sym"] {
margin-inline-start: 0.1em;
margin-inline-end: 0.1em;
color: var(--text);
font-style: normal;
font-weight: bold;
}
table.data.builtin tbody{
border-bottom: 0;
}
table.builtin {
border-bottom: 2px solid grey;
}
table.builtin tr:nth-child(2n) {
background-color: #00000000;
}
table.builtin td {
vertical-align: top;
}
/* Our SVGs aren't responsive to light/dark mode, so they're opaque with a
* white or black background. Rounded corners make them a bit less jarring. */
object[type="image/svg+xml"] {
border-radius: .5em;
}
</style>
<pre class=biblio>
{
"WebGPU": {
"authors": [
"Dzmitry Malyshau",
"Kai Ninomiya",
"Brandon Jones"
],
"href": "https://w3.org/TR/webgpu",
"title": "WebGPU",
"status": "Working Draft",
"publisher": "W3C",
"deliveredBy": [
"https://github.com/gpuweb/gpuweb"
]
},
"WGSL": {
"authors": [
"Alan Baker",
"Mehmet Oguz Derin",
"David Neto"
],
"href": "https://www.w3.org/TR/WGSL/",
"title": "WebGPU Shading Language",
"status": "Working Draft",
"publisher": "W3C",
"deliveredBy": [
"https://github.com/gpuweb/gpuweb"
]
},
"IEEE-754":{
"href":"http://ieeexplore.ieee.org/servlet/opac?punumber=4610933",
"title":"IEEE Standard for Floating-Point Arithmetic",
"publisher":"Institute of Electrical and Electronics Engineers",
"isbn":"978-0-7381-5752-8",
"versions":["IEEE-754-2008","IEEE-754-1985"],
"id":"IEEE-754",
"date":"29 August 2008"
},
"VulkanMemoryModel": {
"authors": [
"Jeff Bolz",
"Alan Baker",
"Tobias Hector",
"David Neto",
"Robert Simpson",
"Brian Sumner"
],
"href": "https://www.khronos.org/registry/vulkan/specs/1.2-extensions/html/vkspec.html#memory-model",
"title": "Vulkan Memory Model",
"publisher": "Khronos Group"
},
"UnicodeVersion14": {
"href":"http://www.unicode.org/versions/Unicode14.0.0/",
"author":"The Unicode Consortium",
"title":"The Unicode Standard, Version 14.0.0",
"isbn":"978-1-936213-29-0",
"id":"UnicodeVersion14"
},
"DeRemer1969": {
"href":"http://publications.csail.mit.edu/lcs/pubs/pdf/MIT-LCS-TR-065.pdf",
"author":"F. L. DeRemer",
"publisher":"Massachusetts Institute of Technology",
"date":"24 October 1969",
"title":"Practical Translators for LR(k) Languages"
},
"VanWyk2007": {
"href":"https://dl.acm.org/doi/10.1145/1289971.1289983",
"title":"Context-Aware Scanning for Parsing Extensible Languages",
"authors": [
"Eric R. Van Wyk",
"August C. Schwerdfeger"
],
"publisher":"Association for Computing Machinery",
"series":"GCPE'07",
"date":"2007"
}
}
</pre>
<pre class='anchors'>
spec: Vulkan ; urlPrefix: https://www.khronos.org/registry/vulkan/specs/1.2-extensions/html/vkspec.html#
type: dfn
text: memory model memory operation; url: memory-model-memory-operation
text: memory model reference; url: memory-model-references
text: memory model atomic operation; url: memory-model-atomic-operation
text: memory model scope; url:memory-model-scope
text: memory model memory semantics; url:memory-model-memory-semantics
text: memory model non-private; url: memory-model-non-private
spec: UAX14; urlPrefix: https://www.unicode.org/reports/tr14
type: dfn
text: UAX14 Section 6.1 Non-tailorable Line Breaking Rules; url: BreakingRules
text: UAX14 LB4; url: LB4
text: UAX14 LB5; url: LB5
spec: UAX31; urlPrefix: https://www.unicode.org/reports/tr31/tr31-35.html
type: dfn
text: Unicode Standard Annex #31 for Unicode Version 14.0.0
text: UAX31 Lexical Classes; url: Table_Lexical_Classes_for_Identifiers
text: UAX31 Grammar; url: D1
spec: Unicode Character Database for Unicode Version 14.0.0; urlPrefix: https://www.unicode.org/Public/14.0.0/ucd/DerivedCoreProperties.txt
type: dfn
text: Unicode Character Database for Unicode Version 14.0.0
spec: UnicodeVersion14; urlPrefix: https://www.unicode.org/versions/Unicode14.0.0/UnicodeStandard-14.0.pdf
type: dfn
text: code point; url:
spec: WebGPU; urlPrefix: https://gpuweb.github.io/gpuweb/#
type: dfn
text: GPU command; url: gpu-command
text: RasterizationPoint; url: rasterizationpoint
text: binding member; url: binding-member
text: binding resource type; url: binding-resource-type
text: binding type; url: binding-type
text: front-facing; url: front-facing
text: shader-output mask; url: shader-output-mask
text: framebuffer; url: framebuffer
for: supported limits
text: maxComputeWorkgroupStorageSize; url: dom-supported-limits-maxcomputeworkgroupstoragesize
type: abstract-op
text: validating GPUProgrammableStage; url: abstract-opdef-validating-gpuprogrammablestage
</pre>
# Introduction # {#intro}
WebGPU Shading Language (WGSL) is the shader language for [[!WebGPU]].
That is, an application using the WebGPU API uses WGSL to express the programs, known as shaders,
that run on the GPU.
<div class='example wgsl global-scope'>
<xmp highlight='rust'>
@fragment
fn main() -> @location(0) vec4<f32> {
return vec4<f32>(0.4, 0.4, 0.8, 1.0);
}
</xmp>
</div>
## Technical Overview ## {#technical-overview}
WebGPU issues a unit of work to the GPU in the form of a [=GPU command=].
WGSL is concerned with two kinds of GPU commands:
* a <dfn noexport>draw command</dfn> executes a [=GPURenderPipeline|render pipeline=]
in the context of [=shader stage input|inputs=], [=shader stage output|outputs=], and attached [=resources=].
* a <dfn noexport>dispatch command</dfn> executes a [=GPUComputePipeline|compute pipeline=]
in the context of [=shader stage input|inputs=] and attached [=resources=].
Both kinds of pipelines use shaders written in WGSL.
A <dfn noexport>shader</dfn> is the portion of a WGSL program that executes a [=shader stage=] in a pipeline.
A shader comprises:
* An [=entry point=] [=function/function=].
* The transitive closure of all called functions, starting with the entry point.
This set includes both [=user-defined function|user-defined=] and [=built-in function|built-in=] functions.
(For a more rigorous definition, see "[=functions in a shader stage=]".)
* The set of variables and constants [=statically accessed=] by all those functions.
* The set of types used to define or analyze all those functions, variables, and constants.
Note: A WGSL program does not require an [=entry point=]; however, such a
program cannot be executed by the API because an entry point is required to
create a {{GPUProgrammableStage}}.
When executing a shader stage, the implementation:
* Computes the values of constants declared at [=module scope|module-scope=].
* Binds [=resources=] to variables in the shader's [=resource interface of a shader|resource interface=],
making the contents of those resources available to the shader during execution.
* Allocates memory for other [=module scope|module-scope=] variables,
and populates that memory with the specified initial values.
* Populates the formal parameters of the entry point, if they exist, with the shader stage's inputs.
* Connects the entry point [=return value=], if one exists, to the shader stage's outputs.
* Then it invokes the entry point.
A WGSL program is organized into:
* Functions, which specify execution behavior.
* Statements, which are declarations or units of executable behavior.
* Literals, which are text representations for pure mathematical values.
* Constants, each providing a name for a value computed at a specific time.
* Variables, each providing a name for memory holding a value.
* Expressions, each of which combines a set of values to produce a result value.
* Types, each of which describes:
* A set of values.
* Constraints on supported expressions.
* The semantics of those expressions.
WGSL is an imperative language: behavior is specified as a sequence of statements to execute.
Statements can:
* Declare constants or variables.
* Modify the contents of variables.
* Modify execution order using structured programming constructs:
* Selective execution: `if` (with optional `else if` and `else` clauses), `switch`.
* Repetition: `loop`, `while`, `for`.
* Escaping a nested execution construct: `continue`, `break`, `break if`.
* Refactoring: function call and `return`.
* Evaluate expressions to compute values as part of the above behaviors.
WGSL is statically typed: each value computed by a particular expression is in a specific type,
determined only by examining the program source.
WGSL has types to describe booleans, numbers, vectors, matrices, and aggregations
of these in the form of arrays and structures.
Additional types describe memory.
WGSL does not have implicit conversions or promotions from [=type/concrete=]
types, but does provide implicit conversions and promotions from
[=type/abstract=] types.
Converting a value from one [=type/concrete=] numeric or boolean type to
another requires an explicit [[#conversion-expr|conversion]],
[[#type-constructor-expr|construction]], or [[#bitcast-expr|reinterpretation of
bits]]; however, WGSL does provide some limited facility to promote [=scalar=]
types to [=vector=] types.
This also applies to [=composite=] types.
WGSL has texture and sampler types.
Together with their associated built-in functions, these support functionality
commonly used for graphics rendering, and commonly provided by GPUs.
The work of a shader stage is partitioned into one or more <dfn noexport>invocations</dfn>,
each of which executes the entry point, but under slightly different conditions.
Invocations in a shader stage share access to certain variables:
* All invocations in the stage share the resources in the shader interface.
* In a [=compute shader stage|compute shader=], invocations in the same
[=compute shader stage/workgroup=] share
variables in the [=address spaces/workgroup=] [=address space=].
Invocations in different workgroups do not share those variables.
However, the invocations act on different sets of shader stage inputs, including built-in inputs
that provide an identifying value to distinguish an invocation from its peers.
Each invocation has its own independent memory space in the form
of variables in the [=address spaces/private=] and [=address spaces/function=] address spaces.
Invocations within a shader stage execute concurrently, and may often execute in parallel.
The shader author is responsible for ensuring the dynamic behavior of the invocations
in a shader stage:
* Meet the [[#uniformity|uniformity]] requirements of certain primitive operations, including texture sampling and control barriers.
* Coordinate potentially conflicting accesses to shared variables, to avoid race conditions.
WGSL sometimes permits several possible behaviors for a given feature.
This is a portability hazard, as different implementations may exhibit the different behaviors.
The design of WGSL aims to minimize such cases, but is constrained by feasibility,
and goals for achieving high performance across a broad range of devices.
<dfn noexport>Behavioral requirements</dfn> are actions the implementation will
perform when processing or executing a WGSL program. They describe the
implementation's obligations in the contract with the programmer.
The specification explicitly states these obligations when they might not be otherwise obvious.
## Syntax Notation ## {#syntax-notation}
Following syntax notation describes the conventions of the syntactic grammar of WGSL:
* Italic text on both sides of a rule indicates a syntax rule.
* Bold monospace text starting and ending with single quotes (**'**) on the right-hand side of a rule indicates keywords and tokens.
* A colon (**:**) in regular text registers a syntax rule.
* A vertical bar (**|**) in regular text indicates alternatives.
* An question mark (**?**) in regular text indicates that previous keyword, token, rule, or group occurs zero or one times (is optional).
* An asterisk (<b>*</b>) in regular text indicates that previous keyword, token, rule, or group occurs zero or more times.
* A plus (**+**) in regular text indicates that previous keyword, token, rule, or group occurs one or more times.
* A matching pair of opening parenthesis (**(**) and closing parenthesis (**)**) in regular text indicates a group of elements.
## Mathematical Terms and Notation ## {#terms-and-notation}
<dfn noexport>Angles</dfn>:
* By convention, angles are measured in radians.
* The reference ray for measuring angles is the ray from the origin (0,0) toward (0,∞).
* Let θ be the angle subtended by a comparison ray and the reference ray.
Then θ increases as the comparison ray moves counterclockwise.
* There are 2 π radians in a complete circle.
* Examples:
* The angle 0 points from the origin to the right, toward (1,0)
* The angle 2π points from the origin to the right, toward (1,0)
* The angle π/4 points from the origin to the point (1,1)
* The angle π/2 points from the origin to the point (0,1)
* The angle π points from the origin to the point (-1,0)
* The angle (3/2)π points from the origin to the point (0,-1)
The <dfn noexport>floor expression</dfn> is defined over real numbers |x| extended with +∞ and −∞:
* ⌊ + ∞ ⌋ = +∞
* ⌊ − ∞ ⌋ = −∞
* for real number |x|, ⌊|x|⌋ = |k|, where |k| is the unique integer such that |k| ≤ |x| < |k|+1
The <dfn noexport>ceiling expression</dfn> is defined over real numbers |x| extended with +∞ and −∞:
* ⌈ +∞ ⌉ = +∞
* ⌈ −∞ ⌉ = −∞
* for real number |x|, ⌈|x|⌉ = |k|, where |k| is the unique integer such that |k|-1 < |x| ≤ |k|
The <dfn noexport>truncate</dfn> function is defined over real numbers |x| extended with +∞ and −∞:
* truncate(+∞) = +∞
* truncate(−∞) = −∞
* for real number |x|, computes the nearest whole number whose absolute value is less than or equal to |x|:
* truncate(|x|) = ⌊|x|⌋ if |x| ≥ 0, and ⌈|x|⌉ if |x| < 0.
The <dfn noexport>roundUp</dfn> function is defined for positive integers |k| and |n| as:
* roundUp(|k|, |n|) = ⌈|n| ÷ |k|⌉ × |k|
The <dfn noexport>transpose</dfn> of an |c|-column |r|-row matrix |A| is the |r|-column |c|-row matrix
|A|<sup>T</sup> formed by copying the rows of |A| as the columns of |A|<sup>T</sup>:
* transpose(|A|) = |A|<sup>T</sup>
* transpose(|A|)<sub>|i|,|j|</sub> = |A|<sub>|j|,|i|</sub>
The transpose of a column vector is defined by interpreting the column vector as a 1-row matrix.
Similarly, the transpose of a row vector is defined by interpreting the row vector as a 1-column matrix.
# Shader Lifecycle # {#shader-lifecycle}
There are four key events in the lifecycle of a WGSL program and the shaders it may contain.
The first two correspond to the WebGPU API methods used to prepare a WGSL program
for execution.
The last two are the start and end of execution of a shader.
The events are:
1. <dfn noexport>Shader module creation</dfn>
* This occurs when the
WebGPU {{GPUDevice/createShaderModule()}} method
is called.
The source text for a WGSL program is provided at this time.
2. <dfn noexport>Pipeline creation</dfn>
* This occurs when the
WebGPU {{GPUDevice/createComputePipeline()}} method
or the
WebGPU {{GPUDevice/createRenderPipeline()}} method
is invoked.
These methods use one or more previously created shader modules, together with other
configuration information.
3. <dfn noexport>Shader execution start</dfn>
* This occurs when a [=draw command|draw=] or [=dispatch command=] is issued to the GPU,
begins executing the pipeline,
and invokes the [=shader stage=] [=entry point=] function.
4. <dfn noexport>Shader execution end</dfn>
* This occurs when all work in the shader completes:
* all its [=invocations=] terminate, and
* all accesses to [=resources=] complete, and
* outputs, if any, are passed to downstream pipeline stages.
The events are ordered due to:
* data dependencies: shader execution requires a pipeline, and a pipeline requires a shader module.
* causality: the shader must start executing before it can finish executing.
## Processing Errors ## {#processing-errors}
A WebGPU implementation may fail to process a shader for two reasons:
* A <dfn export>program error</dfn> occurs if the shader does not satisfy the requirements of the WGSL or WebGPU specifications.
* An <dfn noexport>uncategorized error</dfn> may occur
even when all WGSL and WebGPU requirements have been satisfied.
Possible causes include:
* The shaders are too complex, exceeding the capabilities of the implementation,
but in a way not easily captured by prescribed [[#limits|limits]].
Simplifying the shaders may work around the issue.
* A defect in the WebGPU implementation.
A processing error may occur during three phases in the shader lifecycle:
* A <dfn export>shader-creation error</dfn>
is an error feasibly detectable at [=shader module creation=] time.
Detection relies only on the WGSL program source text
and other information available to the `createShaderModule` API method.
Statements in this specification that describe something the program *must*
do generally produce a shader-creation error if those assertions are violated.
* A <dfn export>pipeline-creation error</dfn>
is an error detectable at [=pipeline creation=] time.
Detection relies on the WGSL program source text
and other information available to the particular pipeline creation API method.
* A <dfn export>dynamic error</dfn> is an error occurring during shader execution.
These errors may or may not be detectable.
Note: For example, a race condition may not be detectable.
Each requirement [=behavioral requirement|will=] be checked at the earliest opportunity.
That is:
* A shader-creation error results when failing to meet a requirement detectable at shader-creation time.
* A pipeline-creation error results when failing to meet a requirement detectable at pipeline-creation time,
but not detectable earlier.
When unclear from context, this specification indicates
whether failure to meet a particular requirement
results in a shader-creation, pipeline-creation, or dynamic error.
The WebGPU specification describes the consequences of each kind of error.
# Textual Structure # {#textual-structure}
The `text/wgsl` media type is used to identify content as a WGSL program.
See [[#text-wgsl-media-type]].
A WGSL program is Unicode text using the UTF-8 encoding, with no byte order mark (BOM).
WGSL program text consists of a sequence of Unicode [=code points=], grouped into contiguous non-empty sets forming:
* [=comments=]
* [=tokens=]
* [=blankspaces=]
The program text [=shader-creation error|must not=] include a null code point (`U+0000`).
## Parsing ## {#parsing}
To parse a WGSL program:
1. Remove [=comments=]:
* Replace the first comment with a space code point (`U+0020`).
* Repeat until no comments remain.
2. Parse the whole text, attempting to match the [=syntax/translation_unit=] grammar rule.
Parsing uses a LALR(1) parser (one token of lookahead) [[!DeRemer1969]], with the following customization:
* Tokenization is interleaved with parsing, and is context-aware.
When the parser requests the next token:
* Consume and ignore an initial sequence of [=blankspace=] code points.
* A <dfn>token candidate</dfn> is any WGSL [=token=] formed from the non-empty prefix of the remaining unconsumed code points.
* The token returned is the longest [=token candidate=] that is also a valid lookahead token for the current parser state. [[!VanWyk2007]]
A [=shader-creation error=] results if:
* the entire source text cannot be converted into a finite sequence of valid tokens, or
* the [=syntax/translation_unit=] grammar rule does not match the entire token sequence.
## Blankspace and line breaks ## {#blankspace-and-line-breaks}
<dfn>Blankspace</dfn> is any combination of one or more of code points from the Unicode
[=Unicode Standard Annex #31 for Unicode Version 14.0.0|Pattern_White_Space=] property.
The following is the set of code points in [=Unicode Standard Annex #31 for Unicode Version 14.0.0|Pattern_White_Space=]:
* space (`U+0020`)
* horizontal tab (`U+0009`)
* line feed (`U+000A`)
* vertical tab (`U+000B`)
* form feed (`U+000C`)
* carriage return (`U+000D`)
* next line (`U+0085`)
* left-to-right mark (`U+200E`)
* right-to-left mark (`U+200F`)
* line separator (`U+2028`)
* paragraph separator (`U+2029`)
<div class='syntax' noexport='true'>
<dfn for=syntax>_blankspace</dfn> :
| `/[\u0020\u0009\u000a\u000b\u000c\u000d\u0085\u200e\u200f\u2028\u2029]/uy`
</div>
A <dfn>line break</dfn> is a contiguous sequence of [=blankspace=] code points indicating the end of a line.
It is defined as the blankspace signalling a "mandatory break" as defined by
[=UAX14 Section 6.1 Non-tailorable Line Breaking Rules=] [=UAX14 LB4|LB4=] and [=UAX14 LB5|LB5=].
That is, a line break is any of:
* line feed (`U+000A`)
* vertical tab (`U+000B`)
* form feed (`U+000C`)
* carriage return (`U+000D`) when not also followed by line feed (`U+000A`)
* carriage return (`U+000D`) followed by line feed (`U+000A`)
* next line (`U+0085`)
* line separator (`U+2028`)
* paragraph separator (`U+2029`)
Note: Diagnostics that report source text locations in terms of line numbers should use [=line breaks=] to
count lines.
## Comments ## {#comments}
A <dfn>comment</dfn> is a span of text that does not influence the validity or meaning of a WGSL
program, except that a comment can separate [=tokens=].
Shader authors can use comments to document their programs.
A <dfn noexport>line-ending comment</dfn> is a kind of [=comment=] consisting
of the two code points `//` (`U+002F` followed by `U+002F`) and the code points that follow,
up until but not including:
* the next [=line break=], or
* the end of the program.
A <dfn noexport>block comment</dfn> is a kind of [=comment=] consisting of:
* The two code points `/*` (`U+002F` followed by `U+002A`)
* Then any sequence of:
* A [=block comment=], or
* Text that does not contain either `*/` (`U+002A` followed by `U+002F`)
or `/*` (`U+002F` followed by `U+002A`)
* Then the two code points `*/` (`U+002A` followed by `U+002F`)
Note: Block comments can be nested.
Since a block comment requires matching start and end text sequences, and allows arbitrary nesting,
a block comment cannot be recognized with a regular expression.
This is a consequence of the Pumping Lemma for Regular Languages.
<div class='example wgsl' heading='Comments'>
<xmp highlight='rust'>
const f = 1.5; // This is line-ending comment.
const g = 2.5; /* This is a block comment
that spans lines.
/* Block comments can nest.
*/
But all block comments must terminate.
*/
</xmp>
</div>
## Tokens ## {#tokens}
A <dfn>token</dfn> is a contiguous sequence of code points forming one of:
* a [=literal=].
* a [=keyword=].
* a [=reserved word=].
* a [=syntactic token=].
* an [=identifier=].
* a [=context-dependent name=].
## Literals ## {#literals}
A <dfn>literal</dfn> is one of:
* A <dfn noexport>boolean literal</dfn>: either `true` or `false`.
* A <dfn>numeric literal</dfn>: either an [=integer literal=] or a [=floating point literal=],
and is used to represent a number.
<div class='syntax' noexport='true'>
<dfn for=syntax>literal</dfn> :
| [=syntax/int_literal=]
| [=syntax/float_literal=]
| [=syntax/bool_literal=]
</div>
### Boolean Literals ### {#boolean-literals}
<div class='example wgsl bool-literals' heading='boolean literals'>
<xmp highlight='rust'>
const a = true;
const b = false;
</xmp>
</div>
<div class='syntax' noexport='true'>
<dfn for=syntax>bool_literal</dfn> :
| <a for=syntax_kw lt=true>`'true'`</a>
| <a for=syntax_kw lt=false>`'false'`</a>
</div>
### Numeric Literals ### {#numeric-literals}
The form of a [=numeric literal=] is defined via pattern-matching.
An <dfn>integer literal</dfn> is:
* An integer specified as any of:
* `0`
* A sequence of decimal digits, where the first digit is not `0`.
* `0x` or `0X` followed by a sequence of hexadecimal digits.
* Then an optional `i` or `u` suffix.
<div class='syntax' noexport='true'>
<dfn for=syntax>int_literal</dfn> :
| [=syntax/decimal_int_literal=]
| [=syntax/hex_int_literal=]
</div>
<div class='syntax' noexport='true'>
<dfn for=syntax>decimal_int_literal</dfn> :
| `/0[iu]?/`
| `/[1-9][0-9]*[iu]?/`
</div>
<div class='example wgsl decimal-int-literals' heading='decimal integer literals'>
<xmp highlight='rust'>
const a = 1u;
const b = 123;
const c = 0;
const d = 0i;
</xmp>
</div>
<div class='syntax' noexport='true'>
<dfn for=syntax>hex_int_literal</dfn> :
| `/0[xX][0-9a-fA-F]+[iu]?/`
</div>
<div class='example wgsl hexadecimal-int-literals' heading='hexadecimal integer literals'>
<xmp highlight='rust'>
const a = 0x123;
const b = 0X123u;
const c = 0x3f;
</xmp>
</div>
A <dfn>floating point literal</dfn> is either a [=decimal floating point literal=]
or a [=hexadecimal floating point literal=].
<div class='syntax' noexport='true'>
<dfn for=syntax>float_literal</dfn> :
| [=syntax/decimal_float_literal=]
| [=syntax/hex_float_literal=]
</div>
A [=floating point literal=] has two logical parts: a mantissa to representing a fraction, and an optional exponent.
Roughly, the value of the literal is the mantissa multiplied by a base value raised to the given exponent.
A mantissa digit is <dfn dfn-for="mantissa">significant</dfn> if it is non-zero,
or if there are mantissa digits to its left and to its right that are both non-zero.
Significant digits are counted from left-to-right: the *N*'th significant digit has *N*-1 significant digits
to its left.
A <dfn noexport>decimal floating point literal</dfn> is:
* A mantissa, specified as a sequence of digits, with an optional decimal point (`.`) somewhere among them.
The mantissa represents a fraction in base 10 notation.
* Then an optional exponent suffix consisting of:
* `e` or `E`.
* Then an exponent specified as an decimal number with an optional leading sign (`+` or `-`).
* Then an optional `f` or `h` suffix.
* At least one of the decimal point, or the exponent, or the `f` or `h` suffix
[=shader-creation error|must=] be present.
If none are, then the token is instead an [=integer literal=].
<div class='syntax' noexport='true'>
<dfn for=syntax>decimal_float_literal</dfn> :
| `/0[fh]/`
| `/[1-9][0-9]*[fh]/`
| `/[0-9]*\.[0-9]+([eE][+-]?[0-9]+)?[fh]?/`
| `/[0-9]+\.[0-9]*([eE][+-]?[0-9]+)?[fh]?/`
| `/[0-9]+[eE][+-]?[0-9]+[fh]?/`
</div>
<div class='example wgsl decimal-float-literals' heading='decimal floating point literals'>
<xmp highlight='rust'>
const a = 0.e+4f;
const b = 01.;
const c = .01;
const d = 12.34;
const f = .0f;
const g = 0h;
const h = 1e-3;
</xmp>
</div>
<div algorithm="mathematical value of decimal floating point literal">
The mathematical value of a [=decimal floating point literal=] is computed as follows:
* Compute |effective_mantissa| from |mantissa|:
* If |mantissa| has 20 or fewer [=mantissa/significant=] digits, then |effective_mantissa| is |mantissa|.
* Otherwise:
* Let |truncated_mantissa| be the same as |mantissa| except each digit to the
right of the 20th significant digit is replaced with 0.
* Let |truncated_mantissa_next| be the same as |mantissa| except:
* the 20th significant digit is incremented by 1, and carries are propagated to the left as needed
needed to ensure each digit remains in the range 0 through 9, and
* each digit to the right of the 20th significant digit is replaced with 0.
* Set |effective_mantissa| to either |truncated_mantissa| or |truncated_mantissa_next|.
This is an implementation choice.
* The mathematical value of the literal is the mathematical value of |effective_mantissa| as a decimal fraction,
multiplied by 10 to the power of the exponent.
When no exponent is specified, an exponent of 0 is assumed.
</div>
Note: The decimal mantissa is truncated after 20 decimal digits, preserving approximately log(10)/log(2)×20 ≈ 66.4 significant bits in the fraction.
A <dfn noexport>hexadecimal floating point literal</dfn> is:
* A `0x` or `0X` prefix
* Then a mantissa, specified as a sequence of hexadecimal digits, with an optional hexadecimal point (`.`) somewhere among them.
The mantissa represents a fraction in base 16 notation.
* Then an optional exponent suffix consisting of:
* `p` or `P`
* Then an exponent specified as an decimal number with an optional leading sign (`+` or `-`).
* Then an optional `f` or `h` suffix.
* At least one of the hexadecimal point, or the exponent [=shader-creation error|must=] be present.
If neither are, then the token is instead an [=integer literal=].
<div class='syntax' noexport='true'>
<dfn for=syntax>hex_float_literal</dfn> :
| `/0[xX][0-9a-fA-F]*\.[0-9a-fA-F]+([pP][+-]?[0-9]+[fh]?)?/`
| `/0[xX][0-9a-fA-F]+\.[0-9a-fA-F]*([pP][+-]?[0-9]+[fh]?)?/`
| `/0[xX][0-9a-fA-F]+[pP][+-]?[0-9]+[fh]?/`
</div>
<div class='example wgsl hexadecimal-float-literals' heading='hexadecimal floating point literals'>
<xmp highlight='rust'>
const a = 0xa.fp+2;
const b = 0x1P+4f;
const c = 0X.3;
const d = 0x3p+2h;
const e = 0X1.fp-4;
const f = 0x3.2p+2h;
</xmp>
</div>
<div algorithm="mathematical value of hexadecimal floating point literal">
The mathematical value of a [=hexadecimal floating point literal=] is computed as follows:
* Compute *effective_mantissa* from *mantissa*:
* If *mantissa* has 16 or fewer [=mantissa/significant=] digits, then *effective_mantissa* is *mantissa*.
* Otherwise:
* Let |truncated_mantissa| be the same as |mantissa| except each digit to the
right of the 16th significant digit is replaced with 0.
* Let |truncated_mantissa_next| be the same as |mantissa| except:
* the 16th significant digit is incremented by 1, and carries are propagated to the left as needed
needed to ensure each digit remains in the range 0 through `f`, and
* each digit to the right of the 16th significant digit is replaced with 0.
* Set |effective_mantissa| to either |truncated_mantissa| or |truncated_mantissa_next|.
This is an implementation choice.
* The mathematical value of the literal is the mathematical value of |effective_mantissa| as a hexadecimal fraction,
multiplied by 2 to the power of the exponent.
When no exponent is specified, an exponent of 0 is assumed.
</div>
Note: The hexadecimal mantissa is truncated after 16 hexadecimal digits, preserving approximately 4 ×16 = 64 significant bits in the fraction.
When a [=numeric literal=] has a suffix, the literal denotes a value in a specific [=type/concrete=] [=scalar=] type.
Otherwise, the literal denotes a value one of the [=abstract numeric types=] defined below.
In either case, the value denoted by the literal is its mathematical value after conversion to the target type,
following the rules in [[#floating-point-conversion]].
<table class=data>
<caption>Mapping numeric literals to types</caption>
<thead>
<tr><th>Numeric Literal<th>Suffix<th>Type<th>Examples
</thead>
<tr><td>[=integer literal=]<td>`i`<td>[=i32=]<td>42i
<tr><td>[=integer literal=]<td>`u`<td>[=u32=]<td>42u
<tr><td>[=integer literal=]<td><td>[=AbstractInt=]<td>124
<tr><td>[=floating point literal=]<td>`f`<td>[=f32=]<td>42f 1e5f 1.2f 0x1.0p10f
<tr><td>[=floating point literal=]<td>`h`<td>[=f16=]<td>42h 1e5h 1.2h 0x1.0p10h
<tr><td>[=floating point literal=]<td><td>[=AbstractFloat=]<td>1e5 1.2 0x1.0p10
</table>
A [=shader-creation error=] results if:
* An [=integer literal=] with a `i` or `u` suffix cannot be represented by the target type.
* A [=hexadecimal floating point literal=] with a `f` or `h` suffix overflows or cannot be exactly represented by the target type.
* A [=decimal floating point literal=] with a `f` or `h` suffix overflows the target type.
* A [=floating point literal=] with a `h` suffix is used while the [=extension/f16|f16 extension=] is not enabled.
Note: The hexadecimal float value 0x1.00000001p0 requires 33 mantissa bits to be represented exactly,
but [=f32=] only has 23 explicit mantissa bits.
Note: If you want to use an `f` suffix to force a hexadecimal float literal to be of type, the literal must also
use a binary exponent. For example, write `0x1p0f`. In comparison, `0x1f` is a hexadecimal integer literal.
## Keywords ## {#keywords}
A <dfn>keyword</dfn> is a [=token=] which refers to a predefined language concept.
See [[#keyword-summary]] for the list of WGSL keywords.
## Identifiers ## {#identifiers}
An <dfn>identifier</dfn> is a kind of [=token=] used as a name.
See [[#declaration-and-scope]].
WGSL uses two grammar nonterminals to separate use cases:
* An [=syntax/ident=] is used to name a declared object.
* A [=syntax/member_ident=] is used to name a [=member=] of a [=structure=] type.
<div class='syntax' noexport='true'>
<dfn for=syntax>ident</dfn> :
| [=syntax/ident_pattern_token=]
</div>
<div class='syntax' noexport='true'>
<dfn for=syntax>member_ident</dfn> :
| [=syntax/ident_pattern_token=]
</div>
The form of an identifier is based on the
[=Unicode Standard Annex #31 for Unicode Version 14.0.0|Unicode Standard Annex #31=] for
[[!UnicodeVersion14|Unicode Version 14.0.0]],
with the following elaborations.
Identifiers use the following profile described in terms of [=UAX31 Grammar=]:
```
<Identifier> := <Start> <Continue>* (<Medial> <Continue>+)*
<Start> := XID_Start + U+005F
<Continue> := <Start> + XID_Continue
<Medial> :=
```
This means identifiers with non-ASCII code points like these are
valid: `Δέλτα`, `réflexion`, `Кызыл`, `𐰓𐰏𐰇`, `朝焼け`, `سلام`, `검정`, `שָׁלוֹם`, `गुलाबी`, `փիրուզ`.
With the following exceptions:
* An identifier [=shader-creation error|must not=] have the same spelling as a [=keyword=] or as a [=reserved word=].
* An identifier [=shader-creation error|must not=] be `_` (a single underscore, `U+005F`).
* An identifier [=shader-creation error|must not=] start with `__` (two underscores, `U+005F` followed by `U+005F`).
<div class='syntax' noexport='true'>
<dfn for=syntax>ident_pattern_token</dfn> :
| `/([_\p{XID_Start}][\p{XID_Continue}]+)|([\p{XID_Start}])/uy`
</div>
[=Unicode Character Database for Unicode Version 14.0.0=] includes non-normative listing
with all valid code points
of both [=UAX31 Lexical Classes|XID_Start=] and
[=UAX31 Lexical Classes|XID_Continue=].
Note: The [=return type=] for some [=built-in functions=] are structure types whose name cannot be used WGSL source.
Those structure types are described as if they were [=predeclared=] with a name starting with two underscores.
The result value can be saved into newly declared `let` or `var` using type inferencing, or immediately have one of its members
immediately extracted by name. See example usages in the description of `frexp` and `modf`.
### Identifier Comparison ### {#identifier-comparison}
Two WGSL identifiers are the same if and only if they consist of the same sequence of code points.
Note: This specification does not permit Unicode normalization of values for the purposes of comparison.
Values that are visually and semantically identical but use different Unicode character sequences will not match.
Content authors are advised to use the same encoding sequence consistently or to avoid potentially troublesome
characters when choosing values. For more information, see [[CHARMOD-NORM]].
Note: A user agent should issue developer-visible warnings when the meaning of a WGSL program would change if
all instances of an identifier are replaced with one of that identifier's homographs.
(A homoglyph is a sequence of code points that may appear the same to a reader as another sequence of code points.
Examples of mappings to detect homoglyphs are the transformations, mappings, and matching algorithms mentioned in
the previous paragraph. Two sequences of code points are homographs if the identifier can transform one into the other by
repeatedly replacing a subsequence with its homoglyph.)
## Context-Dependent Names ## {#context-dependent-names}
A <dfn>context-dependent name</dfn> is a [=token=] used to name a concept, but only in specific grammatical contexts.
The spelling of the token may be the same as an [=identifier=], but the token does not [=resolve=] to a declared object.
Section [[#context-dependent-name-tokens]] lists all such tokens.
## Attributes ## {#attributes}
An <dfn noexport>attribute</dfn> modifies an object.
WGSL provides a unified syntax for applying attributes.
Attributes are used for a variety of purposes such as specifying the interface with the API.
Generally speaking, from the language's point-of-view, attributes can be
ignored for the purposes of type and semantic checking.
Additionally, the attribute name is a [=context-dependent name=], and
some attribute parameters are also context-dependent names.
An attribute [=shader-creation error|must not=] be specified more than once per object or type.
<table class='data'>
<caption>Attributes defined in WGSL</caption>
<thead>
<tr><th>Attribute<th>Valid Values<th>Description
</thead>
<tr><td><dfn noexport dfn-for="attribute">`align`</dfn>
<td>[=shader-creation error|Must=] be a [=const-expression=] that [=type rules|resolves=] to an [=i32=] or [=u32=].<br>
[=shader-creation error|Must=] be positive.
<td>[=shader-creation error|Must=] only be applied to a member of a [=structure=] type.
[=shader-creation error|Must=] be a power of 2.
Note: This attribute influences how a value of the enclosing structure type can appear in memory:
at which byte addresses the structure itself and its component members can appear.
In particular, the rules in [[#memory-layouts]] combine to imply the following constraint:
<p class="note" algorithm="implied constraint on align attribute">
If `align(`|n|`)` is applied to a member of |S|