-
Notifications
You must be signed in to change notification settings - Fork 304
/
index.bs
16071 lines (12939 loc) · 693 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
Shortname: webgpu
Level: None
Status: w3c/ED
Group: webgpu
ED: https://gpuweb.github.io/gpuweb/
TR: https://www.w3.org/TR/webgpu/
Repository: gpuweb/gpuweb
!Participate: <a href="https://github.com/gpuweb/gpuweb/issues/new">File an issue</a> (<a href="https://github.com/gpuweb/gpuweb/issues">open issues</a>)
Editor: Kai Ninomiya, Google https://www.google.com, kainino@google.com, w3cid 99487
Editor: Brandon Jones, Google https://www.google.com, bajones@google.com, w3cid 87824
Editor: Jim Blandy, Mozilla https://www.mozilla.com, jimb@mozilla.com, w3cid 131604
Former Editor: Myles C. Maxfield, Apple Inc. https://www.apple.com, mmaxfield@apple.com, w3cid 77180
Former Editor: Dzmitry Malyshau, Mozilla https://www.mozilla.org, dmalyshau@mozilla.com, w3cid 96977
Former Editor: Justin Fan, Apple Inc. https://www.apple.com, justin_fan@apple.com, w3cid 115633
Abstract: WebGPU exposes an API for performing operations, such as rendering and computation, on a Graphics Processing Unit.
Markup Shorthands: markdown yes
Markup Shorthands: dfn yes
Markup Shorthands: idl yes
Markup Shorthands: css no
Assume Explicit For: yes
</pre>
<pre class=biblio>
{
"SourceMap": {
"authors": [
"John Lenz",
"Nick Fitzgerald"
],
"href": "https://sourcemaps.info/spec.html",
"title": "Source Map Revision 3 Proposal"
}
}
</pre>
<pre class=link-defaults>
spec:webidl; type:exception; text:TypeError
spec:webidl; type:exception; text:RangeError
</pre>
<pre class=ignored-specs>
spec:resource-hints;
</pre>
<pre class=anchors>
spec: ECMA-262; urlPrefix: https://tc39.es/ecma262/#
type: dfn
text: agent; url: agent
text: surrounding agent; url: surrounding-agent
text: agent cluster; url: sec-agent-clusters
text: ?; url: sec-returnifabrupt-shorthands
text: !; url: sec-returnifabrupt-shorthands
text: Data Block; url: sec-data-blocks
type: abstract-op
text: DetachArrayBuffer; url: sec-detacharraybuffer
text: AllocateArrayBuffer; url: sec-allocatearraybuffer
text: CreateByteDataBlock; url: sec-createbytedatablock
type: attribute
for: ArrayBuffer
text: [[ArrayBufferDetachKey]]; url: sec-properties-of-the-arraybuffer-instances
spec: HTML; urlPrefix: https://html.spec.whatwg.org/multipage/
type: dfn
text: origin-clean; url: canvas.html#concept-canvas-origin-clean
text: check the usability of the image argument; url: canvas.html#check-the-usability-of-the-image-argument
text: placeholder canvas element; url: canvas.html#offscreencanvas-placeholder
text: event loop processing model; url: webappapis.html#event-loop-processing-model
for: video
text: intrinsic width; url: media.html#concept-video-intrinsic-width
text: intrinsic height; url: media.html#concept-video-intrinsic-height
spec: WebCodecs; urlPrefix: https://www.w3.org/TR/webcodecs/#
type: dfn
text: Close VideoFrame; url: close-videoframe
spec: WEBGL-1; urlPrefix: https://www.khronos.org/registry/webgl/specs/latest/1.0/#
type: interface
text: WebGLRenderingContextBase; url: WEBGLRENDERINGCONTEXTBASE
type: attribute; for: WebGLRenderingContextBase
text: drawingBufferColorSpace; url: DOM-WebGLRenderingContext-drawingBufferColorSpace
type: attribute; for: WebGLRenderingContextBase
text: drawingBufferWidth; url: DOM-WebGLRenderingContext-drawingBufferWidth
type: attribute; for: WebGLRenderingContextBase
text: drawingBufferHeight; url: DOM-WebGLRenderingContext-drawingBufferHeight
type: dictionary
text: WebGLContextAttributes; url: WEBGLCONTEXTATTRIBUTES
type: dfn
text: WebGL Drawing Buffer; url: THE_DRAWING_BUFFER
spec: WGSL; urlPrefix: https://gpuweb.github.io/gpuweb/wgsl/#
type: dfn
text: f16; url: f16
text: location; url: input-output-locations
text: interpolation; url: interpolation
text: pipeline-overridable; url: pipeline-overridable
text: pipeline constant ID; url: pipeline-constant-id
text: pipeline-overridable constant identifier string; url: pipeline-overridable-constant-identifier-string
text: pipeline-overridable constant default value; url: pipeline-overridable-constant-default-value
text: interface of a shader stage; url: interface-of-a-shader
text: shader execution end; url: shader-execution-end
text: shader stage output; url: shader-stage-output
text: shader stage input; url: shader-stage-input
text: builtin; url: built-in-values
text: position builtin; url: built-in-values-position
text: channel formats; url: channel-formats
text: invalid memory reference; url: invalid-memory-reference
text: shader module creation; url: shader-module-creation
text: pipeline creation; url: pipeline-creation
text: program error; url: program-error
text: roundUp; url: roundup
text: uncategorized error; url: uncategorized-error
text: shader-creation error; url: shader-creation-error
text: pipeline-creation error; url: pipeline-creation-error
text: store type; url: store-type
text: language extension; url: language-extension
text: runtime-sized; url: runtime-sized
text: WGSL floating point conversion; url: floating-point-conversion
text: WGSL identifier comparison; url: identifier-comparison
text: WGSL scalar type; url: scalar-types
text: @binding; url: attribute-binding
text: @group; url: attribute-group
text: line break; url: line-break
for: address spaces
text: workgroup; url: address-spaces-workgroup
for: builtin
text: sample_mask; url: built-in-values-sample_mask
text: frag_depth; url: built-in-values-frag_depth
for: extension
text: f16; url: extension-f16
type: abstract-op
text: SizeOf; url: sizeof
spec: Internationalization Glossary; urlPrefix: https://www.w3.org/TR/i18n-glossary/#
type: dfn
text: localizable text; url: dfn-localizable-text
spec: Strings on the Web; urlPrefix: https://w3c.github.io/string-meta/#
type: dfn
text: best practices for language and direction information; url: bp_and-reco
</pre>
<link rel="icon" type="image/png" sizes="32x32" href="img/favicon-32x32.png">
<link rel="icon" type="image/png" sizes="96x96" href="img/favicon-96x96.png">
<style>
/* Displays the WebGPU logo next to the W3C logo */
.head h1:after {
content: url(img/logo.png);
float: right;
}
/* Make <dl> blocks more distinct from their surroundings. */
main dl:not(.switch) {
border-left: thin solid #f3e48c;
padding-left: .5em;
}
/* Remove unnecessary extra margin on switch bodies */
dl.switch dd {
margin-left: 0em;
}
/* <p> by default has these margins. Update ul/ol/dl to match,
* since they are also put in places where paragraphs go. */
p, ul, ol, dl {
margin: 1em 0;
}
/* Styling for "editorial" issues */
.note.editorial {
border-color: var(--note-editorial-color);
background: var(--note-editorial-bg);
}
.note.editorial > .marker {
color: var(--note-editorial-color);
}
/* 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;
}
/* The new spec template doesn't put a box around algorithms anymore. */
/* Add a similar box for Valid Usage requirements. */
div.algorithm, div.validusage {
margin: .5em 0;
padding: .5em;
border-width: thin;
border-style: solid;
border-radius: .5em;
}
div.validusage {
border-color: #88e;
}
div.algorithm {
border-color: #ddd;
}
/*
* If the Valid Usage requirements are the first child of a *-timeline block give it a larger top
* margin to prevent the block labels from overlapping.
*/
.content-timeline>.validusage:first-child,
.device-timeline>.validusage:first-child,
.queue-timeline>.validusage:first-child {
margin-top: 1.5em;
}
/*
* Boxes for steps that occur on a particular timeline.
*/
div.content-timeline, div.device-timeline, div.queue-timeline {
padding: .5em;
border-radius: .5em;
}
.content-timeline {
background: rgba(0, 255, 0, 0.05);
background: var(--tint-green);
}
.device-timeline {
background: rgba(255, 0, 0, 0.05);
background: var(--tint-red);
}
.queue-timeline {
background: rgba(255, 0, 255, 0.05);
background: var(--tint-purple);
}
span[data-timeline],
dfn[data-timeline],
var[data-timeline],
a[data-timeline],
[href="#content-timeline"],
[href="#device-timeline"],
[href="#queue-timeline"] {
border-style: solid;
border-radius: .3em;
border-width: 0 0 .2em 0;
text-decoration: none;
}
dl[data-timeline],
div[data-timeline] {
border-style: solid;
border-radius: 1em 0 0 1em;
padding: .5em;
}
dl[data-timeline] {
border-width: 0 0 0 .25em !important;
}
div[data-timeline] {
border-width: 1px 0 0 .75em;
}
div.algorithm[data-timeline] {
border-width: 1px 1px 1px .75em;
}
div.algorithm > div[data-timeline] {
/* Remove unnecessary padding in this common case. Makes the border of the
* timeline box line up with the border of the surrounding algorithm box. */
margin-left: calc(-.5em - 1px);
margin-right: calc(-.5em - 1px);
}
/*
* Coloring for steps and other stuff on particular timelines.
*/
[data-timeline="content"],
[href="#content-timeline"] {
border-color: #00cc00 !important;
}
[data-timeline="device"],
[href="#device-timeline"] {
border-color: #880000 !important;
}
[data-timeline="queue"],
[href="#queue-timeline"] {
border-color: #c900f1 !important;
}
[data-timeline="const"] {
/* 186 is perceptual 50% gray, so works for both light and dark modes. */
border-color: rgb(186 186 186 / 30%) !important;
}
/*
* Stylistic labels, for clarity of presentation of these blocks.
*
* NOTE: This text is non-accessible and non-selectable; surrounding
* text must also explain the context.
*/
.validusage,
.content-timeline, .device-timeline, .queue-timeline,
[data-timeline] {
position: relative;
}
.validusage::before,
.content-timeline::before,
.device-timeline::before,
.queue-timeline::before {
font-weight: bold;
font-style: italic;
font-size: 1.3rem;
color: rgba(0, 0, 0, 0.15);
color: var(--watermark-text);
position: absolute;
right: .3em;
top: -.1em;
}
.validusage::before {
content: "Valid Usage";
}
.content-timeline::before {
content: "Content Timeline";
}
.device-timeline::before {
content: "Device Timeline";
}
.queue-timeline::before {
content: "Queue Timeline";
}
/*
* Ensure that argumentdef blocks don't overflow algorithm section borders. This is made far harder
* than it needs to be because the top-level W3C stylesheet has several @media + min-width variants
* that mark themselves as !important and then proceed to do the wrong thing.
*/
@media screen and (min-width: 78em) {
body:not(.toc-inline) .algorithm .overlarge {
margin-right: auto !important;
}
}
@media screen and (min-width: 90em) {
body:not(.toc-inline) .algorithm .overlarge {
margin-right: auto !important;
}
}
.algorithm .overlarge {
margin-right: auto !important;
}
/*
* The default argumentdef style has a caption that doesn't suit this spec's
* formatting particularly well. Hide it.
*/
.algorithm .argumentdef {
margin-top: 0;
}
.algorithm .argumentdef > caption {
display: none;
}
/*
* Argumentdef is also too wide given our typenames, so make some tweaks.
*/
/* Move border to tr and reduce padding. */
.algorithm .argumentdef td,
.algorithm .argumentdef th {
padding: .5em;
border: none;
}
.algorithm .argumentdef > tbody > tr {
border-top: thin solid var(--datacell-border);
}
/* Compress "Nullable" and "Optional" and remove horizontal padding. */
.algorithm .argumentdef > thead > tr > :nth-child(3),
.algorithm .argumentdef > thead > tr > :nth-child(4) {
font-family: monospace;
max-width: 4ch;
word-wrap: break-word;
}
.algorithm .argumentdef tr > :nth-child(3),
.algorithm .argumentdef tr > :nth-child(4) {
padding-left: .5em;
padding-right: 0;
}
/* Wrap Parameter and Type onto separate rows. */
.algorithm .argumentdef > thead > tr > th:nth-child(1),
.algorithm .argumentdef > tbody > tr > td:nth-child(1) {
padding-right: .5em;
float: left;
}
.algorithm .argumentdef > thead > tr > th:nth-child(2),
.algorithm .argumentdef > tbody > tr > td:nth-child(2) {
padding-left: .5em;
float: right;
}
.algorithm .argumentdef > thead > tr > th {
vertical-align: top;
}
/*
* Add vertical lines to demarcate multi-column cells.
*/
table.data td,
table.data th {
/* Only one side is needed because there are no outer borders on the tables.
* 186 is perceptual 50% gray, so works for both light and dark modes. */
border-left: 1px solid rgb(186 186 186 / 30%);
}
table.data.no-colspan-center td[colspan],
table.data.no-colspan-center th[colspan] {
text-align: unset;
}
table.data tr.row-continuation td,
table.data tr.row-continuation th {
border-top: none;
}
/*
* Vertical class for table columns. (Can't use th.vertical because of a Safari bug.)
*/
span.vertical {
writing-mode: vertical-rl;
white-space: nowrap;
}
/*
* Sticky table headers.
*/
.overlarge {
/* position: sticky doesn't work inside scrollable elements. */
overflow-x: unset;
}
thead.stickyheader th, th.stickyheader {
position: sticky;
top: 0;
background: #f8f8f8;
background: var(--stickyheader-background);
}
/*
* Coordinate System Figures
*/
.coordinate-diagram {
width: 500px;
}
/*
* Light-mode and dark-mode colors
*/
:root {
--watermark-text: rgba(0, 0, 0, 15%);
--stickyheader-background: #f8f8f8;
--tint-red: rgba(255, 0, 0, 6%);
--tint-green: rgba(0, 255, 0, 10%);
--tint-blue: rgba(0, 0, 255, 5%);
--tint-purple: rgba(255, 0, 255, 5%);
--note-editorial-color: #c06e00;
--note-editorial-bg: #ffeedd;
}
@media (prefers-color-scheme:dark) {
:root {
--watermark-text: rgba(255, 255, 255, 25%);
--stickyheader-background: #181818;
--tint-red: rgba(255, 0, 0, 20%);
--tint-green: rgba(0, 255, 0, 18%);
--tint-blue: rgba(0, 130, 255, 24%);
--tint-purple: rgba(255, 0, 255, 22%);
--note-editorial-color: #ff9100;
--note-editorial-bg: var(--borderedblock-bg);
}
}
</style>
# Introduction # {#intro}
*This section is non-normative.*
[Graphics Processing Units](https://en.wikipedia.org/wiki/Graphics_processing_unit), or GPUs for short,
have been essential in enabling rich rendering and computational applications in personal computing.
WebGPU is an API that exposes the capabilities of GPU hardware for the Web.
The API is designed from the ground up to efficiently map to (post-2014) native GPU APIs.
WebGPU is not related to [WebGL](https://www.khronos.org/webgl/) and does not explicitly target OpenGL ES.
WebGPU sees physical GPU hardware as {{GPUAdapter}}s. It provides a connection to an adapter via
{{GPUDevice}}, which manages resources, and the device's {{GPUQueue}}s, which execute commands.
{{GPUDevice}} may have its own memory with high-speed access to the processing units.
{{GPUBuffer}} and {{GPUTexture}} are the <dfn dfn>physical resources</dfn> backed by GPU memory.
{{GPUCommandBuffer}} and {{GPURenderBundle}} are containers for user-recorded commands.
{{GPUShaderModule}} contains [=shader=] code. The other resources,
such as {{GPUSampler}} or {{GPUBindGroup}}, configure the way [=physical resources=] are used by the GPU.
GPUs execute commands encoded in {{GPUCommandBuffer}}s by feeding data through a [=pipeline=],
which is a mix of fixed-function and programmable stages. Programmable stages execute
<dfn dfn>shaders</dfn>, which are special programs designed to run on GPU hardware.
Most of the state of a [=pipeline=] is defined by
a {{GPURenderPipeline}} or a {{GPUComputePipeline}} object. The state not included
in these [=pipeline=] objects is set during encoding with commands,
such as {{GPUCommandEncoder/beginRenderPass()}} or {{GPURenderPassEncoder/setBlendConstant()}}.
<pre class=include>
path: sections/privacy-and-security.bs
</pre>
# Fundamentals # {#fundamentals}
## Conventions ## {#api-conventions}
### Syntactic Shorthands ### {#shorthands}
In this specification, the following syntactic shorthands are used:
: The `.` ("dot") syntax, common in programming languages.
::
The phrasing "`Foo.Bar`" means "the `Bar` member of the value (or interface) `Foo`."
If `Foo` is an [=ordered map=], [=asserts=] that the key `Bar` exists.
<p class="note editorial"><span class=marker>Editorial note:</span>
Some phrasing in this spec may currently assume this resolves to `undefined` if `Bar` doesn't exist.
The phrasing "`Foo.Bar` is [=map/exist|provided=]" means
"the `Bar` member [=map/exists=] in the [=map=] value `Foo`"
: The `?.` ("optional chaining") syntax, adopted from JavaScript.
::
The phrasing "`Foo?.Bar`" means
"if `Foo` is `null` or `undefined` or `Bar` does not [=map/exist=] in `Foo`, `undefined`; otherwise, `Foo.Bar`".
For example, where `buffer` is a {{GPUBuffer}}, `buffer?.\[[device]].\[[adapter]]` means
"if `buffer` is `null` or `undefined`, then `undefined`; otherwise,
the `\[[adapter]]` internal slot of the `\[[device]]` internal slot of `buffer`.
: The `??` ("nullish coalescing") syntax, adopted from JavaScript.
::
The phrasing "`x` ?? `y`" means "`x`, if `x` is not null/undefined, and `y` otherwise".
: <dfn dfn>slot-backed attribute</dfn>
::
A WebIDL attribute which is backed by an internal slot of the same name.
It may or may not be mutable.
<h4 id=webgpu-objects>WebGPU Objects
<span id=webgpu-internal-objects></span>
</h4>
A <dfn dfn>WebGPU object</dfn> consists of a [=WebGPU Interface=] and an [=internal object=].
The <dfn dfn>WebGPU interface</dfn> defines the public interface and state of the [=WebGPU object=].
It can be used on the [=content timeline=] where it was created, where it is a JavaScript-exposed
WebIDL interface.
Any interface which includes <dfn interface>GPUObjectBase</dfn> is a [=WebGPU interface=].
The <dfn dfn>internal object</dfn> tracks the state of the [=WebGPU object=] on the [=device timeline=].
All reads/writes to the mutable state of an [=internal object=] occur from steps executing on a
single well-ordered [=device timeline=]. These steps may have been issued from a [=content timeline=]
algorithm on any of multiple [=agents=].
Note: An "[=agent=]" refers to a JavaScript "thread" (i.e. main thread, or Web Worker).
The following special property types can be defined on [=WebGPU objects=]:
: <dfn dfn data-timeline=const>immutable property</dfn>
::
A read-only slot set during initialization of the object. It can be accessed from any timeline.
Note: Since the slot is immutable, implementations may have a copy on multiple timelines, as needed.
[=Immutable properties=] are defined in this way to avoid describing multiple copies in this spec.
If named `[[with brackets]]`, it is an internal slot.<br/>
If named `withoutBrackets`, it is a `readonly` [=slot-backed attribute=] of the [=WebGPU interface=].
: <dfn dfn data-timeline=content>content timeline property</dfn>
::
A property which is only accessible from the [=content timeline=]
where the object was created.
If named `[[with brackets]]`, it is an internal slot.<br/>
If named `withoutBrackets`, it is a [=slot-backed attribute=] of the [=WebGPU interface=].
: <dfn dfn data-timeline=device>device timeline property</dfn>
::
A property which tracks state of the [=internal object=] and is only accessible from the
[=device timeline=] where the object was created. [=device timeline properties=] may be mutable.
[=Device timeline properties=] are named `[[with brackets]]`, and are internal slots.
<script type=idl>
interface mixin GPUObjectBase {
attribute USVString label;
};
</script>
<div algorithm data-timeline=content>
To <dfn abstract-op>create a new WebGPU object</dfn>({{GPUObjectBase}} |parent|,
interface |T|, {{GPUObjectDescriptorBase}} |descriptor|)
(where |T| extends {{GPUObjectBase}}), run the following [=content timeline=] steps:
1. Let |device| be |parent|.{{GPUObjectBase/[[device]]}}.
1. Let |object| be a new instance of |T|.
1. Set |object|.{{GPUObjectBase/[[device]]}} to |device|.
1. Set |object|.{{GPUObjectBase/label}} to |descriptor|.{{GPUObjectDescriptorBase/label}}.
1. Return |object|.
</div>
{{GPUObjectBase}} has the following [=immutable properties=]:
<dl dfn-type=attribute dfn-for=GPUObjectBase data-timeline=const>
: <dfn>\[[device]]</dfn>, of type [=device=], readonly
::
The [=device=] that owns the [=internal object=].
Operations on the contents of this object [=assert=] they are running on the
[=device timeline=], and that the device is [=valid=].
</dl>
{{GPUObjectBase}} has the following [=content timeline properties=]:
<dl dfn-type=attribute dfn-for=GPUObjectBase data-timeline=content>
: <dfn>label</dfn>
::
A developer-provided label which is used in an implementation-defined way.
It can be used by the browser, OS, or other tools to help
identify the underlying [=internal object=] to the developer.
Examples include displaying the label in {{GPUError}} messages, console warnings,
browser developer tools, and platform debugging utilities.
<div class=note heading>
Implementations **should** use labels to enhance error messages by using them to
identify WebGPU objects.
However, this need not be the only way of identifying objects:
implementations **should** also use other available information,
especially when no label is available. For example:
- The label of the parent {{GPUTexture}} when printing a {{GPUTextureView}}.
- The label of the parent {{GPUCommandEncoder}} when printing a
{{GPURenderPassEncoder}} or {{GPUComputePassEncoder}}.
- The label of the source {{GPUCommandEncoder}} when printing a {{GPUCommandBuffer}}.
- The label of the source {{GPURenderBundleEncoder}} when printing a {{GPURenderBundle}}.
</div>
<div class=note heading>
The {{GPUObjectBase/label}} is a property of the {{GPUObjectBase}}.
Two {{GPUObjectBase}} "wrapper" objects have completely separate label states,
even if they refer to the same underlying object
(for example returned by {{GPUPipelineBase/getBindGroupLayout()}}).
The {{GPUObjectBase/label}} property will not change except by being set from JavaScript.
This means one underlying object could be associated with multiple labels.
This specification does not define how the label is propagated to the [=device timeline=].
How labels are used is completely implementation-defined: error messages could
show the most recently set label, all known labels, or no labels at all.
It is defined as a {{USVString}} because some user agents may
supply it to the debug facilities of the underlying native APIs.
</div>
</dl>
<div class=note heading>
Ideally [=WebGPU interfaces=] should not prevent their parent objects, such as the
{{GPUObjectBase/[[device]]}} that owns them, from being garbage collected. This cannot be
guaranteed, however, as holding a strong reference to a parent object may be required in some
implementations.
As a result, developers should assume that a [=WebGPU interface=] may not be garbage collected
until all child objects of that interface have also been garbage collected. This may cause some
resources to remain allocated longer than anticipated.
Calling the `destroy` method on a [=WebGPU interface=] (such as
{{GPUDevice}}.{{GPUDevice/destroy()}} or {{GPUBuffer}}.{{GPUBuffer/destroy()}}) should be
favored over relying on garbage collection if predictable release of allocated resources is
needed.
</div>
### Object Descriptors ### {#object-descriptors}
An <dfn dfn>object descriptor</dfn> holds the information needed to create an object,
which is typically done via one of the `create*` methods of {{GPUDevice}}.
<script type=idl>
dictionary GPUObjectDescriptorBase {
USVString label = "";
};
</script>
{{GPUObjectDescriptorBase}} has the following members:
<dl dfn-type=dict-member dfn-for=GPUObjectDescriptorBase>
: <dfn>label</dfn>
::
The initial value of {{GPUObjectBase/label|GPUObjectBase.label}}.
</dl>
## Asynchrony ## {#asynchrony}
### Invalid Internal Objects & Contagious Invalidity ### {#invalidity}
Object creation operations in WebGPU don't return promises, but nonetheless are internally
asynchronous. Returned objects refer to [=internal objects=] which are manipulated on a
[=device timeline=]. Rather than fail with exceptions or rejections, most errors that occur on a
[=device timeline=] are communicated through {{GPUError}}s generated on the associated [=device=].
[=Internal objects=] are either <dfn dfn>valid</dfn> or <dfn dfn>invalid</dfn>.
An [=invalid=] object will never become [=valid=] at a later time,
but some [=valid=] objects may become [=invalid=].
Objects are [=invalid=] from creation if it wasn't possible to create them.
This can happen, for example, if the [=object descriptor=] doesn't describe a valid
object, or if there is not enough memory to allocate a resource.
It can also happen if an object is created with or from another invalid object
(for example calling {{GPUTexture/createView()}} on an invalid {{GPUTexture}})
(for example the {{GPUTexture}} of a {{GPUTexture/createView()}} call):
this case is referred to as <dfn dfn noexport>contagious invalidity</dfn>.
[=Internal objects=] of *most* types cannot become [=invalid=] after they are created, but still
may become unusable, e.g. if the owning device is [=lose the device|lost=] or
{{GPUDevice/destroy()|destroyed}}, or the object has a special internal state,
like buffer state "[=GPUBuffer/[[internal state]]/destroyed=]".
[=Internal objects=] of some types *can* become [=invalid=] after they are created; specifically,
[=devices=], [=adapters=], {{GPUCommandBuffer}}s, and command/pass/bundle encoders.
<div algorithm data-timeline=device>
A given {{GPUObjectBase}} |object| is <dfn abstract-op>valid to use with</dfn>
a |targetObject| if the all of the requirements in the following [=device timeline=] steps are met:
<div class=validusage>
- |object| must be [=valid=].
- |object|.{{GPUObjectBase/[[device]]}} must be [=valid=].
- |object|.{{GPUObjectBase/[[device]]}} must equal |targetObject|.{{GPUObjectBase/[[device]]}}.
</div>
</div>
### Promise Ordering ### {#promise-ordering}
Several operations in WebGPU return promises.
- {{GPU}}.{{GPU/requestAdapter()}}
- {{GPUAdapter}}.{{GPUAdapter/requestDevice()}}
- {{GPUAdapter}}.{{GPUAdapter/requestAdapterInfo()}}
- {{GPUDevice}}.{{GPUDevice/createComputePipelineAsync()}}
- {{GPUDevice}}.{{GPUDevice/createRenderPipelineAsync()}}
- {{GPUBuffer}}.{{GPUBuffer/mapAsync()}}
- {{GPUShaderModule}}.{{GPUShaderModule/getCompilationInfo()}}
- {{GPUQueue}}.{{GPUQueue/onSubmittedWorkDone()}}
- {{GPUDevice}}.{{GPUDevice/lost}}
- {{GPUDevice}}.{{GPUDevice/popErrorScope()}}
WebGPU does not make any guarantees about the order in which these promises settle
(resolve or reject), except for the following:
- <div algorithm="onSubmittedWorkDone ordering" data-timeline=content>
For some {{GPUQueue}} |q|,
if |p1| = |q|.{{GPUQueue/onSubmittedWorkDone()}} is called before
|p2| = |q|.{{GPUQueue/onSubmittedWorkDone()}},
then |p1| must settle before |p2|.
</div>
- <div algorithm="mapAsync-onSubmittedWorkDone ordering" data-timeline=content>
For some {{GPUQueue}} |q| and {{GPUBuffer}} |b| on the same {{GPUDevice}},
if |p1| = |b|.{{GPUBuffer/mapAsync()}} is called before
|p2| = |q|.{{GPUQueue/onSubmittedWorkDone()}},
then |p1| must settle before |p2|.
<!-- POSTV1(multi-queue):
and |b|'s most recent usage was either another mapping or an exclusive usage on |q| -->
</div>
Applications must not rely on any other promise settlement ordering.
## Coordinate Systems ## {#coordinate-systems}
Rendering operations use the following coordinate systems:
* <dfn lt="NDC">Normalized device coordinates</dfn> (or NDC) have three dimensions, where:
* -1.0 ≤ x ≤ 1.0
* -1.0 ≤ y ≤ 1.0
* 0.0 ≤ z ≤ 1.0
* The bottom-left corner is at (-1.0, -1.0, z).
<figure>
<figcaption>Normalized device coordinates.</figcaption>
<object class=coordinate-diagram type="image/svg+xml" data="img/normalized-device-coordinates.svg"></object>
</figure>
Note: Whether `z = 0` or `z = 1` is treated as the near plane is application specific. The above diagram presents
`z = 0` as the near plane but the observed behavior is determined by a combination of the projection matrices
used by shaders, the {{GPURenderPassDepthStencilAttachment/depthClearValue}}, and the
{{GPUDepthStencilState/depthCompare}} function.
* <dfn noexport>Clip space coordinates</dfn> have four dimensions: (x, y, z, w)
* Clip space coordinates are used for the the [=clip position=] of a vertex (i.e. the [=position builtin|position=] output of a vertex shader),
and for the [=clip volume=].
* [=NDC|Normalized device coordinates=] and clip space coordinates are related as follows:
If point *p = (p.x, p.y, p.z, p.w)* is in the [=clip volume=], then its normalized device coordinates are (*p.x* ÷ *p.w*, *p.y* ÷ *p.w*, *p.z* ÷ *p.w*).
* <dfn noexport>Framebuffer coordinates</dfn> address the pixels in the [=framebuffer=]
* They have two dimensions.
* Each pixel extends 1 unit in x and y dimensions.
* The top-left corner is at (0.0, 0.0).
* x increases to the right.
* y increases down.
* See [[#render-passes]] and [[#rasterization]].
<figure>
<figcaption>Framebuffer coordinates.</figcaption>
<object class=coordinate-diagram type="image/svg+xml" data="img/framebuffer-coordinates.svg"></object>
</figure>
* <dfn>Viewport coordinates</dfn> combine [=framebuffer coordinates=] in x and y dimensions,
with depth in z.
* Normally 0.0 ≤ z ≤ 1.0, but this can be modified by setting {{RenderState/[[viewport]]}}.`minDepth` and `maxDepth` via
{{GPURenderPassEncoder/setViewport()}}
* <dfn noexport>Fragment coordinates</dfn> match [=viewport coordinates=].
* <dfn noexport>Texture coordinates</dfn>, sometimes called "UV coordinates" in 2D, are used to sample
textures and have a number of components matching the {{GPUTextureDimension|texture dimension}}.
* 0 ≤ u ≤ 1.0
* 0 ≤ v ≤ 1.0
* 0 ≤ w ≤ 1.0
* (0.0, 0.0, 0.0) is in the first texel in texture memory address order.
* (1.0, 1.0, 1.0) is in the last texel texture memory address order.
<figure>
<figcaption>2D Texture coordinates.</figcaption>
<object class=coordinate-diagram type="image/svg+xml" data="img/uv-coordinates.svg"></object>
</figure>
* <dfn noexport>Window coordinates</dfn>, or <dfn noexport>present coordinates</dfn>,
match [=framebuffer coordinates=], and are used when interacting with
an external display or conceptually similar interface.
Note: WebGPU's coordinate systems match DirectX's coordinate systems in a graphics pipeline.
## Programming Model ## {#programming-model}
### Timelines ### {#programming-model-timelines}
WebGPU's behavior is described in terms of "timelines".
Each operation (defined as algorithms) occurs on a timeline.
Timelines clearly define both the order of operations, and which state is
available to which operations.
Note:
This "timeline" model describes the constraints of the multi-process models of
browser engines (typically with a "content process" and "GPU process"), as well
as the GPU itself as a separate execution unit in many implementations.
Implementing WebGPU does not require timelines to execute in parallel, so does
not require multiple processes, or even multiple threads.
: <dfn dfn>Content timeline</dfn>
:: Associated with the execution of the Web script.
It includes calling all methods described by this specification.
To issue steps to the content timeline from an operation on {{GPUDevice}} `device`,
[$queue a global task for GPUDevice$] `device` with those steps.
: <dfn dfn>Device timeline</dfn>
:: Associated with the GPU device operations
that are issued by the user agent.
It includes creation of adapters, devices, and GPU resources
and state objects, which are typically synchronous operations from the point
of view of the user agent part that controls the GPU,
but can live in a separate OS process.
: <dfn dfn>Queue timeline</dfn>
:: Associated with the execution of operations
on the compute units of the GPU. It includes actual draw, copy,
and compute jobs that run on the GPU.
: <dfn dfn>Timeline-agnostic</dfn>
:: Associated with any of the above timelines
Steps may be issued to any timeline if they only operate on [=immutable properties=] or
arguments passed from the calling steps.
<div class=example style="background: var(--bg)">
The following show the styling of steps and values associated with each timeline.
This styling is non-normative; the specification text always describes the association.
<dl data-timeline=const>
: <dfn>Immutable value example term</dfn> definition
:: Can be used on any timeline.
</dl>
<dl data-timeline=content>
: <dfn>Content-timeline example term</dfn> definition
:: Can only be used on the [=content timeline=].
</dl>
<dl data-timeline=device>
: <dfn>Device-timeline example term</dfn> definition
:: Can only be used on the [=device timeline=].
</dl>
<dl data-timeline=queue>
: <dfn>Queue-timeline example term</dfn> definition
:: Can only be used on the [=queue timeline=].
</dl>
<div class=algorithm>
<div data-timeline=const>
Steps which are [=timeline-agnostic=] look like this.
[=Immutable value example term=] usage.
</div>
<div data-timeline=content>
Steps executed on the [=content timeline=] look like this.
[=Immutable value example term=] usage.
[=Content-timeline example term=] usage.
</div>
<div data-timeline=device>
Steps executed on the [=device timeline=] look like this.
[=Immutable value example term=] usage.
[=Device-timeline example term=] usage.
</div>
<div data-timeline=queue>
Steps executed on the [=queue timeline=] look like this.
[=Immutable value example term=] usage.
[=Queue-timeline example term=] usage.
</div>
</div>
</div>
In this specification, asynchronous operations are used when the return value
depends on work that happens on any timeline other than the [=Content timeline=].
They are represented by promises and events in API.
<div class=example>
{{GPUComputePassEncoder/dispatchWorkgroups()|GPUComputePassEncoder.dispatchWorkgroups()}}:
1. User encodes a `dispatchWorkgroups` command by calling a method of the
{{GPUComputePassEncoder}} which happens on the [=Content timeline=].
1. User issues {{GPUQueue/submit(commandBuffers)|GPUQueue.submit()}} that hands over
the {{GPUCommandBuffer}} to the user agent, which processes it
on the [=Device timeline=] by calling the OS driver to do a low-level submission.
1. The submit gets dispatched by the GPU invocation scheduler onto the
actual compute units for execution, which happens on the [=Queue timeline=].
</div>
<div class=example>
{{GPUDevice/createBuffer(descriptor)|GPUDevice.createBuffer()}}:
1. User fills out a {{GPUBufferDescriptor}} and creates a {{GPUBuffer}} with it,
which happens on the [=Content timeline=].
2. User agent creates a low-level buffer on the [=Device timeline=].
</div>
<div class=example>
{{GPUBuffer/mapAsync()|GPUBuffer.mapAsync()}}:
1. User requests to map a {{GPUBuffer}} on the [=Content timeline=] and
gets a promise in return.
2. User agent checks if the buffer is currently used by the GPU
and makes a reminder to itself to check back when this usage is over.
3. After the GPU operating on [=Queue timeline=] is done using the buffer,
the user agent maps it to memory and [=resolves=] the promise.
</div>
### Memory Model ### {#programming-model-memory}
*This section is non-normative.*
Once a {{GPUDevice}} has been obtained during an application initialization routine,
we can describe the <dfn dfn>WebGPU platform</dfn> as consisting of the following layers:
1. User agent implementing the specification.
1. Operating system with low-level native API drivers for this device.
1. Actual CPU and GPU hardware.
Each layer of the [=WebGPU platform=] may have different memory types
that the user agent needs to consider when implementing the specification:
- The script-owned memory, such as an {{ArrayBuffer}} created by the script,
is generally not accessible by a GPU driver.
- A user agent may have different processes responsible for running
the content and communication to the GPU driver.
In this case, it uses inter-process shared memory to transfer data.
- Dedicated GPUs have their own memory with high bandwidth,
while integrated GPUs typically share memory with the system.
Most [=physical resources=] are allocated in the memory of type
that is efficient for computation or rendering by the GPU.
When the user needs to provide new data to the GPU,
the data may first need to cross the process boundary in order to reach
the user agent part that communicates with the GPU driver.
Then it may need to be made visible to the driver,
which sometimes requires a copy into driver-allocated staging memory.
Finally, it may need to be transferred to the dedicated GPU memory,
potentially changing the internal layout into one
that is most efficient for GPUs to operate on.
All of these transitions are done by the WebGPU implementation of the user agent.
Note: This example describes the worst case, while in practice
the implementation may not need to cross the process boundary,
or may be able to expose the driver-managed memory directly to
the user behind an `ArrayBuffer`, thus avoiding any data copies.
### Resource Usages ### {#programming-model-resource-usages}
A [=physical resource=] can be used on GPU with an <dfn dfn>internal usage</dfn>:
<dl dfn-type=dfn dfn-for="internal usage">
: <dfn>input</dfn>
:: Buffer with input data for draw or dispatch calls. Preserves the contents.
Allowed by buffer {{GPUBufferUsage/INDEX}}, buffer {{GPUBufferUsage/VERTEX}}, or buffer {{GPUBufferUsage/INDIRECT}}.
: <dfn>constant</dfn>
:: Resource bindings that are constant from the shader point of view. Preserves the contents.
Allowed by buffer {{GPUBufferUsage/UNIFORM}} or texture {{GPUTextureUsage/TEXTURE_BINDING}}.
: <dfn>storage</dfn>
:: Writable storage resource binding.
Allowed by buffer {{GPUBufferUsage/STORAGE}} or texture {{GPUTextureUsage/STORAGE_BINDING}}.
: <dfn>storage-read</dfn>
:: Read-only storage resource bindings. Preserves the contents.