@forgeax/engine-render 0.1.24 → 0.1.25
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 +100 -1
- package/dist/assembly/factory.d.ts +1 -1
- package/dist/assembly/factory.d.ts.map +1 -1
- package/dist/assembly/material/surface-projection.d.ts +24 -0
- package/dist/assembly/material/surface-projection.d.ts.map +1 -0
- package/dist/assembly/material-shader-policy.d.ts +20 -0
- package/dist/assembly/material-shader-policy.d.ts.map +1 -1
- package/dist/assembly/webgpu-ready.d.ts.map +1 -1
- package/dist/assembly/webgpu-renderer.d.ts +1 -1
- package/dist/assembly/webgpu-renderer.d.ts.map +1 -1
- package/dist/assembly/webgpu-vertex-layouts.d.ts +89 -0
- package/dist/assembly/webgpu-vertex-layouts.d.ts.map +1 -0
- package/dist/assets/asset-decoders.d.ts.map +1 -1
- package/dist/authoring.mjs +1 -1
- package/dist/{chunk-Q752SHI5.mjs → chunk-ADHHVYLW.mjs} +3 -3
- package/dist/chunk-ADHHVYLW.mjs.map +1 -0
- package/dist/{chunk-TFH5I7JJ.mjs → chunk-E34VL5VI.mjs} +3 -3
- package/dist/{chunk-TFH5I7JJ.mjs.map → chunk-E34VL5VI.mjs.map} +1 -1
- package/dist/{chunk-KZFTK6DO.mjs → chunk-HKXTW355.mjs} +7 -4
- package/dist/chunk-HKXTW355.mjs.map +1 -0
- package/dist/{chunk-YKB5DQV7.mjs → chunk-JSEDTZYS.mjs} +87 -19
- package/dist/chunk-JSEDTZYS.mjs.map +1 -0
- package/dist/{chunk-UQYS7FRM.mjs → chunk-KM2NOX2I.mjs} +4 -4
- package/dist/{chunk-UQYS7FRM.mjs.map → chunk-KM2NOX2I.mjs.map} +1 -1
- package/dist/{chunk-Z3YYH2MB.mjs → chunk-N3RT2EUR.mjs} +94 -41
- package/dist/chunk-N3RT2EUR.mjs.map +1 -0
- package/dist/{chunk-YRUYGA4A.mjs → chunk-TCLDX7SZ.mjs} +559 -138
- package/dist/chunk-TCLDX7SZ.mjs.map +1 -0
- package/dist/{chunk-RR5L4SRS.mjs → chunk-ZZ4YQ474.mjs} +2 -2
- package/dist/{chunk-RR5L4SRS.mjs.map → chunk-ZZ4YQ474.mjs.map} +1 -1
- package/dist/components/instances.d.ts +13 -31
- package/dist/components/instances.d.ts.map +1 -1
- package/dist/construct-renderer.mjs +865 -142
- package/dist/construct-renderer.mjs.map +1 -1
- package/dist/gpu-driven/production-raster.d.ts +6 -1
- package/dist/gpu-driven/production-raster.d.ts.map +1 -1
- package/dist/gpu-scene.d.ts +4 -0
- package/dist/gpu-scene.d.ts.map +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.mjs +27 -9
- package/dist/index.mjs.map +1 -1
- package/dist/instance-buffer-cache.d.ts +7 -1
- package/dist/instance-buffer-cache.d.ts.map +1 -1
- package/dist/instances.d.ts +101 -0
- package/dist/instances.d.ts.map +1 -0
- package/dist/internal.mjs +5 -5
- package/dist/materials.d.ts +63 -2
- package/dist/materials.d.ts.map +1 -1
- package/dist/pipeline-builder.d.ts.map +1 -1
- package/dist/pipeline-spec.d.ts.map +1 -1
- package/dist/record/frame-snapshot.d.ts +13 -2
- package/dist/record/frame-snapshot.d.ts.map +1 -1
- package/dist/record/frame.d.ts.map +1 -1
- package/dist/record/main-pass-geometry.d.ts +22 -3
- package/dist/record/main-pass-geometry.d.ts.map +1 -1
- package/dist/record/render-context.d.ts +2 -1
- package/dist/record/render-context.d.ts.map +1 -1
- package/dist/record/shadow-pass.d.ts +11 -1
- package/dist/record/shadow-pass.d.ts.map +1 -1
- package/dist/recovery/render-system-candidate.d.ts +1 -1
- package/dist/recovery/render-system-candidate.d.ts.map +1 -1
- package/dist/render-contract.d.ts +4 -0
- package/dist/render-contract.d.ts.map +1 -1
- package/dist/render-system-extract-tail.d.ts +4 -0
- package/dist/render-system-extract-tail.d.ts.map +1 -1
- package/dist/render-system-extract.d.ts +25 -1
- package/dist/render-system-extract.d.ts.map +1 -1
- package/dist/render-system.d.ts +4 -1
- package/dist/render-system.d.ts.map +1 -1
- package/dist/scene/render-scene-types.d.ts +2 -0
- package/dist/scene/render-scene-types.d.ts.map +1 -1
- package/dist/scene/render-scene.d.ts +12 -1
- package/dist/scene/render-scene.d.ts.map +1 -1
- package/dist/systems/skin-palette-allocator.d.ts +6 -0
- package/dist/systems/skin-palette-allocator.d.ts.map +1 -1
- package/dist/temporal/index.mjs +5 -5
- package/package.json +20 -20
- package/src/__tests__/gpu-scene.unit.test.ts +38 -2
- package/src/__tests__/instances-store.unit.test.ts +46 -0
- package/src/__tests__/instances-world-ownership.integration.test.ts +62 -0
- package/src/__tests__/material-contract-inventory.unit.test.ts +5 -13
- package/src/__tests__/material-pass-policy.unit.test.ts +69 -0
- package/src/__tests__/material-snapshot-mutation.integration.test.ts +69 -0
- package/src/__tests__/material-surface-authoring.test-d.ts +62 -0
- package/src/__tests__/materials-transmission-validation.unit.test.ts +24 -0
- package/src/__tests__/mesh-buffer-usage-surface.unit.test.ts +0 -4
- package/src/__tests__/renderer-factory-material-contract.unit.test.ts +42 -0
- package/src/__tests__/skin-motion-regression.unit.test.ts +33 -0
- package/src/__tests__/skinned-shadow-caster.test.ts +30 -2
- package/src/__tests__/surface-adjacent-regressions.integration.test.ts +60 -0
- package/src/__tests__/surface-standard-pipeline.browser.test.ts +20 -0
- package/src/__tests__/surface-standard-pipeline.dawn.test.ts +20 -0
- package/src/__tests__/surface-standard-pipeline.fixture.ts +132 -0
- package/src/__tests__/surface-variant-provenance.integration.test.ts +33 -0
- package/src/__tests__/volumetric-fog-budget-recovery.integration.test.ts +1 -1
- package/src/assembly/factory.ts +2 -0
- package/src/assembly/material/__tests__/standard-layer-plan-projection.integration.test.ts +18 -0
- package/src/assembly/material/__tests__/surface-pass-projection.integration.test.ts +62 -0
- package/src/assembly/material/surface-projection.ts +90 -0
- package/src/assembly/material-shader-policy.ts +88 -10
- package/src/assembly/recovery/renderer-recover.ts +1 -1
- package/src/assembly/webgpu-ready.ts +3 -16
- package/src/assembly/webgpu-renderer.ts +90 -158
- package/src/assembly/webgpu-vertex-layouts.ts +132 -0
- package/src/assets/asset-decoders.ts +27 -4
- package/src/components/instances.ts +14 -197
- package/src/gpu-driven/production-raster.ts +34 -1
- package/src/gpu-scene.ts +84 -29
- package/src/index.ts +1 -0
- package/src/instance-buffer-cache.ts +14 -1
- package/src/instances.ts +288 -0
- package/src/materials.ts +107 -12
- package/src/pipeline-builder.ts +14 -10
- package/src/pipeline-spec.ts +6 -14
- package/src/record/frame-snapshot.ts +19 -2
- package/src/record/frame.ts +31 -2
- package/src/record/main-pass-geometry.ts +498 -59
- package/src/record/main-pass-sprite-draws.ts +1 -1
- package/src/record/render-context.ts +4 -0
- package/src/record/shadow-pass.ts +46 -99
- package/src/recovery/render-system-candidate.ts +41 -4
- package/src/render-contract.ts +4 -0
- package/src/render-system-extract-tail.ts +107 -51
- package/src/render-system-extract.ts +53 -26
- package/src/render-system.ts +40 -5
- package/src/scene/render-scene-types.ts +2 -0
- package/src/scene/render-scene.ts +579 -36
- package/src/systems/skin-palette-allocator.ts +129 -7
- package/src/transmission/__tests__/surface-compatibility.integration.test.ts +32 -0
- package/dist/chunk-KZFTK6DO.mjs.map +0 -1
- package/dist/chunk-Q752SHI5.mjs.map +0 -1
- package/dist/chunk-YKB5DQV7.mjs.map +0 -1
- package/dist/chunk-YRUYGA4A.mjs.map +0 -1
- package/dist/chunk-Z3YYH2MB.mjs.map +0 -1
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import { TRANSPARENT_SORT_MODE_LAYER_Z, TRANSPARENT_SORT_MODE_LAYER_Y } from './chunk-RXZ3RGOU.mjs';
|
|
2
|
-
import { DEFAULT_CLUSTER_GRID, DEFAULT_STANDARD_PROFILE, createIblKernelCache, MAX_LIGHTS, CLUSTER_GRID_STRIDE_U32, LIGHT_INDEX_LIST_CAPACITY, createStandardClusterLayout } from './chunk-
|
|
3
|
-
import { SPRITE_PREMULTIPLIED_ALPHA_BLEND } from './chunk-
|
|
4
|
-
import { GPU_SHADER_STAGE_COMPUTE, GPU_BUFFER_USAGE_STORAGE, GPU_BUFFER_USAGE_COPY_DST, GPU_BUFFER_USAGE_UNIFORM, createHdrpBindGroupLayoutDescriptor, IES_SLICE_WIDTH, IES_SLICE_HEIGHT, COOKIE_SLICE_SIZE, GPU_SHADER_STAGE_VERTEX, GPU_SHADER_STAGE_FRAGMENT, GPU_BUFFER_USAGE_INDEX, GPU_BUFFER_USAGE_VERTEX,
|
|
5
|
-
import { GPU_TEXTURE_USAGE_RENDER_ATTACHMENT, GPU_TEXTURE_USAGE_COPY_SRC, VertexColorVariantConflictError, EquirectProjectionFailedError, SHADOW_ATLAS_DEFAULT_LAYERS, SHADOW_ATLAS_DEFAULT_FACE_SIZE, ShadowAtlas, PointShadowAtlasUninitializedError, PointShadowAtlasBoundsViolationError, StandardClusterTransportUnavailableError, GPU_TEXTURE_USAGE_RENDER_ATTACHMENT_AND_TEXTURE_BINDING, GPU_TEXTURE_USAGE_COPY_DST, GPU_TEXTURE_USAGE_TEXTURE_BINDING, STANDARD_OUTPUT_TRANSFORM_FEATURE_ID, StandardLightBudgetExceededError, RendererOperationError, StandardClusterIndexOverflowError, FXAA_POST_PROCESS_ID, VideoUploadUnsupportedError } from './chunk-
|
|
2
|
+
import { DEFAULT_CLUSTER_GRID, DEFAULT_STANDARD_PROFILE, createIblKernelCache, MAX_LIGHTS, CLUSTER_GRID_STRIDE_U32, LIGHT_INDEX_LIST_CAPACITY, createStandardClusterLayout } from './chunk-E34VL5VI.mjs';
|
|
3
|
+
import { SPRITE_PREMULTIPLIED_ALPHA_BLEND } from './chunk-JSEDTZYS.mjs';
|
|
4
|
+
import { GPU_SHADER_STAGE_COMPUTE, GPU_BUFFER_USAGE_STORAGE, GPU_BUFFER_USAGE_COPY_DST, GPU_BUFFER_USAGE_UNIFORM, createHdrpBindGroupLayoutDescriptor, IES_SLICE_WIDTH, IES_SLICE_HEIGHT, COOKIE_SLICE_SIZE, GPU_SHADER_STAGE_VERTEX, GPU_SHADER_STAGE_FRAGMENT, GPU_BUFFER_USAGE_INDEX, GPU_BUFFER_USAGE_VERTEX, worldEntityKey, instanceCollectionCacheKey, probeBlendRecordOffset, PROBE_BLEND_RECORD_STRIDE, pbrSkinMeshDynamicOffsets, buildPbrMaterialUserRegionEntries, buildBindGroupLayoutDescriptor, isStandardPbrMaterialShader, PROBE_BLEND_RECORD_BYTE_SIZE, SHADOW_CASTER_SHADER_ID, shadowCasterVariantSet, COOKIE_MATRIX_BYTES, matchPass, createPbrSkinMeshBindGroupEntries, getOpaqueResourceIdentity, SPRITE_PASS_PER_INSTANCE_REGION_VARIANT_SET, physicalTextureFields, isCanonicalStandardPbrMaterialShader, isStandardPbrSkinMaterialShader, SKIN_MATERIAL_SHADER_ID, resolveRenderTargetMaterialSource, materialBindGroupLayoutIdentity } from './chunk-HKXTW355.mjs';
|
|
5
|
+
import { GPU_TEXTURE_USAGE_RENDER_ATTACHMENT, GPU_TEXTURE_USAGE_COPY_SRC, VertexColorVariantConflictError, EquirectProjectionFailedError, SHADOW_ATLAS_DEFAULT_LAYERS, SHADOW_ATLAS_DEFAULT_FACE_SIZE, ShadowAtlas, PointShadowAtlasUninitializedError, PointShadowAtlasBoundsViolationError, StandardClusterTransportUnavailableError, GPU_TEXTURE_USAGE_RENDER_ATTACHMENT_AND_TEXTURE_BINDING, GPU_TEXTURE_USAGE_COPY_DST, GPU_TEXTURE_USAGE_TEXTURE_BINDING, STANDARD_OUTPUT_TRANSFORM_FEATURE_ID, StandardLightBudgetExceededError, RendererOperationError, StandardClusterIndexOverflowError, FXAA_POST_PROCESS_ID, VideoUploadUnsupportedError } from './chunk-ZZ4YQ474.mjs';
|
|
6
6
|
import { derive, ok, err as err$1, toShared, ASSET_ERROR_HINTS, deriveTextureLayout, handleSlot, KNOWN_PASS_KINDS, resolveMaterialTextureCoordinates } from '@forgeax/engine-types';
|
|
7
7
|
import { ok as ok$1, err, RhiError } from '@forgeax/engine-rhi';
|
|
8
8
|
import { mat3, vec3, mat4 } from '@forgeax/engine-math';
|
|
9
|
-
import { deriveVertexLayoutProjection, deriveVertexBufferLayout } from '@forgeax/engine-geometry';
|
|
9
|
+
import { deriveVertexLayoutProjection, deriveVertexBufferLayout, deriveVertexBufferLayoutFromProjection } from '@forgeax/engine-geometry';
|
|
10
10
|
import { resolveAssetHandle } from '@forgeax/engine-assets-runtime';
|
|
11
11
|
import { probeVideoHighPerfUpload, VIDEO_ELEMENT_PROVIDER_KEY } from '@forgeax/engine-graphics-extras';
|
|
12
12
|
import { DEFAULT_STANDARD_PBR_PARAM_SCHEMA, STANDARD_PIPELINE_PARAM_SCHEMA, DEFAULT_MSDF_TEXT_PARAM_SCHEMA, DEFAULT_SPRITE_PARAM_SCHEMA, DEFAULT_UNLIT_PARAM_SCHEMA } from '@forgeax/engine-shader';
|
|
@@ -283,18 +283,9 @@ function buildPipelineDescriptor(spec, modules) {
|
|
|
283
283
|
const { attachments, geometry, renderState } = spec;
|
|
284
284
|
const vertexBuffers = geometry.vertexLayoutProjection === void 0 ? deriveVertexBufferLayout(geometry.vertexLayout, {
|
|
285
285
|
...geometry.shaderUvSetCount !== void 0 ? { shaderUvSetCount: geometry.shaderUvSetCount } : {}
|
|
286
|
-
}) : geometry.vertexLayoutProjection
|
|
287
|
-
{
|
|
288
|
-
|
|
289
|
-
attributes: geometry.vertexLayoutProjection.attributes.map(
|
|
290
|
-
({ shaderLocation, offset, format }) => ({
|
|
291
|
-
shaderLocation,
|
|
292
|
-
offset,
|
|
293
|
-
format
|
|
294
|
-
})
|
|
295
|
-
)
|
|
296
|
-
}
|
|
297
|
-
];
|
|
286
|
+
}) : deriveVertexBufferLayoutFromProjection(geometry.vertexLayoutProjection, {
|
|
287
|
+
...geometry.shaderUvSetCount !== void 0 ? { shaderUvSetCount: geometry.shaderUvSetCount } : {}
|
|
288
|
+
});
|
|
298
289
|
const descriptor = {
|
|
299
290
|
vertex: {
|
|
300
291
|
module: modules.vertex,
|
|
@@ -4091,6 +4082,150 @@ var GpuTexture = class {
|
|
|
4091
4082
|
}
|
|
4092
4083
|
};
|
|
4093
4084
|
|
|
4085
|
+
// src/instances.ts
|
|
4086
|
+
var MATRIX_STRIDE = 16;
|
|
4087
|
+
function appendRange(ranges, start, end) {
|
|
4088
|
+
if (start >= end) return;
|
|
4089
|
+
let index = 0;
|
|
4090
|
+
while (index < ranges.length) {
|
|
4091
|
+
const existing = ranges[index];
|
|
4092
|
+
if (existing === void 0 || existing.end >= start) break;
|
|
4093
|
+
index += 1;
|
|
4094
|
+
}
|
|
4095
|
+
while (index < ranges.length) {
|
|
4096
|
+
const existing = ranges[index];
|
|
4097
|
+
if (existing === void 0 || existing.start > end) break;
|
|
4098
|
+
start = Math.min(start, existing.start);
|
|
4099
|
+
end = Math.max(end, existing.end);
|
|
4100
|
+
ranges.splice(index, 1);
|
|
4101
|
+
}
|
|
4102
|
+
ranges.splice(index, 0, { start, end });
|
|
4103
|
+
}
|
|
4104
|
+
var InstanceProjectionStore = class {
|
|
4105
|
+
nextId = 1;
|
|
4106
|
+
identities = /* @__PURE__ */ new WeakMap();
|
|
4107
|
+
records = /* @__PURE__ */ new Map();
|
|
4108
|
+
project(world, entity, transforms) {
|
|
4109
|
+
let entities = this.identities.get(world);
|
|
4110
|
+
if (entities === void 0) {
|
|
4111
|
+
entities = /* @__PURE__ */ new Map();
|
|
4112
|
+
this.identities.set(world, entities);
|
|
4113
|
+
}
|
|
4114
|
+
let collectionId = entities.get(entity);
|
|
4115
|
+
if (collectionId === void 0) {
|
|
4116
|
+
collectionId = this.nextId++;
|
|
4117
|
+
entities.set(entity, collectionId);
|
|
4118
|
+
}
|
|
4119
|
+
const previous = this.records.get(collectionId);
|
|
4120
|
+
const unchanged = previous !== void 0 && previous.transforms.length === transforms.length && previous.transforms.every((value, index) => Object.is(value, transforms[index]));
|
|
4121
|
+
const record = unchanged ? previous : {
|
|
4122
|
+
collectionId,
|
|
4123
|
+
world,
|
|
4124
|
+
entity,
|
|
4125
|
+
transforms: new Float32Array(transforms),
|
|
4126
|
+
count: transforms.length / MATRIX_STRIDE,
|
|
4127
|
+
revision: (previous?.revision ?? 0) + 1
|
|
4128
|
+
};
|
|
4129
|
+
this.records.set(collectionId, record);
|
|
4130
|
+
return { ...this.info(record), transforms: record.transforms };
|
|
4131
|
+
}
|
|
4132
|
+
retain(ids) {
|
|
4133
|
+
for (const [id, record] of this.records) {
|
|
4134
|
+
if (ids.has(id)) continue;
|
|
4135
|
+
this.identities.get(record.world)?.delete(record.entity);
|
|
4136
|
+
this.records.delete(id);
|
|
4137
|
+
}
|
|
4138
|
+
}
|
|
4139
|
+
/** Release one producer-owned collection when its render identity is removed. */
|
|
4140
|
+
release(world, entity) {
|
|
4141
|
+
const entities = this.identities.get(world);
|
|
4142
|
+
const collectionId = entities?.get(entity);
|
|
4143
|
+
if (collectionId === void 0) return;
|
|
4144
|
+
entities?.delete(entity);
|
|
4145
|
+
this.records.delete(collectionId);
|
|
4146
|
+
}
|
|
4147
|
+
dispose() {
|
|
4148
|
+
this.records.clear();
|
|
4149
|
+
this.identities = /* @__PURE__ */ new WeakMap();
|
|
4150
|
+
}
|
|
4151
|
+
/**
|
|
4152
|
+
* Return detached residency facts for every live collection.
|
|
4153
|
+
*
|
|
4154
|
+
* @internal Joins CPU projection identity with the active device residency;
|
|
4155
|
+
* callers only receive immutable PODs and never GPU handles.
|
|
4156
|
+
*/
|
|
4157
|
+
_inspections(residency, frameNumber) {
|
|
4158
|
+
return Object.freeze(
|
|
4159
|
+
[...this.records.values()].map(
|
|
4160
|
+
(record) => this.projectInspection(record, residency?.get(record.collectionId), frameNumber)
|
|
4161
|
+
)
|
|
4162
|
+
);
|
|
4163
|
+
}
|
|
4164
|
+
info(record) {
|
|
4165
|
+
return Object.freeze({
|
|
4166
|
+
collectionId: record.collectionId,
|
|
4167
|
+
count: record.count,
|
|
4168
|
+
revision: record.revision
|
|
4169
|
+
});
|
|
4170
|
+
}
|
|
4171
|
+
projectInspection(record, residency, frameNumber) {
|
|
4172
|
+
return Object.freeze({
|
|
4173
|
+
...this.info(record),
|
|
4174
|
+
residentGeneration: residency?.residentGeneration,
|
|
4175
|
+
lane: residency?.lane ?? "unresident",
|
|
4176
|
+
uploadRanges: Object.freeze(
|
|
4177
|
+
residency?.frameNumber === frameNumber ? residency.uploadRanges.map((range) => ({ ...range })) : []
|
|
4178
|
+
),
|
|
4179
|
+
uploadedBytes: residency?.frameNumber === frameNumber ? residency.uploadedBytes : 0,
|
|
4180
|
+
requestedBytes: residency?.requestedBytes ?? record.count * MATRIX_STRIDE * 4,
|
|
4181
|
+
supportedBytes: residency?.supportedBytes,
|
|
4182
|
+
backend: residency?.backend ?? "unknown",
|
|
4183
|
+
owner: "renderer.instances",
|
|
4184
|
+
error: residency?.error
|
|
4185
|
+
});
|
|
4186
|
+
}
|
|
4187
|
+
};
|
|
4188
|
+
function recordInstanceResidency(residency, input) {
|
|
4189
|
+
const previous = residency.get(input.collectionId);
|
|
4190
|
+
const sameFrame = previous !== void 0 && previous.frameNumber === input.frameNumber && previous.error === void 0;
|
|
4191
|
+
const uploadRanges = sameFrame ? [...previous.uploadRanges].reduce(
|
|
4192
|
+
(ranges, range) => {
|
|
4193
|
+
appendRange(ranges, range.start, range.end);
|
|
4194
|
+
return ranges;
|
|
4195
|
+
},
|
|
4196
|
+
input.uploadRanges.map((range) => ({ ...range }))
|
|
4197
|
+
) : input.uploadRanges.map((range) => ({ ...range }));
|
|
4198
|
+
residency.set(input.collectionId, {
|
|
4199
|
+
frameNumber: input.frameNumber,
|
|
4200
|
+
residentGeneration: input.residentGeneration,
|
|
4201
|
+
lane: input.lane,
|
|
4202
|
+
uploadRanges,
|
|
4203
|
+
uploadedBytes: sameFrame ? previous.uploadedBytes + input.uploadedBytes : input.uploadedBytes,
|
|
4204
|
+
requestedBytes: input.requestedBytes,
|
|
4205
|
+
supportedBytes: input.supportedBytes,
|
|
4206
|
+
backend: input.backend,
|
|
4207
|
+
error: void 0
|
|
4208
|
+
});
|
|
4209
|
+
}
|
|
4210
|
+
function recordInstanceFailure(residency, input) {
|
|
4211
|
+
residency.set(input.collectionId, {
|
|
4212
|
+
frameNumber: -1,
|
|
4213
|
+
residentGeneration: void 0,
|
|
4214
|
+
lane: "unavailable",
|
|
4215
|
+
uploadRanges: [],
|
|
4216
|
+
uploadedBytes: 0,
|
|
4217
|
+
requestedBytes: input.facts.requestedBytes,
|
|
4218
|
+
supportedBytes: input.facts.supportedBytes,
|
|
4219
|
+
backend: input.facts.backend,
|
|
4220
|
+
error: {
|
|
4221
|
+
code: input.code,
|
|
4222
|
+
expected: input.expected,
|
|
4223
|
+
hint: input.hint,
|
|
4224
|
+
detail: { ...input.facts }
|
|
4225
|
+
}
|
|
4226
|
+
});
|
|
4227
|
+
}
|
|
4228
|
+
|
|
4094
4229
|
// src/ibl/skylight-bind-group.ts
|
|
4095
4230
|
var FALLBACK_BYTES_PER_ROW = 256;
|
|
4096
4231
|
function assembleMaterialWithSkylightEntries(materialEntries, skylight, transmission, textureInjections = []) {
|
|
@@ -5853,6 +5988,213 @@ function recordGeometryDraws(c, pass, matchedMaterials, materialSlotIndices, sam
|
|
|
5853
5988
|
}
|
|
5854
5989
|
}
|
|
5855
5990
|
}
|
|
5991
|
+
function uploadInstanceRanges(c, inst, buffer, ranges, storageBacked, sourceOffsetInstances = 0) {
|
|
5992
|
+
const strideBytes = (storageBacked ? INSTANCE_STORAGE_STRIDE_FLOATS : 16) * Float32Array.BYTES_PER_ELEMENT;
|
|
5993
|
+
const uploadedRanges = [];
|
|
5994
|
+
let uploadedBytes = 0;
|
|
5995
|
+
for (const range of ranges) {
|
|
5996
|
+
const start = Math.max(0, Math.min(inst.instanceCount, range.start));
|
|
5997
|
+
const end = Math.max(start, Math.min(inst.instanceCount, range.end));
|
|
5998
|
+
if (end <= start) continue;
|
|
5999
|
+
const source = inst.transforms.subarray(
|
|
6000
|
+
(sourceOffsetInstances + start) * 16,
|
|
6001
|
+
(sourceOffsetInstances + end) * 16
|
|
6002
|
+
);
|
|
6003
|
+
const payload = storageBacked ? packInstanceStorageBuffer(source) : source;
|
|
6004
|
+
const written = c.runtime.device.queue.writeBuffer(buffer, start * strideBytes, payload);
|
|
6005
|
+
if (!written.ok) {
|
|
6006
|
+
c.runtime.errorRegistry.fire(written.error);
|
|
6007
|
+
return { ok: false, ranges: uploadedRanges, bytes: uploadedBytes };
|
|
6008
|
+
}
|
|
6009
|
+
uploadedRanges.push({ start, end });
|
|
6010
|
+
uploadedBytes += payload.byteLength;
|
|
6011
|
+
}
|
|
6012
|
+
return { ok: true, ranges: uploadedRanges, bytes: uploadedBytes };
|
|
6013
|
+
}
|
|
6014
|
+
function reportInstanceResidency(c, inst, input) {
|
|
6015
|
+
if (inst.collectionId === void 0 || c.frameState.instanceResidency === void 0) return;
|
|
6016
|
+
recordInstanceResidency(c.frameState.instanceResidency, {
|
|
6017
|
+
collectionId: inst.collectionId,
|
|
6018
|
+
frameNumber: c.frameState.frameNumber,
|
|
6019
|
+
residentGeneration: c.runtime.deviceScope.generation,
|
|
6020
|
+
lane: input.lane,
|
|
6021
|
+
requestedBytes: input.requestedBytes,
|
|
6022
|
+
supportedBytes: input.supportedBytes,
|
|
6023
|
+
uploadRanges: input.uploadRanges,
|
|
6024
|
+
uploadedBytes: input.uploadedBytes,
|
|
6025
|
+
backend: c.runtime.device.caps.backendKind
|
|
6026
|
+
});
|
|
6027
|
+
}
|
|
6028
|
+
function reportInstanceFailure(c, inst, error, requestedBytes, supportedBytes) {
|
|
6029
|
+
if (inst.collectionId === void 0 || c.frameState.instanceResidency === void 0) return;
|
|
6030
|
+
recordInstanceFailure(c.frameState.instanceResidency, {
|
|
6031
|
+
collectionId: inst.collectionId,
|
|
6032
|
+
code: error.code,
|
|
6033
|
+
expected: error.expected,
|
|
6034
|
+
hint: error.hint,
|
|
6035
|
+
facts: {
|
|
6036
|
+
requestedBytes,
|
|
6037
|
+
supportedBytes,
|
|
6038
|
+
backend: c.runtime.device.caps.backendKind,
|
|
6039
|
+
owner: "renderer.instances",
|
|
6040
|
+
cause: error.code,
|
|
6041
|
+
recovery: error.hint
|
|
6042
|
+
}
|
|
6043
|
+
});
|
|
6044
|
+
}
|
|
6045
|
+
function clearInstanceChunksForOwner(c, ownerKey) {
|
|
6046
|
+
const chunks = c.frameState.instanceBufferChunks;
|
|
6047
|
+
if (chunks === void 0) return;
|
|
6048
|
+
const prefix = `${ownerKey}:`;
|
|
6049
|
+
for (const [key, entry] of chunks.entries()) {
|
|
6050
|
+
if (!key.startsWith(prefix)) continue;
|
|
6051
|
+
if (!entry.buffer.isDestroyed) {
|
|
6052
|
+
const destroyed = entry.buffer.destroy();
|
|
6053
|
+
if (!destroyed.ok) c.runtime.errorRegistry.fire(destroyed.error);
|
|
6054
|
+
}
|
|
6055
|
+
chunks.delete(key);
|
|
6056
|
+
}
|
|
6057
|
+
}
|
|
6058
|
+
function resolveStorageInstanceChunks(c, entry, inst, cap, probeBuffer, probeOffset) {
|
|
6059
|
+
const { runtime, frameState } = c;
|
|
6060
|
+
const strideBytes = INSTANCE_STORAGE_STRIDE_FLOATS * Float32Array.BYTES_PER_ELEMENT;
|
|
6061
|
+
const chunkCapacity = Math.floor(cap / strideBytes);
|
|
6062
|
+
if (chunkCapacity < 1) {
|
|
6063
|
+
reportInstanceFailure(
|
|
6064
|
+
c,
|
|
6065
|
+
inst,
|
|
6066
|
+
{
|
|
6067
|
+
code: "limit-exceeded",
|
|
6068
|
+
expected: `maxStorageBufferBindingSize (${cap}) >= ${strideBytes}`,
|
|
6069
|
+
hint: "use a backend with storage-buffer bindings large enough for one InstanceData record"
|
|
6070
|
+
},
|
|
6071
|
+
inst.instanceCount * strideBytes,
|
|
6072
|
+
cap
|
|
6073
|
+
);
|
|
6074
|
+
runtime.errorRegistry.fire(
|
|
6075
|
+
new RhiError({
|
|
6076
|
+
code: "limit-exceeded",
|
|
6077
|
+
expected: `maxStorageBufferBindingSize (${cap}) >= ${strideBytes}`,
|
|
6078
|
+
hint: "use a backend with storage-buffer bindings large enough for one InstanceData record",
|
|
6079
|
+
detail: { maxStorageBufferBindingSize: cap, requestedBytes: strideBytes }
|
|
6080
|
+
})
|
|
6081
|
+
);
|
|
6082
|
+
return null;
|
|
6083
|
+
}
|
|
6084
|
+
const ownerKey = instanceCollectionCacheKey(entry.source.worldId, inst);
|
|
6085
|
+
const chunks = frameState.instanceBufferChunks;
|
|
6086
|
+
const activeKeys = /* @__PURE__ */ new Set();
|
|
6087
|
+
const draws = [];
|
|
6088
|
+
const uploadedRanges = [];
|
|
6089
|
+
let uploadedBytes = 0;
|
|
6090
|
+
for (let start = 0; start < inst.instanceCount; start += chunkCapacity) {
|
|
6091
|
+
const end = Math.min(inst.instanceCount, start + chunkCapacity);
|
|
6092
|
+
const count = end - start;
|
|
6093
|
+
const chunkKey = `${ownerKey}:${start}`;
|
|
6094
|
+
activeKeys.add(chunkKey);
|
|
6095
|
+
const payloadBytes = count * strideBytes;
|
|
6096
|
+
const previous = chunks?.get(chunkKey);
|
|
6097
|
+
let active = previous !== void 0 && previous.uploadedArchVersion === inst.archVersion && previous.uploadedByteLength === payloadBytes ? previous : void 0;
|
|
6098
|
+
let activeIsNew = false;
|
|
6099
|
+
if (active === void 0) {
|
|
6100
|
+
const created = runtime.device.createBuffer({
|
|
6101
|
+
size: payloadBytes,
|
|
6102
|
+
usage: GPU_BUFFER_USAGE_STORAGE | GPU_BUFFER_USAGE_COPY_DST,
|
|
6103
|
+
mappedAtCreation: false
|
|
6104
|
+
});
|
|
6105
|
+
if (!created.ok) {
|
|
6106
|
+
runtime.errorRegistry.fire(created.error);
|
|
6107
|
+
reportInstanceFailure(c, inst, created.error, inst.instanceCount * strideBytes, cap);
|
|
6108
|
+
return null;
|
|
6109
|
+
}
|
|
6110
|
+
if (previous !== void 0 && !previous.buffer.isDestroyed) {
|
|
6111
|
+
const destroyed = previous.buffer.destroy();
|
|
6112
|
+
if (!destroyed.ok) runtime.errorRegistry.fire(destroyed.error);
|
|
6113
|
+
}
|
|
6114
|
+
active = {
|
|
6115
|
+
buffer: new GpuBuffer(runtime.device, created.value),
|
|
6116
|
+
uploadedArchVersion: inst.archVersion,
|
|
6117
|
+
uploadedByteLength: payloadBytes
|
|
6118
|
+
};
|
|
6119
|
+
activeIsNew = true;
|
|
6120
|
+
chunks?.set(chunkKey, active);
|
|
6121
|
+
if (chunks === void 0) frameState.transientInstanceBuffers.push(active);
|
|
6122
|
+
}
|
|
6123
|
+
if (active === void 0) return null;
|
|
6124
|
+
const needsUpload = activeIsNew || active.uploadedRevision !== (inst.revision ?? inst.archVersion);
|
|
6125
|
+
const rangesToUpload = [
|
|
6126
|
+
{
|
|
6127
|
+
start: 0,
|
|
6128
|
+
end: count
|
|
6129
|
+
}
|
|
6130
|
+
];
|
|
6131
|
+
if (needsUpload && rangesToUpload.length > 0) {
|
|
6132
|
+
const upload = uploadInstanceRanges(
|
|
6133
|
+
c,
|
|
6134
|
+
inst,
|
|
6135
|
+
active.buffer.handle,
|
|
6136
|
+
rangesToUpload,
|
|
6137
|
+
true,
|
|
6138
|
+
start
|
|
6139
|
+
);
|
|
6140
|
+
for (const range of upload.ranges) {
|
|
6141
|
+
uploadedRanges.push({ start: range.start + start, end: range.end + start });
|
|
6142
|
+
}
|
|
6143
|
+
uploadedBytes += upload.bytes;
|
|
6144
|
+
if (!upload.ok) {
|
|
6145
|
+
reportInstanceFailure(
|
|
6146
|
+
c,
|
|
6147
|
+
inst,
|
|
6148
|
+
{
|
|
6149
|
+
code: "queue-write-buffer-failed",
|
|
6150
|
+
expected: "the renderer-owned instance storage buffer accepts the complete instance payload",
|
|
6151
|
+
hint: "retry after the active device is healthy or recover the renderer"
|
|
6152
|
+
},
|
|
6153
|
+
inst.instanceCount * strideBytes,
|
|
6154
|
+
cap
|
|
6155
|
+
);
|
|
6156
|
+
return null;
|
|
6157
|
+
}
|
|
6158
|
+
}
|
|
6159
|
+
if (needsUpload) {
|
|
6160
|
+
{
|
|
6161
|
+
const published = { ...active, uploadedRevision: inst.revision ?? inst.archVersion };
|
|
6162
|
+
active = published;
|
|
6163
|
+
chunks?.set(chunkKey, published);
|
|
6164
|
+
}
|
|
6165
|
+
}
|
|
6166
|
+
const activeBuffer = active;
|
|
6167
|
+
draws.push({
|
|
6168
|
+
instanceBuffer: activeBuffer.buffer.handle,
|
|
6169
|
+
instanceBindGroup: resolveGeometryInstancesBindGroup(
|
|
6170
|
+
c,
|
|
6171
|
+
activeBuffer.buffer.handle,
|
|
6172
|
+
probeBuffer
|
|
6173
|
+
),
|
|
6174
|
+
probeOffset,
|
|
6175
|
+
instanceCount: count
|
|
6176
|
+
});
|
|
6177
|
+
}
|
|
6178
|
+
if (chunks !== void 0) {
|
|
6179
|
+
const prefix = `${ownerKey}:`;
|
|
6180
|
+
for (const [key, stale] of chunks.entries()) {
|
|
6181
|
+
if (!key.startsWith(prefix) || activeKeys.has(key)) continue;
|
|
6182
|
+
if (!stale.buffer.isDestroyed) {
|
|
6183
|
+
const destroyed = stale.buffer.destroy();
|
|
6184
|
+
if (!destroyed.ok) runtime.errorRegistry.fire(destroyed.error);
|
|
6185
|
+
}
|
|
6186
|
+
chunks.delete(key);
|
|
6187
|
+
}
|
|
6188
|
+
}
|
|
6189
|
+
reportInstanceResidency(c, inst, {
|
|
6190
|
+
lane: "chunked-storage",
|
|
6191
|
+
requestedBytes: inst.instanceCount * strideBytes,
|
|
6192
|
+
supportedBytes: cap,
|
|
6193
|
+
uploadRanges: uploadedRanges,
|
|
6194
|
+
uploadedBytes
|
|
6195
|
+
});
|
|
6196
|
+
return draws;
|
|
6197
|
+
}
|
|
5856
6198
|
function resolveGeometryInstanceBuffer(c, entry, identityInstanceDraws, useProbeBlend) {
|
|
5857
6199
|
const { runtime, pipelineState, frameState } = c;
|
|
5858
6200
|
const inst = entry.source.instances;
|
|
@@ -5877,74 +6219,152 @@ function resolveGeometryInstanceBuffer(c, entry, identityInstanceDraws, useProbe
|
|
|
5877
6219
|
];
|
|
5878
6220
|
}
|
|
5879
6221
|
if (inst.instanceCount === 0) return [];
|
|
6222
|
+
const entityCacheKey = instanceCollectionCacheKey(entry.source.worldId, inst);
|
|
6223
|
+
const revision = inst.revision ?? inst.archVersion;
|
|
6224
|
+
const sameRevision = (cached) => cached.uploadedRevision === revision;
|
|
6225
|
+
const fullRange = [{ start: 0, end: inst.instanceCount }];
|
|
5880
6226
|
let instanceBuffer = pipelineState.identityInstanceBuffer;
|
|
5881
6227
|
let instanceCount = 1;
|
|
5882
6228
|
{
|
|
5883
6229
|
const uniformFallback = runtime.device.caps.storageBuffer === false;
|
|
5884
6230
|
let instanceBufferUsage = GPU_BUFFER_USAGE_STORAGE | GPU_BUFFER_USAGE_COPY_DST;
|
|
5885
6231
|
if (uniformFallback && inst.instanceCount > MAX_UNIFORM_INSTANCES) {
|
|
6232
|
+
const ownerKey = instanceCollectionCacheKey(entry.source.worldId, inst);
|
|
6233
|
+
const chunks = frameState.instanceBufferChunks;
|
|
6234
|
+
const activeKeys = /* @__PURE__ */ new Set();
|
|
5886
6235
|
const draws = [];
|
|
6236
|
+
const uniformStrideBytes = 16 * Float32Array.BYTES_PER_ELEMENT;
|
|
6237
|
+
const uploadedRanges = [];
|
|
6238
|
+
let uploadedBytes = 0;
|
|
5887
6239
|
for (let start = 0; start < inst.instanceCount; start += MAX_UNIFORM_INSTANCES) {
|
|
5888
6240
|
const count = Math.min(MAX_UNIFORM_INSTANCES, inst.instanceCount - start);
|
|
5889
|
-
const
|
|
5890
|
-
|
|
5891
|
-
|
|
5892
|
-
|
|
5893
|
-
|
|
5894
|
-
|
|
5895
|
-
if (
|
|
5896
|
-
runtime.
|
|
5897
|
-
|
|
6241
|
+
const chunkKey = `${ownerKey}:${start}`;
|
|
6242
|
+
activeKeys.add(chunkKey);
|
|
6243
|
+
const payloadBytes = count * uniformStrideBytes;
|
|
6244
|
+
const previous = chunks?.get(chunkKey);
|
|
6245
|
+
let active = previous !== void 0 && previous.uploadedArchVersion === inst.archVersion && previous.uploadedByteLength === payloadBytes ? previous : void 0;
|
|
6246
|
+
let activeIsNew = false;
|
|
6247
|
+
if (active === void 0) {
|
|
6248
|
+
const created = runtime.device.createBuffer({
|
|
6249
|
+
size: INSTANCE_UBO_FULL_ARRAY_BYTES,
|
|
6250
|
+
usage: GPU_BUFFER_USAGE_UNIFORM | GPU_BUFFER_USAGE_COPY_DST,
|
|
6251
|
+
mappedAtCreation: false
|
|
6252
|
+
});
|
|
6253
|
+
if (!created.ok) {
|
|
6254
|
+
runtime.errorRegistry.fire(created.error);
|
|
6255
|
+
reportInstanceFailure(
|
|
6256
|
+
c,
|
|
6257
|
+
inst,
|
|
6258
|
+
created.error,
|
|
6259
|
+
inst.instanceCount * uniformStrideBytes,
|
|
6260
|
+
MAX_UNIFORM_INSTANCES * uniformStrideBytes
|
|
6261
|
+
);
|
|
6262
|
+
return null;
|
|
6263
|
+
}
|
|
6264
|
+
if (previous !== void 0 && !previous.buffer.isDestroyed) {
|
|
6265
|
+
const destroyed = previous.buffer.destroy();
|
|
6266
|
+
if (!destroyed.ok) runtime.errorRegistry.fire(destroyed.error);
|
|
6267
|
+
}
|
|
6268
|
+
active = {
|
|
6269
|
+
buffer: new GpuBuffer(runtime.device, created.value),
|
|
6270
|
+
uploadedArchVersion: inst.archVersion,
|
|
6271
|
+
uploadedByteLength: payloadBytes
|
|
6272
|
+
};
|
|
6273
|
+
activeIsNew = true;
|
|
6274
|
+
chunks?.set(chunkKey, active);
|
|
6275
|
+
if (chunks === void 0) frameState.transientInstanceBuffers.push(active);
|
|
5898
6276
|
}
|
|
5899
|
-
const
|
|
5900
|
-
|
|
5901
|
-
|
|
5902
|
-
|
|
5903
|
-
|
|
5904
|
-
|
|
5905
|
-
|
|
5906
|
-
if (
|
|
5907
|
-
|
|
5908
|
-
|
|
6277
|
+
const needsUpload = activeIsNew || !sameRevision(active);
|
|
6278
|
+
const rangesToUpload = [
|
|
6279
|
+
{
|
|
6280
|
+
start: 0,
|
|
6281
|
+
end: count
|
|
6282
|
+
}
|
|
6283
|
+
];
|
|
6284
|
+
if (needsUpload && rangesToUpload.length > 0) {
|
|
6285
|
+
const upload = uploadInstanceRanges(
|
|
6286
|
+
c,
|
|
6287
|
+
inst,
|
|
6288
|
+
active.buffer.handle,
|
|
6289
|
+
rangesToUpload,
|
|
6290
|
+
false,
|
|
6291
|
+
start
|
|
6292
|
+
);
|
|
6293
|
+
for (const range of upload.ranges) {
|
|
6294
|
+
uploadedRanges.push({ start: range.start + start, end: range.end + start });
|
|
6295
|
+
}
|
|
6296
|
+
uploadedBytes += upload.bytes;
|
|
6297
|
+
if (!upload.ok) {
|
|
6298
|
+
reportInstanceFailure(
|
|
6299
|
+
c,
|
|
6300
|
+
inst,
|
|
6301
|
+
{
|
|
6302
|
+
code: "queue-write-buffer-failed",
|
|
6303
|
+
expected: "the renderer-owned instance uniform buffer accepts the complete instance payload",
|
|
6304
|
+
hint: "retry after the active device is healthy or recover the renderer"
|
|
6305
|
+
},
|
|
6306
|
+
inst.instanceCount * uniformStrideBytes,
|
|
6307
|
+
MAX_UNIFORM_INSTANCES * uniformStrideBytes
|
|
6308
|
+
);
|
|
6309
|
+
return null;
|
|
6310
|
+
}
|
|
6311
|
+
}
|
|
6312
|
+
if (needsUpload) {
|
|
6313
|
+
const published = { ...active, uploadedRevision: revision };
|
|
6314
|
+
active = published;
|
|
6315
|
+
chunks?.set(chunkKey, published);
|
|
5909
6316
|
}
|
|
5910
6317
|
draws.push({
|
|
5911
|
-
instanceBuffer: buffer.handle,
|
|
6318
|
+
instanceBuffer: active.buffer.handle,
|
|
5912
6319
|
instanceBindGroup: resolveGeometryInstancesBindGroup(
|
|
5913
6320
|
c,
|
|
5914
|
-
buffer.handle,
|
|
6321
|
+
active.buffer.handle,
|
|
5915
6322
|
probeBinding?.buffer
|
|
5916
6323
|
),
|
|
5917
6324
|
probeOffset: probeBinding?.offset ?? -1,
|
|
5918
6325
|
instanceCount: count
|
|
5919
6326
|
});
|
|
5920
6327
|
}
|
|
6328
|
+
if (chunks !== void 0) {
|
|
6329
|
+
const prefix = `${ownerKey}:`;
|
|
6330
|
+
for (const [key, stale] of chunks.entries()) {
|
|
6331
|
+
if (!key.startsWith(prefix) || activeKeys.has(key)) continue;
|
|
6332
|
+
if (!stale.buffer.isDestroyed) {
|
|
6333
|
+
const destroyed = stale.buffer.destroy();
|
|
6334
|
+
if (!destroyed.ok) runtime.errorRegistry.fire(destroyed.error);
|
|
6335
|
+
}
|
|
6336
|
+
chunks.delete(key);
|
|
6337
|
+
}
|
|
6338
|
+
}
|
|
6339
|
+
reportInstanceResidency(c, inst, {
|
|
6340
|
+
lane: "chunked-uniform",
|
|
6341
|
+
requestedBytes: inst.instanceCount * uniformStrideBytes,
|
|
6342
|
+
supportedBytes: MAX_UNIFORM_INSTANCES * uniformStrideBytes,
|
|
6343
|
+
uploadRanges: uploadedRanges,
|
|
6344
|
+
uploadedBytes
|
|
6345
|
+
});
|
|
5921
6346
|
return draws;
|
|
5922
6347
|
}
|
|
5923
6348
|
if (uniformFallback) {
|
|
5924
6349
|
instanceBufferUsage = GPU_BUFFER_USAGE_UNIFORM | GPU_BUFFER_USAGE_COPY_DST;
|
|
5925
6350
|
}
|
|
5926
6351
|
{
|
|
5927
|
-
const
|
|
5928
|
-
const requestedBytes = instancePayload.byteLength;
|
|
6352
|
+
const requestedBytes = inst.instanceCount * (uniformFallback ? 16 : INSTANCE_STORAGE_STRIDE_FLOATS) * Float32Array.BYTES_PER_ELEMENT;
|
|
5929
6353
|
const cap = runtime.device.limits.maxStorageBufferBindingSize;
|
|
5930
6354
|
if (!uniformFallback && typeof cap === "number" && cap > 0 && requestedBytes > cap) {
|
|
5931
|
-
|
|
5932
|
-
|
|
5933
|
-
|
|
5934
|
-
|
|
5935
|
-
|
|
5936
|
-
|
|
5937
|
-
|
|
5938
|
-
requestedBytes
|
|
5939
|
-
}
|
|
5940
|
-
})
|
|
6355
|
+
const chunked = resolveStorageInstanceChunks(
|
|
6356
|
+
c,
|
|
6357
|
+
entry,
|
|
6358
|
+
inst,
|
|
6359
|
+
cap,
|
|
6360
|
+
probeBinding?.buffer,
|
|
6361
|
+
probeBinding?.offset ?? -1
|
|
5941
6362
|
);
|
|
5942
|
-
return
|
|
6363
|
+
return chunked;
|
|
5943
6364
|
} else {
|
|
5944
|
-
const cached = frameState.instanceBuffers.get(
|
|
5945
|
-
worldEntityKey(entry.source.worldId, inst.cacheKey)
|
|
5946
|
-
);
|
|
6365
|
+
const cached = frameState.instanceBuffers.get(entityCacheKey);
|
|
5947
6366
|
let active = null;
|
|
6367
|
+
let activeIsNew = false;
|
|
5948
6368
|
if (cached !== void 0 && cached.uploadedArchVersion === inst.archVersion && cached.uploadedByteLength === requestedBytes) {
|
|
5949
6369
|
active = cached;
|
|
5950
6370
|
} else if (requestedBytes > 0) {
|
|
@@ -5955,6 +6375,8 @@ function resolveGeometryInstanceBuffer(c, entry, identityInstanceDraws, useProbe
|
|
|
5955
6375
|
});
|
|
5956
6376
|
if (!bufRes.ok) {
|
|
5957
6377
|
runtime.errorRegistry.fire(bufRes.error);
|
|
6378
|
+
reportInstanceFailure(c, inst, bufRes.error, requestedBytes, cap);
|
|
6379
|
+
return null;
|
|
5958
6380
|
} else {
|
|
5959
6381
|
if (cached !== void 0 && !cached.buffer.isDestroyed) {
|
|
5960
6382
|
const r = cached.buffer.destroy();
|
|
@@ -5966,24 +6388,57 @@ function resolveGeometryInstanceBuffer(c, entry, identityInstanceDraws, useProbe
|
|
|
5966
6388
|
uploadedArchVersion: inst.archVersion,
|
|
5967
6389
|
uploadedByteLength: requestedBytes
|
|
5968
6390
|
};
|
|
5969
|
-
|
|
5970
|
-
|
|
5971
|
-
active
|
|
5972
|
-
|
|
6391
|
+
activeIsNew = true;
|
|
6392
|
+
if (active !== null) {
|
|
6393
|
+
frameState.instanceBuffers.set(entityCacheKey, active);
|
|
6394
|
+
}
|
|
5973
6395
|
}
|
|
5974
6396
|
}
|
|
5975
6397
|
if (active !== null) {
|
|
5976
|
-
const
|
|
5977
|
-
|
|
5978
|
-
|
|
5979
|
-
|
|
5980
|
-
)
|
|
5981
|
-
|
|
5982
|
-
|
|
5983
|
-
|
|
5984
|
-
|
|
5985
|
-
|
|
6398
|
+
const needsUpload = activeIsNew || !sameRevision(active);
|
|
6399
|
+
const ranges = [fullRange[0]];
|
|
6400
|
+
let uploadRanges = [];
|
|
6401
|
+
let uploadedBytes = 0;
|
|
6402
|
+
if (needsUpload && ranges.length > 0) {
|
|
6403
|
+
const upload = uploadInstanceRanges(
|
|
6404
|
+
c,
|
|
6405
|
+
inst,
|
|
6406
|
+
active.buffer.handle,
|
|
6407
|
+
ranges,
|
|
6408
|
+
!uniformFallback
|
|
6409
|
+
);
|
|
6410
|
+
uploadRanges = upload.ranges;
|
|
6411
|
+
uploadedBytes = upload.bytes;
|
|
6412
|
+
if (!upload.ok) {
|
|
6413
|
+
reportInstanceFailure(
|
|
6414
|
+
c,
|
|
6415
|
+
inst,
|
|
6416
|
+
{
|
|
6417
|
+
code: "queue-write-buffer-failed",
|
|
6418
|
+
expected: "the renderer-owned instance buffer accepts the complete instance payloads",
|
|
6419
|
+
hint: "retry after the active device is healthy or recover the renderer"
|
|
6420
|
+
},
|
|
6421
|
+
requestedBytes,
|
|
6422
|
+
uniformFallback ? MAX_UNIFORM_INSTANCES * Float32Array.BYTES_PER_ELEMENT * 16 : typeof cap === "number" ? cap : void 0
|
|
6423
|
+
);
|
|
6424
|
+
return null;
|
|
6425
|
+
}
|
|
6426
|
+
}
|
|
6427
|
+
if (needsUpload) {
|
|
6428
|
+
const published = { ...active, uploadedRevision: revision };
|
|
6429
|
+
frameState.instanceBuffers.set(entityCacheKey, published);
|
|
6430
|
+
active = published;
|
|
5986
6431
|
}
|
|
6432
|
+
instanceBuffer = active.buffer.handle;
|
|
6433
|
+
instanceCount = Math.max(1, inst.instanceCount);
|
|
6434
|
+
reportInstanceResidency(c, inst, {
|
|
6435
|
+
lane: uniformFallback ? "direct-uniform" : "direct-storage",
|
|
6436
|
+
requestedBytes,
|
|
6437
|
+
supportedBytes: uniformFallback ? MAX_UNIFORM_INSTANCES * Float32Array.BYTES_PER_ELEMENT * 16 : typeof cap === "number" ? cap : void 0,
|
|
6438
|
+
uploadRanges,
|
|
6439
|
+
uploadedBytes
|
|
6440
|
+
});
|
|
6441
|
+
clearInstanceChunksForOwner(c, entityCacheKey);
|
|
5987
6442
|
}
|
|
5988
6443
|
}
|
|
5989
6444
|
}
|
|
@@ -6521,7 +6976,7 @@ function recordSpriteEntityDraws(c, spritePass, matchedIndices, skylightResource
|
|
|
6521
6976
|
new RhiError({
|
|
6522
6977
|
code: "limit-exceeded",
|
|
6523
6978
|
expected: `requestedBytes (${requestedBytes}) <= maxStorageBufferBindingSize (${cap})`,
|
|
6524
|
-
hint: "reduce
|
|
6979
|
+
hint: "reduce the sprite batch to fit within device.limits.maxStorageBufferBindingSize or use a storage-capable backend",
|
|
6525
6980
|
detail: {
|
|
6526
6981
|
maxStorageBufferBindingSize: cap,
|
|
6527
6982
|
requestedBytes
|
|
@@ -6898,9 +7353,16 @@ function shadowShaderMap(c) {
|
|
|
6898
7353
|
byMaterial = /* @__PURE__ */ new Map();
|
|
6899
7354
|
shaders.set(entry.renderableIndex, byMaterial);
|
|
6900
7355
|
}
|
|
7356
|
+
const candidateSlots = c.materialSlotIndices[entry.renderableIndex] ?? c.materialSlotIndices.flat();
|
|
7357
|
+
const materialSlot = candidateSlots.find(
|
|
7358
|
+
(slot) => c.materialSlots[slot]?.materialHandle === entry.materialHandle
|
|
7359
|
+
);
|
|
6901
7360
|
byMaterial.set(entry.materialHandle, {
|
|
6902
|
-
|
|
6903
|
-
|
|
7361
|
+
materialHandle: entry.materialHandle,
|
|
7362
|
+
materialShaderId: entry.materialShaderId === "forgeax::default-standard-pbr" ? SHADOW_CASTER_SHADER_ID : entry.materialShaderId,
|
|
7363
|
+
renderState: entry.renderState,
|
|
7364
|
+
materialSlot,
|
|
7365
|
+
paramSnapshot: entry.paramSnapshot
|
|
6904
7366
|
});
|
|
6905
7367
|
}
|
|
6906
7368
|
}
|
|
@@ -7131,67 +7593,23 @@ function recordShadowCasterDraws(c, shadowPass, shadowPipeline2, shadowMeshBindG
|
|
|
7131
7593
|
} else {
|
|
7132
7594
|
shadowPass.setBindGroup(2, shadowMeshBindGroup, [i * MESH_PER_ENTITY_STRIDE]);
|
|
7133
7595
|
}
|
|
7134
|
-
|
|
7135
|
-
|
|
7136
|
-
|
|
7137
|
-
|
|
7138
|
-
|
|
7139
|
-
|
|
7140
|
-
|
|
7141
|
-
|
|
7142
|
-
|
|
7143
|
-
|
|
7144
|
-
|
|
7145
|
-
|
|
7146
|
-
const requestedBytes = instancePayload.byteLength;
|
|
7147
|
-
const cached = c.frameState.instanceBuffers.get(
|
|
7148
|
-
worldEntityKey(entry.source.worldId, shadowInst.cacheKey)
|
|
7149
|
-
);
|
|
7150
|
-
let active = null;
|
|
7151
|
-
if (cached !== void 0 && cached.uploadedArchVersion === shadowInst.archVersion && cached.uploadedByteLength === requestedBytes) {
|
|
7152
|
-
active = cached;
|
|
7153
|
-
} else if (requestedBytes > 0) {
|
|
7154
|
-
const bufRes = runtime.device.createBuffer({
|
|
7155
|
-
size: requestedBytes,
|
|
7156
|
-
usage: bufUsage,
|
|
7157
|
-
mappedAtCreation: false
|
|
7158
|
-
});
|
|
7159
|
-
if (!bufRes.ok) {
|
|
7160
|
-
runtime.errorRegistry.fire(bufRes.error);
|
|
7161
|
-
} else {
|
|
7162
|
-
if (cached !== void 0 && !cached.buffer.isDestroyed) {
|
|
7163
|
-
const r = cached.buffer.destroy();
|
|
7164
|
-
if (!r.ok) runtime.errorRegistry.fire(r.error);
|
|
7165
|
-
}
|
|
7166
|
-
const newBuffer = new GpuBuffer(runtime.device, bufRes.value);
|
|
7167
|
-
active = {
|
|
7168
|
-
buffer: newBuffer,
|
|
7169
|
-
uploadedArchVersion: shadowInst.archVersion,
|
|
7170
|
-
uploadedByteLength: requestedBytes
|
|
7171
|
-
};
|
|
7172
|
-
c.frameState.instanceBuffers.set(
|
|
7173
|
-
worldEntityKey(entry.source.worldId, shadowInst.cacheKey),
|
|
7174
|
-
active
|
|
7175
|
-
);
|
|
7176
|
-
}
|
|
7177
|
-
}
|
|
7178
|
-
if (active !== null) {
|
|
7179
|
-
const writeRes = runtime.device.queue.writeBuffer(
|
|
7180
|
-
active.buffer.handle,
|
|
7181
|
-
0,
|
|
7182
|
-
instancePayload
|
|
7183
|
-
);
|
|
7184
|
-
if (!writeRes.ok) {
|
|
7185
|
-
runtime.errorRegistry.fire(writeRes.error);
|
|
7186
|
-
} else {
|
|
7187
|
-
shadowInstanceBuffer = active.buffer.handle;
|
|
7188
|
-
shadowInstanceCount = Math.max(1, shadowInst.instanceCount);
|
|
7189
|
-
}
|
|
7596
|
+
const shadowInstanceDraws = resolveGeometryInstanceBuffer(
|
|
7597
|
+
c,
|
|
7598
|
+
entry,
|
|
7599
|
+
[
|
|
7600
|
+
{
|
|
7601
|
+
instanceBuffer: pipelineState.identityInstanceBuffer,
|
|
7602
|
+
instanceBindGroup: resolveGeometryInstancesBindGroup(
|
|
7603
|
+
c,
|
|
7604
|
+
pipelineState.identityInstanceBuffer
|
|
7605
|
+
),
|
|
7606
|
+
instanceCount: 1,
|
|
7607
|
+
probeOffset: -1
|
|
7190
7608
|
}
|
|
7191
|
-
|
|
7192
|
-
|
|
7193
|
-
|
|
7194
|
-
|
|
7609
|
+
],
|
|
7610
|
+
false
|
|
7611
|
+
);
|
|
7612
|
+
if (shadowInstanceDraws === null) continue;
|
|
7195
7613
|
for (const sm of shadowSubmeshes) {
|
|
7196
7614
|
if (sm.topology !== "triangle-list" && sm.topology !== "triangle-strip") {
|
|
7197
7615
|
continue;
|
|
@@ -7221,10 +7639,13 @@ function recordShadowCasterDraws(c, shadowPass, shadowPipeline2, shadowMeshBindG
|
|
|
7221
7639
|
shadowPass.setPipeline(entryShadowPipeline);
|
|
7222
7640
|
shadowLastPipeline = entryShadowPipeline;
|
|
7223
7641
|
}
|
|
7224
|
-
|
|
7225
|
-
shadowPass.
|
|
7226
|
-
|
|
7227
|
-
|
|
7642
|
+
for (const instanceDraw of shadowInstanceDraws) {
|
|
7643
|
+
shadowPass.setBindGroup(3, instanceDraw.instanceBindGroup);
|
|
7644
|
+
if (entry.mesh.indexed) {
|
|
7645
|
+
shadowPass.drawIndexed(sm.indexCount, instanceDraw.instanceCount, sm.indexOffset, 0, 0);
|
|
7646
|
+
} else {
|
|
7647
|
+
shadowPass.draw(sm.vertexCount, instanceDraw.instanceCount, 0, 0);
|
|
7648
|
+
}
|
|
7228
7649
|
}
|
|
7229
7650
|
}
|
|
7230
7651
|
}
|
|
@@ -9562,6 +9983,6 @@ function addTaaResolvePass(graph, current, currentTemporal, previousColor, previ
|
|
|
9562
9983
|
});
|
|
9563
9984
|
}
|
|
9564
9985
|
|
|
9565
|
-
export { BYTES_PER_DIRECT_LIGHT_SLOT, CAPTURE_VIEW_PROJS, CUBEMAP_FACE_VERTICES, CUBE_CAPTURE_VIEW_SLOT_BASE, DEFERRED_COLOR_FORMATS, DEPTH_MIN_PARAMS_BYTE_SIZE, FALLBACK_BYTES_PER_ROW, GpuBuffer, GpuTexture, MATERIAL_PER_ENTITY_STRIDE, MESH_SSBO_BYTES, POINTS_LINES_MATERIAL_SHADER_ID, POINTS_LINES_VIEW_BUFFER_SIZE, PREFILTER_MIP_LEVELS, PREFILTER_SIZE, PipelineSpecError, PostProcessError, REFLECTION_PROBE_VIEW_SLOT_BASE, SHADOW_CASTER_BUFFER_SIZE, TYPED_BLOOM_PASS_NAMES, VIEW_UNIFORM_BUFFER_SIZE, VIEW_UNIFORM_BYTES, VIEW_UNIFORM_SLOT_STRIDE, abortTemporalGpuSubmit, addReflectionFallbackObservationPass, addStandardSceneDataPass, addTaaResolvePass, addTypedBloomPasses, addTypedCompositePostEffects, addTypedFrameObservationPass, addTypedFullscreenPass, addTypedOutputTransformPass, addTypedScenePass, addTypedSkyboxPass, addTypedSsaoPasses, addTypedTemporalResolvePass, aggregateTemporalDemand, applyParamSnapshotToUbo, assembleMaterialWithSkylightEntries, assertStorageBufferCap, buildFoldDispatchPlan, buildFullscreenPostProcessPass, buildLinearLdrMaterialSpecTable, buildPerFrameBindGroups, buildSpecConstTable, cacheKeyOf, cleanPerEntityCache, colorFormatsForPassKind, commitTemporalGpuSubmit, computeProjectionMatrix, computeSplitLdrSprite, computeViewMatrix, configureSurface, createClusterBinScratch, createFullscreenBindGroup, createHdrpClusterMembershipBindGroupLayoutDescriptor, createIblPipelines, createPointsLinesLaneAdapter, createPointsLinesLaneContract, createRenderPipelineTarget, createSkylightFallback, createStandardSceneDataTarget, deriveRenderDataCubemap, deriveRenderDataMesh, deriveRenderDataTexture, describeTemporalDemand, driveLazyEquirectProjection, encodeDirectionalShadowPass, encodeMainPass, encodePointShadowPass, encodeSpotShadowPass, ensureMeshSsboCapacity, entryHasDepthRead, evaluateFoldBucketUniformCap, foldDispatchBuckets, geometryRenderStateForPass, geometryRenderStateForTopology, getOrBuildPipeline, getOrCreateHdrpBuffers, getOrCreateIblCache, getTemporalBindGroupResources, getTemporalGpuState, getTemporalParamsBuffer, hasPendingTemporalGpuSubmit, importRenderPipelineSurface, incrementFoldedDrawsMetric, isTemporalFullscreenBinding, passKindPolicyTable, postProcessShaderEntrySignature, postProcessShaderModuleLabel, postProcessShaderPipelineLabel, prepareFrameLighting, resetHdrpBuffers, residentTextureView, resolveOutputDither, resolveSkyboxActive, resolveSsaoParameters, resolveSurfaceFormatPair, resolveSurfaceProfile, retireTemporalGpuState, retireTemporalGpuStateAfterFence, runIblPrecompute, selectLazyEquirectHandle, selectSwapChainFormat, setIblComposedShaders, standardStorageVariantSet, standardTemporalLaneAdmission, standardTemporalPostOrder, standardTopologyVariantSet, temporalReadIndex, temporalWriteIndex, typedFrameClearColor, uploadMeshSsboBatch, variantSetFromDefines, variantSetFromVertexLayoutProjection, warnMultiSkybox, warnMultiSkylight, warnZeroLightStandard, writeHdrpClusterAndSsaoBuffers, writePointsLinesViewUbo, writeShadowCasterUniforms, writeShadowParamsBuffer, writeSpotModifierTextures, writeViewUbo };
|
|
9566
|
-
//# sourceMappingURL=chunk-
|
|
9567
|
-
//# sourceMappingURL=chunk-
|
|
9986
|
+
export { BYTES_PER_DIRECT_LIGHT_SLOT, CAPTURE_VIEW_PROJS, CUBEMAP_FACE_VERTICES, CUBE_CAPTURE_VIEW_SLOT_BASE, DEFERRED_COLOR_FORMATS, DEPTH_MIN_PARAMS_BYTE_SIZE, FALLBACK_BYTES_PER_ROW, GpuBuffer, GpuTexture, InstanceProjectionStore, MATERIAL_PER_ENTITY_STRIDE, MESH_SSBO_BYTES, POINTS_LINES_MATERIAL_SHADER_ID, POINTS_LINES_VIEW_BUFFER_SIZE, PREFILTER_MIP_LEVELS, PREFILTER_SIZE, PipelineSpecError, PostProcessError, REFLECTION_PROBE_VIEW_SLOT_BASE, SHADOW_CASTER_BUFFER_SIZE, TYPED_BLOOM_PASS_NAMES, VIEW_UNIFORM_BUFFER_SIZE, VIEW_UNIFORM_BYTES, VIEW_UNIFORM_SLOT_STRIDE, abortTemporalGpuSubmit, addReflectionFallbackObservationPass, addStandardSceneDataPass, addTaaResolvePass, addTypedBloomPasses, addTypedCompositePostEffects, addTypedFrameObservationPass, addTypedFullscreenPass, addTypedOutputTransformPass, addTypedScenePass, addTypedSkyboxPass, addTypedSsaoPasses, addTypedTemporalResolvePass, aggregateTemporalDemand, applyParamSnapshotToUbo, assembleMaterialWithSkylightEntries, assertStorageBufferCap, buildFoldDispatchPlan, buildFullscreenPostProcessPass, buildLinearLdrMaterialSpecTable, buildPerFrameBindGroups, buildSpecConstTable, cacheKeyOf, cleanPerEntityCache, colorFormatsForPassKind, commitTemporalGpuSubmit, computeProjectionMatrix, computeSplitLdrSprite, computeViewMatrix, configureSurface, createClusterBinScratch, createFullscreenBindGroup, createHdrpClusterMembershipBindGroupLayoutDescriptor, createIblPipelines, createPointsLinesLaneAdapter, createPointsLinesLaneContract, createRenderPipelineTarget, createSkylightFallback, createStandardSceneDataTarget, deriveRenderDataCubemap, deriveRenderDataMesh, deriveRenderDataTexture, describeTemporalDemand, driveLazyEquirectProjection, encodeDirectionalShadowPass, encodeMainPass, encodePointShadowPass, encodeSpotShadowPass, ensureMeshSsboCapacity, entryHasDepthRead, evaluateFoldBucketUniformCap, foldDispatchBuckets, geometryRenderStateForPass, geometryRenderStateForTopology, getOrBuildPipeline, getOrCreateHdrpBuffers, getOrCreateIblCache, getTemporalBindGroupResources, getTemporalGpuState, getTemporalParamsBuffer, hasPendingTemporalGpuSubmit, importRenderPipelineSurface, incrementFoldedDrawsMetric, isTemporalFullscreenBinding, passKindPolicyTable, postProcessShaderEntrySignature, postProcessShaderModuleLabel, postProcessShaderPipelineLabel, prepareFrameLighting, resetHdrpBuffers, residentTextureView, resolveGeometryInstanceBuffer, resolveOutputDither, resolveSkyboxActive, resolveSsaoParameters, resolveSurfaceFormatPair, resolveSurfaceProfile, retireTemporalGpuState, retireTemporalGpuStateAfterFence, runIblPrecompute, selectLazyEquirectHandle, selectSwapChainFormat, setIblComposedShaders, standardStorageVariantSet, standardTemporalLaneAdmission, standardTemporalPostOrder, standardTopologyVariantSet, temporalReadIndex, temporalWriteIndex, typedFrameClearColor, uploadMeshSsboBatch, variantSetFromDefines, variantSetFromVertexLayoutProjection, warnMultiSkybox, warnMultiSkylight, warnZeroLightStandard, writeHdrpClusterAndSsaoBuffers, writePointsLinesViewUbo, writeShadowCasterUniforms, writeShadowParamsBuffer, writeSpotModifierTextures, writeViewUbo };
|
|
9987
|
+
//# sourceMappingURL=chunk-TCLDX7SZ.mjs.map
|
|
9988
|
+
//# sourceMappingURL=chunk-TCLDX7SZ.mjs.map
|