@forgeax/engine-render-graph 0.1.20 → 0.1.23

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/types.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import type { Buffer, ComputePassDescriptor, RhiCommandEncoder, RhiComputePassEncoder, RhiDevice, RhiRenderPassEncoder, Texture, TextureFormat, TextureView } from '@forgeax/engine-rhi';
1
+ import type { Buffer, ComputePassDescriptor, QuerySet, RenderPassDescriptor, RhiCommandEncoder, RhiComputePassEncoder, RhiDevice, RhiRenderPassEncoder, Texture, TextureFormat, TextureView } from '@forgeax/engine-rhi';
2
2
  import type { RenderGraphError, Result } from './errors.js';
3
3
  import type { ColorValueDomain } from './pipeline/color-value-domain.js';
4
4
  declare const graphTextureBrand: unique symbol;
@@ -25,7 +25,7 @@ export type GraphExtent = 'surface' | 'half-surface' | {
25
25
  export interface GraphTextureDescriptor {
26
26
  readonly format: TextureFormat;
27
27
  readonly size: GraphExtent;
28
- /** Additional RHI usage required by an external diagnostic consumer. */
28
+ /** Additional RHI usage required by an external diagnostic consumer such as readback. */
29
29
  readonly usage?: number | undefined;
30
30
  readonly mipLevelCount?: number | undefined;
31
31
  readonly sampleCount?: number | undefined;
@@ -92,6 +92,8 @@ export interface RasterGraphPass<FrameCtx> {
92
92
  readonly accesses: readonly GraphAccess[];
93
93
  readonly colorAttachments: readonly RasterColorAttachment<FrameCtx>[];
94
94
  readonly depthStencilAttachment?: RasterDepthStencilAttachment | undefined;
95
+ /** Optional producer-owned occlusion query set for this raster pass. */
96
+ readonly occlusionQuerySet?: QuerySet | undefined;
95
97
  readonly executeIf?: ((frame: FrameCtx) => boolean) | undefined;
96
98
  encode(context: {
97
99
  readonly pass: RhiRenderPassEncoder;
@@ -193,6 +195,21 @@ export interface RenderGraphPassExecution {
193
195
  readonly executionIndex: number;
194
196
  }
195
197
  export type RenderGraphPassRunner = (pass: RenderGraphPassExecution, encode: () => void) => void;
198
+ /**
199
+ * The graph-neutral boundary for observing and decorating an actual pass.
200
+ * Render owns the policy supplied here; the graph only preserves pass
201
+ * provenance and applies the decorated descriptor at the real pass-open
202
+ * boundary. Timestamp policy and acceptance remain outside the graph.
203
+ */
204
+ export interface RenderGraphPassInstrumentationScope {
205
+ readonly renderPassDescriptor?: (descriptor: RenderPassDescriptor) => RenderPassDescriptor;
206
+ readonly computePassDescriptor?: (descriptor: ComputePassDescriptor) => ComputePassDescriptor;
207
+ readonly beforeCopy?: (encoder: RhiCommandEncoder) => void;
208
+ readonly afterCopy?: (encoder: RhiCommandEncoder) => void;
209
+ }
210
+ export interface RenderGraphPassInstrumentation<FrameCtx extends RenderGraphFrame> {
211
+ begin(pass: RenderGraphPassExecution, frame: FrameCtx): RenderGraphPassInstrumentationScope | undefined;
212
+ }
196
213
  export interface RenderGraphCompileOptions {
197
214
  readonly device: RhiDevice;
198
215
  readonly surfaceSize: {
@@ -201,7 +218,7 @@ export interface RenderGraphCompileOptions {
201
218
  };
202
219
  }
203
220
  export interface CompiledRenderGraph<FrameCtx extends RenderGraphFrame> {
204
- execute(frame: FrameCtx, runPass?: RenderGraphPassRunner): Result<void, RenderGraphError>;
221
+ execute(frame: FrameCtx, runPass?: RenderGraphPassRunner, instrumentation?: RenderGraphPassInstrumentation<FrameCtx>): Result<void, RenderGraphError>;
205
222
  inspect(): CompiledRenderGraphInfo;
206
223
  retire(): Promise<Result<void, RenderGraphError>>;
207
224
  }
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@forgeax/engine-render-graph",
3
- "version": "0.1.20",
3
+ "version": "0.1.23",
4
4
  "private": false,
5
5
  "type": "module",
6
6
  "license": "Apache-2.0",
@@ -22,12 +22,12 @@
22
22
  "LICENSE"
23
23
  ],
24
24
  "dependencies": {
25
- "@forgeax/engine-rhi": "0.1.20",
26
- "@forgeax/engine-types": "0.1.20",
25
+ "@forgeax/engine-rhi": "0.1.23",
26
+ "@forgeax/engine-types": "0.1.23",
27
27
  "@webgpu/types": "^0.1.71"
28
28
  },
29
29
  "devDependencies": {
30
- "@forgeax/engine-rhi-null": "0.1.20"
30
+ "@forgeax/engine-rhi-null": "0.1.23"
31
31
  },
32
32
  "forgeax": {
33
33
  "metrics": {
@@ -1,6 +1,7 @@
1
1
  import type {
2
2
  Buffer,
3
3
  ComputePassDescriptor,
4
+ QuerySet,
4
5
  RhiCommandEncoder,
5
6
  RhiComputePassEncoder,
6
7
  RhiDevice,
@@ -10,7 +11,7 @@ import type {
10
11
  import { describe, expect, it } from 'vitest';
11
12
  import { RenderGraphBuilder } from '../builder.js';
12
13
  import { ok } from '../errors.js';
13
- import type { RenderGraphFrame } from '../types.js';
14
+ import type { RenderGraphFrame, RenderGraphPassInstrumentation } from '../types.js';
14
15
 
15
16
  interface Frame extends RenderGraphFrame {
16
17
  readonly imported: Buffer;
@@ -448,6 +449,29 @@ describe('RenderGraphBuilder capability, execution, and lifecycle contracts', ()
448
449
  );
449
450
  });
450
451
 
452
+ it('keeps declared created-texture usage alongside graph-derived usage', () => {
453
+ const graph = new RenderGraphBuilder<Frame>();
454
+ const texture = value(
455
+ graph.createTexture('readback-target', {
456
+ format: 'rgba8unorm',
457
+ size: 'surface',
458
+ usage: 0x01,
459
+ }),
460
+ );
461
+ const view = value(graph.view(texture));
462
+ graph.addRasterPass('write', {
463
+ accesses: [{ resource: view, usage: 'color-attachment' }],
464
+ colorAttachments: [{ view, loadOp: 'clear', storeOp: 'store' }],
465
+ encode: () => undefined,
466
+ });
467
+ const compiled = value(
468
+ graph.compile({ device: mockDevice(), surfaceSize: { width: 1, height: 1 } }),
469
+ );
470
+ expect(compiled.inspect().resources).toContainEqual(
471
+ expect.objectContaining({ label: 'readback-target', derivedUsage: 0x11 }),
472
+ );
473
+ });
474
+
451
475
  it('derives compute and storage capabilities from pass/access declarations', () => {
452
476
  const graph = new RenderGraphBuilder<Frame>();
453
477
  const buffer = value(
@@ -501,6 +525,96 @@ describe('RenderGraphBuilder capability, execution, and lifecycle contracts', ()
501
525
  ]);
502
526
  });
503
527
 
528
+ it('applies pass timestamp instrumentation at the real raster and compute boundaries', () => {
529
+ const graph = new RenderGraphBuilder<Frame>();
530
+ const texture = value(
531
+ graph.importTexture(
532
+ 'surface',
533
+ { format: 'rgba8unorm', size: 'surface', usage: 0x10 },
534
+ (frame) => frame.importedTexture as Texture,
535
+ ),
536
+ );
537
+ const view = value(
538
+ graph.importView(
539
+ texture,
540
+ { label: 'surface.view' },
541
+ (frame) => frame.importedView as TextureView,
542
+ ),
543
+ );
544
+ graph.addRasterPass('timed-raster', {
545
+ accesses: [{ resource: view, usage: 'color-attachment' }],
546
+ colorAttachments: [{ view, loadOp: 'clear', storeOp: 'store' }],
547
+ encode: () => undefined,
548
+ });
549
+ graph.addComputePass('timed-compute', {
550
+ accesses: [],
551
+ encode: () => undefined,
552
+ });
553
+ const compiled = value(
554
+ graph.compile({ device: mockDevice(), surfaceSize: { width: 1, height: 1 } }),
555
+ );
556
+ const querySet = {} as QuerySet;
557
+ const rasterWrites = {
558
+ querySet,
559
+ beginningOfPassWriteIndex: 4,
560
+ endOfPassWriteIndex: 5,
561
+ } as const;
562
+ const computeWrites = {
563
+ querySet,
564
+ beginningOfPassWriteIndex: 6,
565
+ endOfPassWriteIndex: 7,
566
+ } as const;
567
+ let rasterDescriptor: { readonly timestampWrites?: unknown } | undefined;
568
+ const computeDescriptors: Array<{ readonly timestampWrites?: unknown }> = [];
569
+ const encoder = {
570
+ ...mockEncoder(),
571
+ beginRenderPass: (descriptor: { readonly timestampWrites?: unknown }) => {
572
+ rasterDescriptor = descriptor;
573
+ return { end: () => undefined } as never;
574
+ },
575
+ beginComputePass: (descriptor: ComputePassDescriptor = {}) => {
576
+ computeDescriptors.push(descriptor);
577
+ return {
578
+ setPipeline: () => undefined,
579
+ setBindGroup: () => undefined,
580
+ dispatchWorkgroups: () => undefined,
581
+ dispatchWorkgroupsIndirect: () => undefined,
582
+ end: () => undefined,
583
+ } as unknown as RhiComputePassEncoder;
584
+ },
585
+ } as unknown as RhiCommandEncoder;
586
+ const instrumentation: RenderGraphPassInstrumentation<Frame> = {
587
+ begin: (pass) =>
588
+ pass.kind === 'raster'
589
+ ? {
590
+ renderPassDescriptor: (descriptor) => ({
591
+ ...descriptor,
592
+ timestampWrites: rasterWrites,
593
+ }),
594
+ }
595
+ : {
596
+ computePassDescriptor: (descriptor) => ({
597
+ ...descriptor,
598
+ timestampWrites: computeWrites,
599
+ }),
600
+ },
601
+ };
602
+ const executed = compiled.execute(
603
+ {
604
+ encoder,
605
+ imported: {} as Buffer,
606
+ importedTexture: {} as Texture,
607
+ importedView: {} as TextureView,
608
+ },
609
+ undefined,
610
+ instrumentation,
611
+ );
612
+ expect(executed.ok).toBe(true);
613
+ expect(rasterDescriptor?.timestampWrites).toBe(rasterWrites);
614
+ expect(computeDescriptors).toHaveLength(1);
615
+ expect(computeDescriptors[0]?.timestampWrites).toBe(computeWrites);
616
+ });
617
+
504
618
  it('reports a graph-owned compute pass begin failure to the pass owner', () => {
505
619
  const events: string[] = [];
506
620
  const graph = new RenderGraphBuilder<Frame>();
@@ -0,0 +1,183 @@
1
+ import type {
2
+ Buffer,
3
+ ComputePassDescriptor,
4
+ RenderPassDescriptor,
5
+ RhiCommandEncoder,
6
+ RhiComputePassEncoder,
7
+ RhiDevice,
8
+ RhiRenderPassEncoder,
9
+ Texture,
10
+ TextureView,
11
+ } from '@forgeax/engine-rhi';
12
+ import { describe, expect, it } from 'vitest';
13
+ import { RenderGraphBuilder } from '../builder.js';
14
+ import type { RenderGraphFrame, RenderGraphPassInstrumentation } from '../types.js';
15
+
16
+ interface Frame extends RenderGraphFrame {
17
+ readonly source: Buffer;
18
+ }
19
+
20
+ function mockDevice(): RhiDevice {
21
+ let nextId = 0;
22
+ return {
23
+ caps: {
24
+ backendKind: 'null',
25
+ compute: true,
26
+ storageBuffer: true,
27
+ storageTexture: true,
28
+ timestampQuery: false,
29
+ timestampPeriodNanoseconds: null,
30
+ indirectDrawing: true,
31
+ textureCompressionBc: false,
32
+ textureCompressionEtc2: false,
33
+ textureCompressionAstc: false,
34
+ multiDrawIndirect: false,
35
+ pushConstants: false,
36
+ textureBindingArray: false,
37
+ samplerAliasing: true,
38
+ firstInstanceIndirect: false,
39
+ rgba16floatRenderable: true,
40
+ rg11b10ufloatRenderable: true,
41
+ float32Filterable: true,
42
+ maxColorAttachments: 8,
43
+ },
44
+ limits: {} as never,
45
+ features: new Set() as never,
46
+ queue: { onSubmittedWorkDone: async () => undefined } as never,
47
+ createTexture: () => ({ ok: true, value: { id: nextId++ } as unknown as Texture }),
48
+ createTextureView: () => ({ ok: true, value: { id: nextId++ } as unknown as TextureView }),
49
+ createBuffer: () => ({ ok: true, value: { id: nextId++ } as unknown as Buffer }),
50
+ destroyTexture: () => ({ ok: true, value: undefined }),
51
+ destroyBuffer: () => ({ ok: true, value: undefined }),
52
+ } as unknown as RhiDevice;
53
+ }
54
+
55
+ function buildGraph() {
56
+ const graph = new RenderGraphBuilder<Frame>();
57
+ const color = graph.createTexture('color', { format: 'rgba8unorm', size: 'surface' });
58
+ if (!color.ok) throw color.error;
59
+ const view = graph.view(color.value);
60
+ if (!view.ok) throw view.error;
61
+ graph.addRasterPass('raster', {
62
+ accesses: [{ resource: view.value, usage: 'color-attachment' }],
63
+ colorAttachments: [{ view: view.value, loadOp: 'clear', storeOp: 'store' }],
64
+ encode: () => undefined,
65
+ });
66
+ graph.addComputePass('compute', { accesses: [], encode: () => undefined });
67
+ graph.addCopyPass('copy', { accesses: [], encode: () => undefined });
68
+ graph.addComputePass('skipped', {
69
+ accesses: [],
70
+ executeIf: () => false,
71
+ encode: () => undefined,
72
+ });
73
+ return graph;
74
+ }
75
+
76
+ function mockEncoder(events: string[]): RhiCommandEncoder {
77
+ return {
78
+ beginRenderPass: (descriptor: RenderPassDescriptor) => {
79
+ events.push(`begin-raster:${descriptor.timestampWrites === undefined ? 'none' : 'timed'}`);
80
+ return { end: () => events.push('end-raster') } as unknown as RhiRenderPassEncoder;
81
+ },
82
+ beginComputePass: (descriptor: ComputePassDescriptor = {}) => {
83
+ events.push(`begin-compute:${descriptor.timestampWrites === undefined ? 'none' : 'timed'}`);
84
+ return { end: () => events.push('end-compute') } as unknown as RhiComputePassEncoder;
85
+ },
86
+ clearBuffer: () => events.push('clear-buffer'),
87
+ } as unknown as RhiCommandEncoder;
88
+ }
89
+
90
+ function value<T>(result: { readonly ok: true; readonly value: T } | { readonly ok: false }): T {
91
+ if (!result.ok) throw new Error('expected ok result');
92
+ return result.value;
93
+ }
94
+
95
+ describe('RenderGraph actual-pass timing instrumentation', () => {
96
+ it('reports only actual passes with compiled provenance and injects at pass boundaries', () => {
97
+ const graph = buildGraph();
98
+ const compiled = graph.compile({
99
+ device: mockDevice(),
100
+ surfaceSize: { width: 1, height: 1 },
101
+ });
102
+ expect(compiled.ok).toBe(true);
103
+ if (!compiled.ok) return;
104
+
105
+ const events: string[] = [];
106
+ const actualPasses: string[] = [];
107
+ const instrumentation: RenderGraphPassInstrumentation<Frame> = {
108
+ begin(pass) {
109
+ actualPasses.push(`${pass.executionIndex}:${pass.kind}:${pass.name}`);
110
+ return {
111
+ renderPassDescriptor: (descriptor) => ({
112
+ ...descriptor,
113
+ timestampWrites: {
114
+ querySet: {} as never,
115
+ beginningOfPassWriteIndex: 0,
116
+ endOfPassWriteIndex: 1,
117
+ },
118
+ }),
119
+ computePassDescriptor: (descriptor) => ({
120
+ ...descriptor,
121
+ timestampWrites: {
122
+ querySet: {} as never,
123
+ beginningOfPassWriteIndex: 2,
124
+ endOfPassWriteIndex: 3,
125
+ },
126
+ }),
127
+ beforeCopy: () => events.push('before-copy'),
128
+ afterCopy: () => events.push('after-copy'),
129
+ };
130
+ },
131
+ };
132
+
133
+ const result = value(compiled).execute(
134
+ { encoder: mockEncoder(events), source: {} as Buffer },
135
+ undefined,
136
+ instrumentation,
137
+ );
138
+ expect(result.ok).toBe(true);
139
+ expect(actualPasses).toEqual(['0:raster:raster', '1:compute:compute', '2:copy:copy']);
140
+ expect(events).toEqual([
141
+ 'begin-raster:timed',
142
+ 'end-raster',
143
+ 'begin-compute:timed',
144
+ 'end-compute',
145
+ 'before-copy',
146
+ 'after-copy',
147
+ ]);
148
+ });
149
+
150
+ it('keeps the no-hook graph and command ledger equivalent', () => {
151
+ const graph = buildGraph();
152
+ const compiled = graph.compile({
153
+ device: mockDevice(),
154
+ surfaceSize: { width: 1, height: 1 },
155
+ });
156
+ expect(compiled.ok).toBe(true);
157
+ if (!compiled.ok) return;
158
+
159
+ const events: string[] = [];
160
+ const result = value(compiled).execute({ encoder: mockEncoder(events), source: {} as Buffer });
161
+ expect(result.ok).toBe(true);
162
+ expect(events).toEqual([
163
+ 'begin-raster:none',
164
+ 'end-raster',
165
+ 'begin-compute:none',
166
+ 'end-compute',
167
+ ]);
168
+ expect(
169
+ value(compiled)
170
+ .inspect()
171
+ .passes.map(({ name, kind, executionIndex }) => ({
172
+ name,
173
+ kind,
174
+ executionIndex,
175
+ })),
176
+ ).toEqual([
177
+ { name: 'raster', kind: 'raster', executionIndex: 0 },
178
+ { name: 'compute', kind: 'compute', executionIndex: 1 },
179
+ { name: 'copy', kind: 'copy', executionIndex: 2 },
180
+ { name: 'skipped', kind: 'compute', executionIndex: 3 },
181
+ ]);
182
+ });
183
+ });
package/src/builder.ts CHANGED
@@ -597,10 +597,14 @@ export class RenderGraphBuilder<FrameCtx extends RenderGraphFrame> {
597
597
  const item = this.normalizeAccess(passIndex, pass, access);
598
598
  if (!item.ok) return item;
599
599
  normalized.push(item.value);
600
+ const resource = this.resources.get(item.value.resourceId);
600
601
  const usage =
601
- this.resources.get(item.value.resourceId)?.kind === 'buffer'
602
+ (resource?.kind === 'texture' && resource.origin === 'created'
603
+ ? (resource.descriptor.usage ?? 0)
604
+ : 0) |
605
+ (resource?.kind === 'buffer'
602
606
  ? bufferUsage(access.usage as GraphBufferAccess)
603
- : textureUsage(access.usage as GraphTextureAccess);
607
+ : textureUsage(access.usage as GraphTextureAccess));
604
608
  usageByResource.set(
605
609
  item.value.resourceId,
606
610
  (usageByResource.get(item.value.resourceId) ?? 0) | usage,
@@ -24,6 +24,7 @@ import type {
24
24
  GraphTexture,
25
25
  GraphTextureView,
26
26
  RenderGraphFrame,
27
+ RenderGraphPassInstrumentation,
27
28
  RenderGraphPassRunner,
28
29
  } from './types.js';
29
30
 
@@ -82,7 +83,11 @@ export class CompiledRenderGraphImpl<FrameCtx extends RenderGraphFrame>
82
83
  return this.colorTargetDescriptors.get(name);
83
84
  }
84
85
 
85
- execute(frame: FrameCtx, runPass?: RenderGraphPassRunner): Result<void, RenderGraphError> {
86
+ execute(
87
+ frame: FrameCtx,
88
+ runPass?: RenderGraphPassRunner,
89
+ instrumentation?: RenderGraphPassInstrumentation<FrameCtx>,
90
+ ): Result<void, RenderGraphError> {
86
91
  if (this.retired) {
87
92
  return err(
88
93
  new RenderGraphError({
@@ -101,8 +106,14 @@ export class CompiledRenderGraphImpl<FrameCtx extends RenderGraphFrame>
101
106
  const resolver = this.createPassResolver(pass, resolved.value);
102
107
  try {
103
108
  if (pass.pass.descriptor.executeIf?.(frame) === false) continue;
109
+ const execution = { name: pass.name, kind: pass.pass.kind, executionIndex };
104
110
  let encodeResult: Result<void, RenderGraphError> = ok(undefined);
105
111
  const encode = () => {
112
+ // Resolve instrumentation only when the runner actually enters the
113
+ // pass. A runner may inspect or skip a pass without calling encode;
114
+ // such a pass must not reserve timestamp queries that it never
115
+ // writes.
116
+ const scope = instrumentation?.begin(execution, frame);
106
117
  switch (pass.pass.kind) {
107
118
  case 'raster': {
108
119
  const descriptor = pass.pass.descriptor;
@@ -172,11 +183,17 @@ export class CompiledRenderGraphImpl<FrameCtx extends RenderGraphFrame>
172
183
  : { stencilReadOnly: attachment.stencilReadOnly }),
173
184
  };
174
185
  }
175
- const encoder = frame.encoder.beginRenderPass({
186
+ const baseDescriptor = {
176
187
  label: pass.name,
177
188
  colorAttachments,
178
189
  ...(depthStencilAttachment === undefined ? {} : { depthStencilAttachment }),
179
- });
190
+ ...(pass.pass.descriptor.occlusionQuerySet === undefined
191
+ ? {}
192
+ : { occlusionQuerySet: pass.pass.descriptor.occlusionQuerySet }),
193
+ };
194
+ const instrumentedDescriptor =
195
+ scope?.renderPassDescriptor?.(baseDescriptor) ?? baseDescriptor;
196
+ const encoder = frame.encoder.beginRenderPass(instrumentedDescriptor);
180
197
  try {
181
198
  descriptor.encode({ pass: encoder, frame, resources: resolver });
182
199
  } finally {
@@ -186,9 +203,13 @@ export class CompiledRenderGraphImpl<FrameCtx extends RenderGraphFrame>
186
203
  }
187
204
  case 'compute': {
188
205
  const begin = pass.pass.descriptor.begin?.(frame);
206
+ const instrumentedBegin = scope?.computePassDescriptor?.(begin ?? {}) ?? begin;
189
207
  let encoder: RhiComputePassEncoder;
190
208
  try {
191
- encoder = frame.encoder.beginComputePass({ ...(begin ?? {}), label: pass.name });
209
+ encoder = frame.encoder.beginComputePass({
210
+ ...(instrumentedBegin ?? {}),
211
+ label: pass.name,
212
+ });
192
213
  } catch (cause) {
193
214
  pass.pass.descriptor.onBeginError?.(frame, cause);
194
215
  throw cause;
@@ -202,14 +223,19 @@ export class CompiledRenderGraphImpl<FrameCtx extends RenderGraphFrame>
202
223
  break;
203
224
  }
204
225
  case 'copy':
205
- pass.pass.descriptor.encode({ encoder: frame.encoder, frame, resources: resolver });
226
+ scope?.beforeCopy?.(frame.encoder);
227
+ try {
228
+ pass.pass.descriptor.encode({ encoder: frame.encoder, frame, resources: resolver });
229
+ } finally {
230
+ scope?.afterCopy?.(frame.encoder);
231
+ }
206
232
  break;
207
233
  }
208
234
  };
209
235
  if (runPass === undefined) {
210
236
  encode();
211
237
  } else {
212
- runPass({ name: pass.name, kind: pass.pass.kind, executionIndex }, encode);
238
+ runPass(execution, encode);
213
239
  }
214
240
  if (!encodeResult.ok) return encodeResult;
215
241
  } catch (cause) {
package/src/index.ts CHANGED
@@ -97,5 +97,7 @@ export type {
97
97
  RenderGraphCompileOptions,
98
98
  RenderGraphFrame,
99
99
  RenderGraphPassExecution,
100
+ RenderGraphPassInstrumentation,
101
+ RenderGraphPassInstrumentationScope,
100
102
  RenderGraphPassRunner,
101
103
  } from './types.js';
package/src/types.ts CHANGED
@@ -1,6 +1,8 @@
1
1
  import type {
2
2
  Buffer,
3
3
  ComputePassDescriptor,
4
+ QuerySet,
5
+ RenderPassDescriptor,
4
6
  RhiCommandEncoder,
5
7
  RhiComputePassEncoder,
6
8
  RhiDevice,
@@ -45,7 +47,7 @@ export type GraphExtent =
45
47
  export interface GraphTextureDescriptor {
46
48
  readonly format: TextureFormat;
47
49
  readonly size: GraphExtent;
48
- /** Additional RHI usage required by an external diagnostic consumer. */
50
+ /** Additional RHI usage required by an external diagnostic consumer such as readback. */
49
51
  readonly usage?: number | undefined;
50
52
  readonly mipLevelCount?: number | undefined;
51
53
  readonly sampleCount?: number | undefined;
@@ -139,6 +141,8 @@ export interface RasterGraphPass<FrameCtx> {
139
141
  readonly accesses: readonly GraphAccess[];
140
142
  readonly colorAttachments: readonly RasterColorAttachment<FrameCtx>[];
141
143
  readonly depthStencilAttachment?: RasterDepthStencilAttachment | undefined;
144
+ /** Optional producer-owned occlusion query set for this raster pass. */
145
+ readonly occlusionQuerySet?: QuerySet | undefined;
142
146
  readonly executeIf?: ((frame: FrameCtx) => boolean) | undefined;
143
147
  encode(context: {
144
148
  readonly pass: RhiRenderPassEncoder;
@@ -244,13 +248,37 @@ export interface RenderGraphPassExecution {
244
248
 
245
249
  export type RenderGraphPassRunner = (pass: RenderGraphPassExecution, encode: () => void) => void;
246
250
 
251
+ /**
252
+ * The graph-neutral boundary for observing and decorating an actual pass.
253
+ * Render owns the policy supplied here; the graph only preserves pass
254
+ * provenance and applies the decorated descriptor at the real pass-open
255
+ * boundary. Timestamp policy and acceptance remain outside the graph.
256
+ */
257
+ export interface RenderGraphPassInstrumentationScope {
258
+ readonly renderPassDescriptor?: (descriptor: RenderPassDescriptor) => RenderPassDescriptor;
259
+ readonly computePassDescriptor?: (descriptor: ComputePassDescriptor) => ComputePassDescriptor;
260
+ readonly beforeCopy?: (encoder: RhiCommandEncoder) => void;
261
+ readonly afterCopy?: (encoder: RhiCommandEncoder) => void;
262
+ }
263
+
264
+ export interface RenderGraphPassInstrumentation<FrameCtx extends RenderGraphFrame> {
265
+ begin(
266
+ pass: RenderGraphPassExecution,
267
+ frame: FrameCtx,
268
+ ): RenderGraphPassInstrumentationScope | undefined;
269
+ }
270
+
247
271
  export interface RenderGraphCompileOptions {
248
272
  readonly device: RhiDevice;
249
273
  readonly surfaceSize: { readonly width: number; readonly height: number };
250
274
  }
251
275
 
252
276
  export interface CompiledRenderGraph<FrameCtx extends RenderGraphFrame> {
253
- execute(frame: FrameCtx, runPass?: RenderGraphPassRunner): Result<void, RenderGraphError>;
277
+ execute(
278
+ frame: FrameCtx,
279
+ runPass?: RenderGraphPassRunner,
280
+ instrumentation?: RenderGraphPassInstrumentation<FrameCtx>,
281
+ ): Result<void, RenderGraphError>;
254
282
  inspect(): CompiledRenderGraphInfo;
255
283
  retire(): Promise<Result<void, RenderGraphError>>;
256
284
  }