0
# Commands and Passes
1
2
Command recording, encoding, and execution including render passes and compute passes for GPU work submission.
3
4
## Capabilities
5
6
### GPU Command Encoder
7
8
Main interface for recording GPU commands into command buffers.
9
10
```typescript { .api }
11
interface GPUCommandEncoder {
12
/** Optional debug label */
13
readonly label: string | undefined;
14
15
/**
16
* Begins a render pass
17
* @param descriptor - Render pass configuration
18
* @returns Render pass encoder
19
*/
20
beginRenderPass(descriptor: GPURenderPassDescriptor): GPURenderPassEncoder;
21
22
/**
23
* Begins a compute pass
24
* @param descriptor - Optional compute pass configuration
25
* @returns Compute pass encoder
26
*/
27
beginComputePass(descriptor?: GPUComputePassDescriptor): GPUComputePassEncoder;
28
29
/**
30
* Copies data between buffers
31
* @param source - Source buffer
32
* @param sourceOffset - Byte offset in source
33
* @param destination - Destination buffer
34
* @param destinationOffset - Byte offset in destination
35
* @param size - Number of bytes to copy
36
*/
37
copyBufferToBuffer(
38
source: GPUBuffer,
39
sourceOffset: GPUSize64,
40
destination: GPUBuffer,
41
destinationOffset: GPUSize64,
42
size: GPUSize64
43
): void;
44
45
/**
46
* Copies buffer data to a texture
47
* @param source - Source buffer and layout
48
* @param destination - Destination texture info
49
* @param copySize - Size of the region to copy
50
*/
51
copyBufferToTexture(
52
source: GPUTexelCopyBufferInfo,
53
destination: GPUTexelCopyTextureInfo,
54
copySize: GPUExtent3D
55
): void;
56
57
/**
58
* Copies texture data to a buffer
59
* @param source - Source texture info
60
* @param destination - Destination buffer and layout
61
* @param copySize - Size of the region to copy
62
*/
63
copyTextureToBuffer(
64
source: GPUTexelCopyTextureInfo,
65
destination: GPUTexelCopyBufferInfo,
66
copySize: GPUExtent3D
67
): void;
68
69
/**
70
* Copies data between textures
71
* @param source - Source texture info
72
* @param destination - Destination texture info
73
* @param copySize - Size of the region to copy
74
*/
75
copyTextureToTexture(
76
source: GPUTexelCopyTextureInfo,
77
destination: GPUTexelCopyTextureInfo,
78
copySize: GPUExtent3D
79
): void;
80
81
/**
82
* Clears a buffer with zeros
83
* @param buffer - Buffer to clear
84
* @param offset - Byte offset (optional)
85
* @param size - Number of bytes to clear (optional)
86
*/
87
clearBuffer(buffer: GPUBuffer, offset?: GPUSize64, size?: GPUSize64): void;
88
89
/**
90
* Writes a timestamp to a query set
91
* @param querySet - Query set for timestamps
92
* @param queryIndex - Query index to write to
93
*/
94
writeTimestamp(querySet: GPUQuerySet, queryIndex: GPUSize32): void;
95
96
/**
97
* Resolves query results to a buffer
98
* @param querySet - Query set to resolve
99
* @param firstQuery - First query index
100
* @param queryCount - Number of queries to resolve
101
* @param destination - Destination buffer
102
* @param destinationOffset - Byte offset in destination
103
*/
104
resolveQuerySet(
105
querySet: GPUQuerySet,
106
firstQuery: GPUSize32,
107
queryCount: GPUSize32,
108
destination: GPUBuffer,
109
destinationOffset: GPUSize64
110
): void;
111
112
/**
113
* Finishes command recording
114
* @param descriptor - Optional command buffer configuration
115
* @returns Completed command buffer
116
*/
117
finish(descriptor?: GPUCommandBufferDescriptor): GPUCommandBuffer;
118
119
// Debug commands
120
pushDebugGroup(groupLabel: string): void;
121
popDebugGroup(): void;
122
insertDebugMarker(markerLabel: string): void;
123
}
124
125
interface GPUCommandEncoderDescriptor extends GPUObjectDescriptorBase {}
126
127
interface GPUCommandBufferDescriptor extends GPUObjectDescriptorBase {}
128
```
129
130
### GPU Command Buffer
131
132
Immutable recorded commands ready for submission to the GPU queue.
133
134
```typescript { .api }
135
interface GPUCommandBuffer {
136
/** Optional debug label */
137
readonly label: string | undefined;
138
}
139
```
140
141
### GPU Render Pass Encoder
142
143
Records rendering commands within a render pass.
144
145
```typescript { .api }
146
interface GPURenderPassEncoder extends GPURenderCommandsMixin {
147
/**
148
* Sets the viewport transformation
149
* @param x - X coordinate of viewport origin
150
* @param y - Y coordinate of viewport origin
151
* @param width - Viewport width
152
* @param height - Viewport height
153
* @param minDepth - Minimum depth value (0.0-1.0)
154
* @param maxDepth - Maximum depth value (0.0-1.0)
155
*/
156
setViewport(
157
x: number,
158
y: number,
159
width: number,
160
height: number,
161
minDepth: number,
162
maxDepth: number
163
): void;
164
165
/**
166
* Sets the scissor rectangle
167
* @param x - X coordinate of scissor origin
168
* @param y - Y coordinate of scissor origin
169
* @param width - Scissor width
170
* @param height - Scissor height
171
*/
172
setScissorRect(
173
x: GPUIntegerCoordinate,
174
y: GPUIntegerCoordinate,
175
width: GPUIntegerCoordinate,
176
height: GPUIntegerCoordinate
177
): void;
178
179
/**
180
* Begins an occlusion query
181
* @param queryIndex - Index in the query set
182
*/
183
beginOcclusionQuery(queryIndex: GPUSize32): void;
184
185
/** Ends the current occlusion query */
186
endOcclusionQuery(): void;
187
188
/** Ends the render pass */
189
end(): void;
190
191
// Inherited from GPURenderCommandsMixin
192
setPipeline(pipeline: GPURenderPipeline): void;
193
setIndexBuffer(buffer: GPUBuffer, format: GPUIndexFormat, offset?: GPUSize64, size?: GPUSize64): void;
194
setVertexBuffer(slot: GPUIndex32, buffer: GPUBuffer | null, offset?: GPUSize64, size?: GPUSize64): void;
195
draw(vertexCount: GPUSize32, instanceCount?: GPUSize32, firstVertex?: GPUSize32, firstInstance?: GPUSize32): void;
196
drawIndexed(indexCount: GPUSize32, instanceCount?: GPUSize32, firstIndex?: GPUSize32, baseVertex?: GPUSignedOffset32, firstInstance?: GPUSize32): void;
197
drawIndirect(indirectBuffer: GPUBuffer, indirectOffset: GPUSize64): void;
198
drawIndexedIndirect(indirectBuffer: GPUBuffer, indirectOffset: GPUSize64): void;
199
200
// Inherited from GPUBindingCommandsMixin
201
setBindGroup(index: GPUIndex32, bindGroup: GPUBindGroup | null, dynamicOffsets?: Iterable<GPUBufferDynamicOffset>): void;
202
203
// Inherited from GPUDebugCommandsMixin
204
pushDebugGroup(groupLabel: string): void;
205
popDebugGroup(): void;
206
insertDebugMarker(markerLabel: string): void;
207
}
208
```
209
210
### GPU Compute Pass Encoder
211
212
Records compute commands within a compute pass.
213
214
```typescript { .api }
215
interface GPUComputePassEncoder {
216
/** Optional debug label */
217
readonly label: string | undefined;
218
219
/**
220
* Sets the compute pipeline
221
* @param pipeline - Compute pipeline to use
222
*/
223
setPipeline(pipeline: GPUComputePipeline): void;
224
225
/**
226
* Dispatches compute workgroups
227
* @param workgroupCountX - Number of workgroups in X dimension
228
* @param workgroupCountY - Number of workgroups in Y dimension (default: 1)
229
* @param workgroupCountZ - Number of workgroups in Z dimension (default: 1)
230
*/
231
dispatchWorkgroups(
232
workgroupCountX: GPUSize32,
233
workgroupCountY?: GPUSize32,
234
workgroupCountZ?: GPUSize32
235
): void;
236
237
/**
238
* Dispatches workgroups with counts from buffer
239
* @param indirectBuffer - Buffer containing dispatch parameters
240
* @param indirectOffset - Byte offset in buffer
241
*/
242
dispatchWorkgroupsIndirect(
243
indirectBuffer: GPUBuffer,
244
indirectOffset: GPUSize64
245
): void;
246
247
/** Ends the compute pass */
248
end(): void;
249
250
// Inherited from GPUBindingCommandsMixin
251
setBindGroup(index: GPUIndex32, bindGroup: GPUBindGroup | null, dynamicOffsets?: Iterable<GPUBufferDynamicOffset>): void;
252
253
// Inherited from GPUDebugCommandsMixin
254
pushDebugGroup(groupLabel: string): void;
255
popDebugGroup(): void;
256
insertDebugMarker(markerLabel: string): void;
257
}
258
```
259
260
### Render Pass Configuration
261
262
Configuration for render passes including attachments and timing.
263
264
```typescript { .api }
265
interface GPURenderPassDescriptor extends GPUObjectDescriptorBase {
266
/** Color attachments */
267
colorAttachments: Iterable<GPURenderPassColorAttachment | null>;
268
269
/** Depth/stencil attachment */
270
depthStencilAttachment?: GPURenderPassDepthStencilAttachment;
271
272
/** Occlusion query set */
273
occlusionQuerySet?: GPUQuerySet;
274
275
/** Timestamp query writes */
276
timestampWrites?: GPURenderPassTimestampWrites;
277
278
/** Maximum number of draw commands */
279
maxDrawCount?: GPUSize64;
280
}
281
282
interface GPURenderPassColorAttachment {
283
/** Color attachment texture view */
284
view: GPUTextureView;
285
286
/** Depth slice for 3D textures */
287
depthSlice?: GPUIntegerCoordinate;
288
289
/** Resolve target for multisampled textures */
290
resolveTarget?: GPUTextureView;
291
292
/** Clear value when loadOp is "clear" */
293
clearValue?: GPUColor;
294
295
/** Load operation */
296
loadOp: GPULoadOp;
297
298
/** Store operation */
299
storeOp: GPUStoreOp;
300
}
301
302
interface GPURenderPassDepthStencilAttachment {
303
/** Depth/stencil texture view */
304
view: GPUTextureView;
305
306
/** Depth clear value */
307
depthClearValue?: number;
308
309
/** Depth load operation */
310
depthLoadOp?: GPULoadOp;
311
312
/** Depth store operation */
313
depthStoreOp?: GPUStoreOp;
314
315
/** Whether depth is read-only */
316
depthReadOnly?: boolean;
317
318
/** Stencil clear value */
319
stencilClearValue?: GPUStencilValue;
320
321
/** Stencil load operation */
322
stencilLoadOp?: GPULoadOp;
323
324
/** Stencil store operation */
325
stencilStoreOp?: GPUStoreOp;
326
327
/** Whether stencil is read-only */
328
stencilReadOnly?: boolean;
329
}
330
331
interface GPURenderPassTimestampWrites {
332
/** Query set for timestamps */
333
querySet: GPUQuerySet;
334
335
/** Query index for beginning of pass */
336
beginningOfPassWriteIndex?: GPUSize32;
337
338
/** Query index for end of pass */
339
endOfPassWriteIndex?: GPUSize32;
340
}
341
```
342
343
### Compute Pass Configuration
344
345
Configuration for compute passes.
346
347
```typescript { .api }
348
interface GPUComputePassDescriptor extends GPUObjectDescriptorBase {
349
/** Timestamp query writes */
350
timestampWrites?: GPUComputePassTimestampWrites;
351
}
352
353
interface GPUComputePassTimestampWrites {
354
/** Query set for timestamps */
355
querySet: GPUQuerySet;
356
357
/** Query index for beginning of pass */
358
beginningOfPassWriteIndex?: GPUSize32;
359
360
/** Query index for end of pass */
361
endOfPassWriteIndex?: GPUSize32;
362
}
363
```
364
365
### Command Mixin Interfaces
366
367
Shared command functionality across different encoder types.
368
369
```typescript { .api }
370
interface GPUBindingCommandsMixin {
371
/**
372
* Binds a bind group to a pipeline
373
* @param index - Bind group index
374
* @param bindGroup - Bind group to bind (null to unbind)
375
* @param dynamicOffsets - Dynamic buffer offsets
376
*/
377
setBindGroup(
378
index: GPUIndex32,
379
bindGroup: GPUBindGroup | null,
380
dynamicOffsets?: Iterable<GPUBufferDynamicOffset>
381
): void;
382
}
383
384
interface GPUDebugCommandsMixin {
385
/** Pushes a debug group for annotation */
386
pushDebugGroup(groupLabel: string): void;
387
388
/** Pops the current debug group */
389
popDebugGroup(): void;
390
391
/** Inserts a debug marker */
392
insertDebugMarker(markerLabel: string): void;
393
}
394
395
interface GPURenderCommandsMixin extends GPUBindingCommandsMixin, GPUDebugCommandsMixin {
396
/**
397
* Sets the render pipeline
398
* @param pipeline - Render pipeline to use
399
*/
400
setPipeline(pipeline: GPURenderPipeline): void;
401
402
/**
403
* Sets the index buffer
404
* @param buffer - Index buffer
405
* @param format - Index format (uint16 or uint32)
406
* @param offset - Byte offset in buffer
407
* @param size - Number of bytes to bind
408
*/
409
setIndexBuffer(
410
buffer: GPUBuffer,
411
format: GPUIndexFormat,
412
offset?: GPUSize64,
413
size?: GPUSize64
414
): void;
415
416
/**
417
* Sets a vertex buffer
418
* @param slot - Vertex buffer slot
419
* @param buffer - Vertex buffer (null to unbind)
420
* @param offset - Byte offset in buffer
421
* @param size - Number of bytes to bind
422
*/
423
setVertexBuffer(
424
slot: GPUIndex32,
425
buffer: GPUBuffer | null,
426
offset?: GPUSize64,
427
size?: GPUSize64
428
): void;
429
430
/**
431
* Draws primitives
432
* @param vertexCount - Number of vertices to draw
433
* @param instanceCount - Number of instances (default: 1)
434
* @param firstVertex - First vertex index (default: 0)
435
* @param firstInstance - First instance index (default: 0)
436
*/
437
draw(
438
vertexCount: GPUSize32,
439
instanceCount?: GPUSize32,
440
firstVertex?: GPUSize32,
441
firstInstance?: GPUSize32
442
): void;
443
444
/**
445
* Draws indexed primitives
446
* @param indexCount - Number of indices to draw
447
* @param instanceCount - Number of instances (default: 1)
448
* @param firstIndex - First index (default: 0)
449
* @param baseVertex - Value added to vertex index (default: 0)
450
* @param firstInstance - First instance index (default: 0)
451
*/
452
drawIndexed(
453
indexCount: GPUSize32,
454
instanceCount?: GPUSize32,
455
firstIndex?: GPUSize32,
456
baseVertex?: GPUSignedOffset32,
457
firstInstance?: GPUSize32
458
): void;
459
460
/**
461
* Draws with parameters from buffer
462
* @param indirectBuffer - Buffer containing draw parameters
463
* @param indirectOffset - Byte offset in buffer
464
*/
465
drawIndirect(indirectBuffer: GPUBuffer, indirectOffset: GPUSize64): void;
466
467
/**
468
* Draws indexed with parameters from buffer
469
* @param indirectBuffer - Buffer containing draw parameters
470
* @param indirectOffset - Byte offset in buffer
471
*/
472
drawIndexedIndirect(indirectBuffer: GPUBuffer, indirectOffset: GPUSize64): void;
473
}
474
```
475
476
### Copy Operations Data Structures
477
478
Data structures for texture and buffer copy operations.
479
480
```typescript { .api }
481
interface GPUTexelCopyBufferInfo {
482
/** Buffer to copy from/to */
483
buffer: GPUBuffer;
484
485
/** Byte offset in buffer */
486
offset?: GPUSize64;
487
488
/** Bytes per row of texel data */
489
bytesPerRow?: GPUSize32;
490
491
/** Rows per image */
492
rowsPerImage?: GPUSize32;
493
}
494
495
interface GPUTexelCopyTextureInfo {
496
/** Texture to copy from/to */
497
texture: GPUTexture;
498
499
/** Mip level to access */
500
mipLevel?: GPUIntegerCoordinate;
501
502
/** Origin for the copy */
503
origin?: GPUOrigin3D;
504
505
/** Texture aspect to access */
506
aspect?: GPUTextureAspect;
507
}
508
509
interface GPUCopyExternalImageSourceInfo {
510
/** External image source */
511
source: GPUCopyExternalImageSource;
512
513
/** Origin in the source */
514
origin?: GPUOrigin2D;
515
516
/** Whether to flip Y coordinate */
517
flipY?: boolean;
518
}
519
520
interface GPUCopyExternalImageDestInfo {
521
/** Destination texture */
522
texture: GPUTexture;
523
524
/** Mip level to write to */
525
mipLevel?: GPUIntegerCoordinate;
526
527
/** Origin in destination */
528
origin?: GPUOrigin3D;
529
530
/** Texture aspect to write to */
531
aspect?: GPUTextureAspect;
532
533
/** Color space conversion */
534
colorSpace?: GPUImageCopyColorSpace;
535
536
/** Premultiply alpha */
537
premultipliedAlpha?: boolean;
538
}
539
540
type GPUImageCopyColorSpace = "srgb" | "display-p3";
541
```
542
543
## Usage Examples
544
545
### Basic Rendering Commands
546
547
```typescript
548
// Create command encoder
549
const encoder = device.createCommandEncoder({ label: "Main Render Commands" });
550
551
// Begin render pass
552
const renderPass = encoder.beginRenderPass({
553
colorAttachments: [{
554
view: context.getCurrentTexture().createView(),
555
clearValue: { r: 0.2, g: 0.3, b: 0.8, a: 1.0 },
556
loadOp: "clear",
557
storeOp: "store"
558
}],
559
depthStencilAttachment: {
560
view: depthTexture.createView(),
561
depthClearValue: 1.0,
562
depthLoadOp: "clear",
563
depthStoreOp: "store"
564
},
565
label: "Main Render Pass"
566
});
567
568
// Set pipeline and resources
569
renderPass.setPipeline(renderPipeline);
570
renderPass.setBindGroup(0, uniformBindGroup);
571
renderPass.setBindGroup(1, materialBindGroup);
572
renderPass.setVertexBuffer(0, vertexBuffer);
573
renderPass.setIndexBuffer(indexBuffer, "uint16");
574
575
// Draw geometry
576
renderPass.drawIndexed(indexCount);
577
578
// End pass and submit
579
renderPass.end();
580
const commandBuffer = encoder.finish();
581
device.queue.submit([commandBuffer]);
582
```
583
584
### Compute Operations
585
586
```typescript
587
// Create compute command encoder
588
const computeEncoder = device.createCommandEncoder({ label: "Compute Commands" });
589
590
// Begin compute pass
591
const computePass = computeEncoder.beginComputePass({
592
label: "Data Processing Pass"
593
});
594
595
// Set compute pipeline and bind groups
596
computePass.setPipeline(computePipeline);
597
computePass.setBindGroup(0, computeBindGroup);
598
599
// Dispatch compute workgroups
600
const workgroupsX = Math.ceil(dataSize / 64); // 64 = workgroup size
601
computePass.dispatchWorkgroups(workgroupsX);
602
603
// End pass
604
computePass.end();
605
606
// Submit compute work
607
const computeCommandBuffer = computeEncoder.finish();
608
device.queue.submit([computeCommandBuffer]);
609
```
610
611
### Buffer and Texture Copies
612
613
```typescript
614
const copyEncoder = device.createCommandEncoder({ label: "Copy Commands" });
615
616
// Copy buffer to buffer
617
copyEncoder.copyBufferToBuffer(
618
sourceBuffer, 0, // source and offset
619
destBuffer, 256, // destination and offset
620
1024 // size in bytes
621
);
622
623
// Copy buffer to texture
624
copyEncoder.copyBufferToTexture(
625
{
626
buffer: imageBuffer,
627
bytesPerRow: 1024 * 4, // 4 bytes per pixel
628
rowsPerImage: 768
629
},
630
{
631
texture: colorTexture,
632
mipLevel: 0
633
},
634
{ width: 1024, height: 768, depthOrArrayLayers: 1 }
635
);
636
637
// Copy texture to texture (mip generation)
638
for (let mip = 1; mip < mipLevels; mip++) {
639
const mipSize = Math.max(1, textureSize >> mip);
640
641
copyEncoder.copyTextureToTexture(
642
{
643
texture: sourceTexture,
644
mipLevel: mip - 1
645
},
646
{
647
texture: sourceTexture,
648
mipLevel: mip
649
},
650
{ width: mipSize, height: mipSize, depthOrArrayLayers: 1 }
651
);
652
}
653
654
device.queue.submit([copyEncoder.finish()]);
655
```
656
657
### Multi-Pass Rendering
658
659
```typescript
660
const frameEncoder = device.createCommandEncoder({ label: "Frame Commands" });
661
662
// Shadow pass
663
const shadowPass = frameEncoder.beginRenderPass({
664
colorAttachments: [],
665
depthStencilAttachment: {
666
view: shadowMap.createView(),
667
depthClearValue: 1.0,
668
depthLoadOp: "clear",
669
depthStoreOp: "store"
670
},
671
label: "Shadow Pass"
672
});
673
674
shadowPass.setPipeline(shadowPipeline);
675
shadowPass.setBindGroup(0, lightBindGroup);
676
// ... render shadow casters
677
shadowPass.end();
678
679
// Main render pass
680
const mainPass = frameEncoder.beginRenderPass({
681
colorAttachments: [{
682
view: colorTarget.createView(),
683
clearValue: { r: 0.1, g: 0.1, b: 0.2, a: 1.0 },
684
loadOp: "clear",
685
storeOp: "store"
686
}],
687
depthStencilAttachment: {
688
view: depthBuffer.createView(),
689
depthClearValue: 1.0,
690
depthLoadOp: "clear",
691
depthStoreOp: "store"
692
},
693
label: "Main Pass"
694
});
695
696
mainPass.setPipeline(mainPipeline);
697
mainPass.setBindGroup(0, sceneBindGroup);
698
mainPass.setBindGroup(1, shadowBindGroup); // Shadow map from previous pass
699
// ... render scene
700
mainPass.end();
701
702
// Post-processing pass
703
const postPass = frameEncoder.beginRenderPass({
704
colorAttachments: [{
705
view: context.getCurrentTexture().createView(),
706
loadOp: "load",
707
storeOp: "store"
708
}],
709
label: "Post Process Pass"
710
});
711
712
postPass.setPipeline(postProcessPipeline);
713
postPass.setBindGroup(0, postProcessBindGroup);
714
postPass.draw(3); // Fullscreen triangle
715
postPass.end();
716
717
device.queue.submit([frameEncoder.finish()]);
718
```
719
720
### Query and Timing
721
722
```typescript
723
// Create timestamp queries
724
const timestampQuerySet = device.createQuerySet({
725
type: "timestamp",
726
count: 4
727
});
728
729
const queryBuffer = device.createBuffer({
730
size: 8 * 4, // 8 bytes per timestamp
731
usage: GPUBufferUsage.QUERY_RESOLVE | GPUBufferUsage.COPY_SRC
732
});
733
734
const readBuffer = device.createBuffer({
735
size: 8 * 4,
736
usage: GPUBufferUsage.COPY_DST | GPUBufferUsage.MAP_READ
737
});
738
739
// Record with timing
740
const timedEncoder = device.createCommandEncoder();
741
742
timedEncoder.writeTimestamp(timestampQuerySet, 0); // Frame start
743
744
const renderPass = timedEncoder.beginRenderPass({
745
colorAttachments: [/* ... */],
746
timestampWrites: {
747
querySet: timestampQuerySet,
748
beginningOfPassWriteIndex: 1,
749
endOfPassWriteIndex: 2
750
}
751
});
752
753
// ... rendering commands ...
754
renderPass.end();
755
756
timedEncoder.writeTimestamp(timestampQuerySet, 3); // Frame end
757
758
// Resolve timestamps
759
timedEncoder.resolveQuerySet(timestampQuerySet, 0, 4, queryBuffer, 0);
760
timedEncoder.copyBufferToBuffer(queryBuffer, 0, readBuffer, 0, 8 * 4);
761
762
device.queue.submit([timedEncoder.finish()]);
763
764
// Read timing results
765
await readBuffer.mapAsync(GPUMapMode.READ);
766
const times = new BigUint64Array(readBuffer.getMappedRange());
767
const frameTime = Number(times[3] - times[0]) / 1000000; // Convert to milliseconds
768
console.log(`Frame time: ${frameTime.toFixed(2)}ms`);
769
readBuffer.unmap();
770
```
771
772
### Debug Annotations
773
774
```typescript
775
const debugEncoder = device.createCommandEncoder({ label: "Debug Annotated Commands" });
776
777
debugEncoder.pushDebugGroup("Scene Rendering");
778
779
const renderPass = debugEncoder.beginRenderPass({
780
colorAttachments: [/* ... */],
781
label: "Scene Pass"
782
});
783
784
renderPass.pushDebugGroup("Opaque Objects");
785
renderPass.setPipeline(opaquePipeline);
786
// ... render opaque objects
787
renderPass.popDebugGroup();
788
789
renderPass.insertDebugMarker("Begin Transparent Objects");
790
renderPass.setPipeline(transparentPipeline);
791
// ... render transparent objects
792
793
renderPass.end();
794
debugEncoder.popDebugGroup();
795
796
debugEncoder.pushDebugGroup("Post Processing");
797
// ... post processing passes
798
debugEncoder.popDebugGroup();
799
800
device.queue.submit([debugEncoder.finish()]);
801
```