@forgeax/engine-render-graph 0.1.19 → 0.1.21
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/README.md +9 -0
- package/dist/.tsbuildinfo +1 -1
- package/dist/__tests__/render-graph-gpu-timing-instrumentation.unit.test.d.ts +2 -0
- package/dist/__tests__/render-graph-gpu-timing-instrumentation.unit.test.d.ts.map +1 -0
- package/dist/__tests__/texture-dimensions-lifecycle.unit.test.d.ts +2 -0
- package/dist/__tests__/texture-dimensions-lifecycle.unit.test.d.ts.map +1 -0
- package/dist/__tests__/texture-dimensions.unit.test.d.ts +2 -0
- package/dist/__tests__/texture-dimensions.unit.test.d.ts.map +1 -0
- package/dist/builder.d.ts.map +1 -1
- package/dist/compiled-graph.d.ts +2 -2
- package/dist/compiled-graph.d.ts.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.mjs +220 -126
- package/dist/index.mjs.map +1 -1
- package/dist/resource-registry.d.ts +2 -0
- package/dist/resource-registry.d.ts.map +1 -1
- package/dist/types.d.ts +33 -4
- package/dist/types.d.ts.map +1 -1
- package/package.json +4 -4
- package/src/__tests__/render-graph-builder.unit.test.ts +23 -0
- package/src/__tests__/render-graph-gpu-timing-instrumentation.unit.test.ts +183 -0
- package/src/__tests__/texture-dimensions-lifecycle.unit.test.ts +95 -0
- package/src/__tests__/texture-dimensions.unit.test.ts +99 -0
- package/src/builder.ts +159 -26
- package/src/compiled-graph.ts +25 -6
- package/src/index.ts +2 -0
- package/src/resource-registry.ts +10 -0
- package/src/types.ts +40 -2
package/src/builder.ts
CHANGED
|
@@ -15,6 +15,7 @@ import {
|
|
|
15
15
|
textureHandle,
|
|
16
16
|
textureViewHandle,
|
|
17
17
|
} from './kernel-internal.js';
|
|
18
|
+
import { isTextureViewDimensionCompatible } from './resource-registry.js';
|
|
18
19
|
import type {
|
|
19
20
|
CompiledRenderGraph,
|
|
20
21
|
CompiledRenderGraphInfo,
|
|
@@ -60,6 +61,60 @@ const TEXTURE_USAGE = {
|
|
|
60
61
|
|
|
61
62
|
let nextGeneration = 1;
|
|
62
63
|
|
|
64
|
+
function textureByteSize(
|
|
65
|
+
format: GPUTextureFormat,
|
|
66
|
+
extent: { readonly width: number; readonly height: number; readonly depthOrArrayLayers: number },
|
|
67
|
+
mipLevelCount: number,
|
|
68
|
+
): number | undefined {
|
|
69
|
+
const bytesPerTexel =
|
|
70
|
+
format === 'r8unorm' || format === 'r8snorm' || format === 'r8uint' || format === 'r8sint'
|
|
71
|
+
? 1
|
|
72
|
+
: format === 'rg8unorm' ||
|
|
73
|
+
format === 'rg8snorm' ||
|
|
74
|
+
format === 'rg8uint' ||
|
|
75
|
+
format === 'rg8sint'
|
|
76
|
+
? 2
|
|
77
|
+
: format === 'rgba8unorm' ||
|
|
78
|
+
format === 'rgba8unorm-srgb' ||
|
|
79
|
+
format === 'rgba8snorm' ||
|
|
80
|
+
format === 'rgba8uint' ||
|
|
81
|
+
format === 'rgba8sint' ||
|
|
82
|
+
format === 'r32float' ||
|
|
83
|
+
format === 'r32uint' ||
|
|
84
|
+
format === 'r32sint'
|
|
85
|
+
? 4
|
|
86
|
+
: format === 'rg16float' ||
|
|
87
|
+
format === 'rg16uint' ||
|
|
88
|
+
format === 'rg16sint' ||
|
|
89
|
+
format === 'rg16snorm' ||
|
|
90
|
+
format === 'rg16unorm'
|
|
91
|
+
? 4
|
|
92
|
+
: format === 'rgba16float' ||
|
|
93
|
+
format === 'rgba16uint' ||
|
|
94
|
+
format === 'rgba16sint' ||
|
|
95
|
+
format === 'rgba16snorm' ||
|
|
96
|
+
format === 'rgba16unorm' ||
|
|
97
|
+
format === 'rg32float' ||
|
|
98
|
+
format === 'rg32uint' ||
|
|
99
|
+
format === 'rg32sint'
|
|
100
|
+
? 8
|
|
101
|
+
: format === 'rgba32float' || format === 'rgba32uint' || format === 'rgba32sint'
|
|
102
|
+
? 16
|
|
103
|
+
: undefined;
|
|
104
|
+
if (bytesPerTexel === undefined) return undefined;
|
|
105
|
+
let bytes = 0;
|
|
106
|
+
let width = extent.width;
|
|
107
|
+
let height = extent.height;
|
|
108
|
+
let depth = extent.depthOrArrayLayers;
|
|
109
|
+
for (let level = 0; level < mipLevelCount; level += 1) {
|
|
110
|
+
bytes += width * height * depth * bytesPerTexel;
|
|
111
|
+
width = Math.max(1, Math.floor(width / 2));
|
|
112
|
+
height = Math.max(1, Math.floor(height / 2));
|
|
113
|
+
depth = Math.max(1, Math.floor(depth / 2));
|
|
114
|
+
}
|
|
115
|
+
return bytes;
|
|
116
|
+
}
|
|
117
|
+
|
|
63
118
|
interface NormalizedRange {
|
|
64
119
|
readonly mipStart: number;
|
|
65
120
|
readonly mipEnd: number;
|
|
@@ -108,6 +163,8 @@ function textureUsage(access: GraphTextureAccess): number {
|
|
|
108
163
|
case 'storage-write':
|
|
109
164
|
case 'storage-read-write':
|
|
110
165
|
return TEXTURE_USAGE.storageBinding;
|
|
166
|
+
case 'sampled-storage-read-write':
|
|
167
|
+
return TEXTURE_USAGE.storageBinding | TEXTURE_USAGE.textureBinding;
|
|
111
168
|
case 'color-attachment':
|
|
112
169
|
case 'depth-stencil-read':
|
|
113
170
|
case 'depth-stencil-write':
|
|
@@ -125,6 +182,7 @@ function accessMode(access: GraphBufferAccess | GraphTextureAccess): {
|
|
|
125
182
|
} {
|
|
126
183
|
switch (access) {
|
|
127
184
|
case 'storage-read-write':
|
|
185
|
+
case 'sampled-storage-read-write':
|
|
128
186
|
return { read: true, write: true };
|
|
129
187
|
case 'storage-write':
|
|
130
188
|
case 'color-attachment':
|
|
@@ -160,6 +218,7 @@ function freezeInfo(info: CompiledRenderGraphInfo): CompiledRenderGraphInfo {
|
|
|
160
218
|
return Object.freeze({ ...descriptor, size });
|
|
161
219
|
};
|
|
162
220
|
return Object.freeze({
|
|
221
|
+
generation: info.generation,
|
|
163
222
|
passes: Object.freeze(
|
|
164
223
|
info.passes.map((pass) =>
|
|
165
224
|
Object.freeze({
|
|
@@ -351,7 +410,20 @@ export class RenderGraphBuilder<FrameCtx extends RenderGraphFrame> {
|
|
|
351
410
|
);
|
|
352
411
|
if (!allocated.ok) return allocated;
|
|
353
412
|
|
|
413
|
+
const generation = nextGeneration;
|
|
414
|
+
const physicalAllocationKeys = new WeakMap<object, string>();
|
|
415
|
+
let nextPhysicalAllocationKey = 1;
|
|
416
|
+
const physicalKey = (resource: CompiledResource<FrameCtx>): string | undefined => {
|
|
417
|
+
const handle = resource.texture ?? resource.buffer;
|
|
418
|
+
if (handle === undefined) return undefined;
|
|
419
|
+
const existing = physicalAllocationKeys.get(handle);
|
|
420
|
+
if (existing !== undefined) return existing;
|
|
421
|
+
const key = `allocation-${nextPhysicalAllocationKey++}`;
|
|
422
|
+
physicalAllocationKeys.set(handle, key);
|
|
423
|
+
return key;
|
|
424
|
+
};
|
|
354
425
|
const info = freezeInfo({
|
|
426
|
+
generation,
|
|
355
427
|
passes: analyzed.value.passes.map((pass, executionIndex) => ({
|
|
356
428
|
name: pass.name,
|
|
357
429
|
kind: pass.pass.kind,
|
|
@@ -367,31 +439,63 @@ export class RenderGraphBuilder<FrameCtx extends RenderGraphFrame> {
|
|
|
367
439
|
(dependency) => analyzed.value.passes[dependency]?.name ?? 'unknown',
|
|
368
440
|
),
|
|
369
441
|
})),
|
|
370
|
-
resources: [...allocated.value.resources.values()].map((resource) =>
|
|
371
|
-
|
|
372
|
-
kind: resource.record.kind,
|
|
373
|
-
origin: resource.record.origin,
|
|
374
|
-
descriptor:
|
|
442
|
+
resources: [...allocated.value.resources.values()].map((resource) => {
|
|
443
|
+
const texture =
|
|
375
444
|
resource.record.kind === 'texture'
|
|
376
|
-
?
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
445
|
+
? (resource.record.descriptor as GraphTextureDescriptor)
|
|
446
|
+
: undefined;
|
|
447
|
+
const buffer =
|
|
448
|
+
resource.record.kind === 'buffer'
|
|
449
|
+
? (resource.record.descriptor as GraphBufferDescriptor)
|
|
450
|
+
: undefined;
|
|
451
|
+
const allocationKey = physicalKey(resource);
|
|
452
|
+
const extent =
|
|
453
|
+
texture === undefined ? undefined : this.resolveExtent(texture.size, options.surfaceSize);
|
|
454
|
+
return {
|
|
455
|
+
label: resource.record.label,
|
|
456
|
+
kind: resource.record.kind,
|
|
457
|
+
origin: resource.record.origin,
|
|
458
|
+
descriptor:
|
|
459
|
+
texture === undefined
|
|
460
|
+
? {
|
|
461
|
+
kind: 'buffer' as const,
|
|
462
|
+
size: buffer?.size ?? 0,
|
|
463
|
+
}
|
|
464
|
+
: {
|
|
465
|
+
kind: 'texture' as const,
|
|
466
|
+
format: texture.format,
|
|
467
|
+
...(texture.domain === undefined ? {} : { domain: texture.domain }),
|
|
468
|
+
size: texture.size,
|
|
469
|
+
width: extent?.width ?? 1,
|
|
470
|
+
height: extent?.height ?? 1,
|
|
471
|
+
depthOrArrayLayers: extent?.depthOrArrayLayers ?? 1,
|
|
472
|
+
mipLevelCount: texture.mipLevelCount ?? 1,
|
|
473
|
+
sampleCount: texture.sampleCount ?? 1,
|
|
474
|
+
},
|
|
475
|
+
firstUse: resource.firstUse,
|
|
476
|
+
lastUse: resource.lastUse,
|
|
477
|
+
derivedUsage: resource.usage,
|
|
478
|
+
...(allocationKey === undefined ? {} : { physicalAllocationKey: allocationKey }),
|
|
479
|
+
...(texture === undefined ? {} : { format: texture.format }),
|
|
480
|
+
...(texture === undefined
|
|
481
|
+
? buffer === undefined
|
|
482
|
+
? {}
|
|
483
|
+
: { byteSize: buffer.size }
|
|
387
484
|
: {
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
485
|
+
byteSize: textureByteSize(
|
|
486
|
+
texture.format,
|
|
487
|
+
this.resolveExtent(texture.size, options.surfaceSize),
|
|
488
|
+
texture.mipLevelCount ?? 1,
|
|
489
|
+
),
|
|
490
|
+
}),
|
|
491
|
+
...(texture === undefined
|
|
492
|
+
? {}
|
|
493
|
+
: {
|
|
494
|
+
dimension: texture.dimension ?? '2d',
|
|
495
|
+
extent,
|
|
496
|
+
}),
|
|
497
|
+
};
|
|
498
|
+
}),
|
|
395
499
|
});
|
|
396
500
|
|
|
397
501
|
const colorTargetDescriptors = new Map<string, ResolvedColorTargetDescriptor>();
|
|
@@ -493,10 +597,14 @@ export class RenderGraphBuilder<FrameCtx extends RenderGraphFrame> {
|
|
|
493
597
|
const item = this.normalizeAccess(passIndex, pass, access);
|
|
494
598
|
if (!item.ok) return item;
|
|
495
599
|
normalized.push(item.value);
|
|
600
|
+
const resource = this.resources.get(item.value.resourceId);
|
|
496
601
|
const usage =
|
|
497
|
-
|
|
602
|
+
(resource?.kind === 'texture' && resource.origin === 'created'
|
|
603
|
+
? (resource.descriptor.usage ?? 0)
|
|
604
|
+
: 0) |
|
|
605
|
+
(resource?.kind === 'buffer'
|
|
498
606
|
? bufferUsage(access.usage as GraphBufferAccess)
|
|
499
|
-
: textureUsage(access.usage as GraphTextureAccess);
|
|
607
|
+
: textureUsage(access.usage as GraphTextureAccess));
|
|
500
608
|
usageByResource.set(
|
|
501
609
|
item.value.resourceId,
|
|
502
610
|
(usageByResource.get(item.value.resourceId) ?? 0) | usage,
|
|
@@ -717,7 +825,11 @@ export class RenderGraphBuilder<FrameCtx extends RenderGraphFrame> {
|
|
|
717
825
|
continue;
|
|
718
826
|
}
|
|
719
827
|
if (!left.write && !right.write) continue;
|
|
720
|
-
if (
|
|
828
|
+
if (
|
|
829
|
+
left.usage === right.usage &&
|
|
830
|
+
(left.usage === 'storage-read-write' || left.usage === 'sampled-storage-read-write')
|
|
831
|
+
)
|
|
832
|
+
continue;
|
|
721
833
|
const label = this.resources.get(left.resourceId)?.label;
|
|
722
834
|
return err(
|
|
723
835
|
new RenderGraphError({
|
|
@@ -891,6 +1003,27 @@ export class RenderGraphBuilder<FrameCtx extends RenderGraphFrame> {
|
|
|
891
1003
|
}
|
|
892
1004
|
}
|
|
893
1005
|
}
|
|
1006
|
+
for (const view of this.views.values()) {
|
|
1007
|
+
const texture = this.resources.get(view.textureId);
|
|
1008
|
+
if (texture?.kind !== 'texture') continue;
|
|
1009
|
+
const allocationDimension = texture.descriptor.dimension ?? '2d';
|
|
1010
|
+
const viewDimension = view.descriptor.dimension;
|
|
1011
|
+
if (!isTextureViewDimensionCompatible(allocationDimension, viewDimension)) {
|
|
1012
|
+
return err(
|
|
1013
|
+
new RenderGraphError({
|
|
1014
|
+
code: 'resource-descriptor-invalid',
|
|
1015
|
+
expected: `texture '${texture.label}' view dimension matches allocation dimension`,
|
|
1016
|
+
hint: 'use a 3d view only for a 3d allocation and preserve array views on 2d allocations',
|
|
1017
|
+
detail: {
|
|
1018
|
+
resourceLabel: texture.label,
|
|
1019
|
+
field: 'dimension',
|
|
1020
|
+
expected: allocationDimension,
|
|
1021
|
+
actual: viewDimension ?? '2d',
|
|
1022
|
+
},
|
|
1023
|
+
}),
|
|
1024
|
+
);
|
|
1025
|
+
}
|
|
1026
|
+
}
|
|
894
1027
|
return ok(undefined);
|
|
895
1028
|
}
|
|
896
1029
|
|
package/src/compiled-graph.ts
CHANGED
|
@@ -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(
|
|
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,6 +106,8 @@ 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 };
|
|
110
|
+
const scope = instrumentation?.begin(execution, frame);
|
|
104
111
|
let encodeResult: Result<void, RenderGraphError> = ok(undefined);
|
|
105
112
|
const encode = () => {
|
|
106
113
|
switch (pass.pass.kind) {
|
|
@@ -172,11 +179,14 @@ export class CompiledRenderGraphImpl<FrameCtx extends RenderGraphFrame>
|
|
|
172
179
|
: { stencilReadOnly: attachment.stencilReadOnly }),
|
|
173
180
|
};
|
|
174
181
|
}
|
|
175
|
-
const
|
|
182
|
+
const baseDescriptor = {
|
|
176
183
|
label: pass.name,
|
|
177
184
|
colorAttachments,
|
|
178
185
|
...(depthStencilAttachment === undefined ? {} : { depthStencilAttachment }),
|
|
179
|
-
}
|
|
186
|
+
};
|
|
187
|
+
const instrumentedDescriptor =
|
|
188
|
+
scope?.renderPassDescriptor?.(baseDescriptor) ?? baseDescriptor;
|
|
189
|
+
const encoder = frame.encoder.beginRenderPass(instrumentedDescriptor);
|
|
180
190
|
try {
|
|
181
191
|
descriptor.encode({ pass: encoder, frame, resources: resolver });
|
|
182
192
|
} finally {
|
|
@@ -186,9 +196,13 @@ export class CompiledRenderGraphImpl<FrameCtx extends RenderGraphFrame>
|
|
|
186
196
|
}
|
|
187
197
|
case 'compute': {
|
|
188
198
|
const begin = pass.pass.descriptor.begin?.(frame);
|
|
199
|
+
const instrumentedBegin = scope?.computePassDescriptor?.(begin ?? {}) ?? begin;
|
|
189
200
|
let encoder: RhiComputePassEncoder;
|
|
190
201
|
try {
|
|
191
|
-
encoder = frame.encoder.beginComputePass({
|
|
202
|
+
encoder = frame.encoder.beginComputePass({
|
|
203
|
+
...(instrumentedBegin ?? {}),
|
|
204
|
+
label: pass.name,
|
|
205
|
+
});
|
|
192
206
|
} catch (cause) {
|
|
193
207
|
pass.pass.descriptor.onBeginError?.(frame, cause);
|
|
194
208
|
throw cause;
|
|
@@ -202,14 +216,19 @@ export class CompiledRenderGraphImpl<FrameCtx extends RenderGraphFrame>
|
|
|
202
216
|
break;
|
|
203
217
|
}
|
|
204
218
|
case 'copy':
|
|
205
|
-
|
|
219
|
+
scope?.beforeCopy?.(frame.encoder);
|
|
220
|
+
try {
|
|
221
|
+
pass.pass.descriptor.encode({ encoder: frame.encoder, frame, resources: resolver });
|
|
222
|
+
} finally {
|
|
223
|
+
scope?.afterCopy?.(frame.encoder);
|
|
224
|
+
}
|
|
206
225
|
break;
|
|
207
226
|
}
|
|
208
227
|
};
|
|
209
228
|
if (runPass === undefined) {
|
|
210
229
|
encode();
|
|
211
230
|
} else {
|
|
212
|
-
runPass(
|
|
231
|
+
runPass(execution, encode);
|
|
213
232
|
}
|
|
214
233
|
if (!encodeResult.ok) return encodeResult;
|
|
215
234
|
} catch (cause) {
|
package/src/index.ts
CHANGED
package/src/resource-registry.ts
CHANGED
|
@@ -26,6 +26,16 @@ import type {
|
|
|
26
26
|
} from './graph.js';
|
|
27
27
|
import type { ColorValueDomain } from './pipeline/color-value-domain.js';
|
|
28
28
|
|
|
29
|
+
/** Check the only allocation/view dimension combinations supported by WebGPU. */
|
|
30
|
+
export function isTextureViewDimensionCompatible(
|
|
31
|
+
allocationDimension: GPUTextureDimension,
|
|
32
|
+
viewDimension: GPUTextureViewDimension | undefined,
|
|
33
|
+
): boolean {
|
|
34
|
+
if (viewDimension === undefined) return true;
|
|
35
|
+
if (allocationDimension === '3d') return viewDimension === '3d';
|
|
36
|
+
return viewDimension !== '3d';
|
|
37
|
+
}
|
|
38
|
+
|
|
29
39
|
/**
|
|
30
40
|
* Per-resource GPU allocation metadata carried through compile.
|
|
31
41
|
* When the resource was registered via addColorTarget, colorTarget
|
package/src/types.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import type {
|
|
2
2
|
Buffer,
|
|
3
3
|
ComputePassDescriptor,
|
|
4
|
+
RenderPassDescriptor,
|
|
4
5
|
RhiCommandEncoder,
|
|
5
6
|
RhiComputePassEncoder,
|
|
6
7
|
RhiDevice,
|
|
@@ -45,7 +46,7 @@ export type GraphExtent =
|
|
|
45
46
|
export interface GraphTextureDescriptor {
|
|
46
47
|
readonly format: TextureFormat;
|
|
47
48
|
readonly size: GraphExtent;
|
|
48
|
-
/** Additional RHI usage required by an external diagnostic consumer. */
|
|
49
|
+
/** Additional RHI usage required by an external diagnostic consumer such as readback. */
|
|
49
50
|
readonly usage?: number | undefined;
|
|
50
51
|
readonly mipLevelCount?: number | undefined;
|
|
51
52
|
readonly sampleCount?: number | undefined;
|
|
@@ -97,6 +98,7 @@ export type GraphTextureAccess =
|
|
|
97
98
|
| 'storage-read'
|
|
98
99
|
| 'storage-write'
|
|
99
100
|
| 'storage-read-write'
|
|
101
|
+
| 'sampled-storage-read-write'
|
|
100
102
|
| 'color-attachment'
|
|
101
103
|
| 'depth-stencil-read'
|
|
102
104
|
| 'depth-stencil-write'
|
|
@@ -215,7 +217,20 @@ export interface CompiledRenderGraphInfo {
|
|
|
215
217
|
readonly firstUse: number | null;
|
|
216
218
|
readonly lastUse: number | null;
|
|
217
219
|
readonly derivedUsage: number;
|
|
220
|
+
/** Stable compile-local identity of the physical RHI allocation. */
|
|
221
|
+
readonly physicalAllocationKey?: string | undefined;
|
|
222
|
+
/** Descriptor-derived byte size when the format is uncompressed and known. */
|
|
223
|
+
readonly byteSize?: number | undefined;
|
|
224
|
+
/** Texture format retained for producer-owned resource inspection. */
|
|
225
|
+
readonly format?: TextureFormat | undefined;
|
|
226
|
+
/** Texture allocation facts retained for capability/lifetime inspection. */
|
|
227
|
+
readonly dimension?: GPUTextureDimension | undefined;
|
|
228
|
+
readonly extent?:
|
|
229
|
+
| { readonly width: number; readonly height: number; readonly depthOrArrayLayers: number }
|
|
230
|
+
| undefined;
|
|
218
231
|
}[];
|
|
232
|
+
/** Monotonic graph generation assigned when this graph was compiled. */
|
|
233
|
+
readonly generation: number;
|
|
219
234
|
}
|
|
220
235
|
|
|
221
236
|
export interface RenderGraphFrame {
|
|
@@ -230,13 +245,36 @@ export interface RenderGraphPassExecution {
|
|
|
230
245
|
|
|
231
246
|
export type RenderGraphPassRunner = (pass: RenderGraphPassExecution, encode: () => void) => void;
|
|
232
247
|
|
|
248
|
+
/**
|
|
249
|
+
* The graph-neutral boundary for observing and decorating an actual pass.
|
|
250
|
+
* Render owns the policy supplied here; the graph only preserves pass
|
|
251
|
+
* provenance and the existing encoder boundaries.
|
|
252
|
+
*/
|
|
253
|
+
export interface RenderGraphPassInstrumentationScope {
|
|
254
|
+
readonly renderPassDescriptor?: (descriptor: RenderPassDescriptor) => RenderPassDescriptor;
|
|
255
|
+
readonly computePassDescriptor?: (descriptor: ComputePassDescriptor) => ComputePassDescriptor;
|
|
256
|
+
readonly beforeCopy?: (encoder: RhiCommandEncoder) => void;
|
|
257
|
+
readonly afterCopy?: (encoder: RhiCommandEncoder) => void;
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
export interface RenderGraphPassInstrumentation<FrameCtx extends RenderGraphFrame> {
|
|
261
|
+
begin(
|
|
262
|
+
pass: RenderGraphPassExecution,
|
|
263
|
+
frame: FrameCtx,
|
|
264
|
+
): RenderGraphPassInstrumentationScope | undefined;
|
|
265
|
+
}
|
|
266
|
+
|
|
233
267
|
export interface RenderGraphCompileOptions {
|
|
234
268
|
readonly device: RhiDevice;
|
|
235
269
|
readonly surfaceSize: { readonly width: number; readonly height: number };
|
|
236
270
|
}
|
|
237
271
|
|
|
238
272
|
export interface CompiledRenderGraph<FrameCtx extends RenderGraphFrame> {
|
|
239
|
-
execute(
|
|
273
|
+
execute(
|
|
274
|
+
frame: FrameCtx,
|
|
275
|
+
runPass?: RenderGraphPassRunner,
|
|
276
|
+
instrumentation?: RenderGraphPassInstrumentation<FrameCtx>,
|
|
277
|
+
): Result<void, RenderGraphError>;
|
|
240
278
|
inspect(): CompiledRenderGraphInfo;
|
|
241
279
|
retire(): Promise<Result<void, RenderGraphError>>;
|
|
242
280
|
}
|