@forgeax/engine-render 0.1.6 → 0.1.7
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 +139 -0
- package/dist/.tsbuildinfo +1 -1
- package/dist/__tests__/gpu-driven-indirect-raster-evidence.d.ts.map +1 -1
- package/dist/assembly/factory.d.ts +7 -0
- package/dist/assembly/factory.d.ts.map +1 -1
- package/dist/assembly/material/assembly.d.ts.map +1 -1
- package/dist/authoring.d.ts +1 -0
- package/dist/authoring.d.ts.map +1 -1
- package/dist/authoring.mjs +1 -1
- package/dist/{chunk-QC4VW3XJ.mjs → chunk-HCOGPHKS.mjs} +17 -3
- package/dist/chunk-HCOGPHKS.mjs.map +1 -0
- package/dist/chunk-YEJIUW7D.mjs +1152 -0
- package/dist/chunk-YEJIUW7D.mjs.map +1 -0
- package/dist/components/__tests__/points-lines-admission.unit.test.d.ts +2 -0
- package/dist/components/__tests__/points-lines-admission.unit.test.d.ts.map +1 -0
- package/dist/components/__tests__/points-lines-schema.unit.test.d.ts +2 -0
- package/dist/components/__tests__/points-lines-schema.unit.test.d.ts.map +1 -0
- package/dist/components/index.d.ts +2 -0
- package/dist/components/index.d.ts.map +1 -1
- package/dist/components/lines.d.ts +5 -0
- package/dist/components/lines.d.ts.map +1 -0
- package/dist/components/points.d.ts +15 -0
- package/dist/components/points.d.ts.map +1 -0
- package/dist/construct-renderer.mjs +952 -497
- package/dist/construct-renderer.mjs.map +1 -1
- package/dist/errors/render.d.ts +82 -1
- package/dist/errors/render.d.ts.map +1 -1
- package/dist/features/render-graph-raster.d.ts +5 -1
- package/dist/features/render-graph-raster.d.ts.map +1 -1
- package/dist/gpu-driven/production-raster.d.ts.map +1 -1
- package/dist/index.d.ts +4 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.mjs +4 -2
- package/dist/index.mjs.map +1 -1
- package/dist/inspection-types.d.ts +3 -0
- package/dist/inspection-types.d.ts.map +1 -1
- package/dist/pbr-pipeline.d.ts +2 -0
- package/dist/pbr-pipeline.d.ts.map +1 -1
- package/dist/plugin.d.ts.map +1 -1
- package/dist/points-lines/__tests__/bounds.unit.test.d.ts +2 -0
- package/dist/points-lines/__tests__/bounds.unit.test.d.ts.map +1 -0
- package/dist/points-lines/__tests__/cache-recovery.unit.test.d.ts +2 -0
- package/dist/points-lines/__tests__/cache-recovery.unit.test.d.ts.map +1 -0
- package/dist/points-lines/__tests__/inspection-lanes.integration.test.d.ts +2 -0
- package/dist/points-lines/__tests__/inspection-lanes.integration.test.d.ts.map +1 -0
- package/dist/points-lines/__tests__/inspection.unit.test.d.ts +2 -0
- package/dist/points-lines/__tests__/inspection.unit.test.d.ts.map +1 -0
- package/dist/points-lines/__tests__/lane-structural.integration.test.d.ts +2 -0
- package/dist/points-lines/__tests__/lane-structural.integration.test.d.ts.map +1 -0
- package/dist/points-lines/__tests__/points-lines.bench.d.ts +2 -0
- package/dist/points-lines/__tests__/points-lines.bench.d.ts.map +1 -0
- package/dist/points-lines/__tests__/raster-lane.integration.test.d.ts +2 -0
- package/dist/points-lines/__tests__/raster-lane.integration.test.d.ts.map +1 -0
- package/dist/points-lines/__tests__/snapshot.unit.test.d.ts +2 -0
- package/dist/points-lines/__tests__/snapshot.unit.test.d.ts.map +1 -0
- package/dist/points-lines/__tests__/view-ubo.unit.test.d.ts +2 -0
- package/dist/points-lines/__tests__/view-ubo.unit.test.d.ts.map +1 -0
- package/dist/points-lines/admission.d.ts +36 -0
- package/dist/points-lines/admission.d.ts.map +1 -0
- package/dist/points-lines/bounds.d.ts +8 -0
- package/dist/points-lines/bounds.d.ts.map +1 -0
- package/dist/points-lines/expansion-cache.d.ts +28 -0
- package/dist/points-lines/expansion-cache.d.ts.map +1 -0
- package/dist/points-lines/inspection.d.ts +53 -0
- package/dist/points-lines/inspection.d.ts.map +1 -0
- package/dist/points-lines/prepare.d.ts +67 -0
- package/dist/points-lines/prepare.d.ts.map +1 -0
- package/dist/points-lines/record.d.ts +60 -0
- package/dist/points-lines/record.d.ts.map +1 -0
- package/dist/points-lines/snapshot.d.ts +49 -0
- package/dist/points-lines/snapshot.d.ts.map +1 -0
- package/dist/record/frame-lighting.d.ts.map +1 -1
- package/dist/record/frame.d.ts +1 -1
- package/dist/record/frame.d.ts.map +1 -1
- package/dist/record/main-pass-geometry.d.ts +7 -0
- package/dist/record/main-pass-geometry.d.ts.map +1 -1
- package/dist/record/main-pass.d.ts.map +1 -1
- package/dist/record/render-context.d.ts +17 -0
- package/dist/record/render-context.d.ts.map +1 -1
- package/dist/record/shadow-pass.d.ts.map +1 -1
- package/dist/record/skybox-post-pass.d.ts.map +1 -1
- package/dist/record/typed-frame-graph.d.ts.map +1 -1
- package/dist/record/view-ubo.d.ts +6 -0
- package/dist/record/view-ubo.d.ts.map +1 -1
- package/dist/render-contract.d.ts +10 -2
- package/dist/render-contract.d.ts.map +1 -1
- package/dist/render-system-extract.d.ts +3 -0
- 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 +3 -0
- package/dist/scene/render-scene-types.d.ts.map +1 -1
- package/dist/scene/render-scene.d.ts +7 -0
- package/dist/scene/render-scene.d.ts.map +1 -1
- package/package.json +19 -19
- package/src/__tests__/authoring-path.unit.test.ts +9 -0
- package/src/__tests__/gpu-driven-indirect-raster-evidence.ts +12 -2
- package/src/__tests__/material-cooked-projection.unit.test.ts +29 -7
- package/src/__tests__/material-static-dynamic-route.unit.test.ts +28 -28
- package/src/__tests__/render-error-code-owner.test-d.ts +6 -0
- package/src/__tests__/render-error-exhaustive.test-d.ts +19 -0
- package/src/__tests__/renderer-factory-material-contract.unit.test.ts +38 -0
- package/src/assembly/factory.ts +72 -3
- package/src/assembly/material/assembly.ts +2 -5
- package/src/authoring.ts +1 -0
- package/src/components/__tests__/points-lines-admission.unit.test.ts +219 -0
- package/src/components/__tests__/points-lines-schema.unit.test.ts +56 -0
- package/src/components/index.ts +7 -0
- package/src/components/lines.ts +18 -0
- package/src/components/points.ts +40 -0
- package/src/errors/render.ts +144 -1
- package/src/features/render-graph-raster.ts +22 -3
- package/src/gpu-driven/production-raster.ts +6 -1
- package/src/index.ts +17 -0
- package/src/inspection-types.ts +4 -0
- package/src/pbr-pipeline.ts +8 -1
- package/src/plugin.ts +4 -0
- package/src/points-lines/__tests__/bounds.unit.test.ts +21 -0
- package/src/points-lines/__tests__/cache-recovery.unit.test.ts +157 -0
- package/src/points-lines/__tests__/inspection-lanes.integration.test.ts +146 -0
- package/src/points-lines/__tests__/inspection.unit.test.ts +173 -0
- package/src/points-lines/__tests__/lane-structural.integration.test.ts +122 -0
- package/src/points-lines/__tests__/points-lines.bench.ts +400 -0
- package/src/points-lines/__tests__/raster-lane.integration.test.ts +44 -0
- package/src/points-lines/__tests__/snapshot.unit.test.ts +101 -0
- package/src/points-lines/__tests__/view-ubo.unit.test.ts +73 -0
- package/src/points-lines/admission.ts +238 -0
- package/src/points-lines/bounds.ts +23 -0
- package/src/points-lines/expansion-cache.ts +215 -0
- package/src/points-lines/inspection.ts +97 -0
- package/src/points-lines/prepare.ts +177 -0
- package/src/points-lines/record.ts +125 -0
- package/src/points-lines/snapshot.ts +130 -0
- package/src/record/frame-lighting.ts +14 -2
- package/src/record/frame.ts +12 -1
- package/src/record/main-pass-geometry.ts +92 -0
- package/src/record/main-pass-sprite-draws.ts +1 -1
- package/src/record/main-pass.ts +6 -3
- package/src/record/render-context.ts +20 -0
- package/src/record/shadow-pass.ts +16 -5
- package/src/record/skybox-post-pass.ts +2 -1
- package/src/record/typed-frame-graph.ts +17 -16
- package/src/record/view-ubo.ts +47 -0
- package/src/render-contract.ts +13 -2
- package/src/render-system-extract.ts +71 -8
- package/src/render-system.ts +304 -2
- package/src/scene/render-scene-types.ts +3 -0
- package/src/scene/render-scene.ts +57 -2
- package/dist/chunk-QC4VW3XJ.mjs.map +0 -1
- package/dist/chunk-SCRSAK5B.mjs +0 -480
- package/dist/chunk-SCRSAK5B.mjs.map +0 -1
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { getTransparentSortConfig, TRANSPARENT_SORT_MODE_DISTANCE, GlyphText, TRANSPARENT_SORT_MODE_LAYER_Z, TRANSPARENT_SORT_MODE_LAYER_Y, TRANSPARENT_SORT_MODE_LAYER_YZ } from './chunk-
|
|
2
|
-
import { MeshFilter, MeshRenderer, Instances, Layer, Visibility, Camera, DirectionalLight, PointLight, PointLightShadow, SpotLight, Skylight, SkyboxBackground, PostProcessParams, DEFAULT_STANDARD_PROFILE, RENDER_PHASE_CATALOG, DEFAULT_CLUSTER_GRID, STANDARD_TONEMAP_FEATURE_ID, STANDARD_PIPELINE_ID, STANDARD_LIGHT_COUNTS, resolveVisibility, CLUSTER_GRID_STRIDE_U32, LIGHT_INDEX_LIST_CAPACITY, resolveStandardLane, CAMERA_PROJECTION_ORTHOGRAPHIC, bloomEnabledFromF32, antialiasFromF32, tonemapFromF32, cameraProjectionFromF32, tonemapToU32, MAX_LIGHTS } from './chunk-
|
|
1
|
+
import { getTransparentSortConfig, TRANSPARENT_SORT_MODE_DISTANCE, GlyphText, TRANSPARENT_SORT_MODE_LAYER_Z, TRANSPARENT_SORT_MODE_LAYER_Y, TRANSPARENT_SORT_MODE_LAYER_YZ, selectActiveCameraIndex, getActiveCamera } from './chunk-HCOGPHKS.mjs';
|
|
2
|
+
import { MeshFilter, MeshRenderer, Instances, Layer, Visibility, Camera, DirectionalLight, PointLight, PointLightShadow, SpotLight, Skylight, SkyboxBackground, PostProcessParams, RendererContractFailureError, RendererOperationError, DEFAULT_STANDARD_PROFILE, RENDER_PHASE_CATALOG, DEFAULT_CLUSTER_GRID, FrameReceiptStaleError, RenderFeatureStageFailedError, RenderFeatureCapabilityMissingError, RenderFeatureRegistrationConflictError, LifecycleConstructionError, STANDARD_TONEMAP_FEATURE_ID, PointsLinesMaterialUnsupportedError, admitPointsLines, STANDARD_PIPELINE_ID, STANDARD_LIGHT_COUNTS, ObservationUnavailableError, resolveVisibility, Points, Lines, SortKey, SkinMaterialMismatchError, MaterialSkinAttrMissingError, pointShapeFromU32, CLUSTER_GRID_STRIDE_U32, LIGHT_INDEX_LIST_CAPACITY, RenderFeaturePreparationFailedError, PointShadowAtlasUninitializedError, PointShadowAtlasBoundsViolationError, EquirectProjectionFailedError, HdrpLightBudgetExceededError, resolveStandardLane, CAMERA_PROJECTION_ORTHOGRAPHIC, PointsLinesPrepareFailedError, bloomEnabledFromF32, antialiasFromF32, tonemapFromF32, cameraProjectionFromF32, ShadowInvalidConfigError, tonemapToU32, MAX_LIGHTS, HdrpIndexListOverflowError, RenderFeaturePreparedStateMismatchError, RenderFeatureDrawRecordingFailedError, HdrpDeferredCapsInsufficientError, SkinPaletteOverflowError, VideoUploadUnsupportedError, VertexColorVariantConflictError } from './chunk-YEJIUW7D.mjs';
|
|
3
3
|
import { SpriteInstances, SpriteRegionOverride, TileLayer, decodeSortScope, Tilemap, SPRITE_PREMULTIPLIED_ALPHA_BLEND } from './chunk-CQXZC5XI.mjs';
|
|
4
4
|
import { AssetRegistry, DynamicTextureStore, adaptDynamicTextureDevice, getOrCreateMipmapPipeline, blitMipmapsSync, numMipLevels, HANDLE_CUBE, HANDLE_TRIANGLE, HANDLE_QUAD, HANDLE_SPHERE, HANDLE_NINESLICE_QUAD, BuiltinAssetRegistry, resolveAssetHandle, walkMaterialPassesOverSharedRefs, resolveTilesetRuntime, MeshSsboCeilingReachedError, MeshSsboCapacityExceededError } from '@forgeax/engine-assets-runtime';
|
|
5
5
|
import { audioLoader } from '@forgeax/engine-audio-webaudio';
|
|
@@ -2261,422 +2261,6 @@ var RenderRecoveryError = class extends Error {
|
|
|
2261
2261
|
this.detail = detail;
|
|
2262
2262
|
}
|
|
2263
2263
|
};
|
|
2264
|
-
|
|
2265
|
-
// src/errors/render.ts
|
|
2266
|
-
var LifecycleConstructionError = class extends Error {
|
|
2267
|
-
code = "lifecycle-construction-failed";
|
|
2268
|
-
expected = "all DeviceScope resources establish and terminate in order";
|
|
2269
|
-
hint = "inspect detail and cleanupFailures, then recover or rebuild the DeviceScope";
|
|
2270
|
-
detail;
|
|
2271
|
-
constructor(detail) {
|
|
2272
|
-
super(`lifecycle-construction-failed: ${detail.resourceKind} lifecycle transaction failed`);
|
|
2273
|
-
this.name = "LifecycleConstructionError";
|
|
2274
|
-
this.detail = detail;
|
|
2275
|
-
}
|
|
2276
|
-
};
|
|
2277
|
-
var ShadowInvalidConfigError = class extends Error {
|
|
2278
|
-
code = "shadow-invalid-config";
|
|
2279
|
-
expected;
|
|
2280
|
-
hint;
|
|
2281
|
-
detail;
|
|
2282
|
-
constructor(field, value, min, maxOrComparator) {
|
|
2283
|
-
const isComparator = maxOrComparator === ">" || maxOrComparator === ">=";
|
|
2284
|
-
const max = !isComparator && typeof maxOrComparator === "number" ? maxOrComparator : void 0;
|
|
2285
|
-
const comparator = isComparator ? maxOrComparator : ">=";
|
|
2286
|
-
const isInteger = field === "cascadeCount" || field === "pcfKernelSize";
|
|
2287
|
-
const isOdd = field === "pcfKernelSize";
|
|
2288
|
-
const hint = max !== void 0 ? isInteger ? `set ${field} to an integer in [${min}, ${max}]; got ${value}` : `set ${field} to a value in [${min}, ${max}]; got ${value}` : isOdd ? `set ${field} to an odd integer ${comparator} ${min}; got ${value}` : `set ${field} to a value ${comparator} ${min}; got ${value}`;
|
|
2289
|
-
const expected = max !== void 0 ? `${field} in [${min}, ${max}]` : `${field} ${comparator} ${min}`;
|
|
2290
|
-
super(
|
|
2291
|
-
max !== void 0 ? `shadow component .${field} must be in [${min}, ${max}], got ${value}` : `shadow component .${field} must be ${comparator} ${min}, got ${value}`
|
|
2292
|
-
);
|
|
2293
|
-
this.name = "ShadowInvalidConfigError";
|
|
2294
|
-
this.hint = hint;
|
|
2295
|
-
this.expected = expected;
|
|
2296
|
-
this.detail = { field, value, min, ...max !== void 0 ? { max } : {} };
|
|
2297
|
-
}
|
|
2298
|
-
};
|
|
2299
|
-
var EquirectProjectionFailedError = class extends Error {
|
|
2300
|
-
code = "equirect-projection-failed";
|
|
2301
|
-
expected;
|
|
2302
|
-
hint;
|
|
2303
|
-
detail;
|
|
2304
|
-
constructor(handle) {
|
|
2305
|
-
const expected = `equirect handle ${handle} projects to a GPU cubemap + IBL precompute`;
|
|
2306
|
-
const hint = `equirect handle ${handle} referenced by Skylight/SkyboxBackground failed projection; declare Skylight{equirect} with a valid HDR equirect source and check device.caps.rgba16floatRenderable. The projection is internal (no user upload call); the record arm does not retry`;
|
|
2307
|
-
super(`equirect handle ${handle} cubemap projection failed`);
|
|
2308
|
-
this.name = "EquirectProjectionFailedError";
|
|
2309
|
-
this.expected = expected;
|
|
2310
|
-
this.hint = hint;
|
|
2311
|
-
this.detail = { handle };
|
|
2312
|
-
}
|
|
2313
|
-
};
|
|
2314
|
-
var HdrpLightBudgetExceededError = class extends Error {
|
|
2315
|
-
code = "hdrp-light-budget-exceeded";
|
|
2316
|
-
expected;
|
|
2317
|
-
hint;
|
|
2318
|
-
detail;
|
|
2319
|
-
constructor(actual, budget) {
|
|
2320
|
-
const expected = `light count <= ${budget}`;
|
|
2321
|
-
const hint = `${actual} lights exceed HDRP budget ${budget}; truncating to 256. Reduce light count or wait for OOS-hdrp-larger-budget`;
|
|
2322
|
-
super(`HDRP light budget exceeded: ${actual} > ${budget}`);
|
|
2323
|
-
this.name = "HdrpLightBudgetExceededError";
|
|
2324
|
-
this.expected = expected;
|
|
2325
|
-
this.hint = hint;
|
|
2326
|
-
this.detail = { actual, budget };
|
|
2327
|
-
}
|
|
2328
|
-
};
|
|
2329
|
-
var HdrpIndexListOverflowError = class extends Error {
|
|
2330
|
-
code = "hdrp-index-list-overflow";
|
|
2331
|
-
expected;
|
|
2332
|
-
hint;
|
|
2333
|
-
detail;
|
|
2334
|
-
constructor(actual, capacity) {
|
|
2335
|
-
const expected = `light index list entries <= ${capacity}`;
|
|
2336
|
-
const hint = `cluster binner overflow: writeCount ${actual} exceeds capacity ${capacity}; reduce lights, shrink cluster grid, or increase LIGHT_INDEX_LIST_CAPACITY`;
|
|
2337
|
-
super(`HDRP index list overflow: ${actual} > ${capacity}`);
|
|
2338
|
-
this.name = "HdrpIndexListOverflowError";
|
|
2339
|
-
this.expected = expected;
|
|
2340
|
-
this.hint = hint;
|
|
2341
|
-
this.detail = { actual, capacity };
|
|
2342
|
-
}
|
|
2343
|
-
};
|
|
2344
|
-
var HdrpDeferredCapsInsufficientError = class extends Error {
|
|
2345
|
-
code = "hdrp-deferred-caps-insufficient";
|
|
2346
|
-
expected;
|
|
2347
|
-
hint;
|
|
2348
|
-
detail;
|
|
2349
|
-
constructor(actual) {
|
|
2350
|
-
const _expected = 4;
|
|
2351
|
-
const _expectedStr = `maxColorAttachments >= ${_expected}`;
|
|
2352
|
-
const hint = `WebGPU maxColorAttachments = ${actual} (need >= ${_expected}). Upgrade browser to latest Chrome/Edge/Safari, or use URP (forgeax::urp) instead of HDRP.`;
|
|
2353
|
-
super(
|
|
2354
|
-
`HDRP deferred caps insufficient: maxColorAttachments = ${actual} (need >= ${_expected})`
|
|
2355
|
-
);
|
|
2356
|
-
this.name = "HdrpDeferredCapsInsufficientError";
|
|
2357
|
-
this.expected = _expectedStr;
|
|
2358
|
-
this.hint = hint;
|
|
2359
|
-
this.detail = { actual, expected: _expected };
|
|
2360
|
-
}
|
|
2361
|
-
};
|
|
2362
|
-
var PointShadowAtlasUninitializedError = class extends Error {
|
|
2363
|
-
code = "point-shadow-atlas-uninitialized";
|
|
2364
|
-
expected;
|
|
2365
|
-
hint;
|
|
2366
|
-
constructor() {
|
|
2367
|
-
const expected = "ShadowAtlas.ensure() invoked before faceView()";
|
|
2368
|
-
const hint = "Gate faceView on isAllocated() or call ensure() once in the per-frame extract step before iterating face views";
|
|
2369
|
-
super("ShadowAtlas.faceView called before ensure(); the cube_array texture is not allocated");
|
|
2370
|
-
this.name = "PointShadowAtlasUninitializedError";
|
|
2371
|
-
this.expected = expected;
|
|
2372
|
-
this.hint = hint;
|
|
2373
|
-
}
|
|
2374
|
-
};
|
|
2375
|
-
var PointShadowAtlasBoundsViolationError = class extends Error {
|
|
2376
|
-
code = "point-shadow-atlas-bounds-violation";
|
|
2377
|
-
expected;
|
|
2378
|
-
hint;
|
|
2379
|
-
detail;
|
|
2380
|
-
constructor(axis, value, max) {
|
|
2381
|
-
const expected = `0 <= ${axis} < ${max}`;
|
|
2382
|
-
const hint = axis === "layer" ? `clamp PointLight.shadowAtlasLayer to [0, ${max}); the cap on layers equals PointLightShadow cardinality (4)` : `clamp face index to [0, ${max}); cube faces are indexed 0..5 in +X/-X/+Y/-Y/+Z/-Z order`;
|
|
2383
|
-
super(`ShadowAtlas.faceView ${axis} out of range: ${value} (must be in [0, ${max}))`);
|
|
2384
|
-
this.name = "PointShadowAtlasBoundsViolationError";
|
|
2385
|
-
this.expected = expected;
|
|
2386
|
-
this.hint = hint;
|
|
2387
|
-
this.detail = { axis, value, max };
|
|
2388
|
-
}
|
|
2389
|
-
};
|
|
2390
|
-
var VideoUploadUnsupportedError = class extends Error {
|
|
2391
|
-
code = "video-upload-unsupported";
|
|
2392
|
-
expected;
|
|
2393
|
-
hint;
|
|
2394
|
-
constructor() {
|
|
2395
|
-
const expected = "at least one video upload path available: a host HTMLVideoElement (general copyExternalImageToTexture path) or GPUExternalTexture capability (high-perf path)";
|
|
2396
|
-
const hint = "this backend exposes no usable video upload path; render a static texture instead, or switch to a WebGPU backend that supports video texture upload";
|
|
2397
|
-
super("video upload unsupported \u2014 no general or high-perf path available");
|
|
2398
|
-
this.name = "VideoUploadUnsupportedError";
|
|
2399
|
-
this.expected = expected;
|
|
2400
|
-
this.hint = hint;
|
|
2401
|
-
}
|
|
2402
|
-
};
|
|
2403
|
-
var VertexColorVariantConflictError = class extends Error {
|
|
2404
|
-
code = "vertex-color-variant-conflict";
|
|
2405
|
-
expected;
|
|
2406
|
-
hint;
|
|
2407
|
-
detail;
|
|
2408
|
-
constructor(authoredValue, projected) {
|
|
2409
|
-
const expected = `VERTEX_COLOR_AVAILABLE=${projected ? "true" : "false"}`;
|
|
2410
|
-
const hint = "derive the shader variant from the mesh VertexLayoutProjection; COLOR_0 presence is a geometry fact";
|
|
2411
|
-
super(`authored vertex-color variant ${authoredValue} disagrees with projected ${expected}`);
|
|
2412
|
-
this.name = "VertexColorVariantConflictError";
|
|
2413
|
-
this.expected = expected;
|
|
2414
|
-
this.hint = hint;
|
|
2415
|
-
this.detail = { authored: true, authoredValue, projected };
|
|
2416
|
-
}
|
|
2417
|
-
};
|
|
2418
|
-
var SkinPaletteOverflowError = class extends Error {
|
|
2419
|
-
code = "skin-palette-overflow";
|
|
2420
|
-
expected;
|
|
2421
|
-
hint;
|
|
2422
|
-
detail;
|
|
2423
|
-
constructor(requestedBytes, limit) {
|
|
2424
|
-
const expected = `skinned joint palette (${requestedBytes} B) fits within device.limits.maxStorageBufferBindingSize (${limit} B)`;
|
|
2425
|
-
const hint = "palette buffer exceeds device maxStorageBufferBindingSize; reduce skinned entity count or split into multiple palette buffers (OOS-skin-palette-batch)";
|
|
2426
|
-
super(`skin palette buffer needs ${requestedBytes} B, exceeds device limit ${limit} B`);
|
|
2427
|
-
this.name = "SkinPaletteOverflowError";
|
|
2428
|
-
this.expected = expected;
|
|
2429
|
-
this.hint = hint;
|
|
2430
|
-
this.detail = { requestedBytes, limit };
|
|
2431
|
-
}
|
|
2432
|
-
};
|
|
2433
|
-
var SkinMaterialMismatchError = class extends Error {
|
|
2434
|
-
code = "skin-material-mismatch";
|
|
2435
|
-
expected;
|
|
2436
|
-
hint;
|
|
2437
|
-
detail;
|
|
2438
|
-
constructor(entity, actualShader) {
|
|
2439
|
-
const expected = "Skin entity's first material program module === 'forgeax::pbr-skin'";
|
|
2440
|
-
const hint = `entity ${entity} has Skin but the first material program module is ${actualShader ?? "<empty>"}; load the mesh via the gltf importer (cooker auto-routes 'forgeax::pbr-skin' for skinned primitives), or remove the Skin component to render the entity unskinned with Materials.standard / Materials.unlit`;
|
|
2441
|
-
super(
|
|
2442
|
-
`Skin / material mismatch on entity ${entity}: expected forgeax::pbr-skin, got ${actualShader ?? "<empty>"}`
|
|
2443
|
-
);
|
|
2444
|
-
this.name = "SkinMaterialMismatchError";
|
|
2445
|
-
this.expected = expected;
|
|
2446
|
-
this.hint = hint;
|
|
2447
|
-
this.detail = { entity, actualShader };
|
|
2448
|
-
}
|
|
2449
|
-
};
|
|
2450
|
-
var MaterialSkinAttrMissingError = class extends Error {
|
|
2451
|
-
code = "material-skin-attr-missing";
|
|
2452
|
-
expected;
|
|
2453
|
-
hint;
|
|
2454
|
-
detail;
|
|
2455
|
-
constructor(entity, missing2) {
|
|
2456
|
-
const expected = "pbr-skin material requires mesh.attributes.skinIndex + skinWeight";
|
|
2457
|
-
const hint = `entity ${entity} uses forgeax::pbr-skin but its MeshAsset is missing ${missing2}; switch the entity to a skinned glTF mesh authored with JOINTS_0 + WEIGHTS_0, or change the material to a non-skin shader via Materials.standard / Materials.unlit`;
|
|
2458
|
-
super(
|
|
2459
|
-
`material/skin attribute mismatch on entity ${entity}: pbr-skin material with mesh missing ${missing2}`
|
|
2460
|
-
);
|
|
2461
|
-
this.name = "MaterialSkinAttrMissingError";
|
|
2462
|
-
this.expected = expected;
|
|
2463
|
-
this.hint = hint;
|
|
2464
|
-
this.detail = { entity, missing: missing2 };
|
|
2465
|
-
}
|
|
2466
|
-
};
|
|
2467
|
-
var renderFeatureRecoveryHintByRecovery = {
|
|
2468
|
-
"next-frame": (featureIdentity, stage) => `correct '${featureIdentity}' ${stage} data and retry on the next frame`,
|
|
2469
|
-
"renderer-recover": (featureIdentity, _stage) => `wait for renderer recovery before retrying '${featureIdentity}'`,
|
|
2470
|
-
registration: (featureIdentity, _stage) => `correct '${featureIdentity}' registration before retrying`
|
|
2471
|
-
};
|
|
2472
|
-
var RenderFeatureRegistrationConflictError = class extends Error {
|
|
2473
|
-
code = "render-feature-registration-conflict";
|
|
2474
|
-
expected;
|
|
2475
|
-
hint;
|
|
2476
|
-
detail;
|
|
2477
|
-
constructor(featureIdentity, order, conflictingOrder) {
|
|
2478
|
-
const expected = `feature identity '${featureIdentity}' is unique`;
|
|
2479
|
-
const hint = `rename '${featureIdentity}' or remove the duplicate feature before registration`;
|
|
2480
|
-
super(`render feature registration conflict for '${featureIdentity}'`);
|
|
2481
|
-
this.name = "RenderFeatureRegistrationConflictError";
|
|
2482
|
-
this.expected = expected;
|
|
2483
|
-
this.hint = hint;
|
|
2484
|
-
this.detail = { featureIdentity, order, conflictingOrder };
|
|
2485
|
-
}
|
|
2486
|
-
};
|
|
2487
|
-
var RenderFeatureStageFailedError = class extends Error {
|
|
2488
|
-
code = "render-feature-stage-failed";
|
|
2489
|
-
expected;
|
|
2490
|
-
hint;
|
|
2491
|
-
detail;
|
|
2492
|
-
constructor(featureIdentity, order, stage, recovery) {
|
|
2493
|
-
const expected = `feature '${featureIdentity}' completes its ${stage} stage without an error`;
|
|
2494
|
-
const hint = renderFeatureRecoveryHintByRecovery[recovery](featureIdentity, stage);
|
|
2495
|
-
super(`render feature '${featureIdentity}' failed during ${stage}`);
|
|
2496
|
-
this.name = "RenderFeatureStageFailedError";
|
|
2497
|
-
this.expected = expected;
|
|
2498
|
-
this.hint = hint;
|
|
2499
|
-
this.detail = { featureIdentity, order, stage, recovery };
|
|
2500
|
-
}
|
|
2501
|
-
};
|
|
2502
|
-
var RenderFeatureCapabilityMissingError = class extends Error {
|
|
2503
|
-
code = "render-feature-capability-missing";
|
|
2504
|
-
expected;
|
|
2505
|
-
hint;
|
|
2506
|
-
detail;
|
|
2507
|
-
constructor(featureIdentity, order, capability) {
|
|
2508
|
-
const expected = `device capability '${capability}' is available for feature '${featureIdentity}'`;
|
|
2509
|
-
const hint = `disable '${featureIdentity}' or use a device with '${capability}' capability`;
|
|
2510
|
-
super(`render feature '${featureIdentity}' requires missing capability '${capability}'`);
|
|
2511
|
-
this.name = "RenderFeatureCapabilityMissingError";
|
|
2512
|
-
this.expected = expected;
|
|
2513
|
-
this.hint = hint;
|
|
2514
|
-
this.detail = { featureIdentity, order, capability };
|
|
2515
|
-
}
|
|
2516
|
-
};
|
|
2517
|
-
var RenderFeaturePreparationFailedError = class extends Error {
|
|
2518
|
-
code = "render-feature-preparation-failed";
|
|
2519
|
-
expected;
|
|
2520
|
-
hint;
|
|
2521
|
-
detail;
|
|
2522
|
-
constructor(featureIdentity, order, operation, resourceKind, resourceName, reason, recovery) {
|
|
2523
|
-
const expected = `${resourceKind} '${resourceName}' is prepared during ${operation}`;
|
|
2524
|
-
const hint = `repair '${resourceName}' and retry feature '${featureIdentity}' on ${recovery}`;
|
|
2525
|
-
super(`render feature '${featureIdentity}' preparation failed for '${resourceName}'`);
|
|
2526
|
-
this.name = "RenderFeaturePreparationFailedError";
|
|
2527
|
-
this.expected = expected;
|
|
2528
|
-
this.hint = hint;
|
|
2529
|
-
this.detail = {
|
|
2530
|
-
featureIdentity,
|
|
2531
|
-
order,
|
|
2532
|
-
stage: "prepare",
|
|
2533
|
-
operation,
|
|
2534
|
-
resourceKind,
|
|
2535
|
-
resourceName,
|
|
2536
|
-
reason,
|
|
2537
|
-
recovery
|
|
2538
|
-
};
|
|
2539
|
-
}
|
|
2540
|
-
};
|
|
2541
|
-
var RenderFeaturePreparedStateMismatchError = class extends Error {
|
|
2542
|
-
code = "render-feature-prepared-state-mismatch";
|
|
2543
|
-
expected;
|
|
2544
|
-
hint;
|
|
2545
|
-
detail;
|
|
2546
|
-
constructor(detail) {
|
|
2547
|
-
const expected = `${detail.resourceKind} state is compatible for '${detail.operation}'`;
|
|
2548
|
-
const hint = `repair '${detail.reason}' for feature '${detail.featureIdentity}' and retry`;
|
|
2549
|
-
super(`render feature '${detail.featureIdentity}' prepared state mismatch`);
|
|
2550
|
-
this.name = "RenderFeaturePreparedStateMismatchError";
|
|
2551
|
-
this.expected = expected;
|
|
2552
|
-
this.hint = hint;
|
|
2553
|
-
this.detail = detail;
|
|
2554
|
-
}
|
|
2555
|
-
};
|
|
2556
|
-
var RenderFeatureDrawRecordingFailedError = class extends Error {
|
|
2557
|
-
code = "render-feature-draw-recording-failed";
|
|
2558
|
-
expected;
|
|
2559
|
-
hint;
|
|
2560
|
-
detail;
|
|
2561
|
-
constructor(featureIdentity, order, operation, resourceKind, reason, backendReason, recovery) {
|
|
2562
|
-
const expected = `${resourceKind} recording succeeds for '${operation}'`;
|
|
2563
|
-
const hint = `repair '${reason}' and retry feature '${featureIdentity}' after ${recovery}`;
|
|
2564
|
-
super(`render feature '${featureIdentity}' draw recording failed`);
|
|
2565
|
-
this.name = "RenderFeatureDrawRecordingFailedError";
|
|
2566
|
-
this.expected = expected;
|
|
2567
|
-
this.hint = hint;
|
|
2568
|
-
this.detail = {
|
|
2569
|
-
featureIdentity,
|
|
2570
|
-
order,
|
|
2571
|
-
stage: "record",
|
|
2572
|
-
operation,
|
|
2573
|
-
resourceKind,
|
|
2574
|
-
reason,
|
|
2575
|
-
backendReason,
|
|
2576
|
-
recovery
|
|
2577
|
-
};
|
|
2578
|
-
}
|
|
2579
|
-
};
|
|
2580
|
-
var ObservationUnavailableError = class extends Error {
|
|
2581
|
-
code = "observation-unavailable";
|
|
2582
|
-
expected;
|
|
2583
|
-
hint;
|
|
2584
|
-
detail;
|
|
2585
|
-
constructor(reason, hint) {
|
|
2586
|
-
let recovery;
|
|
2587
|
-
if (reason === "copy-src") recovery = "enable-copy-src";
|
|
2588
|
-
else if (reason === "resource" || reason === "readback-failed") recovery = "retry-readback";
|
|
2589
|
-
else recovery = "draw-current-frame";
|
|
2590
|
-
super(`current-frame observation unavailable: ${reason}`);
|
|
2591
|
-
this.name = "ObservationUnavailableError";
|
|
2592
|
-
this.expected = "a fresh producer-owned rgba16float current-frame observation";
|
|
2593
|
-
this.hint = hint;
|
|
2594
|
-
this.detail = { reason, recovery };
|
|
2595
|
-
}
|
|
2596
|
-
};
|
|
2597
|
-
var FrameReceiptStaleError = class extends Error {
|
|
2598
|
-
code = "frame-receipt-stale";
|
|
2599
|
-
expected = "the observation receipt belongs to the active device generation";
|
|
2600
|
-
hint = "draw a new frame and call observe with its returned FrameReceipt";
|
|
2601
|
-
detail;
|
|
2602
|
-
constructor(detail) {
|
|
2603
|
-
super("frame receipt belongs to a retired device generation");
|
|
2604
|
-
this.name = "FrameReceiptStaleError";
|
|
2605
|
-
this.detail = detail;
|
|
2606
|
-
}
|
|
2607
|
-
};
|
|
2608
|
-
var RendererContractFailureError = class extends Error {
|
|
2609
|
-
code = "renderer-contract-failed";
|
|
2610
|
-
expected = "renderer owner contracts remain valid at the public boundary";
|
|
2611
|
-
hint = "repair the owner contract and retry the operation";
|
|
2612
|
-
detail;
|
|
2613
|
-
constructor(operation, cause) {
|
|
2614
|
-
super(`renderer ${operation} contract failed: ${cause}`);
|
|
2615
|
-
this.name = "RendererContractFailureError";
|
|
2616
|
-
this.detail = { operation, cause };
|
|
2617
|
-
}
|
|
2618
|
-
};
|
|
2619
|
-
var RENDERER_OPERATION_ERROR_POLICY = {
|
|
2620
|
-
"world-lease-invalid": {
|
|
2621
|
-
expected: "every render World is represented by a live lease owned by this Renderer",
|
|
2622
|
-
hint: "attach the World to this Renderer and use the returned lease"
|
|
2623
|
-
},
|
|
2624
|
-
"frame-input-invalid": {
|
|
2625
|
-
expected: "the frame input references attached leases and a valid immutable RenderProfile",
|
|
2626
|
-
hint: "repair the frame input and retry draw or setProfile"
|
|
2627
|
-
},
|
|
2628
|
-
"scene-projection-failed": {
|
|
2629
|
-
expected: "the attached World projects into the renderer-owned RenderScene",
|
|
2630
|
-
hint: "inspect the structured cause, repair the World publication, and retry draw"
|
|
2631
|
-
},
|
|
2632
|
-
"asset-binding-failed": {
|
|
2633
|
-
expected: "all frame assets resolve to valid renderer-owned bindings",
|
|
2634
|
-
hint: "inspect the structured cause, rebuild or cold-cook the asset, and retry draw"
|
|
2635
|
-
},
|
|
2636
|
-
"feature-plan-failed": {
|
|
2637
|
-
expected: "every installed RenderFeature produces a valid declarative plan",
|
|
2638
|
-
hint: "inspect the feature cause, repair its plan, and retry draw"
|
|
2639
|
-
},
|
|
2640
|
-
"graph-build-failed": {
|
|
2641
|
-
expected: "the Standard graph builds from the active profile and feature plans",
|
|
2642
|
-
hint: "inspect the graph cause, repair the profile or plan, and retry"
|
|
2643
|
-
},
|
|
2644
|
-
"device-operation-failed": {
|
|
2645
|
-
expected: "the active device generation completes the renderer-owned operation",
|
|
2646
|
-
hint: "inspect renderer state and the structured cause, then retry or recover"
|
|
2647
|
-
},
|
|
2648
|
-
"surface-unavailable": {
|
|
2649
|
-
expected: "the presentation surface accepts the requested lifecycle operation",
|
|
2650
|
-
hint: "inspect renderer state, then restore the surface or create a new Renderer"
|
|
2651
|
-
},
|
|
2652
|
-
"renderer-state-invalid": {
|
|
2653
|
-
expected: "the Renderer is in a state that accepts the requested operation",
|
|
2654
|
-
hint: "inspect renderer state and choose retry, restoreSurface, recover, or stop"
|
|
2655
|
-
},
|
|
2656
|
-
"recovery-failed": {
|
|
2657
|
-
expected: "one recovery attempt publishes a complete replacement device generation",
|
|
2658
|
-
hint: "inspect the structured cause and retry recover after the host-selected delay"
|
|
2659
|
-
},
|
|
2660
|
-
"cleanup-failed": {
|
|
2661
|
-
expected: "Renderer disposal completes every registered cleanup in reverse ownership order",
|
|
2662
|
-
hint: "inspect the ordered cleanup causes; the Renderer remains disposed and must not be reused"
|
|
2663
|
-
}
|
|
2664
|
-
};
|
|
2665
|
-
var RendererOperationError = class extends Error {
|
|
2666
|
-
code;
|
|
2667
|
-
expected;
|
|
2668
|
-
hint;
|
|
2669
|
-
detail;
|
|
2670
|
-
constructor(code, detail) {
|
|
2671
|
-
const policy = RENDERER_OPERATION_ERROR_POLICY[code];
|
|
2672
|
-
super(`${code}: ${policy.expected}`);
|
|
2673
|
-
this.name = "RendererOperationError";
|
|
2674
|
-
this.code = code;
|
|
2675
|
-
this.expected = policy.expected;
|
|
2676
|
-
this.hint = policy.hint;
|
|
2677
|
-
this.detail = detail;
|
|
2678
|
-
}
|
|
2679
|
-
};
|
|
2680
2264
|
function stageFailure(identity) {
|
|
2681
2265
|
return {
|
|
2682
2266
|
code: "render-feature-stage-failed",
|
|
@@ -4627,6 +4211,11 @@ function buildPbrViewBglEntries(caps) {
|
|
|
4627
4211
|
binding: 8,
|
|
4628
4212
|
visibility: GPU_SHADER_STAGE_FRAGMENT,
|
|
4629
4213
|
texture: { sampleType: "depth", viewDimension: "2d" }
|
|
4214
|
+
},
|
|
4215
|
+
{
|
|
4216
|
+
binding: 10,
|
|
4217
|
+
visibility: GPU_SHADER_STAGE_VERTEX,
|
|
4218
|
+
buffer: { type: "uniform", hasDynamicOffset: true }
|
|
4630
4219
|
}
|
|
4631
4220
|
];
|
|
4632
4221
|
}
|
|
@@ -4831,7 +4420,7 @@ function buildBindGroupLayoutDescriptor(spec, options) {
|
|
|
4831
4420
|
const desc = createHdrpBindGroupLayoutDescriptor(caps.storageBuffer);
|
|
4832
4421
|
return {
|
|
4833
4422
|
label: desc.label ?? "hdrp-unified-bgl-group2",
|
|
4834
|
-
entries: desc.entries ?? []
|
|
4423
|
+
entries: [...desc.entries ?? []]
|
|
4835
4424
|
};
|
|
4836
4425
|
}
|
|
4837
4426
|
case "fullscreen-post": {
|
|
@@ -7598,12 +7187,47 @@ function clampPcfKernelSize(value) {
|
|
|
7598
7187
|
|
|
7599
7188
|
// src/record/view-ubo.ts
|
|
7600
7189
|
var VIEW_UNIFORM_BYTES = 960;
|
|
7190
|
+
var POINTS_LINES_VIEW_BYTES = 160;
|
|
7191
|
+
var POINTS_LINES_VIEW_SLOT_STRIDE = 256;
|
|
7192
|
+
var POINTS_LINES_VIEW_SLOT_COUNT = 1024;
|
|
7193
|
+
var POINTS_LINES_VIEW_BUFFER_SIZE = POINTS_LINES_VIEW_SLOT_STRIDE * POINTS_LINES_VIEW_SLOT_COUNT;
|
|
7601
7194
|
var VIEW_UNIFORM_SLOT_STRIDE = 1024;
|
|
7602
7195
|
var POINT_SHADOW_VIEW_SLOT_COUNT = 24;
|
|
7603
7196
|
var VIEW_UNIFORM_BUFFER_SIZE = VIEW_UNIFORM_SLOT_STRIDE * (1 + POINT_SHADOW_VIEW_SLOT_COUNT);
|
|
7604
7197
|
function pointShadowViewOffset(layer, face) {
|
|
7605
7198
|
return VIEW_UNIFORM_SLOT_STRIDE * (1 + layer * 6 + face);
|
|
7606
7199
|
}
|
|
7200
|
+
function writePointsLinesViewUbo(queue, buffer, camera, width, height, model, style, byteOffset = 0) {
|
|
7201
|
+
const projection = computeProjectionMatrix(camera);
|
|
7202
|
+
const view = computeViewMatrix(camera);
|
|
7203
|
+
const worldViewProj = mat4.create();
|
|
7204
|
+
mat4.multiply(worldViewProj, projection, view);
|
|
7205
|
+
const payload = new Float32Array(40);
|
|
7206
|
+
payload.set(worldViewProj);
|
|
7207
|
+
if (model === void 0) {
|
|
7208
|
+
payload[16] = 1;
|
|
7209
|
+
payload[21] = 1;
|
|
7210
|
+
payload[26] = 1;
|
|
7211
|
+
payload[31] = 1;
|
|
7212
|
+
} else {
|
|
7213
|
+
for (let index = 0; index < 16; index += 1) {
|
|
7214
|
+
payload[16 + index] = model[index] ?? 0;
|
|
7215
|
+
}
|
|
7216
|
+
}
|
|
7217
|
+
payload[32] = width;
|
|
7218
|
+
payload[33] = height;
|
|
7219
|
+
if (style?.kind === "points") {
|
|
7220
|
+
payload[36] = style.sizePx;
|
|
7221
|
+
payload[38] = style.shape === "circle" ? 1 : 0;
|
|
7222
|
+
} else if (style?.kind === "lines") {
|
|
7223
|
+
payload[36] = style.widthPx;
|
|
7224
|
+
payload[37] = 1;
|
|
7225
|
+
} else {
|
|
7226
|
+
payload[36] = 1;
|
|
7227
|
+
}
|
|
7228
|
+
const uploaded = queue.writeBuffer(buffer, byteOffset, payload);
|
|
7229
|
+
if (!uploaded.ok) throw uploaded.error;
|
|
7230
|
+
}
|
|
7607
7231
|
function writeViewUbo(queue, viewUniformBuffer, camera, light, lights, spotShadowSnapshots) {
|
|
7608
7232
|
const projMatrix = computeProjectionMatrix(camera);
|
|
7609
7233
|
const viewMatrix = computeViewMatrix(camera);
|
|
@@ -7719,7 +7343,8 @@ function buildPerFrameBindGroups(internals, frameState, pipelineState, hasValida
|
|
|
7719
7343
|
shadowSampler,
|
|
7720
7344
|
b5View,
|
|
7721
7345
|
pipelineState.shadowParamsBuffer,
|
|
7722
|
-
b8View
|
|
7346
|
+
b8View,
|
|
7347
|
+
pipelineState.pointsLinesViewBuffer ?? pipelineState.viewUniformBuffer
|
|
7723
7348
|
],
|
|
7724
7349
|
"view-main",
|
|
7725
7350
|
() => {
|
|
@@ -7806,11 +7431,22 @@ function buildPerFrameBindGroups(internals, frameState, pipelineState, hasValida
|
|
|
7806
7431
|
kind: "textureView",
|
|
7807
7432
|
value: b8View
|
|
7808
7433
|
}
|
|
7434
|
+
},
|
|
7435
|
+
{
|
|
7436
|
+
binding: 10,
|
|
7437
|
+
resource: {
|
|
7438
|
+
kind: "buffer",
|
|
7439
|
+
value: {
|
|
7440
|
+
buffer: pipelineState.pointsLinesViewBuffer ?? pipelineState.viewUniformBuffer,
|
|
7441
|
+
size: POINTS_LINES_VIEW_BYTES
|
|
7442
|
+
}
|
|
7443
|
+
}
|
|
7809
7444
|
}
|
|
7810
7445
|
// feat-20260625-spot-light-shadow-mapping w25: the per-spot
|
|
7811
7446
|
// fragment-read lightViewProj matrices fold into the View UBO
|
|
7812
7447
|
// (binding 0, `view.spotLightViewProj`) — no standalone binding 9
|
|
7813
|
-
// (WebGL2 fragment uniform-buffer budget). binding
|
|
7448
|
+
// (WebGL2 fragment uniform-buffer budget). binding 10 is the
|
|
7449
|
+
// dedicated vertex-only Points/Lines viewport UBO.
|
|
7814
7450
|
]
|
|
7815
7451
|
});
|
|
7816
7452
|
if (!viewBindGroupResult.ok) throw viewBindGroupResult.error;
|
|
@@ -8306,6 +7942,53 @@ function resolveSkyboxActive(internals, frameState, camera, skybox) {
|
|
|
8306
7942
|
return { tonemapActive, skyboxActive };
|
|
8307
7943
|
}
|
|
8308
7944
|
|
|
7945
|
+
// src/points-lines/record.ts
|
|
7946
|
+
var POINTS_LINES_MATERIAL_SHADER_ID = "forgeax::points-lines";
|
|
7947
|
+
function createPointsLinesLaneContract(lane, backend) {
|
|
7948
|
+
return {
|
|
7949
|
+
lane,
|
|
7950
|
+
backend,
|
|
7951
|
+
authoring: "shared",
|
|
7952
|
+
evidence: backend === "null" ? "structural-only" : "runtime",
|
|
7953
|
+
material: {
|
|
7954
|
+
source: "MaterialAsset",
|
|
7955
|
+
shaderId: POINTS_LINES_MATERIAL_SHADER_ID,
|
|
7956
|
+
shadingModel: "unlit",
|
|
7957
|
+
clusteredLighting: false,
|
|
7958
|
+
lit: false
|
|
7959
|
+
},
|
|
7960
|
+
graph: { additionalAttachments: 0, additionalPasses: 0 },
|
|
7961
|
+
shadowDrawCount: 0,
|
|
7962
|
+
capabilities: { compute: false, storage: false, indirect: false }
|
|
7963
|
+
};
|
|
7964
|
+
}
|
|
7965
|
+
function createPointsLinesRecordPlan(snapshot, geometry, contract) {
|
|
7966
|
+
const primitiveCount = geometry.pointCount + geometry.segmentCount;
|
|
7967
|
+
const visible = snapshot.visible && primitiveCount > 0;
|
|
7968
|
+
const conservativeMarginPx = snapshot.style?.kind === "points" ? snapshot.style.sizePx * 0.5 : (snapshot.style?.widthPx ?? 0) * 0.5;
|
|
7969
|
+
return {
|
|
7970
|
+
lane: contract.lane,
|
|
7971
|
+
backend: contract.backend,
|
|
7972
|
+
materialShaderId: POINTS_LINES_MATERIAL_SHADER_ID,
|
|
7973
|
+
component: geometry.component,
|
|
7974
|
+
meshGeneration: snapshot.meshGeneration,
|
|
7975
|
+
materialGeneration: snapshot.materialGeneration,
|
|
7976
|
+
vertexCount: primitiveCount * 4,
|
|
7977
|
+
indexCount: primitiveCount * 6,
|
|
7978
|
+
drawCount: visible ? 1 : 0,
|
|
7979
|
+
shadowDrawCount: 0,
|
|
7980
|
+
conservativeMarginPx,
|
|
7981
|
+
graph: contract.graph
|
|
7982
|
+
};
|
|
7983
|
+
}
|
|
7984
|
+
function createPointsLinesLaneAdapter(lane, backend) {
|
|
7985
|
+
const contract = createPointsLinesLaneContract(lane, backend);
|
|
7986
|
+
return {
|
|
7987
|
+
contract,
|
|
7988
|
+
createRecordPlan: (snapshot, geometry) => createPointsLinesRecordPlan(snapshot, geometry, contract)
|
|
7989
|
+
};
|
|
7990
|
+
}
|
|
7991
|
+
|
|
8309
7992
|
// src/record/render-context.ts
|
|
8310
7993
|
var STANDARD_PBR_UBO_SIZE = 304;
|
|
8311
7994
|
var MATERIAL_PER_ENTITY_STRIDE = 512;
|
|
@@ -8894,6 +8577,14 @@ function submitSubmeshDraws(pass, state, pipeline, instanceDraws, indexed, index
|
|
|
8894
8577
|
}
|
|
8895
8578
|
}
|
|
8896
8579
|
}
|
|
8580
|
+
function recordPointsLinesDraw(pass, plan) {
|
|
8581
|
+
if (plan.drawCount === 0) return;
|
|
8582
|
+
if (plan.indexCount > 0) {
|
|
8583
|
+
pass.drawIndexed(plan.indexCount, 1, 0, 0, 0);
|
|
8584
|
+
return;
|
|
8585
|
+
}
|
|
8586
|
+
pass.draw(plan.vertexCount, 1, 0, 0);
|
|
8587
|
+
}
|
|
8897
8588
|
function recordGeometryDraws(c, pass, matchedMaterials, materialSlotIndices, sampleCount, meshGroup2, meshBindGroup, resolveMaterialBindGroup, passKind = "forward") {
|
|
8898
8589
|
const {
|
|
8899
8590
|
runtime,
|
|
@@ -8904,7 +8595,8 @@ function recordGeometryDraws(c, pass, matchedMaterials, materialSlotIndices, sam
|
|
|
8904
8595
|
tonemapActive,
|
|
8905
8596
|
msaaActive,
|
|
8906
8597
|
validatedOrdered,
|
|
8907
|
-
splitLdrSprite
|
|
8598
|
+
splitLdrSprite,
|
|
8599
|
+
viewBindGroup
|
|
8908
8600
|
} = c;
|
|
8909
8601
|
const colorFormatOverride = c.transparentColorFormat;
|
|
8910
8602
|
let lastVertexBuffer = null;
|
|
@@ -8989,6 +8681,9 @@ function recordGeometryDraws(c, pass, matchedMaterials, materialSlotIndices, sam
|
|
|
8989
8681
|
for (let i = 0; i < validatedOrdered.length; i++) {
|
|
8990
8682
|
const entry = validatedOrdered[i];
|
|
8991
8683
|
if (entry === void 0) continue;
|
|
8684
|
+
const pointsLinesSubmission = c.pointsLines?.prepare(entry, frameState.isHdrpActive);
|
|
8685
|
+
if (entry.source.pointsLines !== void 0 && pointsLinesSubmission?.plan.drawCount !== 1)
|
|
8686
|
+
continue;
|
|
8992
8687
|
if (passKind === "forward" && c.gpuDrivenEntityKeys.has(worldEntityKey(entry.source.worldId, entry.source.entityKey))) {
|
|
8993
8688
|
continue;
|
|
8994
8689
|
}
|
|
@@ -8999,6 +8694,66 @@ function recordGeometryDraws(c, pass, matchedMaterials, materialSlotIndices, sam
|
|
|
8999
8694
|
pass.setStencilReference(stencilReference);
|
|
9000
8695
|
lastStencilReference = stencilReference;
|
|
9001
8696
|
}
|
|
8697
|
+
if (pointsLinesSubmission !== void 0 && entry.source.pointsLines !== void 0) {
|
|
8698
|
+
const pointsLinesMaterial = {
|
|
8699
|
+
...entry.source.material,
|
|
8700
|
+
materialShaderId: POINTS_LINES_MATERIAL_SHADER_ID,
|
|
8701
|
+
materialParamSchema: runtime.getParamSchema?.(POINTS_LINES_MATERIAL_SHADER_ID) ?? entry.source.material.materialParamSchema
|
|
8702
|
+
};
|
|
8703
|
+
const materialSlot = materialSlotIndices[i]?.[0] ?? 0;
|
|
8704
|
+
const pointsLinesBindGroup = resolveMaterialBindGroup(
|
|
8705
|
+
materialSlot,
|
|
8706
|
+
pointsLinesMaterial,
|
|
8707
|
+
entry.source.entityKey,
|
|
8708
|
+
entry.world ?? c.world
|
|
8709
|
+
);
|
|
8710
|
+
const pointsLinesPipeline = resolveMaterialPipeline(
|
|
8711
|
+
POINTS_LINES_MATERIAL_SHADER_ID,
|
|
8712
|
+
{
|
|
8713
|
+
...pointsLinesMaterial.renderState,
|
|
8714
|
+
cullMode: "none"
|
|
8715
|
+
},
|
|
8716
|
+
"triangle-list",
|
|
8717
|
+
"uint32",
|
|
8718
|
+
void 0,
|
|
8719
|
+
colorFormatOverride,
|
|
8720
|
+
pointsLinesSubmission.layoutProjection
|
|
8721
|
+
);
|
|
8722
|
+
if (pointsLinesPipeline === null) continue;
|
|
8723
|
+
if (pipelineState.pointsLinesViewBuffer === void 0) continue;
|
|
8724
|
+
writePointsLinesViewUbo(
|
|
8725
|
+
runtime.device.queue,
|
|
8726
|
+
pipelineState.pointsLinesViewBuffer,
|
|
8727
|
+
c.camera,
|
|
8728
|
+
c.targetW,
|
|
8729
|
+
c.targetH,
|
|
8730
|
+
entry.source.transform.world,
|
|
8731
|
+
entry.source.pointsLines.style,
|
|
8732
|
+
i * POINTS_LINES_VIEW_SLOT_STRIDE
|
|
8733
|
+
);
|
|
8734
|
+
pass.setBindGroup(
|
|
8735
|
+
0,
|
|
8736
|
+
viewBindGroup,
|
|
8737
|
+
new Uint32Array([i * POINTS_LINES_VIEW_SLOT_STRIDE]),
|
|
8738
|
+
0,
|
|
8739
|
+
1
|
|
8740
|
+
);
|
|
8741
|
+
pass.setPipeline(pointsLinesPipeline);
|
|
8742
|
+
pass.setVertexBuffer(0, pointsLinesSubmission.vertexBuffer);
|
|
8743
|
+
pass.setIndexBuffer(pointsLinesSubmission.indexBuffer, "uint32");
|
|
8744
|
+
materialGroup1DynamicOffsets[0] = materialSlot * MATERIAL_PER_ENTITY_STRIDE;
|
|
8745
|
+
pass.setBindGroup(1, pointsLinesBindGroup, materialGroup1DynamicOffsets, 0, 1);
|
|
8746
|
+
const pointsLinesMeshGroup = meshBindGroup ?? meshGroup2;
|
|
8747
|
+
if (pointsLinesMeshGroup === null) continue;
|
|
8748
|
+
pass.setBindGroup(2, pointsLinesMeshGroup, meshGroup2DynamicOffsets);
|
|
8749
|
+
pass.setBindGroup(
|
|
8750
|
+
3,
|
|
8751
|
+
identityInstanceDraws[0]?.instanceBindGroup ?? resolveGeometryInstancesBindGroup(c, identityInstanceBuffer)
|
|
8752
|
+
);
|
|
8753
|
+
recordPointsLinesDraw(pass, pointsLinesSubmission.plan);
|
|
8754
|
+
pass.setBindGroup(0, viewBindGroup, [0]);
|
|
8755
|
+
continue;
|
|
8756
|
+
}
|
|
9002
8757
|
if (entry.mesh.vertexBuffer !== lastVertexBuffer) {
|
|
9003
8758
|
pass.setVertexBuffer(0, entry.mesh.vertexBuffer.handle);
|
|
9004
8759
|
lastVertexBuffer = entry.mesh.vertexBuffer;
|
|
@@ -9468,7 +9223,7 @@ function recordSpritePass(c, pass, matchedIndices, materialSlotIndices, sampleCo
|
|
|
9468
9223
|
{ colorLoadOp: "load", depthLoadOp: "load" }
|
|
9469
9224
|
)
|
|
9470
9225
|
);
|
|
9471
|
-
spritePass.setBindGroup(0, viewBindGroup);
|
|
9226
|
+
spritePass.setBindGroup(0, viewBindGroup, [0]);
|
|
9472
9227
|
const spritePremulBlend = {
|
|
9473
9228
|
depthWriteEnabled: false,
|
|
9474
9229
|
depthCompare: "less-equal",
|
|
@@ -10160,7 +9915,8 @@ function ensureTypedShadowViewBg(c, viewOffset, cascadeOffset, variant) {
|
|
|
10160
9915
|
pipelineState.shadowAtlasFallbackTextureView,
|
|
10161
9916
|
pipelineState.shadowParamsBuffer,
|
|
10162
9917
|
pipelineState.shadowCasterCascadeBuffer,
|
|
10163
|
-
pipelineState.shadowFallbackTextureView
|
|
9918
|
+
pipelineState.shadowFallbackTextureView,
|
|
9919
|
+
pipelineState.pointsLinesViewBuffer ?? pipelineState.viewUniformBuffer
|
|
10164
9920
|
],
|
|
10165
9921
|
variant,
|
|
10166
9922
|
() => {
|
|
@@ -10213,13 +9969,23 @@ function ensureTypedShadowViewBg(c, viewOffset, cascadeOffset, variant) {
|
|
|
10213
9969
|
value: {
|
|
10214
9970
|
buffer: pipelineState.shadowCasterCascadeBuffer,
|
|
10215
9971
|
offset: cascadeOffset,
|
|
10216
|
-
size:
|
|
9972
|
+
size: POINTS_LINES_VIEW_BYTES
|
|
10217
9973
|
}
|
|
10218
9974
|
}
|
|
10219
9975
|
},
|
|
10220
9976
|
{
|
|
10221
9977
|
binding: 8,
|
|
10222
9978
|
resource: { kind: "textureView", value: pipelineState.shadowFallbackTextureView }
|
|
9979
|
+
},
|
|
9980
|
+
{
|
|
9981
|
+
binding: 10,
|
|
9982
|
+
resource: {
|
|
9983
|
+
kind: "buffer",
|
|
9984
|
+
value: {
|
|
9985
|
+
buffer: pipelineState.pointsLinesViewBuffer ?? pipelineState.viewUniformBuffer,
|
|
9986
|
+
size: 80
|
|
9987
|
+
}
|
|
9988
|
+
}
|
|
10223
9989
|
}
|
|
10224
9990
|
]
|
|
10225
9991
|
});
|
|
@@ -10270,7 +10036,7 @@ function encodeDirectionalShadowPass(c, pass, cascadeIndex, viewport) {
|
|
|
10270
10036
|
c.frameState.directionalShadowCacheRecorded = true;
|
|
10271
10037
|
pass.setViewport(viewport.x, viewport.y, viewport.w, viewport.h, 0, 1);
|
|
10272
10038
|
pass.setPipeline(pipeline);
|
|
10273
|
-
pass.setBindGroup(0, viewBg);
|
|
10039
|
+
pass.setBindGroup(0, viewBg, [0]);
|
|
10274
10040
|
pass.setBindGroup(1, materialBg, [0]);
|
|
10275
10041
|
recordShadowCasterDraws(
|
|
10276
10042
|
c,
|
|
@@ -10294,7 +10060,7 @@ function encodePointShadowPass(c, pass, snapshotIndex, face) {
|
|
|
10294
10060
|
const materialBg = ensureSpotShadowMaterialBg(c);
|
|
10295
10061
|
if (pipeline === null || viewBg === null || materialBg === null) return;
|
|
10296
10062
|
pass.setPipeline(pipeline);
|
|
10297
|
-
pass.setBindGroup(0, viewBg);
|
|
10063
|
+
pass.setBindGroup(0, viewBg, [0]);
|
|
10298
10064
|
pass.setBindGroup(1, materialBg, [0]);
|
|
10299
10065
|
recordShadowCasterDraws(
|
|
10300
10066
|
c,
|
|
@@ -10332,7 +10098,7 @@ function encodeSpotShadowPass(c, pass, snapshotIndex) {
|
|
|
10332
10098
|
1
|
|
10333
10099
|
);
|
|
10334
10100
|
pass.setPipeline(pipeline);
|
|
10335
|
-
pass.setBindGroup(0, viewBg);
|
|
10101
|
+
pass.setBindGroup(0, viewBg, [0]);
|
|
10336
10102
|
pass.setBindGroup(1, materialBg, [0]);
|
|
10337
10103
|
recordShadowCasterDraws(
|
|
10338
10104
|
c,
|
|
@@ -10819,8 +10585,8 @@ function recordMainPass(c, selector, options, graphPass) {
|
|
|
10819
10585
|
owner.world ?? world
|
|
10820
10586
|
);
|
|
10821
10587
|
}
|
|
10822
|
-
const resolveMaterialBindGroup = (materialSlot, material, entityKey, materialWorld = world) => preparedMaterialBindGroups[materialSlot] ?? buildPerSubmeshMaterialBg2(material, entityKey, materialWorld);
|
|
10823
|
-
pass.setBindGroup(0, viewBindGroup);
|
|
10588
|
+
const resolveMaterialBindGroup = (materialSlot, material, entityKey, materialWorld = world) => material.materialShaderId !== POINTS_LINES_MATERIAL_SHADER_ID ? preparedMaterialBindGroups[materialSlot] ?? buildPerSubmeshMaterialBg2(material, entityKey, materialWorld) : buildPerSubmeshMaterialBg2(material, entityKey, materialWorld);
|
|
10589
|
+
pass.setBindGroup(0, viewBindGroup, [0]);
|
|
10824
10590
|
const recordGeometry = () => {
|
|
10825
10591
|
recordGeometryDraws(
|
|
10826
10592
|
c,
|
|
@@ -10910,7 +10676,7 @@ function recordSkyboxPass(c, graphPass) {
|
|
|
10910
10676
|
binding: 2,
|
|
10911
10677
|
resource: {
|
|
10912
10678
|
kind: "buffer",
|
|
10913
|
-
value: { buffer: pipelineState.viewUniformBuffer }
|
|
10679
|
+
value: { buffer: pipelineState.viewUniformBuffer, size: VIEW_UNIFORM_BYTES }
|
|
10914
10680
|
}
|
|
10915
10681
|
},
|
|
10916
10682
|
{
|
|
@@ -14829,7 +14595,7 @@ var GpuDrivenProduction = class {
|
|
|
14829
14595
|
return ok({
|
|
14830
14596
|
accesses,
|
|
14831
14597
|
encode: (viewBindGroup, pass, resources) => {
|
|
14832
|
-
pass.setBindGroup(0, viewBindGroup);
|
|
14598
|
+
pass.setBindGroup(0, viewBindGroup, [0]);
|
|
14833
14599
|
let currentPipeline;
|
|
14834
14600
|
let currentVertex;
|
|
14835
14601
|
let currentIndex;
|
|
@@ -14905,6 +14671,305 @@ var GpuDrivenProduction = class {
|
|
|
14905
14671
|
}
|
|
14906
14672
|
};
|
|
14907
14673
|
|
|
14674
|
+
// src/points-lines/expansion-cache.ts
|
|
14675
|
+
var PointsLinesExpansionCache = class {
|
|
14676
|
+
entries = /* @__PURE__ */ new Map();
|
|
14677
|
+
getOrCreate(snapshot, mesh) {
|
|
14678
|
+
if (snapshot.component === void 0 || snapshot.style === void 0) {
|
|
14679
|
+
return emptyGeometry(snapshot);
|
|
14680
|
+
}
|
|
14681
|
+
const key = expansionKey(snapshot);
|
|
14682
|
+
const cached = this.entries.get(key);
|
|
14683
|
+
if (cached !== void 0) return cached;
|
|
14684
|
+
const geometry = deriveExpandedGeometry(snapshot, mesh, key);
|
|
14685
|
+
this.entries.set(key, geometry);
|
|
14686
|
+
return geometry;
|
|
14687
|
+
}
|
|
14688
|
+
clear() {
|
|
14689
|
+
this.entries.clear();
|
|
14690
|
+
}
|
|
14691
|
+
get size() {
|
|
14692
|
+
return this.entries.size;
|
|
14693
|
+
}
|
|
14694
|
+
};
|
|
14695
|
+
function expansionKey(snapshot) {
|
|
14696
|
+
return `mesh:${snapshot.meshHandle}:${snapshot.meshGeneration}:component=${snapshot.component ?? "none"}`;
|
|
14697
|
+
}
|
|
14698
|
+
function deriveExpandedGeometry(snapshot, mesh, key) {
|
|
14699
|
+
const component = snapshot.component;
|
|
14700
|
+
const style = snapshot.style;
|
|
14701
|
+
if (component === void 0 || style === void 0) return emptyGeometry(snapshot);
|
|
14702
|
+
const sourcePositions = readPositions(mesh);
|
|
14703
|
+
const positions = [];
|
|
14704
|
+
const vertices = [];
|
|
14705
|
+
const indices = [];
|
|
14706
|
+
let sourceCursor = 0;
|
|
14707
|
+
let pointCount = 0;
|
|
14708
|
+
let segmentCount = 0;
|
|
14709
|
+
const expectedTopology = component === "Points" ? "point-list" : "line-list";
|
|
14710
|
+
for (const submesh of mesh.submeshes) {
|
|
14711
|
+
if (submesh.topology !== expectedTopology) {
|
|
14712
|
+
sourceCursor += submesh.vertexCount;
|
|
14713
|
+
continue;
|
|
14714
|
+
}
|
|
14715
|
+
const elements = mesh.indices !== void 0 && submesh.indexCount > 0 ? Array.from(
|
|
14716
|
+
mesh.indices.slice(submesh.indexOffset, submesh.indexOffset + submesh.indexCount)
|
|
14717
|
+
) : Array.from({ length: submesh.vertexCount }, (_, index) => sourceCursor + index);
|
|
14718
|
+
for (const index of elements) {
|
|
14719
|
+
const offset2 = index * 3;
|
|
14720
|
+
positions.push(
|
|
14721
|
+
sourcePositions[offset2] ?? 0,
|
|
14722
|
+
sourcePositions[offset2 + 1] ?? 0,
|
|
14723
|
+
sourcePositions[offset2 + 2] ?? 0
|
|
14724
|
+
);
|
|
14725
|
+
}
|
|
14726
|
+
if (component === "Points") {
|
|
14727
|
+
pointCount += elements.length;
|
|
14728
|
+
for (const index of elements) {
|
|
14729
|
+
const offset2 = index * 3;
|
|
14730
|
+
const position = [
|
|
14731
|
+
sourcePositions[offset2] ?? 0,
|
|
14732
|
+
sourcePositions[offset2 + 1] ?? 0,
|
|
14733
|
+
sourcePositions[offset2 + 2] ?? 0
|
|
14734
|
+
];
|
|
14735
|
+
if (style.kind !== "points") continue;
|
|
14736
|
+
emitQuad(vertices, indices, position, position);
|
|
14737
|
+
}
|
|
14738
|
+
} else {
|
|
14739
|
+
segmentCount += Math.floor(elements.length / 2);
|
|
14740
|
+
for (let element = 0; element + 1 < elements.length; element += 2) {
|
|
14741
|
+
const startOffset = (elements[element] ?? 0) * 3;
|
|
14742
|
+
const endOffset = (elements[element + 1] ?? 0) * 3;
|
|
14743
|
+
emitQuad(
|
|
14744
|
+
vertices,
|
|
14745
|
+
indices,
|
|
14746
|
+
[
|
|
14747
|
+
sourcePositions[startOffset] ?? 0,
|
|
14748
|
+
sourcePositions[startOffset + 1] ?? 0,
|
|
14749
|
+
sourcePositions[startOffset + 2] ?? 0
|
|
14750
|
+
],
|
|
14751
|
+
[
|
|
14752
|
+
sourcePositions[endOffset] ?? 0,
|
|
14753
|
+
sourcePositions[endOffset + 1] ?? 0,
|
|
14754
|
+
sourcePositions[endOffset + 2] ?? 0
|
|
14755
|
+
]
|
|
14756
|
+
);
|
|
14757
|
+
}
|
|
14758
|
+
}
|
|
14759
|
+
sourceCursor += submesh.vertexCount;
|
|
14760
|
+
}
|
|
14761
|
+
const expanded = new Float32Array(positions);
|
|
14762
|
+
const expandedVertices = new Float32Array(vertices);
|
|
14763
|
+
const expandedIndices = new Uint32Array(indices);
|
|
14764
|
+
return {
|
|
14765
|
+
key,
|
|
14766
|
+
component,
|
|
14767
|
+
positions: expanded,
|
|
14768
|
+
vertices: expandedVertices,
|
|
14769
|
+
indices: expandedIndices,
|
|
14770
|
+
sourceVertexCount: sourcePositions.length / 3,
|
|
14771
|
+
pointCount,
|
|
14772
|
+
segmentCount,
|
|
14773
|
+
expandedVertexCount: expandedVertices.length / 8,
|
|
14774
|
+
expandedIndexCount: expandedIndices.length,
|
|
14775
|
+
sourceBytes: mesh.vertices.byteLength + (mesh.indices?.byteLength ?? 0),
|
|
14776
|
+
derivedBytes: expandedVertices.byteLength + expandedIndices.byteLength,
|
|
14777
|
+
bounds: boundsOf(expanded)
|
|
14778
|
+
};
|
|
14779
|
+
}
|
|
14780
|
+
function emitQuad(vertices, indices, start, end) {
|
|
14781
|
+
const base = vertices.length / 8;
|
|
14782
|
+
const corners = [
|
|
14783
|
+
[-1, -1],
|
|
14784
|
+
[-1, 1],
|
|
14785
|
+
[1, -1],
|
|
14786
|
+
[1, 1]
|
|
14787
|
+
];
|
|
14788
|
+
for (const [x, y] of corners) {
|
|
14789
|
+
vertices.push(
|
|
14790
|
+
start[0] ?? 0,
|
|
14791
|
+
start[1] ?? 0,
|
|
14792
|
+
start[2] ?? 0,
|
|
14793
|
+
end[0] ?? 0,
|
|
14794
|
+
end[1] ?? 0,
|
|
14795
|
+
end[2] ?? 0,
|
|
14796
|
+
x,
|
|
14797
|
+
y
|
|
14798
|
+
);
|
|
14799
|
+
}
|
|
14800
|
+
indices.push(base, base + 1, base + 2, base + 2, base + 1, base + 3);
|
|
14801
|
+
}
|
|
14802
|
+
function readPositions(mesh) {
|
|
14803
|
+
const attribute = mesh.attributes.position;
|
|
14804
|
+
if (attribute instanceof Float32Array && attribute.length >= 3) {
|
|
14805
|
+
return attribute;
|
|
14806
|
+
}
|
|
14807
|
+
const vertexCount = mesh.vertices.length / 3;
|
|
14808
|
+
const stride = vertexCount > 0 ? mesh.vertices.length / vertexCount : 3;
|
|
14809
|
+
const positions = new Float32Array(vertexCount * 3);
|
|
14810
|
+
for (let vertex = 0; vertex < vertexCount; vertex += 1) {
|
|
14811
|
+
const source = vertex * stride;
|
|
14812
|
+
positions.set(mesh.vertices.subarray(source, source + 3), vertex * 3);
|
|
14813
|
+
}
|
|
14814
|
+
return positions;
|
|
14815
|
+
}
|
|
14816
|
+
function boundsOf(positions) {
|
|
14817
|
+
if (positions.length === 0) return new Float32Array(0);
|
|
14818
|
+
const bounds = new Float32Array([Infinity, Infinity, Infinity, -Infinity, -Infinity, -Infinity]);
|
|
14819
|
+
for (let index = 0; index < positions.length; index += 3) {
|
|
14820
|
+
bounds[0] = Math.min(bounds[0] ?? Infinity, positions[index] ?? 0);
|
|
14821
|
+
bounds[1] = Math.min(bounds[1] ?? Infinity, positions[index + 1] ?? 0);
|
|
14822
|
+
bounds[2] = Math.min(bounds[2] ?? Infinity, positions[index + 2] ?? 0);
|
|
14823
|
+
bounds[3] = Math.max(bounds[3] ?? -Infinity, positions[index] ?? 0);
|
|
14824
|
+
bounds[4] = Math.max(bounds[4] ?? -Infinity, positions[index + 1] ?? 0);
|
|
14825
|
+
bounds[5] = Math.max(bounds[5] ?? -Infinity, positions[index + 2] ?? 0);
|
|
14826
|
+
}
|
|
14827
|
+
return bounds;
|
|
14828
|
+
}
|
|
14829
|
+
function emptyGeometry(snapshot) {
|
|
14830
|
+
return {
|
|
14831
|
+
key: `empty:${snapshot.entityKey}`,
|
|
14832
|
+
component: snapshot.component ?? "Points",
|
|
14833
|
+
positions: new Float32Array(0),
|
|
14834
|
+
vertices: new Float32Array(0),
|
|
14835
|
+
indices: new Uint32Array(0),
|
|
14836
|
+
sourceVertexCount: 0,
|
|
14837
|
+
pointCount: 0,
|
|
14838
|
+
segmentCount: 0,
|
|
14839
|
+
expandedVertexCount: 0,
|
|
14840
|
+
expandedIndexCount: 0,
|
|
14841
|
+
sourceBytes: 0,
|
|
14842
|
+
derivedBytes: 0,
|
|
14843
|
+
bounds: new Float32Array(0)
|
|
14844
|
+
};
|
|
14845
|
+
}
|
|
14846
|
+
|
|
14847
|
+
// src/points-lines/inspection.ts
|
|
14848
|
+
function inspectPointsLines(input) {
|
|
14849
|
+
const { snapshot } = input;
|
|
14850
|
+
if (snapshot.component === void 0) {
|
|
14851
|
+
throw new Error("Points/Lines inspection requires a retained style component");
|
|
14852
|
+
}
|
|
14853
|
+
return {
|
|
14854
|
+
entityKey: snapshot.entityKey,
|
|
14855
|
+
worldId: snapshot.worldId,
|
|
14856
|
+
component: snapshot.component,
|
|
14857
|
+
meshHandle: snapshot.meshHandle,
|
|
14858
|
+
meshGeneration: snapshot.meshGeneration,
|
|
14859
|
+
materialHandle: snapshot.materialHandle,
|
|
14860
|
+
materialGeneration: snapshot.materialGeneration,
|
|
14861
|
+
style: snapshot.style ?? { kind: "lines", widthPx: 0 },
|
|
14862
|
+
topology: input.topology,
|
|
14863
|
+
lane: input.lane,
|
|
14864
|
+
pointCount: input.pointCount,
|
|
14865
|
+
segmentCount: input.segmentCount,
|
|
14866
|
+
sourceBytes: input.sourceBytes,
|
|
14867
|
+
derivedBytes: input.derivedBytes,
|
|
14868
|
+
cache: { ...input.cache },
|
|
14869
|
+
drawCount: input.drawCount,
|
|
14870
|
+
uploadBytes: input.uploadBytes,
|
|
14871
|
+
lastKnownGood: input.lastKnownGood,
|
|
14872
|
+
...input.refusal === void 0 ? {} : { refusal: { ...input.refusal } }
|
|
14873
|
+
};
|
|
14874
|
+
}
|
|
14875
|
+
var PointsLinesPreparation = class {
|
|
14876
|
+
constructor(options) {
|
|
14877
|
+
this.options = options;
|
|
14878
|
+
}
|
|
14879
|
+
options;
|
|
14880
|
+
live;
|
|
14881
|
+
pendingCandidateBytes = 0;
|
|
14882
|
+
status = "empty";
|
|
14883
|
+
uploads = 0;
|
|
14884
|
+
rebuilds = 0;
|
|
14885
|
+
failures = 0;
|
|
14886
|
+
prepare(snapshot, mesh) {
|
|
14887
|
+
const geometry = this.options.cache.getOrCreate(snapshot, mesh);
|
|
14888
|
+
if (this.live?.geometry.key === geometry.key) {
|
|
14889
|
+
this.live = {
|
|
14890
|
+
...this.live,
|
|
14891
|
+
snapshot,
|
|
14892
|
+
uploadedBytes: 0
|
|
14893
|
+
};
|
|
14894
|
+
this.status = "resident";
|
|
14895
|
+
return ok$1(this.live);
|
|
14896
|
+
}
|
|
14897
|
+
this.pendingCandidateBytes = geometry.derivedBytes;
|
|
14898
|
+
const created = this.options.adapter.create(geometry);
|
|
14899
|
+
if (!created.ok) return this.fail(snapshot, created.error);
|
|
14900
|
+
const candidate = created.value;
|
|
14901
|
+
const uploaded = this.options.adapter.upload(candidate, geometry);
|
|
14902
|
+
if (!uploaded.ok) {
|
|
14903
|
+
this.options.adapter.destroy(candidate);
|
|
14904
|
+
return this.fail(snapshot, uploaded.error);
|
|
14905
|
+
}
|
|
14906
|
+
this.uploads += 1;
|
|
14907
|
+
const validated = this.options.adapter.validate(candidate, geometry);
|
|
14908
|
+
if (!validated.ok) {
|
|
14909
|
+
this.options.adapter.destroy(candidate);
|
|
14910
|
+
return this.fail(snapshot, validated.error);
|
|
14911
|
+
}
|
|
14912
|
+
const previous = this.live;
|
|
14913
|
+
this.live = {
|
|
14914
|
+
resource: candidate,
|
|
14915
|
+
geometry,
|
|
14916
|
+
snapshot,
|
|
14917
|
+
uploadedBytes: uploaded.value,
|
|
14918
|
+
lastKnownGood: true
|
|
14919
|
+
};
|
|
14920
|
+
this.pendingCandidateBytes = 0;
|
|
14921
|
+
this.status = "resident";
|
|
14922
|
+
this.rebuilds += 1;
|
|
14923
|
+
if (previous !== void 0) this.options.adapter.destroy(previous.resource);
|
|
14924
|
+
return ok$1(this.live);
|
|
14925
|
+
}
|
|
14926
|
+
resetForDeviceLoss() {
|
|
14927
|
+
if (this.live !== void 0) this.options.adapter.destroy(this.live.resource);
|
|
14928
|
+
this.live = void 0;
|
|
14929
|
+
this.pendingCandidateBytes = 0;
|
|
14930
|
+
this.status = "rebuild-pending";
|
|
14931
|
+
}
|
|
14932
|
+
lastKnownGood() {
|
|
14933
|
+
return this.live;
|
|
14934
|
+
}
|
|
14935
|
+
inspect() {
|
|
14936
|
+
return {
|
|
14937
|
+
status: this.status,
|
|
14938
|
+
lastKnownGood: this.live?.lastKnownGood ?? false,
|
|
14939
|
+
liveResource: this.live?.resource,
|
|
14940
|
+
liveBytes: this.live?.geometry.derivedBytes ?? 0,
|
|
14941
|
+
candidateBytes: this.pendingCandidateBytes,
|
|
14942
|
+
cacheEntries: this.options.cache.size,
|
|
14943
|
+
uploads: this.uploads,
|
|
14944
|
+
rebuilds: this.rebuilds,
|
|
14945
|
+
failures: this.failures
|
|
14946
|
+
};
|
|
14947
|
+
}
|
|
14948
|
+
fail(snapshot, cause) {
|
|
14949
|
+
this.pendingCandidateBytes = 0;
|
|
14950
|
+
this.failures += 1;
|
|
14951
|
+
return err$1(
|
|
14952
|
+
new PointsLinesPrepareFailedError({
|
|
14953
|
+
owner: "points-lines",
|
|
14954
|
+
generation: snapshot.meshGeneration,
|
|
14955
|
+
stage: "prepare",
|
|
14956
|
+
cause: cause.message,
|
|
14957
|
+
lastKnownGood: this.live !== void 0
|
|
14958
|
+
})
|
|
14959
|
+
);
|
|
14960
|
+
}
|
|
14961
|
+
};
|
|
14962
|
+
function createPointsLinesLanePreparationAdapter(lane, backend, options) {
|
|
14963
|
+
const preparation = new PointsLinesPreparation(options);
|
|
14964
|
+
return {
|
|
14965
|
+
contract: createPointsLinesLaneContract(lane, backend),
|
|
14966
|
+
prepare: (snapshot, mesh) => preparation.prepare(snapshot, mesh),
|
|
14967
|
+
resetForDeviceLoss: () => preparation.resetForDeviceLoss(),
|
|
14968
|
+
lastKnownGood: () => preparation.lastKnownGood(),
|
|
14969
|
+
inspect: () => preparation.inspect()
|
|
14970
|
+
};
|
|
14971
|
+
}
|
|
14972
|
+
|
|
14908
14973
|
// src/instance-buffer-cache.ts
|
|
14909
14974
|
function destroyInstanceBufferEntries(entries, errorRegistry) {
|
|
14910
14975
|
for (const entry of entries) {
|
|
@@ -15515,10 +15580,12 @@ var RenderFeatureRasterGraphProjection = class {
|
|
|
15515
15580
|
for (const [group, reference] of draw.bindings.entries()) {
|
|
15516
15581
|
const binding = resolved(snapshot, reference);
|
|
15517
15582
|
if (binding?.kind !== "bindings") throw missing(featureIdentity, order);
|
|
15518
|
-
const
|
|
15583
|
+
const resolvedBindings = binding.handle ?? this.resolveBindings?.({ frame, binding, resources, resolveTarget: this.resolveTarget });
|
|
15584
|
+
const handle = resolvedBindings !== void 0 && typeof resolvedBindings === "object" && "handle" in resolvedBindings ? resolvedBindings.handle : resolvedBindings;
|
|
15519
15585
|
if (handle === void 0) throw missing(featureIdentity, order);
|
|
15520
15586
|
const targetGroup = binding.descriptor?.values.group ?? group;
|
|
15521
|
-
|
|
15587
|
+
const dynamicOffsets = resolvedBindings !== void 0 && typeof resolvedBindings === "object" && "handle" in resolvedBindings ? resolvedBindings.dynamicOffsets : binding.dynamicOffsets;
|
|
15588
|
+
pass.setBindGroup(targetGroup, handle, dynamicOffsets);
|
|
15522
15589
|
}
|
|
15523
15590
|
for (const vertex of draw.vertexData) {
|
|
15524
15591
|
const handle = buffers.vertex.get(vertex.resource);
|
|
@@ -15786,7 +15853,7 @@ function resolveTargetBindings(input) {
|
|
|
15786
15853
|
return created2.value;
|
|
15787
15854
|
}
|
|
15788
15855
|
if (sceneDepth === void 0) {
|
|
15789
|
-
|
|
15856
|
+
const viewBindGroup = buildPerFrameBindGroups(
|
|
15790
15857
|
frame.runtime,
|
|
15791
15858
|
frame.frameState,
|
|
15792
15859
|
frame.pipelineState,
|
|
@@ -15796,7 +15863,8 @@ function resolveTargetBindings(input) {
|
|
|
15796
15863
|
directionalShadow: frame.frameState.currentDirectionalShadowView ?? void 0,
|
|
15797
15864
|
spotShadow: frame.frameState.currentSpotShadowView ?? void 0
|
|
15798
15865
|
}
|
|
15799
|
-
).viewBindGroup
|
|
15866
|
+
).viewBindGroup;
|
|
15867
|
+
return viewBindGroup === null ? void 0 : { handle: viewBindGroup, dynamicOffsets: [0] };
|
|
15800
15868
|
}
|
|
15801
15869
|
const target3 = input.resolveTarget(sceneDepth);
|
|
15802
15870
|
if (target3 === void 0) return void 0;
|
|
@@ -16023,7 +16091,7 @@ var EMPTY_ENTITY_KEYS = /* @__PURE__ */ new Set();
|
|
|
16023
16091
|
function runRecordProfilePhase(runner, phase, action) {
|
|
16024
16092
|
return runner === void 0 ? action() : runner(phase, action);
|
|
16025
16093
|
}
|
|
16026
|
-
function recordFrame(internals, world, cameras, lights, renderables, transparentDispatch, frameState, dispatchCounts, bindGroupCounts, skylight, skylightCount, skybox, skyboxCount, postProcessParams, worlds = [world], profilePhase, gpuDriven, renderReadLeases, featureGraphCandidate) {
|
|
16094
|
+
function recordFrame(internals, world, cameras, lights, renderables, transparentDispatch, frameState, dispatchCounts, bindGroupCounts, skylight, skylightCount, skybox, skyboxCount, postProcessParams, worlds = [world], profilePhase, gpuDriven, renderReadLeases, featureGraphCandidate, pointsLinesOwner) {
|
|
16027
16095
|
let activeCameras = cameras;
|
|
16028
16096
|
if (activeCameras.length === 0) {
|
|
16029
16097
|
internals.errorRegistry.fire(
|
|
@@ -16220,6 +16288,15 @@ function recordFrame(internals, world, cameras, lights, renderables, transparent
|
|
|
16220
16288
|
lights,
|
|
16221
16289
|
frameState.spotShadowSnapshots
|
|
16222
16290
|
);
|
|
16291
|
+
if (pipelineState.pointsLinesViewBuffer !== void 0) {
|
|
16292
|
+
writePointsLinesViewUbo(
|
|
16293
|
+
internals.device.queue,
|
|
16294
|
+
pipelineState.pointsLinesViewBuffer,
|
|
16295
|
+
camera,
|
|
16296
|
+
targetW,
|
|
16297
|
+
targetH
|
|
16298
|
+
);
|
|
16299
|
+
}
|
|
16223
16300
|
writeShadowCasterUniforms(
|
|
16224
16301
|
internals.device.queue,
|
|
16225
16302
|
pipelineState.shadowCasterCascadeBuffer,
|
|
@@ -16310,6 +16387,7 @@ function recordFrame(internals, world, cameras, lights, renderables, transparent
|
|
|
16310
16387
|
materialSlots,
|
|
16311
16388
|
materialSlotOwners,
|
|
16312
16389
|
materialSlotCount,
|
|
16390
|
+
pointsLines: pointsLinesOwner,
|
|
16313
16391
|
materialBgAssemblyCache: frameState.materialBgAssemblyCache,
|
|
16314
16392
|
directionalShadowCacheReuse: directionalShadowCache.reuse,
|
|
16315
16393
|
...profilePhase !== void 0 ? { profilePhase } : {}
|
|
@@ -16788,15 +16866,19 @@ function resolveMeshMaterialBindings(mesh, rendererOverrides, deps) {
|
|
|
16788
16866
|
return { ok: true, bindings, diagnostics };
|
|
16789
16867
|
}
|
|
16790
16868
|
|
|
16791
|
-
// src/
|
|
16792
|
-
|
|
16793
|
-
|
|
16794
|
-
|
|
16795
|
-
|
|
16796
|
-
|
|
16797
|
-
|
|
16798
|
-
|
|
16799
|
-
|
|
16869
|
+
// src/points-lines/bounds.ts
|
|
16870
|
+
function expandPointsLinesBounds(bounds, style) {
|
|
16871
|
+
if (bounds.length < 6 || style === void 0) return new Float32Array(bounds);
|
|
16872
|
+
const marginPx = style.kind === "points" ? style.sizePx * 0.5 : style.widthPx * 0.5;
|
|
16873
|
+
if (!Number.isFinite(marginPx) || marginPx <= 0) return new Float32Array(bounds);
|
|
16874
|
+
return new Float32Array([
|
|
16875
|
+
(bounds[0] ?? 0) - marginPx,
|
|
16876
|
+
(bounds[1] ?? 0) - marginPx,
|
|
16877
|
+
(bounds[2] ?? 0) - marginPx,
|
|
16878
|
+
(bounds[3] ?? 0) + marginPx,
|
|
16879
|
+
(bounds[4] ?? 0) + marginPx,
|
|
16880
|
+
(bounds[5] ?? 0) + marginPx
|
|
16881
|
+
]);
|
|
16800
16882
|
}
|
|
16801
16883
|
|
|
16802
16884
|
// src/render-system-extract.ts
|
|
@@ -16832,7 +16914,9 @@ function appendMaterialDispatchEntries(pendingDispatch, passes, entity, material
|
|
|
16832
16914
|
layer,
|
|
16833
16915
|
tags: passState.tags ?? {},
|
|
16834
16916
|
renderState: pipelineRenderState(passState),
|
|
16835
|
-
|
|
16917
|
+
// Material module identity is already closed in the cooked program.
|
|
16918
|
+
// It must never become a draw-time define map.
|
|
16919
|
+
defines: void 0,
|
|
16836
16920
|
vertexEntry: pass.program.vertexEntry,
|
|
16837
16921
|
fragmentEntry: pass.program.fragmentEntry,
|
|
16838
16922
|
materialShaderId: runtimeMaterialShaderId(pass.program.module, pass.name),
|
|
@@ -17023,7 +17107,7 @@ function isEngineInjectedTextureField(shaderId, fieldName) {
|
|
|
17023
17107
|
function materialParametersToParamSchema(parameters, shaderId) {
|
|
17024
17108
|
const engineInjectedTextureFields = isStandardPbrMaterialShader(shaderId) ? ENGINE_INJECTED_TEXTURE_FIELDS : void 0;
|
|
17025
17109
|
return parameters.flatMap((parameter) => {
|
|
17026
|
-
if (parameter.
|
|
17110
|
+
if (parameter.type === "bool") return [];
|
|
17027
17111
|
if (parameter.type === "texture") {
|
|
17028
17112
|
if (engineInjectedTextureFields?.has(parameter.name) === true) return [];
|
|
17029
17113
|
return [{ name: parameter.name, type: "texture2d" }];
|
|
@@ -17536,9 +17620,9 @@ function extractFrames(worlds, owner, assets, pipelineState, materialSnapshotCac
|
|
|
17536
17620
|
});
|
|
17537
17621
|
const frame = extractFrame(world, prepared);
|
|
17538
17622
|
framesByWorld.set(wi, frame);
|
|
17539
|
-
} catch (
|
|
17623
|
+
} catch (err29) {
|
|
17540
17624
|
try {
|
|
17541
|
-
createWorldInternalView(world)._routeError(
|
|
17625
|
+
createWorldInternalView(world)._routeError(err29, {
|
|
17542
17626
|
severity: Severity.Error,
|
|
17543
17627
|
systemName: `RenderSystem.extractFrames(world[${wi}])`
|
|
17544
17628
|
});
|
|
@@ -17571,7 +17655,11 @@ function extractFrames(worlds, owner, assets, pipelineState, materialSnapshotCac
|
|
|
17571
17655
|
}
|
|
17572
17656
|
hiddenEntityReports.push(...f.hiddenEntityReports);
|
|
17573
17657
|
for (const r of f.renderables) {
|
|
17574
|
-
renderables.push({
|
|
17658
|
+
renderables.push({
|
|
17659
|
+
...r,
|
|
17660
|
+
worldId: wId,
|
|
17661
|
+
...r.pointsLines === void 0 ? {} : { pointsLines: { ...r.pointsLines, worldId: wId } }
|
|
17662
|
+
});
|
|
17575
17663
|
}
|
|
17576
17664
|
for (const d of f.dispatch) {
|
|
17577
17665
|
dispatchEntries.push({ ...d, renderableIndex: (d.renderableIndex ?? 0) + base });
|
|
@@ -18133,7 +18221,10 @@ function extractFrame(world, context) {
|
|
|
18133
18221
|
Layer,
|
|
18134
18222
|
MorphWeights,
|
|
18135
18223
|
SpriteRegionOverride,
|
|
18136
|
-
SpriteInstances
|
|
18224
|
+
SpriteInstances,
|
|
18225
|
+
Points,
|
|
18226
|
+
Lines,
|
|
18227
|
+
SortKey
|
|
18137
18228
|
]
|
|
18138
18229
|
}).unwrap();
|
|
18139
18230
|
const resolveArchVersion = (entity) => {
|
|
@@ -18164,6 +18255,10 @@ function extractFrame(world, context) {
|
|
|
18164
18255
|
const hasMeshFilter = meshFilter !== void 0;
|
|
18165
18256
|
const hasSkin = skin !== void 0;
|
|
18166
18257
|
const hasSpriteInstances = row.has(SpriteInstances);
|
|
18258
|
+
const points = row.get(Points);
|
|
18259
|
+
const lines = row.get(Lines);
|
|
18260
|
+
const sortKey = row.get(SortKey)?.value;
|
|
18261
|
+
const pointsLinesComponent = points !== void 0 ? "Points" : lines !== void 0 ? "Lines" : void 0;
|
|
18167
18262
|
const isRenderable = hasTransform && hasMeshFilter;
|
|
18168
18263
|
const fAssetHandle = meshFilter?.assetHandle;
|
|
18169
18264
|
const fLayerValue = row.get(Layer)?.value;
|
|
@@ -18361,28 +18456,28 @@ function extractFrame(world, context) {
|
|
|
18361
18456
|
} else {
|
|
18362
18457
|
const resolvedResult = walkMaterialPassesOverSharedRefs(world, tagged, assets);
|
|
18363
18458
|
if (!resolvedResult.ok) {
|
|
18364
|
-
const
|
|
18365
|
-
switch (
|
|
18459
|
+
const err29 = resolvedResult.error;
|
|
18460
|
+
switch (err29.code) {
|
|
18366
18461
|
case "material-parent-not-found":
|
|
18367
18462
|
case "material-no-effective-pass":
|
|
18368
18463
|
case "material-value-unknown":
|
|
18369
18464
|
case "material-value-type-mismatch":
|
|
18370
18465
|
case "material-contract-program-mismatch":
|
|
18371
|
-
worldInternal._routeError(
|
|
18466
|
+
worldInternal._routeError(err29, {
|
|
18372
18467
|
severity: Severity.Error,
|
|
18373
|
-
systemName: `RenderSystem.extract (${
|
|
18468
|
+
systemName: `RenderSystem.extract (${err29.code})`
|
|
18374
18469
|
});
|
|
18375
18470
|
break;
|
|
18376
18471
|
case "material-circular-inheritance":
|
|
18377
|
-
worldInternal._routeError(
|
|
18472
|
+
worldInternal._routeError(err29, {
|
|
18378
18473
|
severity: Severity.Error,
|
|
18379
18474
|
systemName: "RenderSystem.extract (material-circular-inheritance)"
|
|
18380
18475
|
});
|
|
18381
18476
|
break;
|
|
18382
18477
|
default:
|
|
18383
|
-
worldInternal._routeError(
|
|
18478
|
+
worldInternal._routeError(err29, {
|
|
18384
18479
|
severity: Severity.Error,
|
|
18385
|
-
systemName: `RenderSystem.extract (_materialWalk: ${
|
|
18480
|
+
systemName: `RenderSystem.extract (_materialWalk: ${err29.code})`
|
|
18386
18481
|
});
|
|
18387
18482
|
}
|
|
18388
18483
|
continue;
|
|
@@ -18841,6 +18936,27 @@ function extractFrame(world, context) {
|
|
|
18841
18936
|
}
|
|
18842
18937
|
}
|
|
18843
18938
|
}
|
|
18939
|
+
const pointsLinesStyle = points !== void 0 ? (() => {
|
|
18940
|
+
const shape = pointShapeFromU32(points.shape);
|
|
18941
|
+
return shape === void 0 ? void 0 : { kind: "points", sizePx: points.sizePx, shape };
|
|
18942
|
+
})() : lines === void 0 ? void 0 : { kind: "lines", widthPx: lines.widthPx };
|
|
18943
|
+
const cullingLocalAabb = expandPointsLinesBounds(localAabb ?? [], pointsLinesStyle);
|
|
18944
|
+
const pointsLines = pointsLinesComponent === void 0 ? void 0 : {
|
|
18945
|
+
worldId: 0,
|
|
18946
|
+
entityKey: entity,
|
|
18947
|
+
component: pointsLinesComponent,
|
|
18948
|
+
meshHandle: assetHandleRaw,
|
|
18949
|
+
meshGeneration: assets?.catalogEpoch ?? 0,
|
|
18950
|
+
materialHandle: handleRaw,
|
|
18951
|
+
materialGeneration: assets?.catalogEpoch ?? 0,
|
|
18952
|
+
style: pointsLinesStyle,
|
|
18953
|
+
layer: layerVal,
|
|
18954
|
+
sortKey,
|
|
18955
|
+
visible: true,
|
|
18956
|
+
sourceBounds: cullingLocalAabb,
|
|
18957
|
+
viewport: { width: 0, height: 0, dpr: 1 },
|
|
18958
|
+
projection: identityProjection()
|
|
18959
|
+
};
|
|
18844
18960
|
let nonIndexedFirst = 0;
|
|
18845
18961
|
const gpuDrivenDraws = gpuDrivenSubmeshes.flatMap((submesh) => {
|
|
18846
18962
|
const drawMaterial = materialsArr[submesh.materialSlot] ?? materialSnap;
|
|
@@ -18863,7 +18979,7 @@ function extractFrame(world, context) {
|
|
|
18863
18979
|
const baseRenderable = {
|
|
18864
18980
|
assetHandle: Math.round(fAssetHandle ?? 0),
|
|
18865
18981
|
transform: transformSnap,
|
|
18866
|
-
...localAabb !== void 0 ? { localAabb } : {},
|
|
18982
|
+
...localAabb !== void 0 ? { localAabb: cullingLocalAabb } : {},
|
|
18867
18983
|
material: materialSnap,
|
|
18868
18984
|
materials: materialsArr,
|
|
18869
18985
|
materialBindingSources,
|
|
@@ -18873,11 +18989,12 @@ function extractFrame(world, context) {
|
|
|
18873
18989
|
entityKey: entity,
|
|
18874
18990
|
...skinSlice !== void 0 ? { skin: skinSlice } : {},
|
|
18875
18991
|
...morph !== void 0 ? { morph } : {},
|
|
18876
|
-
...spriteInstancesSnap !== void 0 ? { spriteInstances: spriteInstancesSnap } : {}
|
|
18992
|
+
...spriteInstancesSnap !== void 0 ? { spriteInstances: spriteInstancesSnap } : {},
|
|
18993
|
+
...pointsLines !== void 0 ? { pointsLines } : {}
|
|
18877
18994
|
};
|
|
18878
18995
|
if (localAabb !== void 0) {
|
|
18879
18996
|
const worldAabb = box3.create();
|
|
18880
|
-
box3.transformBox3(worldAabb,
|
|
18997
|
+
box3.transformBox3(worldAabb, cullingLocalAabb, transformSnap.world);
|
|
18881
18998
|
frustumTotal += 1;
|
|
18882
18999
|
let visible = frustumPlanes.length === 0;
|
|
18883
19000
|
for (let ci = 0; ci < frustumPlanes.length; ci++) {
|
|
@@ -18968,6 +19085,14 @@ function defaultMaterialSnapshot(materialHandle = 0) {
|
|
|
18968
19085
|
materialHandle
|
|
18969
19086
|
};
|
|
18970
19087
|
}
|
|
19088
|
+
function identityProjection() {
|
|
19089
|
+
const projection = new Float32Array(16);
|
|
19090
|
+
projection[0] = 1;
|
|
19091
|
+
projection[5] = 1;
|
|
19092
|
+
projection[10] = 1;
|
|
19093
|
+
projection[15] = 1;
|
|
19094
|
+
return projection;
|
|
19095
|
+
}
|
|
18971
19096
|
|
|
18972
19097
|
// src/gpu-driven/batch-topology.ts
|
|
18973
19098
|
function eligibleKeys(slot) {
|
|
@@ -19762,7 +19887,17 @@ function ownSnapshot(snapshot) {
|
|
|
19762
19887
|
transforms: new Float32Array(snapshot.spriteInstances.transforms),
|
|
19763
19888
|
regions: new Float32Array(snapshot.spriteInstances.regions)
|
|
19764
19889
|
}
|
|
19765
|
-
}
|
|
19890
|
+
},
|
|
19891
|
+
...snapshot.pointsLines === void 0 ? {} : { pointsLines: ownPointsLinesSnapshot(snapshot.pointsLines) }
|
|
19892
|
+
};
|
|
19893
|
+
}
|
|
19894
|
+
function ownPointsLinesSnapshot(snapshot) {
|
|
19895
|
+
return {
|
|
19896
|
+
...snapshot,
|
|
19897
|
+
style: snapshot.style === void 0 ? void 0 : { ...snapshot.style },
|
|
19898
|
+
sourceBounds: new Float32Array(snapshot.sourceBounds),
|
|
19899
|
+
viewport: { ...snapshot.viewport },
|
|
19900
|
+
projection: new Float32Array(snapshot.projection)
|
|
19766
19901
|
};
|
|
19767
19902
|
}
|
|
19768
19903
|
function withWorld(snapshot, world) {
|
|
@@ -19803,6 +19938,10 @@ var RenderScene = class {
|
|
|
19803
19938
|
freeSlots = [];
|
|
19804
19939
|
slotsByWorld = /* @__PURE__ */ new Map();
|
|
19805
19940
|
slotsByMaterial = /* @__PURE__ */ new Map();
|
|
19941
|
+
// World bounds are a pure projection of each immutable snapshot. Cache the
|
|
19942
|
+
// derived value by snapshot identity so repeated view queries do not redo
|
|
19943
|
+
// the eight-corner transform for every view in the same frame.
|
|
19944
|
+
worldBoundsCache = /* @__PURE__ */ new WeakMap();
|
|
19806
19945
|
orderedSlots = [];
|
|
19807
19946
|
materialized;
|
|
19808
19947
|
slotSnapshot;
|
|
@@ -19994,6 +20133,17 @@ var RenderScene = class {
|
|
|
19994
20133
|
snapshot(worldId, entityKey) {
|
|
19995
20134
|
return this.lookup(worldId, entityKey)?.snapshot;
|
|
19996
20135
|
}
|
|
20136
|
+
pointsLinesSnapshots() {
|
|
20137
|
+
const snapshots = [];
|
|
20138
|
+
for (const slot of this.orderedSlots) {
|
|
20139
|
+
const record = this.slots[slot];
|
|
20140
|
+
const snapshot = record?.snapshot.pointsLines;
|
|
20141
|
+
if (record !== void 0 && snapshot !== void 0) {
|
|
20142
|
+
snapshots.push(ownPointsLinesSnapshot({ ...snapshot, worldId: record.worldId }));
|
|
20143
|
+
}
|
|
20144
|
+
}
|
|
20145
|
+
return Object.freeze(snapshots);
|
|
20146
|
+
}
|
|
19997
20147
|
slotsForMaterial(materialHandle) {
|
|
19998
20148
|
const slots = this.slotsByMaterial.get(materialHandle);
|
|
19999
20149
|
if (slots === void 0) return [];
|
|
@@ -20009,8 +20159,14 @@ var RenderScene = class {
|
|
|
20009
20159
|
for (const slot of this.orderedSlots) {
|
|
20010
20160
|
const record = this.slots[slot];
|
|
20011
20161
|
if (record === void 0) continue;
|
|
20012
|
-
const
|
|
20013
|
-
|
|
20162
|
+
const snapshot = record.snapshot;
|
|
20163
|
+
let candidate = this.worldBoundsCache.get(snapshot);
|
|
20164
|
+
if (candidate === void 0 && !this.worldBoundsCache.has(snapshot)) {
|
|
20165
|
+
candidate = worldBounds(snapshot) ?? null;
|
|
20166
|
+
this.worldBoundsCache.set(snapshot, candidate);
|
|
20167
|
+
}
|
|
20168
|
+
if (candidate === null || candidate === void 0) continue;
|
|
20169
|
+
if (intersects(candidate, bounds)) records.push(record);
|
|
20014
20170
|
}
|
|
20015
20171
|
return records;
|
|
20016
20172
|
}
|
|
@@ -20230,6 +20386,7 @@ var PersistentRenderScene = class {
|
|
|
20230
20386
|
gpuOwner;
|
|
20231
20387
|
gpuDevice;
|
|
20232
20388
|
gpuStatus = "inactive";
|
|
20389
|
+
pointsLinesInspections = [];
|
|
20233
20390
|
/** RenderScene owns the per-World material fact cache used during extraction. */
|
|
20234
20391
|
materialSnapshotCacheStore() {
|
|
20235
20392
|
return this.materialSnapshotCaches;
|
|
@@ -20375,6 +20532,13 @@ var PersistentRenderScene = class {
|
|
|
20375
20532
|
this.gpuDevice = void 0;
|
|
20376
20533
|
this.gpuStatus = this.options.getDevice === void 0 ? "inactive" : "rebuild-pending";
|
|
20377
20534
|
}
|
|
20535
|
+
setPointsLinesInspections(inspections) {
|
|
20536
|
+
this.pointsLinesInspections = inspections.map((inspection) => ({
|
|
20537
|
+
...inspection,
|
|
20538
|
+
cache: { ...inspection.cache },
|
|
20539
|
+
...inspection.refusal === void 0 ? {} : { refusal: { ...inspection.refusal } }
|
|
20540
|
+
}));
|
|
20541
|
+
}
|
|
20378
20542
|
dispose() {
|
|
20379
20543
|
this.gpuScene?.dispose();
|
|
20380
20544
|
this.gpuScene = void 0;
|
|
@@ -20382,9 +20546,11 @@ var PersistentRenderScene = class {
|
|
|
20382
20546
|
this.gpuDevice = void 0;
|
|
20383
20547
|
this.gpuStatus = "inactive";
|
|
20384
20548
|
this.composition = void 0;
|
|
20549
|
+
this.pointsLinesInspections = [];
|
|
20385
20550
|
}
|
|
20386
20551
|
inspect() {
|
|
20387
20552
|
const entry = this.composition;
|
|
20553
|
+
const pointsLines = this.pointsLinesInspections;
|
|
20388
20554
|
return {
|
|
20389
20555
|
worldEntitiesScanned: this.worldEntitiesScanned,
|
|
20390
20556
|
fullRebuilds: this.fullRebuilds,
|
|
@@ -20401,7 +20567,8 @@ var PersistentRenderScene = class {
|
|
|
20401
20567
|
patches: 0,
|
|
20402
20568
|
ineligible: 0
|
|
20403
20569
|
},
|
|
20404
|
-
gpu: this.inspectGpu()
|
|
20570
|
+
gpu: this.inspectGpu(),
|
|
20571
|
+
pointsLines
|
|
20405
20572
|
};
|
|
20406
20573
|
}
|
|
20407
20574
|
compositionGpuDrivenState() {
|
|
@@ -20415,6 +20582,9 @@ var PersistentRenderScene = class {
|
|
|
20415
20582
|
slots: entry.projection.slotsSnapshot()
|
|
20416
20583
|
};
|
|
20417
20584
|
}
|
|
20585
|
+
pointsLinesSnapshots() {
|
|
20586
|
+
return this.composition?.projection.pointsLinesSnapshots() ?? [];
|
|
20587
|
+
}
|
|
20418
20588
|
inspectGpu() {
|
|
20419
20589
|
if (this.gpuStatus === "resident" && this.gpuScene !== void 0) {
|
|
20420
20590
|
return { status: "resident", ...this.gpuScene.inspect() };
|
|
@@ -20628,6 +20798,242 @@ function makePreparedPipelinePendingError() {
|
|
|
20628
20798
|
hint: "retry the prepared graphics pass on the next frame"
|
|
20629
20799
|
});
|
|
20630
20800
|
}
|
|
20801
|
+
var StandardPointsLinesOwner = class {
|
|
20802
|
+
constructor(internals) {
|
|
20803
|
+
this.internals = internals;
|
|
20804
|
+
}
|
|
20805
|
+
internals;
|
|
20806
|
+
cache = new PointsLinesExpansionCache();
|
|
20807
|
+
preparations = /* @__PURE__ */ new Map();
|
|
20808
|
+
active = /* @__PURE__ */ new Map();
|
|
20809
|
+
layoutProjection = deriveVertexLayoutProjection({
|
|
20810
|
+
position: new Float32Array(0),
|
|
20811
|
+
normal: new Float32Array(0),
|
|
20812
|
+
uv: new Float32Array(0),
|
|
20813
|
+
tangent: new Float32Array(0)
|
|
20814
|
+
});
|
|
20815
|
+
beginFrame() {
|
|
20816
|
+
this.active.clear();
|
|
20817
|
+
}
|
|
20818
|
+
prepare(entry, clustered) {
|
|
20819
|
+
const snapshot = entry.source.pointsLines;
|
|
20820
|
+
if (snapshot === void 0 || snapshot.component === void 0 || entry.world === void 0) {
|
|
20821
|
+
return void 0;
|
|
20822
|
+
}
|
|
20823
|
+
const key = `${snapshot.worldId}:${snapshot.entityKey}`;
|
|
20824
|
+
const topology = snapshot.component === "Points" ? "point-list" : "line-list";
|
|
20825
|
+
const backend = this.backend();
|
|
20826
|
+
const lane = backend === "wgpu-webgl2" ? "cpu-webgl2" : clustered ? "clustered" : "direct";
|
|
20827
|
+
const meshResult = resolveAssetHandle(
|
|
20828
|
+
entry.world,
|
|
20829
|
+
toShared(entry.source.assetHandle)
|
|
20830
|
+
);
|
|
20831
|
+
const materialResult = resolveAssetHandle(
|
|
20832
|
+
entry.world,
|
|
20833
|
+
toShared(snapshot.materialHandle)
|
|
20834
|
+
);
|
|
20835
|
+
if (!meshResult.ok || !materialResult.ok) {
|
|
20836
|
+
this.publishRefusal(
|
|
20837
|
+
snapshot,
|
|
20838
|
+
new PointsLinesMaterialUnsupportedError({
|
|
20839
|
+
entity: snapshot.entityKey,
|
|
20840
|
+
material: "unresolved",
|
|
20841
|
+
pass: "forward",
|
|
20842
|
+
module: "asset-resolution",
|
|
20843
|
+
reason: "source MeshAsset or MaterialAsset could not be resolved"
|
|
20844
|
+
})
|
|
20845
|
+
);
|
|
20846
|
+
return void 0;
|
|
20847
|
+
}
|
|
20848
|
+
const admission = admitPointsLines({
|
|
20849
|
+
entity: snapshot.entityKey,
|
|
20850
|
+
mesh: meshResult.value,
|
|
20851
|
+
material: materialResult.value,
|
|
20852
|
+
...snapshot.style?.kind === "points" ? {
|
|
20853
|
+
points: {
|
|
20854
|
+
sizePx: snapshot.style.sizePx,
|
|
20855
|
+
shape: snapshot.style.shape === "circle" ? 1 : 0
|
|
20856
|
+
}
|
|
20857
|
+
} : { lines: { widthPx: snapshot.style?.widthPx ?? 1 } }
|
|
20858
|
+
});
|
|
20859
|
+
if (!admission.ok) {
|
|
20860
|
+
this.publishRefusal(snapshot, admission.error);
|
|
20861
|
+
return void 0;
|
|
20862
|
+
}
|
|
20863
|
+
const geometryKey = this.cache.getOrCreate(snapshot, meshResult.value).key;
|
|
20864
|
+
const prepKey = `${geometryKey}:${lane}:${backend}`;
|
|
20865
|
+
let preparation = this.preparations.get(prepKey);
|
|
20866
|
+
if (preparation === void 0) {
|
|
20867
|
+
preparation = createPointsLinesLanePreparationAdapter(lane, backend, {
|
|
20868
|
+
cache: this.cache,
|
|
20869
|
+
adapter: {
|
|
20870
|
+
create: (geometry) => {
|
|
20871
|
+
const vertex = this.internals.device.createBuffer({
|
|
20872
|
+
label: `points-lines-vertices:${geometryKey}`,
|
|
20873
|
+
size: Math.max(4, geometry.vertices.byteLength),
|
|
20874
|
+
usage: GPU_BUFFER_USAGE_VERTEX | GPU_BUFFER_USAGE_COPY_DST,
|
|
20875
|
+
mappedAtCreation: false
|
|
20876
|
+
});
|
|
20877
|
+
if (!vertex.ok) return err(vertex.error);
|
|
20878
|
+
const index = this.internals.device.createBuffer({
|
|
20879
|
+
label: `points-lines-indices:${geometryKey}`,
|
|
20880
|
+
size: Math.max(4, geometry.indices.byteLength),
|
|
20881
|
+
usage: GPU_BUFFER_USAGE_INDEX | GPU_BUFFER_USAGE_COPY_DST,
|
|
20882
|
+
mappedAtCreation: false
|
|
20883
|
+
});
|
|
20884
|
+
if (!index.ok) {
|
|
20885
|
+
this.internals.device.destroyBuffer(vertex.value);
|
|
20886
|
+
return err(index.error);
|
|
20887
|
+
}
|
|
20888
|
+
return ok({ vertexBuffer: vertex.value, indexBuffer: index.value });
|
|
20889
|
+
},
|
|
20890
|
+
upload: (resource, geometry) => {
|
|
20891
|
+
if (geometry.vertices.byteLength > 0) {
|
|
20892
|
+
const vertexWrite = this.internals.device.queue.writeBuffer(
|
|
20893
|
+
resource.vertexBuffer,
|
|
20894
|
+
0,
|
|
20895
|
+
geometry.vertices
|
|
20896
|
+
);
|
|
20897
|
+
if (!vertexWrite.ok) return err(vertexWrite.error);
|
|
20898
|
+
}
|
|
20899
|
+
if (geometry.indices.byteLength > 0) {
|
|
20900
|
+
const indexWrite = this.internals.device.queue.writeBuffer(
|
|
20901
|
+
resource.indexBuffer,
|
|
20902
|
+
0,
|
|
20903
|
+
geometry.indices
|
|
20904
|
+
);
|
|
20905
|
+
if (!indexWrite.ok) return err(indexWrite.error);
|
|
20906
|
+
}
|
|
20907
|
+
return ok(geometry.derivedBytes);
|
|
20908
|
+
},
|
|
20909
|
+
validate: (_resource, geometry) => geometry.expandedVertexCount > 0 && geometry.expandedIndexCount > 0 ? ok(void 0) : err(new Error("Points/Lines expansion contains no drawable triangles")),
|
|
20910
|
+
destroy: (resource) => {
|
|
20911
|
+
this.internals.device.destroyBuffer(resource.vertexBuffer);
|
|
20912
|
+
this.internals.device.destroyBuffer(resource.indexBuffer);
|
|
20913
|
+
}
|
|
20914
|
+
}
|
|
20915
|
+
});
|
|
20916
|
+
this.preparations.set(prepKey, preparation);
|
|
20917
|
+
}
|
|
20918
|
+
const prepared = preparation.prepare(snapshot, meshResult.value);
|
|
20919
|
+
if (!prepared.ok) {
|
|
20920
|
+
const lkg = preparation.lastKnownGood();
|
|
20921
|
+
if (lkg !== void 0) {
|
|
20922
|
+
const lkgPlan = createPointsLinesLaneAdapter(lane, backend).createRecordPlan(
|
|
20923
|
+
lkg.snapshot,
|
|
20924
|
+
lkg.geometry
|
|
20925
|
+
);
|
|
20926
|
+
const state2 = preparation.inspect();
|
|
20927
|
+
this.active.set(
|
|
20928
|
+
key,
|
|
20929
|
+
inspectPointsLines({
|
|
20930
|
+
snapshot,
|
|
20931
|
+
topology,
|
|
20932
|
+
lane,
|
|
20933
|
+
pointCount: lkg.geometry.pointCount,
|
|
20934
|
+
segmentCount: lkg.geometry.segmentCount,
|
|
20935
|
+
sourceBytes: lkg.geometry.sourceBytes,
|
|
20936
|
+
derivedBytes: lkg.geometry.derivedBytes,
|
|
20937
|
+
cache: { hit: true, rebuilds: state2.rebuilds, evictions: 0 },
|
|
20938
|
+
drawCount: lkgPlan.drawCount,
|
|
20939
|
+
uploadBytes: 0,
|
|
20940
|
+
lastKnownGood: true,
|
|
20941
|
+
refusal: {
|
|
20942
|
+
code: prepared.error.code,
|
|
20943
|
+
expected: prepared.error.expected,
|
|
20944
|
+
hint: prepared.error.hint,
|
|
20945
|
+
detail: prepared.error.detail,
|
|
20946
|
+
generation: prepared.error.detail.generation,
|
|
20947
|
+
lastKnownGood: true
|
|
20948
|
+
}
|
|
20949
|
+
})
|
|
20950
|
+
);
|
|
20951
|
+
return {
|
|
20952
|
+
plan: lkgPlan,
|
|
20953
|
+
vertexBuffer: lkg.resource.vertexBuffer,
|
|
20954
|
+
indexBuffer: lkg.resource.indexBuffer,
|
|
20955
|
+
layoutProjection: this.layoutProjection
|
|
20956
|
+
};
|
|
20957
|
+
}
|
|
20958
|
+
this.publishRefusal(snapshot, prepared.error);
|
|
20959
|
+
return void 0;
|
|
20960
|
+
}
|
|
20961
|
+
const plan = createPointsLinesLaneAdapter(lane, backend).createRecordPlan(
|
|
20962
|
+
snapshot,
|
|
20963
|
+
prepared.value.geometry
|
|
20964
|
+
);
|
|
20965
|
+
const state = preparation.inspect();
|
|
20966
|
+
this.active.set(
|
|
20967
|
+
key,
|
|
20968
|
+
inspectPointsLines({
|
|
20969
|
+
snapshot,
|
|
20970
|
+
topology,
|
|
20971
|
+
lane,
|
|
20972
|
+
pointCount: prepared.value.geometry.pointCount,
|
|
20973
|
+
segmentCount: prepared.value.geometry.segmentCount,
|
|
20974
|
+
sourceBytes: prepared.value.geometry.sourceBytes,
|
|
20975
|
+
derivedBytes: prepared.value.geometry.derivedBytes,
|
|
20976
|
+
cache: {
|
|
20977
|
+
hit: prepared.value.uploadedBytes === 0,
|
|
20978
|
+
rebuilds: state.rebuilds,
|
|
20979
|
+
evictions: 0
|
|
20980
|
+
},
|
|
20981
|
+
drawCount: plan.drawCount,
|
|
20982
|
+
uploadBytes: prepared.value.uploadedBytes,
|
|
20983
|
+
lastKnownGood: prepared.value.lastKnownGood
|
|
20984
|
+
})
|
|
20985
|
+
);
|
|
20986
|
+
return {
|
|
20987
|
+
plan,
|
|
20988
|
+
vertexBuffer: prepared.value.resource.vertexBuffer,
|
|
20989
|
+
indexBuffer: prepared.value.resource.indexBuffer,
|
|
20990
|
+
layoutProjection: this.layoutProjection
|
|
20991
|
+
};
|
|
20992
|
+
}
|
|
20993
|
+
resetForDeviceLoss() {
|
|
20994
|
+
for (const preparation of this.preparations.values()) preparation.resetForDeviceLoss();
|
|
20995
|
+
this.active.clear();
|
|
20996
|
+
}
|
|
20997
|
+
inspections() {
|
|
20998
|
+
return [...this.active.values()];
|
|
20999
|
+
}
|
|
21000
|
+
backend() {
|
|
21001
|
+
switch (this.internals.device.caps.backendKind) {
|
|
21002
|
+
case "wgpu-webgl2":
|
|
21003
|
+
return "wgpu-webgl2";
|
|
21004
|
+
case "null":
|
|
21005
|
+
return "null";
|
|
21006
|
+
default:
|
|
21007
|
+
return "webgpu";
|
|
21008
|
+
}
|
|
21009
|
+
}
|
|
21010
|
+
publishRefusal(snapshot, error) {
|
|
21011
|
+
this.active.set(
|
|
21012
|
+
`${snapshot.worldId}:${snapshot.entityKey}`,
|
|
21013
|
+
inspectPointsLines({
|
|
21014
|
+
snapshot,
|
|
21015
|
+
topology: snapshot.component === "Points" ? "point-list" : "line-list",
|
|
21016
|
+
lane: "refused",
|
|
21017
|
+
pointCount: 0,
|
|
21018
|
+
segmentCount: 0,
|
|
21019
|
+
sourceBytes: 0,
|
|
21020
|
+
derivedBytes: 0,
|
|
21021
|
+
cache: { hit: false, rebuilds: 0, evictions: 0 },
|
|
21022
|
+
drawCount: 0,
|
|
21023
|
+
uploadBytes: 0,
|
|
21024
|
+
lastKnownGood: false,
|
|
21025
|
+
refusal: {
|
|
21026
|
+
code: error.code,
|
|
21027
|
+
expected: error.expected,
|
|
21028
|
+
hint: error.hint,
|
|
21029
|
+
detail: error.detail,
|
|
21030
|
+
generation: snapshot.meshGeneration,
|
|
21031
|
+
lastKnownGood: false
|
|
21032
|
+
}
|
|
21033
|
+
})
|
|
21034
|
+
);
|
|
21035
|
+
}
|
|
21036
|
+
};
|
|
20631
21037
|
function createRenderSystem(internals) {
|
|
20632
21038
|
const phaseCatalogRegistration = internals.profiler?.registerPhaseCatalog(
|
|
20633
21039
|
"render",
|
|
@@ -20635,6 +21041,7 @@ function createRenderSystem(internals) {
|
|
|
20635
21041
|
);
|
|
20636
21042
|
let releaseProfilerCatalog = phaseCatalogRegistration?.ok === true ? phaseCatalogRegistration.value : void 0;
|
|
20637
21043
|
let preparedWorlds = [];
|
|
21044
|
+
const pointsLinesOwner = new StandardPointsLinesOwner(internals);
|
|
20638
21045
|
const persistentRenderScene = new PersistentRenderScene({
|
|
20639
21046
|
getDevice: () => internals.device,
|
|
20640
21047
|
onGpuError: (error) => internals.errorRegistry.fire(error),
|
|
@@ -21152,6 +21559,9 @@ function createRenderSystem(internals) {
|
|
|
21152
21559
|
gpuDriven: gpuDrivenProduction.inspect()
|
|
21153
21560
|
};
|
|
21154
21561
|
},
|
|
21562
|
+
get pointsLinesSnapshots() {
|
|
21563
|
+
return persistentRenderScene.pointsLinesSnapshots();
|
|
21564
|
+
},
|
|
21155
21565
|
detachScene(world) {
|
|
21156
21566
|
persistentRenderScene.detach(world);
|
|
21157
21567
|
},
|
|
@@ -21168,6 +21578,7 @@ function createRenderSystem(internals) {
|
|
|
21168
21578
|
}
|
|
21169
21579
|
}
|
|
21170
21580
|
try {
|
|
21581
|
+
pointsLinesOwner.beginFrame();
|
|
21171
21582
|
const { cameraOwner, resourceOwner } = opts;
|
|
21172
21583
|
if (frameState.installedPipelineHandle !== lastBuiltPipelineHandle) {
|
|
21173
21584
|
resetRenderFeatureGraphState(internals);
|
|
@@ -21330,9 +21741,11 @@ function createRenderSystem(internals) {
|
|
|
21330
21741
|
}
|
|
21331
21742
|
},
|
|
21332
21743
|
renderReadLeases,
|
|
21333
|
-
featureGraphCandidate
|
|
21744
|
+
featureGraphCandidate,
|
|
21745
|
+
pointsLinesOwner
|
|
21334
21746
|
)
|
|
21335
21747
|
);
|
|
21748
|
+
persistentRenderScene.setPointsLinesInspections(pointsLinesOwner.inspections());
|
|
21336
21749
|
if (internals.featureHost !== void 0 && preparedResourceBatches.length > 0) {
|
|
21337
21750
|
const batches = preparedResourceBatches;
|
|
21338
21751
|
if (submitted) {
|
|
@@ -21348,8 +21761,8 @@ function createRenderSystem(internals) {
|
|
|
21348
21761
|
if (!retired.ok) internals.errorRegistry.fire(retired.error);
|
|
21349
21762
|
}
|
|
21350
21763
|
}
|
|
21351
|
-
} catch (
|
|
21352
|
-
const innerError =
|
|
21764
|
+
} catch (err29) {
|
|
21765
|
+
const innerError = err29 instanceof RhiError ? err29 : { code: "unknown", message: String(err29), name: err29?.name };
|
|
21353
21766
|
internals.errorRegistry.fire(
|
|
21354
21767
|
new RhiError({
|
|
21355
21768
|
code: "webgpu-runtime-error",
|
|
@@ -22468,7 +22881,7 @@ function selectHdrpPbrPrewarmVariants(manifestEntry, storageBufferCapable) {
|
|
|
22468
22881
|
) ?? [];
|
|
22469
22882
|
}
|
|
22470
22883
|
function selectNoColorPbrVariant(manifestEntry, storageBufferCapable, variantSet) {
|
|
22471
|
-
const hdrpRequested = variantSet === "" || variantSet?.includes("CLUSTER_FORWARD_AVAILABLE=true")
|
|
22884
|
+
const hdrpRequested = variantSet === "" || (variantSet?.includes("CLUSTER_FORWARD_AVAILABLE=true") ?? false);
|
|
22472
22885
|
return manifestEntry?.variants.find(
|
|
22473
22886
|
(variant) => variant.defines.STORAGE_BUFFER_AVAILABLE === storageBufferCapable && variant.defines.VERTEX_COLOR_AVAILABLE === false && (!("CLUSTER_FORWARD_AVAILABLE" in variant.defines) || variant.defines.CLUSTER_FORWARD_AVAILABLE === hdrpRequested)
|
|
22474
22887
|
);
|
|
@@ -22544,6 +22957,9 @@ function resolveMaterialShaderVariantSet(requestedVariantSet, variants, backendK
|
|
|
22544
22957
|
const sorted = Object.entries(filtered).sort(([a], [b]) => a < b ? -1 : a > b ? 1 : 0);
|
|
22545
22958
|
return sorted.every(([, value]) => value) ? requestedVariantSet === "" ? "" : void 0 : sorted.map(([name, value]) => `${name}=${value}`).join("+");
|
|
22546
22959
|
}
|
|
22960
|
+
function normalizeMaterialShaderVariantSet(requestedVariantSet, manifestEntry) {
|
|
22961
|
+
return manifestEntry !== void 0 && manifestEntry.variants.length === 0 ? void 0 : requestedVariantSet;
|
|
22962
|
+
}
|
|
22547
22963
|
async function createRenderer(canvas, options, bundler, backend) {
|
|
22548
22964
|
const pack = backend ?? (options?.rhi === void 0 ? void 0 : loadRhiPack({ rhi: options.rhi, ...options.rhi }, options.rhiInstrumentation));
|
|
22549
22965
|
if (pack === void 0) {
|
|
@@ -22594,20 +23010,20 @@ function attachDeviceLostFanout(device, pack, registries) {
|
|
|
22594
23010
|
);
|
|
22595
23011
|
}
|
|
22596
23012
|
}
|
|
22597
|
-
}).catch((
|
|
23013
|
+
}).catch((err29) => {
|
|
22598
23014
|
pack.instrumentation?.onDeviceLost?.();
|
|
22599
|
-
onDeviceLost?.(`device.lost rejected: ${String(
|
|
22600
|
-
lostRegistry.fire({ reason: "unknown", message: String(
|
|
23015
|
+
onDeviceLost?.(`device.lost rejected: ${String(err29)}`);
|
|
23016
|
+
lostRegistry.fire({ reason: "unknown", message: String(err29) });
|
|
22601
23017
|
healthRegistry.fire({
|
|
22602
23018
|
reason: "device-lost",
|
|
22603
|
-
detail: { lostReason: "unknown", message: String(
|
|
23019
|
+
detail: { lostReason: "unknown", message: String(err29) },
|
|
22604
23020
|
recoverable: true
|
|
22605
23021
|
});
|
|
22606
23022
|
errorRegistry.fire(
|
|
22607
23023
|
new RhiError({
|
|
22608
23024
|
code: "device-lost",
|
|
22609
23025
|
expected: "device.lost Promise resolves with GPUDeviceLostInfo",
|
|
22610
|
-
hint: `device.lost Promise rejected unexpectedly: ${String(
|
|
23026
|
+
hint: `device.lost Promise rejected unexpectedly: ${String(err29)}`
|
|
22611
23027
|
})
|
|
22612
23028
|
);
|
|
22613
23029
|
});
|
|
@@ -23181,7 +23597,7 @@ async function makeWebGPURenderer(internals) {
|
|
|
23181
23597
|
const resolvedUvSetCount = shaderUvSetCount ?? materialShaderUvSetCounts.get(materialShaderId);
|
|
23182
23598
|
const manifestEntry = findMaterialShaderManifestEntry(materialShaderId);
|
|
23183
23599
|
const resolvedVariantSet = resolveCachedMaterialShaderVariantSet(variantSet, manifestEntry);
|
|
23184
|
-
let effectiveVariantSet = resolvedVariantSet;
|
|
23600
|
+
let effectiveVariantSet = normalizeMaterialShaderVariantSet(resolvedVariantSet, manifestEntry);
|
|
23185
23601
|
if (vertexLayoutProjection === void 0 && manifestEntry?.variants.some((variant) => "VERTEX_COLOR_AVAILABLE" in variant.defines)) {
|
|
23186
23602
|
if (effectiveVariantSet === "") {
|
|
23187
23603
|
const noColorVariant = manifestEntry.variants.find(
|
|
@@ -23573,6 +23989,7 @@ async function makeWebGPURenderer(internals) {
|
|
|
23573
23989
|
features: Object.freeze(
|
|
23574
23990
|
(internals.featureHost?.features ?? []).map((feature) => feature.identity)
|
|
23575
23991
|
),
|
|
23992
|
+
featureDiagnostics: internals.featureHost?.diagnostics() ?? Object.freeze([]),
|
|
23576
23993
|
frustumStats: Object.freeze({ ...renderSystem.frustumStats }),
|
|
23577
23994
|
visibilityStats: Object.freeze({ ...renderSystem.visibilityStats }),
|
|
23578
23995
|
renderScene: renderSystem.renderScene,
|
|
@@ -24356,6 +24773,13 @@ function exposeRenderer(renderer) {
|
|
|
24356
24773
|
draw: (request) => {
|
|
24357
24774
|
const result = renderer.drawFrame(request);
|
|
24358
24775
|
if (!result.ok) return err(drawError(result.error));
|
|
24776
|
+
emit(
|
|
24777
|
+
Object.freeze({
|
|
24778
|
+
kind: "frame-submitted",
|
|
24779
|
+
frameId: result.value.frameId,
|
|
24780
|
+
deviceGeneration: result.value.deviceGeneration
|
|
24781
|
+
})
|
|
24782
|
+
);
|
|
24359
24783
|
return ok(result.value);
|
|
24360
24784
|
},
|
|
24361
24785
|
inspect: () => renderer.inspect(),
|
|
@@ -24989,6 +25413,24 @@ async function buildReadyWebGPU(rhiDevice, getShader, gpuStore, asyncCreateShade
|
|
|
24989
25413
|
brdfLut: iblBrdfLutEntry.wgsl
|
|
24990
25414
|
});
|
|
24991
25415
|
}
|
|
25416
|
+
const pointsLinesLookup = registry.findMaterialArtifact(POINTS_LINES_MATERIAL_SHADER_ID);
|
|
25417
|
+
if (pointsLinesLookup.ok) {
|
|
25418
|
+
const pointsLinesLabel = `module-${POINTS_LINES_MATERIAL_SHADER_ID}`;
|
|
25419
|
+
const pointsLinesShaderResult = await runShimStep(
|
|
25420
|
+
() => asyncCreateShaderModule ? asyncCreateShaderModule(rhiDevice, {
|
|
25421
|
+
code: pointsLinesLookup.value.source,
|
|
25422
|
+
label: pointsLinesLabel
|
|
25423
|
+
}) : invokeDeviceCreateShaderModule(rhiDevice, {
|
|
25424
|
+
code: pointsLinesLookup.value.source,
|
|
25425
|
+
label: pointsLinesLabel
|
|
25426
|
+
}),
|
|
25427
|
+
"shader-compile-failed",
|
|
25428
|
+
`engine material shader '${POINTS_LINES_MATERIAL_SHADER_ID}' compiled`,
|
|
25429
|
+
`inspect the composed WGSL for '${POINTS_LINES_MATERIAL_SHADER_ID}' and check device.features`
|
|
25430
|
+
);
|
|
25431
|
+
if (!pointsLinesShaderResult.ok) throw pointsLinesShaderResult.error;
|
|
25432
|
+
seedShaderModule(pointsLinesLabel, pointsLinesShaderResult.value);
|
|
25433
|
+
}
|
|
24992
25434
|
for (const materialShaderId of requiredMaterialShaders) {
|
|
24993
25435
|
const lookup = registry.findMaterialArtifact(materialShaderId);
|
|
24994
25436
|
if (!lookup.ok) {
|
|
@@ -25452,6 +25894,18 @@ async function buildReadyWebGPU(rhiDevice, getShader, gpuStore, asyncCreateShade
|
|
|
25452
25894
|
"check device.limits.maxUniformBufferBindingSize"
|
|
25453
25895
|
);
|
|
25454
25896
|
if (!viewUboResult.ok) throw viewUboResult.error;
|
|
25897
|
+
const pointsLinesViewBufferResult = runShimSyncStep(
|
|
25898
|
+
() => rhiDevice.createBuffer({
|
|
25899
|
+
label: "points-lines-view-ubo",
|
|
25900
|
+
size: POINTS_LINES_VIEW_BUFFER_SIZE,
|
|
25901
|
+
usage: GPU_BUFFER_USAGE_UNIFORM | GPU_BUFFER_USAGE_COPY_DST,
|
|
25902
|
+
mappedAtCreation: false
|
|
25903
|
+
}),
|
|
25904
|
+
"webgpu-runtime-error",
|
|
25905
|
+
"createBuffer (points-lines view ubo) succeeded",
|
|
25906
|
+
"check device.limits.maxUniformBufferBindingSize"
|
|
25907
|
+
);
|
|
25908
|
+
if (!pointsLinesViewBufferResult.ok) throw pointsLinesViewBufferResult.error;
|
|
25455
25909
|
const shadowCasterCascadeUboResult = runShimSyncStep(
|
|
25456
25910
|
() => rhiDevice.createBuffer({
|
|
25457
25911
|
label: "shadow-caster-cascade-ubo",
|
|
@@ -25927,11 +26381,11 @@ async function buildReadyWebGPU(rhiDevice, getShader, gpuStore, asyncCreateShade
|
|
|
25927
26381
|
}
|
|
25928
26382
|
try {
|
|
25929
26383
|
getOrBuildPipeline(spec, pipelineDeviceProvider, pipelineCache, modules);
|
|
25930
|
-
} catch (
|
|
25931
|
-
if (
|
|
26384
|
+
} catch (err29) {
|
|
26385
|
+
if (err29 instanceof PipelineSpecError) throw err29;
|
|
25932
26386
|
throw new PipelineSpecError({
|
|
25933
26387
|
code: "pipeline-build-failed",
|
|
25934
|
-
detail: { cause:
|
|
26388
|
+
detail: { cause: err29 },
|
|
25935
26389
|
hint: `Boot-time SPEC_CONST pre-warm failed for shader '${spec.shader.id}'; inspect gpuMessage on the cause`
|
|
25936
26390
|
});
|
|
25937
26391
|
}
|
|
@@ -26051,11 +26505,11 @@ async function buildReadyWebGPU(rhiDevice, getShader, gpuStore, asyncCreateShade
|
|
|
26051
26505
|
pipelineCache,
|
|
26052
26506
|
modules
|
|
26053
26507
|
);
|
|
26054
|
-
} catch (
|
|
26055
|
-
if (
|
|
26508
|
+
} catch (err29) {
|
|
26509
|
+
if (err29 instanceof PipelineSpecError) throw err29;
|
|
26056
26510
|
throw new PipelineSpecError({
|
|
26057
26511
|
code: "pipeline-build-failed",
|
|
26058
|
-
detail: { cause:
|
|
26512
|
+
detail: { cause: err29 },
|
|
26059
26513
|
hint: "createRenderPipeline (fxaa fullscreen) failed; inspect gpuMessage"
|
|
26060
26514
|
});
|
|
26061
26515
|
}
|
|
@@ -26295,11 +26749,11 @@ async function buildReadyWebGPU(rhiDevice, getShader, gpuStore, asyncCreateShade
|
|
|
26295
26749
|
pipelineCache,
|
|
26296
26750
|
modules
|
|
26297
26751
|
);
|
|
26298
|
-
} catch (
|
|
26299
|
-
if (
|
|
26752
|
+
} catch (err29) {
|
|
26753
|
+
if (err29 instanceof PipelineSpecError) throw err29;
|
|
26300
26754
|
throw new PipelineSpecError({
|
|
26301
26755
|
code: "pipeline-build-failed",
|
|
26302
|
-
detail: { cause:
|
|
26756
|
+
detail: { cause: err29 },
|
|
26303
26757
|
hint: "createRenderPipeline (bloom-bright fullscreen) failed; inspect gpuMessage"
|
|
26304
26758
|
});
|
|
26305
26759
|
}
|
|
@@ -26388,11 +26842,11 @@ async function buildReadyWebGPU(rhiDevice, getShader, gpuStore, asyncCreateShade
|
|
|
26388
26842
|
pipelineCache,
|
|
26389
26843
|
modules
|
|
26390
26844
|
);
|
|
26391
|
-
} catch (
|
|
26392
|
-
if (
|
|
26845
|
+
} catch (err29) {
|
|
26846
|
+
if (err29 instanceof PipelineSpecError) throw err29;
|
|
26393
26847
|
throw new PipelineSpecError({
|
|
26394
26848
|
code: "pipeline-build-failed",
|
|
26395
|
-
detail: { cause:
|
|
26849
|
+
detail: { cause: err29 },
|
|
26396
26850
|
hint: "createRenderPipeline (bloom-blur-h fullscreen) failed; inspect gpuMessage"
|
|
26397
26851
|
});
|
|
26398
26852
|
}
|
|
@@ -26499,11 +26953,11 @@ async function buildReadyWebGPU(rhiDevice, getShader, gpuStore, asyncCreateShade
|
|
|
26499
26953
|
pipelineCache,
|
|
26500
26954
|
modules
|
|
26501
26955
|
);
|
|
26502
|
-
} catch (
|
|
26503
|
-
if (
|
|
26956
|
+
} catch (err29) {
|
|
26957
|
+
if (err29 instanceof PipelineSpecError) throw err29;
|
|
26504
26958
|
throw new PipelineSpecError({
|
|
26505
26959
|
code: "pipeline-build-failed",
|
|
26506
|
-
detail: { cause:
|
|
26960
|
+
detail: { cause: err29 },
|
|
26507
26961
|
hint: "createRenderPipeline (bloom-composite fullscreen) failed; inspect gpuMessage"
|
|
26508
26962
|
});
|
|
26509
26963
|
}
|
|
@@ -26635,11 +27089,11 @@ async function buildReadyWebGPU(rhiDevice, getShader, gpuStore, asyncCreateShade
|
|
|
26635
27089
|
pipelineCache,
|
|
26636
27090
|
{ ...baseModules, fragmentEntryPoint: "fs_ssao_calc" }
|
|
26637
27091
|
);
|
|
26638
|
-
} catch (
|
|
26639
|
-
if (
|
|
27092
|
+
} catch (err29) {
|
|
27093
|
+
if (err29 instanceof PipelineSpecError) throw err29;
|
|
26640
27094
|
throw new PipelineSpecError({
|
|
26641
27095
|
code: "pipeline-build-failed",
|
|
26642
|
-
detail: { cause:
|
|
27096
|
+
detail: { cause: err29 },
|
|
26643
27097
|
hint: "createRenderPipeline (ssao-calc fullscreen) failed; inspect gpuMessage"
|
|
26644
27098
|
});
|
|
26645
27099
|
}
|
|
@@ -26670,11 +27124,11 @@ async function buildReadyWebGPU(rhiDevice, getShader, gpuStore, asyncCreateShade
|
|
|
26670
27124
|
pipelineCache,
|
|
26671
27125
|
{ ...baseModules, fragmentEntryPoint: "fs_ssao_blur" }
|
|
26672
27126
|
);
|
|
26673
|
-
} catch (
|
|
26674
|
-
if (
|
|
27127
|
+
} catch (err29) {
|
|
27128
|
+
if (err29 instanceof PipelineSpecError) throw err29;
|
|
26675
27129
|
throw new PipelineSpecError({
|
|
26676
27130
|
code: "pipeline-build-failed",
|
|
26677
|
-
detail: { cause:
|
|
27131
|
+
detail: { cause: err29 },
|
|
26678
27132
|
hint: "createRenderPipeline (ssao-blur fullscreen) failed; inspect gpuMessage"
|
|
26679
27133
|
});
|
|
26680
27134
|
}
|
|
@@ -26768,6 +27222,7 @@ async function buildReadyWebGPU(rhiDevice, getShader, gpuStore, asyncCreateShade
|
|
|
26768
27222
|
materialBindGroupLayout: materialBglResult.value,
|
|
26769
27223
|
meshBindGroupLayout: meshArrayBglResult.value,
|
|
26770
27224
|
viewUniformBuffer: viewUboResult.value,
|
|
27225
|
+
pointsLinesViewBuffer: pointsLinesViewBufferResult.value,
|
|
26771
27226
|
shadowCasterCascadeBuffer: shadowCasterCascadeUboResult.value,
|
|
26772
27227
|
// feat-20260608-mesh-ssbo-dynamic-grow-l1-lift-1024-entity-cap M2 /
|
|
26773
27228
|
// T-M2-05: PipelineState now references the wrapper objects owned by
|