@forgeax/engine-runtime 0.1.19 → 0.1.20
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/.tsbuildinfo +1 -1
- package/dist/__tests__/helpers/tilemap-assets.d.ts.map +1 -1
- package/dist/__tests__/material-texture-dimension-mismatch.unit.test.d.ts +2 -0
- package/dist/__tests__/material-texture-dimension-mismatch.unit.test.d.ts.map +1 -0
- package/dist/__tests__/render-error-exhaustive.test-d.d.ts.map +1 -1
- package/dist/__tests__/texture-dimensions.browser.test.d.ts +2 -0
- package/dist/__tests__/texture-dimensions.browser.test.d.ts.map +1 -0
- package/dist/__tests__/volumetric-fog-record-recovery.integration.test.d.ts +2 -0
- package/dist/__tests__/volumetric-fog-record-recovery.integration.test.d.ts.map +1 -0
- package/dist/createRenderer.d.ts.map +1 -1
- package/dist/index.mjs +1 -0
- package/dist/index.mjs.map +1 -1
- package/package.json +30 -30
- package/src/__tests__/asset-registry.recursive.spec.ts +12 -18
- package/src/__tests__/asset.unit.test.ts +28 -25
- package/src/__tests__/basis-catalog-dispatch.integration.test.ts +10 -9
- package/src/__tests__/compressed-texture-physical-extent.integration.test.ts +12 -10
- package/src/__tests__/dawn/hello-sprite-nineslice-section.dawn.test.ts +2 -3
- package/src/__tests__/dawn/material-alpha.dawn.test.ts +2 -3
- package/src/__tests__/dawn/mipmap-srgb-linear.dawn.test.ts +2 -3
- package/src/__tests__/dawn/per-entity-material-texture-isolation.dawn.test.ts +2 -3
- package/src/__tests__/dawn/sprite-nineslice-mesh-bind.dawn.test.ts +2 -3
- package/src/__tests__/dawn/upload-texture.dawn.test.ts +4 -6
- package/src/__tests__/derive-bgl-integration.test.ts +11 -0
- package/src/__tests__/equirect-bc6h.integration.test.ts +6 -4
- package/src/__tests__/errors.unit.test.ts +20 -0
- package/src/__tests__/four-path-compression.integration.test.ts +2 -2
- package/src/__tests__/gpu-resource-cow-survivor.test.ts +2 -3
- package/src/__tests__/helpers/tilemap-assets.ts +3 -4
- package/src/__tests__/light-gpu-byte-neutral.unit.test.ts +4 -2
- package/src/__tests__/lights.unit.test.ts +38 -17
- package/src/__tests__/loadbyguid-texture-intern.unit.test.ts +3 -4
- package/src/__tests__/loader-name-survival.test.ts +2 -3
- package/src/__tests__/material-texture-dimension-mismatch.unit.test.ts +18 -0
- package/src/__tests__/material-texture-uv-scale.unit.test.ts +10 -2
- package/src/__tests__/mip-gate.unit.test.ts +11 -8
- package/src/__tests__/msaa-sprite-pixel-diff.dawn.test.ts +2 -3
- package/src/__tests__/new-kind-refs-contract.test.ts +2 -3
- package/src/__tests__/pbr-pipeline.unit.test.ts +23 -4
- package/src/__tests__/pipeline.unit.test.ts +18 -19
- package/src/__tests__/point-light-shadow.unit.test.ts +6 -5
- package/src/__tests__/render-error-exhaustive.test-d.ts +29 -0
- package/src/__tests__/render-system-extract.test.ts +4 -6
- package/src/__tests__/render-system-record-multi-material-textureview.test.ts +4 -6
- package/src/__tests__/render-system-record-per-submesh-transparency.test.ts +2 -3
- package/src/__tests__/shadow-fields-observable.dawn.test.ts +56 -39
- package/src/__tests__/skinned-shadow-mixed.dawn.test.ts +3 -1
- package/src/__tests__/sprite-cullmode-flip.dawn.test.ts +4 -6
- package/src/__tests__/sprite-lit-bgl-byte-identical.test.ts +4 -2
- package/src/__tests__/systems.unit.test.ts +15 -2
- package/src/__tests__/texture-dimensions.browser.test.ts +127 -0
- package/src/__tests__/transcode-fallback.unit.test.ts +5 -1
- package/src/__tests__/volumetric-fog-record-recovery.integration.test.ts +180 -0
- package/src/createRenderer.ts +3 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@forgeax/engine-runtime",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.20",
|
|
4
4
|
"private": false,
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "Apache-2.0",
|
|
@@ -26,37 +26,37 @@
|
|
|
26
26
|
"LICENSE"
|
|
27
27
|
],
|
|
28
28
|
"dependencies": {
|
|
29
|
-
"@forgeax/engine-animation": "0.1.
|
|
30
|
-
"@forgeax/engine-assets-runtime": "0.1.
|
|
31
|
-
"@forgeax/engine-audio-webaudio": "0.1.
|
|
32
|
-
"@forgeax/engine-codec": "0.1.
|
|
33
|
-
"@forgeax/engine-debug-draw": "0.1.
|
|
34
|
-
"@forgeax/engine-ecs": "0.1.
|
|
35
|
-
"@forgeax/engine-font": "0.1.
|
|
36
|
-
"@forgeax/engine-geometry": "0.1.
|
|
37
|
-
"@forgeax/engine-graphics-extras": "0.1.
|
|
38
|
-
"@forgeax/engine-image": "0.1.
|
|
39
|
-
"@forgeax/engine-input": "0.1.
|
|
40
|
-
"@forgeax/engine-math": "0.1.
|
|
41
|
-
"@forgeax/engine-pack": "0.1.
|
|
42
|
-
"@forgeax/engine-profiler": "0.1.
|
|
43
|
-
"@forgeax/engine-render": "0.1.
|
|
44
|
-
"@forgeax/engine-render-graph": "0.1.
|
|
45
|
-
"@forgeax/engine-rhi": "0.1.
|
|
46
|
-
"@forgeax/engine-rhi-null": "0.1.
|
|
47
|
-
"@forgeax/engine-rhi-webgpu": "0.1.
|
|
48
|
-
"@forgeax/engine-rhi-wgpu": "0.1.
|
|
49
|
-
"@forgeax/engine-scene": "0.1.
|
|
50
|
-
"@forgeax/engine-shader": "0.1.
|
|
51
|
-
"@forgeax/engine-skinning": "0.1.
|
|
52
|
-
"@forgeax/engine-types": "0.1.
|
|
53
|
-
"@forgeax/engine-vfx": "0.1.
|
|
29
|
+
"@forgeax/engine-animation": "0.1.20",
|
|
30
|
+
"@forgeax/engine-assets-runtime": "0.1.20",
|
|
31
|
+
"@forgeax/engine-audio-webaudio": "0.1.20",
|
|
32
|
+
"@forgeax/engine-codec": "0.1.20",
|
|
33
|
+
"@forgeax/engine-debug-draw": "0.1.20",
|
|
34
|
+
"@forgeax/engine-ecs": "0.1.20",
|
|
35
|
+
"@forgeax/engine-font": "0.1.20",
|
|
36
|
+
"@forgeax/engine-geometry": "0.1.20",
|
|
37
|
+
"@forgeax/engine-graphics-extras": "0.1.20",
|
|
38
|
+
"@forgeax/engine-image": "0.1.20",
|
|
39
|
+
"@forgeax/engine-input": "0.1.20",
|
|
40
|
+
"@forgeax/engine-math": "0.1.20",
|
|
41
|
+
"@forgeax/engine-pack": "0.1.20",
|
|
42
|
+
"@forgeax/engine-profiler": "0.1.20",
|
|
43
|
+
"@forgeax/engine-render": "0.1.20",
|
|
44
|
+
"@forgeax/engine-render-graph": "0.1.20",
|
|
45
|
+
"@forgeax/engine-rhi": "0.1.20",
|
|
46
|
+
"@forgeax/engine-rhi-null": "0.1.20",
|
|
47
|
+
"@forgeax/engine-rhi-webgpu": "0.1.20",
|
|
48
|
+
"@forgeax/engine-rhi-wgpu": "0.1.20",
|
|
49
|
+
"@forgeax/engine-scene": "0.1.20",
|
|
50
|
+
"@forgeax/engine-shader": "0.1.20",
|
|
51
|
+
"@forgeax/engine-skinning": "0.1.20",
|
|
52
|
+
"@forgeax/engine-types": "0.1.20",
|
|
53
|
+
"@forgeax/engine-vfx": "0.1.20"
|
|
54
54
|
},
|
|
55
55
|
"devDependencies": {
|
|
56
|
-
"@forgeax/engine-import": "0.1.
|
|
57
|
-
"@forgeax/engine-naga": "0.1.
|
|
58
|
-
"@forgeax/engine-state": "0.1.
|
|
59
|
-
"@forgeax/engine-vite-plugin-shader": "0.1.
|
|
56
|
+
"@forgeax/engine-import": "0.1.20",
|
|
57
|
+
"@forgeax/engine-naga": "0.1.20",
|
|
58
|
+
"@forgeax/engine-state": "0.1.20",
|
|
59
|
+
"@forgeax/engine-vite-plugin-shader": "0.1.20",
|
|
60
60
|
"@types/node": "^20.14.0"
|
|
61
61
|
},
|
|
62
62
|
"forgeax": {
|
|
@@ -374,12 +374,11 @@ describe('mesh default material ready boundary', () => {
|
|
|
374
374
|
if (refs.length > 0) {
|
|
375
375
|
reg.catalog(parseGuid(WRONG_DEFAULT_KIND_GUID), {
|
|
376
376
|
kind: 'texture' as const,
|
|
377
|
-
width: 1,
|
|
378
|
-
height: 1,
|
|
377
|
+
shape: { viewDimension: '2d', extent: { width: 1, height: 1 } },
|
|
379
378
|
format: 'rgba8unorm' as const,
|
|
380
379
|
data: new Uint8Array([255, 255, 255, 255]),
|
|
381
380
|
colorSpace: 'srgb' as const,
|
|
382
|
-
|
|
381
|
+
mips: { kind: 'none' as const },
|
|
383
382
|
});
|
|
384
383
|
}
|
|
385
384
|
const omittedDefaultGuid = 'b0000000-0000-4000-b000-000000000099';
|
|
@@ -445,12 +444,11 @@ describe('mesh default material ready boundary', () => {
|
|
|
445
444
|
const reg = makeRegistry();
|
|
446
445
|
reg.catalog(parseGuid(WRONG_DEFAULT_KIND_GUID), {
|
|
447
446
|
kind: 'texture' as const,
|
|
448
|
-
width: 1,
|
|
449
|
-
height: 1,
|
|
447
|
+
shape: { viewDimension: '2d', extent: { width: 1, height: 1 } },
|
|
450
448
|
format: 'rgba8unorm' as const,
|
|
451
449
|
data: new Uint8Array([255, 255, 255, 255]),
|
|
452
450
|
colorSpace: 'srgb' as const,
|
|
453
|
-
|
|
451
|
+
mips: { kind: 'none' as const },
|
|
454
452
|
});
|
|
455
453
|
|
|
456
454
|
const packIndex = [
|
|
@@ -740,21 +738,19 @@ describe('AC-02 — material recursive loadByGuid', () => {
|
|
|
740
738
|
// Pre-register textures in dev mode (fast-path compatible)
|
|
741
739
|
reg.catalog(parseGuid(TEXTURE_A_GUID), {
|
|
742
740
|
kind: 'texture' as const,
|
|
743
|
-
width: 4,
|
|
744
|
-
height: 4,
|
|
741
|
+
shape: { viewDimension: '2d', extent: { width: 4, height: 4 } },
|
|
745
742
|
format: 'rgba8unorm' as const,
|
|
746
743
|
data: new Uint8Array(64),
|
|
747
744
|
colorSpace: 'srgb' as const,
|
|
748
|
-
|
|
745
|
+
mips: { kind: 'none' as const },
|
|
749
746
|
});
|
|
750
747
|
reg.catalog(parseGuid(TEXTURE_B_GUID), {
|
|
751
748
|
kind: 'texture' as const,
|
|
752
|
-
width: 4,
|
|
753
|
-
height: 4,
|
|
749
|
+
shape: { viewDimension: '2d', extent: { width: 4, height: 4 } },
|
|
754
750
|
format: 'rgba8unorm' as const,
|
|
755
751
|
data: new Uint8Array(64),
|
|
756
752
|
colorSpace: 'srgb' as const,
|
|
757
|
-
|
|
753
|
+
mips: { kind: 'none' as const },
|
|
758
754
|
});
|
|
759
755
|
|
|
760
756
|
const packIndex = [
|
|
@@ -900,12 +896,11 @@ describe('AC-03 — gltf-shaped scene composite (via SceneAsset, D-9)', () => {
|
|
|
900
896
|
// Pre-register texture in dev mode.
|
|
901
897
|
reg.catalog(parseGuid(TEXTURE_C_GUID), {
|
|
902
898
|
kind: 'texture' as const,
|
|
903
|
-
width: 4,
|
|
904
|
-
height: 4,
|
|
899
|
+
shape: { viewDimension: '2d', extent: { width: 4, height: 4 } },
|
|
905
900
|
format: 'rgba8unorm' as const,
|
|
906
901
|
data: new Uint8Array(64),
|
|
907
902
|
colorSpace: 'srgb' as const,
|
|
908
|
-
|
|
903
|
+
mips: { kind: 'none' as const },
|
|
909
904
|
});
|
|
910
905
|
|
|
911
906
|
const packIndex = [
|
|
@@ -1103,12 +1098,11 @@ const LEAF_FIXTURES: readonly LeafFixture[] = [
|
|
|
1103
1098
|
kind: 'texture',
|
|
1104
1099
|
makeAsset: () => ({
|
|
1105
1100
|
kind: 'texture' as const,
|
|
1106
|
-
width: 4,
|
|
1107
|
-
height: 4,
|
|
1101
|
+
shape: { viewDimension: '2d', extent: { width: 4, height: 4 } },
|
|
1108
1102
|
format: 'rgba8unorm' as const,
|
|
1109
1103
|
data: new Uint8Array(64),
|
|
1110
1104
|
colorSpace: 'srgb' as const,
|
|
1111
|
-
|
|
1105
|
+
mips: { kind: 'none' as const },
|
|
1112
1106
|
}),
|
|
1113
1107
|
},
|
|
1114
1108
|
{
|
|
@@ -689,11 +689,10 @@ function _makeStubGPU(): unknown {
|
|
|
689
689
|
kind: 'texture',
|
|
690
690
|
payload: {
|
|
691
691
|
kind: 'texture',
|
|
692
|
-
width: 2,
|
|
693
|
-
height: 2,
|
|
692
|
+
shape: { viewDimension: '2d', extent: { width: 2, height: 2 } },
|
|
694
693
|
format: 'rgba8unorm',
|
|
695
694
|
colorSpace: 'srgb',
|
|
696
|
-
|
|
695
|
+
mips: { kind: 'none' },
|
|
697
696
|
},
|
|
698
697
|
refs: [],
|
|
699
698
|
artifacts: {
|
|
@@ -706,7 +705,11 @@ function _makeStubGPU(): unknown {
|
|
|
706
705
|
const out = await textureLoader.loadPack?.(input, mockCtx());
|
|
707
706
|
expect(out.ok).toBe(true);
|
|
708
707
|
if (out.ok) {
|
|
709
|
-
expect(out.value).toMatchObject({
|
|
708
|
+
expect(out.value).toMatchObject({
|
|
709
|
+
kind: 'texture',
|
|
710
|
+
shape: { viewDimension: '2d', extent: { width: 2, height: 2 } },
|
|
711
|
+
mips: { kind: 'none' },
|
|
712
|
+
});
|
|
710
713
|
}
|
|
711
714
|
});
|
|
712
715
|
|
|
@@ -3414,11 +3417,10 @@ function _makeStubGPU(): unknown {
|
|
|
3414
3417
|
|
|
3415
3418
|
const TEXTURE_METADATA = {
|
|
3416
3419
|
kind: 'texture',
|
|
3417
|
-
width: 2,
|
|
3418
|
-
height: 2,
|
|
3420
|
+
shape: { viewDimension: '2d', extent: { width: 2, height: 2 } },
|
|
3419
3421
|
format: 'rgba8unorm',
|
|
3420
3422
|
colorSpace: 'srgb',
|
|
3421
|
-
|
|
3423
|
+
mips: { kind: 'none' },
|
|
3422
3424
|
} as const;
|
|
3423
3425
|
|
|
3424
3426
|
function unimportedTextureRow() {
|
|
@@ -3731,10 +3733,13 @@ function _makeStubGPU(): unknown {
|
|
|
3731
3733
|
guid: GUID_IMPORTED,
|
|
3732
3734
|
kind: 'texture',
|
|
3733
3735
|
payload: {
|
|
3734
|
-
|
|
3735
|
-
|
|
3736
|
+
shape: {
|
|
3737
|
+
viewDimension: '2d',
|
|
3738
|
+
extent: { width: binWidth, height: binHeight },
|
|
3739
|
+
},
|
|
3736
3740
|
format: 'rgba16float',
|
|
3737
3741
|
colorSpace: 'linear',
|
|
3742
|
+
mips: { kind: 'none' },
|
|
3738
3743
|
},
|
|
3739
3744
|
refs: [],
|
|
3740
3745
|
artifacts: {
|
|
@@ -3771,8 +3776,10 @@ function _makeStubGPU(): unknown {
|
|
|
3771
3776
|
const tex: TextureAsset = result.value;
|
|
3772
3777
|
expect(tex.format).toBe('rgba16float');
|
|
3773
3778
|
expect(tex.colorSpace).toBe('linear');
|
|
3774
|
-
expect(tex.
|
|
3775
|
-
|
|
3779
|
+
expect(tex.shape).toEqual({
|
|
3780
|
+
viewDimension: '2d',
|
|
3781
|
+
extent: { width: binWidth, height: binHeight },
|
|
3782
|
+
});
|
|
3776
3783
|
expect(tex.data.length).toBe(binWidth * binHeight * 4 * 2);
|
|
3777
3784
|
});
|
|
3778
3785
|
});
|
|
@@ -5544,11 +5551,10 @@ function _makeStubGPU(): unknown {
|
|
|
5544
5551
|
kind: 'texture',
|
|
5545
5552
|
payload: {
|
|
5546
5553
|
kind: 'texture',
|
|
5547
|
-
width: 4,
|
|
5548
|
-
height: 4,
|
|
5554
|
+
shape: { viewDimension: '2d', extent: { width: 4, height: 4 } },
|
|
5549
5555
|
format: 'rgba8unorm',
|
|
5550
5556
|
colorSpace: 'linear',
|
|
5551
|
-
|
|
5557
|
+
mips: { kind: 'none' },
|
|
5552
5558
|
},
|
|
5553
5559
|
refs: [],
|
|
5554
5560
|
artifacts: {
|
|
@@ -5577,11 +5583,10 @@ function _makeStubGPU(): unknown {
|
|
|
5577
5583
|
// loadByGuid returns the payload directly.
|
|
5578
5584
|
const asset = result.value;
|
|
5579
5585
|
expect(asset.kind).toBe('texture');
|
|
5580
|
-
expect(asset.
|
|
5581
|
-
expect(asset.height).toBe(4);
|
|
5586
|
+
expect(asset.shape).toEqual({ viewDimension: '2d', extent: { width: 4, height: 4 } });
|
|
5582
5587
|
expect(asset.format).toBe('rgba8unorm');
|
|
5583
5588
|
expect(asset.colorSpace).toBe('linear');
|
|
5584
|
-
expect(asset.
|
|
5589
|
+
expect(asset.mips).toEqual({ kind: 'none' });
|
|
5585
5590
|
expect(asset.data.byteLength).toBe(4 * 4 * 4);
|
|
5586
5591
|
expect(asset.data[0]).toBe(0);
|
|
5587
5592
|
expect(asset.data[63]).toBe(63);
|
|
@@ -6040,12 +6045,11 @@ function _makeStubGPU(): unknown {
|
|
|
6040
6045
|
|
|
6041
6046
|
return {
|
|
6042
6047
|
kind: 'texture' as const,
|
|
6043
|
-
width: 1,
|
|
6044
|
-
height: 1,
|
|
6048
|
+
shape: { viewDimension: '2d' as const, extent: { width: 1, height: 1 } },
|
|
6045
6049
|
format: 'rgba16float',
|
|
6046
6050
|
data,
|
|
6047
6051
|
colorSpace: 'linear' as const,
|
|
6048
|
-
|
|
6052
|
+
mips: { kind: 'none' as const },
|
|
6049
6053
|
};
|
|
6050
6054
|
}
|
|
6051
6055
|
|
|
@@ -6065,8 +6069,8 @@ function _makeStubGPU(): unknown {
|
|
|
6065
6069
|
if (got === undefined) return;
|
|
6066
6070
|
expect(got.format).toBe('rgba16float');
|
|
6067
6071
|
expect(got.colorSpace).toBe('linear');
|
|
6068
|
-
expect(got.
|
|
6069
|
-
expect(got.
|
|
6072
|
+
expect(got.shape).toEqual({ viewDimension: '2d', extent: { width: 1, height: 1 } });
|
|
6073
|
+
expect(got.mips).toEqual({ kind: 'none' });
|
|
6070
6074
|
expect(got.data.length).toBe(8);
|
|
6071
6075
|
});
|
|
6072
6076
|
|
|
@@ -6815,12 +6819,11 @@ function _makeStubGPU(): unknown {
|
|
|
6815
6819
|
function makeTexture(format: GPUTextureFormat, colorSpace: 'srgb' | 'linear'): TextureAsset {
|
|
6816
6820
|
return {
|
|
6817
6821
|
kind: 'texture',
|
|
6818
|
-
width: 1,
|
|
6819
|
-
height: 1,
|
|
6822
|
+
shape: { viewDimension: '2d', extent: { width: 1, height: 1 } },
|
|
6820
6823
|
format,
|
|
6821
6824
|
data: new Uint8Array([255, 255, 255, 255]),
|
|
6822
6825
|
colorSpace,
|
|
6823
|
-
|
|
6826
|
+
mips: { kind: 'none' },
|
|
6824
6827
|
};
|
|
6825
6828
|
}
|
|
6826
6829
|
|
|
@@ -166,10 +166,10 @@ function wireFetch(
|
|
|
166
166
|
guid: GUID_TEX,
|
|
167
167
|
kind: 'texture',
|
|
168
168
|
payload: {
|
|
169
|
-
width: W,
|
|
170
|
-
height: H,
|
|
169
|
+
shape: { viewDimension: '2d', extent: { width: W, height: H } },
|
|
171
170
|
format: fixture.colorSpace === 'srgb' ? 'rgba8unorm-srgb' : 'rgba16float',
|
|
172
171
|
colorSpace: fixture.colorSpace,
|
|
172
|
+
mips: { kind: 'none' },
|
|
173
173
|
},
|
|
174
174
|
refs: [],
|
|
175
175
|
artifacts: {
|
|
@@ -238,10 +238,13 @@ describe.skipIf(!pkgBuilt)('Basis catalog dispatch round-trip (M6 fix)', () => {
|
|
|
238
238
|
const result = await loadWith(true);
|
|
239
239
|
expect(result.ok).toBe(true);
|
|
240
240
|
if (!result.ok) throw new Error(`load failed: ${result.error.code}`);
|
|
241
|
-
const tex = result.value as {
|
|
241
|
+
const tex = result.value as {
|
|
242
|
+
kind: string;
|
|
243
|
+
shape: { viewDimension: string; extent: { width: number; height: number } };
|
|
244
|
+
format: string;
|
|
245
|
+
};
|
|
242
246
|
expect(tex.kind).toBe('texture');
|
|
243
|
-
expect(tex.
|
|
244
|
-
expect(tex.height).toBe(H);
|
|
247
|
+
expect(tex.shape).toEqual({ viewDimension: '2d', extent: { width: W, height: H } });
|
|
245
248
|
// NO_CAPS -> the transcode arm degrades to the uncompressed sRGB fallback
|
|
246
249
|
// (section 8 P3), never a scheme=1 reject.
|
|
247
250
|
expect(tex.format).toBe('rgba8unorm-srgb');
|
|
@@ -290,15 +293,13 @@ describe.skipIf(!pkgBuilt)('Basis catalog dispatch round-trip (M6 fix)', () => {
|
|
|
290
293
|
if (!result.ok) continue;
|
|
291
294
|
const texture = result.value as {
|
|
292
295
|
kind: string;
|
|
293
|
-
width: number;
|
|
294
|
-
height: number;
|
|
296
|
+
shape: { viewDimension: string; extent: { width: number; height: number } };
|
|
295
297
|
format: string;
|
|
296
298
|
data: Uint8Array;
|
|
297
299
|
colorSpace: string;
|
|
298
300
|
};
|
|
299
301
|
expect(texture.kind).toBe('texture');
|
|
300
|
-
expect(texture.
|
|
301
|
-
expect(texture.height).toBe(H);
|
|
302
|
+
expect(texture.shape).toEqual({ viewDimension: '2d', extent: { width: W, height: H } });
|
|
302
303
|
expect(texture.data.byteLength).toBeGreaterThan(0);
|
|
303
304
|
expect(texture.colorSpace).toBe(fixture.colorSpace);
|
|
304
305
|
const expected =
|
|
@@ -79,13 +79,11 @@ function compressedPod(): TextureAsset {
|
|
|
79
79
|
bytes.fill(level.level + 1, level.byteOffset, level.byteOffset + level.byteLength);
|
|
80
80
|
return {
|
|
81
81
|
kind: 'texture',
|
|
82
|
-
width: 2085,
|
|
83
|
-
height: 1573,
|
|
82
|
+
shape: { viewDimension: '2d', extent: { width: 2085, height: 1573 } },
|
|
84
83
|
format: 'bc7-rgba-unorm',
|
|
85
84
|
data: bytes,
|
|
86
85
|
colorSpace: 'linear',
|
|
87
|
-
|
|
88
|
-
mipLevelCount: layout.length,
|
|
86
|
+
mips: { kind: 'packed', levelCount: layout.length },
|
|
89
87
|
};
|
|
90
88
|
}
|
|
91
89
|
|
|
@@ -93,13 +91,18 @@ describe('compressed texture physical extent recorded-RHI witness [w36]', () =>
|
|
|
93
91
|
it('allocates and uploads BC7 physical extents while preserving logical asset metadata', () => {
|
|
94
92
|
const calls = { create: [] as TextureCall[], writes: [] as WriteCall[] };
|
|
95
93
|
const pod = compressedPod();
|
|
96
|
-
const expected = deriveMipUploadLayout(
|
|
94
|
+
const expected = deriveMipUploadLayout(
|
|
95
|
+
pod.format,
|
|
96
|
+
pod.shape.extent.width,
|
|
97
|
+
pod.shape.extent.height,
|
|
98
|
+
pod.mips.kind === 'packed' ? pod.mips.levelCount : 1,
|
|
99
|
+
);
|
|
97
100
|
|
|
98
101
|
const result = makeStore(calls).ensureResident(toShared<'TextureAsset'>(36), pod);
|
|
99
102
|
if (!result.ok) throw result.error;
|
|
100
103
|
|
|
101
|
-
expect(pod.width).toBe(2085);
|
|
102
|
-
expect(pod.height).toBe(1573);
|
|
104
|
+
expect(pod.shape.extent.width).toBe(2085);
|
|
105
|
+
expect(pod.shape.extent.height).toBe(1573);
|
|
103
106
|
expect(calls.create).toHaveLength(1);
|
|
104
107
|
expect(calls.create[0]?.size).toMatchObject({ width: 2088, height: 1576 });
|
|
105
108
|
expect(calls.writes).toHaveLength(expected.length);
|
|
@@ -122,12 +125,11 @@ describe('compressed texture physical extent recorded-RHI witness [w36]', () =>
|
|
|
122
125
|
const calls = { create: [] as TextureCall[], writes: [] as WriteCall[] };
|
|
123
126
|
const pod: TextureAsset = {
|
|
124
127
|
kind: 'texture',
|
|
125
|
-
width: 17,
|
|
126
|
-
height: 9,
|
|
128
|
+
shape: { viewDimension: '2d', extent: { width: 17, height: 9 } },
|
|
127
129
|
format: 'rgba8unorm',
|
|
128
130
|
data: new Uint8Array(17 * 9 * 4),
|
|
129
131
|
colorSpace: 'linear',
|
|
130
|
-
|
|
132
|
+
mips: { kind: 'none' },
|
|
131
133
|
};
|
|
132
134
|
|
|
133
135
|
expect(makeStore(calls).ensureResident(toShared<'TextureAsset'>(37), pod).ok).toBe(true);
|
|
@@ -89,11 +89,10 @@ function makeCornerCheckerTexture(): TextureAsset {
|
|
|
89
89
|
}
|
|
90
90
|
return {
|
|
91
91
|
kind: 'texture',
|
|
92
|
-
width: side,
|
|
93
|
-
height: side,
|
|
92
|
+
shape: { viewDimension: '2d', extent: { width: side, height: side } },
|
|
94
93
|
format: 'rgba8unorm-srgb',
|
|
95
94
|
colorSpace: 'srgb',
|
|
96
|
-
|
|
95
|
+
mips: { kind: 'none' },
|
|
97
96
|
data: bytes,
|
|
98
97
|
};
|
|
99
98
|
}
|
|
@@ -99,12 +99,11 @@ function textureBytes(color: readonly [number, number, number, number]): Uint8Ar
|
|
|
99
99
|
function makeTexture(color: readonly [number, number, number, number]): TextureAsset {
|
|
100
100
|
return {
|
|
101
101
|
kind: 'texture',
|
|
102
|
-
width: 1,
|
|
103
|
-
height: 1,
|
|
102
|
+
shape: { viewDimension: '2d', extent: { width: 1, height: 1 } },
|
|
104
103
|
format: 'rgba8unorm-srgb',
|
|
105
104
|
data: textureBytes(color),
|
|
106
105
|
colorSpace: 'srgb',
|
|
107
|
-
|
|
106
|
+
mips: { kind: 'none' },
|
|
108
107
|
};
|
|
109
108
|
}
|
|
110
109
|
|
|
@@ -42,12 +42,11 @@ function makeTexture(
|
|
|
42
42
|
): TextureAsset {
|
|
43
43
|
return {
|
|
44
44
|
kind: 'texture',
|
|
45
|
-
width,
|
|
46
|
-
height,
|
|
45
|
+
shape: { viewDimension: '2d', extent: { width, height } },
|
|
47
46
|
format,
|
|
48
47
|
data: new Uint8Array(width * height * 4),
|
|
49
48
|
colorSpace,
|
|
50
|
-
mipmap,
|
|
49
|
+
mips: mipmap ? { kind: 'generate' } : { kind: 'none' },
|
|
51
50
|
};
|
|
52
51
|
}
|
|
53
52
|
|
|
@@ -60,12 +60,11 @@ function makeChequerTexture(primaryR: number, primaryG: number, primaryB: number
|
|
|
60
60
|
}
|
|
61
61
|
return {
|
|
62
62
|
kind: 'texture',
|
|
63
|
-
width: side,
|
|
64
|
-
height: side,
|
|
63
|
+
shape: { viewDimension: '2d', extent: { width: side, height: side } },
|
|
65
64
|
format: 'rgba8unorm',
|
|
66
65
|
data: bytes,
|
|
67
66
|
colorSpace: 'srgb',
|
|
68
|
-
|
|
67
|
+
mips: { kind: 'none' },
|
|
69
68
|
};
|
|
70
69
|
}
|
|
71
70
|
|
|
@@ -126,11 +126,10 @@ describe('feat-20260527-sprite-nineslice w13 dawn smoke (HANDLE_NINESLICE_QUAD b
|
|
|
126
126
|
}
|
|
127
127
|
const texAsset: TextureAsset = {
|
|
128
128
|
kind: 'texture',
|
|
129
|
-
width: 4,
|
|
130
|
-
height: 4,
|
|
129
|
+
shape: { viewDimension: '2d', extent: { width: 4, height: 4 } },
|
|
131
130
|
format: 'rgba8unorm-srgb',
|
|
132
131
|
colorSpace: 'srgb',
|
|
133
|
-
|
|
132
|
+
mips: { kind: 'none' },
|
|
134
133
|
data: pixels,
|
|
135
134
|
};
|
|
136
135
|
const texHandle = world.allocSharedRef<'TextureAsset', TextureAsset>('TextureAsset', texAsset);
|
|
@@ -72,12 +72,11 @@ function makeTexture(
|
|
|
72
72
|
): TextureAsset {
|
|
73
73
|
return {
|
|
74
74
|
kind: 'texture',
|
|
75
|
-
width,
|
|
76
|
-
height,
|
|
75
|
+
shape: { viewDimension: '2d', extent: { width, height } },
|
|
77
76
|
format,
|
|
78
77
|
data: new Uint8Array(width * height * 4),
|
|
79
78
|
colorSpace,
|
|
80
|
-
mipmap,
|
|
79
|
+
mips: mipmap ? { kind: 'generate' } : { kind: 'none' },
|
|
81
80
|
};
|
|
82
81
|
}
|
|
83
82
|
|
|
@@ -182,12 +181,11 @@ describe('AC-04: uploadTexture non-256-aligned width (real GPU path)', () => {
|
|
|
182
181
|
|
|
183
182
|
const tex: TextureAsset = {
|
|
184
183
|
kind: 'texture',
|
|
185
|
-
width,
|
|
186
|
-
height,
|
|
184
|
+
shape: { viewDimension: '2d', extent: { width, height } },
|
|
187
185
|
format: 'rgba8unorm',
|
|
188
186
|
data: buf,
|
|
189
187
|
colorSpace: 'linear',
|
|
190
|
-
|
|
188
|
+
mips: { kind: 'none' },
|
|
191
189
|
};
|
|
192
190
|
|
|
193
191
|
const handle = world.allocSharedRef('TextureAsset', tex);
|
|
@@ -87,6 +87,17 @@ const builtinSchemas: ReadonlyArray<{ id: string; schema: readonly ParamSchemaEn
|
|
|
87
87
|
];
|
|
88
88
|
|
|
89
89
|
describe('derive(schema) integration over 5 built-in shader families (M3 w11)', () => {
|
|
90
|
+
it('derives array and volume texture schemas without a second binding path', () => {
|
|
91
|
+
for (const schema of [
|
|
92
|
+
[{ name: 'layers', type: 'texture2d_array' as const }],
|
|
93
|
+
[{ name: 'volume', type: 'texture3d' as const }],
|
|
94
|
+
]) {
|
|
95
|
+
const out = derive(schema);
|
|
96
|
+
expect(out.bglEntries.map((entry) => entry.binding)).toEqual([0, 1, 2]);
|
|
97
|
+
expect(out.resourceBindings[1]?.name).toBe(schema[0]?.name);
|
|
98
|
+
expect(out.textureFieldNames).toContain(schema[0]?.name);
|
|
99
|
+
}
|
|
100
|
+
});
|
|
90
101
|
it('(a) every built-in shader derives a well-formed BGL with consistent userRegionBindingEnd', () => {
|
|
91
102
|
for (const { id, schema } of builtinSchemas) {
|
|
92
103
|
const out = derive(schema);
|
|
@@ -145,12 +145,14 @@ describe.skipIf(!hasGpu)('equirect renderable-source integration (feat-20260707
|
|
|
145
145
|
// POD mirrors that 2D surface.
|
|
146
146
|
const source = {
|
|
147
147
|
kind: 'texture' as const,
|
|
148
|
-
width: asset.width,
|
|
149
|
-
height: asset.height,
|
|
148
|
+
shape: { viewDimension: '2d' as const, extent: { width: asset.width, height: asset.height } },
|
|
150
149
|
format: asset.format,
|
|
151
|
-
data:
|
|
150
|
+
data:
|
|
151
|
+
asset.data instanceof Uint8ClampedArray
|
|
152
|
+
? new Uint8Array(asset.data.buffer, asset.data.byteOffset, asset.data.byteLength)
|
|
153
|
+
: asset.data,
|
|
152
154
|
colorSpace: asset.colorSpace,
|
|
153
|
-
|
|
155
|
+
mips: { kind: 'none' as const },
|
|
154
156
|
};
|
|
155
157
|
const res = deriveRenderDataCubemap(source);
|
|
156
158
|
expect(res.ok).toBe(true);
|
|
@@ -530,6 +530,16 @@ type RuntimeLayerError = RenderError | AssetRuntimeError | SkinError;
|
|
|
530
530
|
return 'points lines prepare failed';
|
|
531
531
|
case 'transmission-capability-missing':
|
|
532
532
|
return 'transmission capability missing';
|
|
533
|
+
case 'projector-binding-failed':
|
|
534
|
+
return 'projector binding failed';
|
|
535
|
+
case 'volume-owner-conflict':
|
|
536
|
+
return 'volume owner conflict';
|
|
537
|
+
case 'volume-density-shape-mismatch':
|
|
538
|
+
return 'volume density shape mismatch';
|
|
539
|
+
case 'volume-invalid-bounds':
|
|
540
|
+
return 'volume invalid bounds';
|
|
541
|
+
case 'volume-invalid-parameters':
|
|
542
|
+
return 'volume invalid parameters';
|
|
533
543
|
}
|
|
534
544
|
}
|
|
535
545
|
expect(exhaustive('equirect-projection-failed')).toBe('equirect projection failed');
|
|
@@ -680,6 +690,16 @@ type RuntimeLayerError = RenderError | AssetRuntimeError | SkinError;
|
|
|
680
690
|
return 'ok';
|
|
681
691
|
case 'transmission-capability-missing':
|
|
682
692
|
return 'ok';
|
|
693
|
+
case 'projector-binding-failed':
|
|
694
|
+
return 'ok';
|
|
695
|
+
case 'volume-owner-conflict':
|
|
696
|
+
return 'ok';
|
|
697
|
+
case 'volume-density-shape-mismatch':
|
|
698
|
+
return 'ok';
|
|
699
|
+
case 'volume-invalid-bounds':
|
|
700
|
+
return 'ok';
|
|
701
|
+
case 'volume-invalid-parameters':
|
|
702
|
+
return 'ok';
|
|
683
703
|
}
|
|
684
704
|
}
|
|
685
705
|
expect(exhaustive('hdrp-deferred-caps-insufficient')).toBe('ok');
|
|
@@ -216,10 +216,10 @@ describe('w16: 4-path compressed-fixture loading', () => {
|
|
|
216
216
|
guid: GUID_TEX,
|
|
217
217
|
kind: 'texture',
|
|
218
218
|
payload: {
|
|
219
|
-
width: 4,
|
|
220
|
-
height: 4,
|
|
219
|
+
shape: { viewDimension: '2d', extent: { width: 4, height: 4 } },
|
|
221
220
|
format: 'rgba8unorm',
|
|
222
221
|
colorSpace: 'srgb',
|
|
222
|
+
mips: { kind: 'none' },
|
|
223
223
|
},
|
|
224
224
|
refs: [],
|
|
225
225
|
artifacts: {
|
|
@@ -144,12 +144,11 @@ function configuredStore(probe: CowProbe): GpuResidencyCache {
|
|
|
144
144
|
function texturePod(w = 2, h = 2): TextureAsset {
|
|
145
145
|
return {
|
|
146
146
|
kind: 'texture',
|
|
147
|
-
width: w,
|
|
148
|
-
height: h,
|
|
147
|
+
shape: { viewDimension: '2d', extent: { width: w, height: h } },
|
|
149
148
|
format: 'rgba8unorm-srgb',
|
|
150
149
|
data: new Uint8Array(w * h * 4).fill(188),
|
|
151
150
|
colorSpace: 'srgb',
|
|
152
|
-
|
|
151
|
+
mips: { kind: 'none' },
|
|
153
152
|
};
|
|
154
153
|
}
|
|
155
154
|
|
|
@@ -6,12 +6,11 @@ export const TEST_ATLAS_GUID = 'test/atlas';
|
|
|
6
6
|
export function makeTestTexture(seed = 0): TextureAsset {
|
|
7
7
|
return {
|
|
8
8
|
kind: 'texture',
|
|
9
|
-
width: 32,
|
|
10
|
-
|
|
11
|
-
format: 'rgba8unorm',
|
|
9
|
+
shape: { viewDimension: '2d', extent: { width: 32, height: 32 } },
|
|
10
|
+
format: 'rgba8unorm-srgb',
|
|
12
11
|
data: new Uint8Array(32 * 32 * 4).fill(seed),
|
|
13
12
|
colorSpace: 'srgb',
|
|
14
|
-
|
|
13
|
+
mips: { kind: 'none' },
|
|
15
14
|
};
|
|
16
15
|
}
|
|
17
16
|
|
|
@@ -117,7 +117,7 @@ describe('w7 -- light GPU pack byte-neutral (AC-11)', () => {
|
|
|
117
117
|
expect(out[6]).toBeCloseTo(0.6, 6);
|
|
118
118
|
});
|
|
119
119
|
|
|
120
|
-
it('packSpotLight writes color slots 4..6 + direction slots 8..10 byte-for-byte (
|
|
120
|
+
it('packSpotLight writes color slots 4..6 + direction slots 8..10 byte-for-byte (80 B)', () => {
|
|
121
121
|
const snap: SpotLightSnapshot = {
|
|
122
122
|
kind: 'spot',
|
|
123
123
|
position: vec3.create(0, 5, 0),
|
|
@@ -135,7 +135,9 @@ describe('w7 -- light GPU pack byte-neutral (AC-11)', () => {
|
|
|
135
135
|
shadowAtlasTile: -1,
|
|
136
136
|
};
|
|
137
137
|
const out = packSpotLight(snap);
|
|
138
|
-
|
|
138
|
+
// SpotLight carries projector receiver controls and the shadow intensity
|
|
139
|
+
// tail in the current std430 payload.
|
|
140
|
+
expect(out.byteLength).toBe(80);
|
|
139
141
|
expect(out[4]).toBeCloseTo(0.3, 6);
|
|
140
142
|
expect(out[5]).toBeCloseTo(0.4, 6);
|
|
141
143
|
expect(out[6]).toBeCloseTo(0.5, 6);
|