@forgeax/engine-assets-runtime 0.1.7 → 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__/texture-pack-loader.unit.test.d.ts +2 -0
- package/dist/__tests__/texture-pack-loader.unit.test.d.ts.map +1 -0
- package/dist/decode-image-bytes.d.ts +2 -2
- package/dist/decode-image-bytes.d.ts.map +1 -1
- package/dist/errors/asset.d.ts +20 -0
- package/dist/errors/asset.d.ts.map +1 -1
- package/dist/index.d.ts +2 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.mjs +264 -198
- package/dist/index.mjs.map +1 -1
- package/dist/loaders/pack-artifact.d.ts +25 -1
- package/dist/loaders/pack-artifact.d.ts.map +1 -1
- package/dist/mipmap-generator.d.ts +3 -1
- package/dist/mipmap-generator.d.ts.map +1 -1
- package/dist/registry/instantiate.d.ts +2 -0
- package/dist/registry/instantiate.d.ts.map +1 -1
- package/dist/registry/validate-material.d.ts +26 -0
- package/dist/registry/validate-material.d.ts.map +1 -1
- package/package.json +14 -14
- package/src/__tests__/catalog-replica.unit.test.ts +36 -0
- package/src/__tests__/decode-image-bytes.browser.test.ts +5 -8
- package/src/__tests__/inline-pack-loaders.unit.test.ts +37 -0
- package/src/__tests__/instantiate-publication-fence.unit.test.ts +59 -1
- package/src/__tests__/material-ready.integration.test.ts +65 -0
- package/src/__tests__/pack-basis-load.integration.test.ts +66 -7
- package/src/__tests__/texture-pack-loader.unit.test.ts +145 -0
- package/src/__tests__/validate-material.unit.test.ts +45 -0
- package/src/decode-image-bytes.ts +6 -11
- package/src/errors/asset.ts +33 -0
- package/src/index.ts +7 -2
- package/src/loaders/pack-artifact.ts +218 -17
- package/src/mipmap-generator.ts +43 -1
- package/src/registry/instantiate.ts +14 -4
- package/src/registry/validate-material.ts +148 -0
|
@@ -1,4 +1,26 @@
|
|
|
1
|
-
import type { Loader } from '@forgeax/engine-types';
|
|
1
|
+
import type { LoadContext, Loader, TextureAsset } from '@forgeax/engine-types';
|
|
2
|
+
import { AssetError } from '@forgeax/engine-types';
|
|
3
|
+
import { TexturePackVerificationError } from '../errors/asset.js';
|
|
4
|
+
import type { PackLoaderInput } from '../loader-registry';
|
|
5
|
+
export interface TexturePackLoadInput {
|
|
6
|
+
readonly pack: PackLoaderInput;
|
|
7
|
+
readonly sourceKey: string;
|
|
8
|
+
readonly generation: number;
|
|
9
|
+
readonly expectedDigest: string;
|
|
10
|
+
}
|
|
11
|
+
export type VerifiedTexturePack = {
|
|
12
|
+
readonly asset: TextureAsset;
|
|
13
|
+
readonly sourceKey: string;
|
|
14
|
+
readonly generation: number;
|
|
15
|
+
readonly digest: string;
|
|
16
|
+
};
|
|
17
|
+
export type VerifiedTexturePackResult = {
|
|
18
|
+
readonly ok: true;
|
|
19
|
+
readonly value: VerifiedTexturePack;
|
|
20
|
+
} | {
|
|
21
|
+
readonly ok: false;
|
|
22
|
+
readonly error: TexturePackVerificationError | AssetError;
|
|
23
|
+
};
|
|
2
24
|
export type CodecContextFailure = {
|
|
3
25
|
readonly code: 'basis-profile-unsupported';
|
|
4
26
|
readonly detail: {
|
|
@@ -11,6 +33,8 @@ export type CodecContextFailure = {
|
|
|
11
33
|
readonly dfdColorSpace: 'srgb' | 'linear' | 'unknown';
|
|
12
34
|
};
|
|
13
35
|
};
|
|
36
|
+
/** Verify producer facts and then expose one accepted texture projection. */
|
|
37
|
+
export declare function loadVerifiedTexturePack(input: TexturePackLoadInput, ctx: LoadContext): Promise<VerifiedTexturePackResult>;
|
|
14
38
|
export declare const textureLoader: Loader;
|
|
15
39
|
export declare const equirectLoader: Loader;
|
|
16
40
|
export declare const fontLoader: Loader;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"pack-artifact.d.ts","sourceRoot":"","sources":["../../src/loaders/pack-artifact.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,
|
|
1
|
+
{"version":3,"file":"pack-artifact.d.ts","sourceRoot":"","sources":["../../src/loaders/pack-artifact.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAKV,WAAW,EACX,MAAM,EAGN,YAAY,EAEb,MAAM,uBAAuB,CAAC;AAC/B,OAAO,EAAE,UAAU,EAAuB,MAAM,uBAAuB,CAAC;AACxE,OAAO,EAEL,4BAA4B,EAC7B,MAAM,oBAAoB,CAAC;AAC5B,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAC;AAI1D,MAAM,WAAW,oBAAoB;IACnC,QAAQ,CAAC,IAAI,EAAE,eAAe,CAAC;IAC/B,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,cAAc,EAAE,MAAM,CAAC;CACjC;AAED,MAAM,MAAM,mBAAmB,GAAG;IAChC,QAAQ,CAAC,KAAK,EAAE,YAAY,CAAC;IAC7B,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;CACzB,CAAC;AAEF,MAAM,MAAM,yBAAyB,GACjC;IAAE,QAAQ,CAAC,EAAE,EAAE,IAAI,CAAC;IAAC,QAAQ,CAAC,KAAK,EAAE,mBAAmB,CAAA;CAAE,GAC1D;IAAE,QAAQ,CAAC,EAAE,EAAE,KAAK,CAAC;IAAC,QAAQ,CAAC,KAAK,EAAE,4BAA4B,GAAG,UAAU,CAAA;CAAE,CAAC;AAkPtF,MAAM,MAAM,mBAAmB,GAC3B;IACE,QAAQ,CAAC,IAAI,EAAE,2BAA2B,CAAC;IAC3C,QAAQ,CAAC,MAAM,EAAE;QAAE,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAA;KAAE,CAAC;CAC/C,GACD;IACE,QAAQ,CAAC,IAAI,EAAE,2BAA2B,CAAC;IAC3C,QAAQ,CAAC,MAAM,EAAE;QACf,QAAQ,CAAC,kBAAkB,EAAE,MAAM,GAAG,QAAQ,CAAC;QAC/C,QAAQ,CAAC,aAAa,EAAE,MAAM,GAAG,QAAQ,GAAG,SAAS,CAAC;KACvD,CAAC;CACH,CAAC;AAkRN,6EAA6E;AAC7E,wBAAsB,uBAAuB,CAC3C,KAAK,EAAE,oBAAoB,EAC3B,GAAG,EAAE,WAAW,GACf,OAAO,CAAC,yBAAyB,CAAC,CAiHpC;AA8GD,eAAO,MAAM,aAAa,EAAE,MAI3B,CAAC;AAEF,eAAO,MAAM,cAAc,EAAE,MAI5B,CAAC;AAEF,eAAO,MAAM,UAAU,EAAE,MAIxB,CAAC;AAEF,eAAO,MAAM,oBAAoB,EAAE,MAkBlC,CAAC;AAEF,eAAO,MAAM,aAAa,EAAE,MA0B3B,CAAC;AAEF,eAAO,MAAM,qBAAqB,EAAE,SAAS,MAAM,EAMlD,CAAC"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { type Result, RhiError } from '@forgeax/engine-rhi';
|
|
1
|
+
import { type Result, RhiError, type RhiRenderPassEncoder } from '@forgeax/engine-rhi';
|
|
2
2
|
/**
|
|
3
3
|
* Subset of `RhiDevice` consumed by the mipmap utility (charter F2: only
|
|
4
4
|
* the methods the algorithm actually invokes; the dawn integration tests
|
|
@@ -129,4 +129,6 @@ export declare function blitMipmapsSync(device: MipmapBlitDevice, texture: any,
|
|
|
129
129
|
readonly height: number;
|
|
130
130
|
readonly levels?: number;
|
|
131
131
|
}): Result<void, RhiError>;
|
|
132
|
+
/** Encode one prewarmed mip level into a caller-owned graph render pass. */
|
|
133
|
+
export declare function encodeMipmapLevel(device: MipmapBlitDevice, pass: RhiRenderPassEncoder, sourceView: unknown, format: GPUTextureFormat): Result<void, RhiError>;
|
|
132
134
|
//# sourceMappingURL=mipmap-generator.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"mipmap-generator.d.ts","sourceRoot":"","sources":["../src/mipmap-generator.ts"],"names":[],"mappings":"AA+CA,OAAO,EAAW,KAAK,MAAM,EAAE,QAAQ,EAAE,MAAM,qBAAqB,CAAC;
|
|
1
|
+
{"version":3,"file":"mipmap-generator.d.ts","sourceRoot":"","sources":["../src/mipmap-generator.ts"],"names":[],"mappings":"AA+CA,OAAO,EAAW,KAAK,MAAM,EAAE,QAAQ,EAAE,KAAK,oBAAoB,EAAE,MAAM,qBAAqB,CAAC;AAEhG;;;;;;;;;;;;;;;;;;;GAmBG;AACH,MAAM,MAAM,YAAY,GAAG;IAEzB,aAAa,CAAC,IAAI,CAAC,EAAE,GAAG,GAAG,MAAM,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC;IAE5C,qBAAqB,CAAC,IAAI,EAAE,GAAG,GAAG,MAAM,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC;IAEnD,oBAAoB,CAAC,IAAI,EAAE,GAAG,GAAG,MAAM,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC;IAElD,oBAAoB,CAAC,IAAI,EAAE,GAAG,GAAG,MAAM,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC;CACnD,CAAC;AAEF;;;;;;;;;;;;GAYG;AACH,MAAM,MAAM,yBAAyB,GAAG,CACtC,MAAM,EAAE,YAAY,EACpB,IAAI,EAAE;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAA;CAAE,KACnC,OAAO,CAAC,MAAM,CAAC,OAAO,EAAE,QAAQ,CAAC,CAAC,CAAC;AAgExC;;;;;;;;;;;GAWG;AACH,wBAAgB,YAAY,CAAC,IAAI,EAAE;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,GAAG,MAAM,CAI5E;AAED;;;;;GAKG;AACH,wBAAgB,eAAe,CAAC,MAAM,EAAE,YAAY,GAAG,MAAM,CAG5D;AAED;;;;;;;GAOG;AACH,wBAAsB,yBAAyB,CAC7C,MAAM,EAAE,YAAY,EACpB,MAAM,EAAE,gBAAgB,EACxB,uBAAuB,EAAE,yBAAyB,GAEjD,OAAO,CAAC,MAAM,CAAC,GAAG,EAAE,OAAO,CAAC,CAAC,CA0B/B;AAgDD;;;;;GAKG;AACH,MAAM,MAAM,gBAAgB,GAAG,YAAY,GAAG;IAE5C,aAAa,CAAC,IAAI,EAAE,GAAG,GAAG,MAAM,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC;IAE3C,eAAe,CAAC,IAAI,EAAE,GAAG,GAAG,MAAM,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC;IAE7C,iBAAiB,CAAC,OAAO,EAAE,GAAG,EAAE,IAAI,EAAE,GAAG,GAAG,MAAM,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC;IAE7D,oBAAoB,CAAC,IAAI,CAAC,EAAE,GAAG,GAAG,MAAM,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC;IACnD,QAAQ,CAAC,KAAK,EAAE;QAEd,MAAM,CAAC,OAAO,EAAE,aAAa,CAAC,GAAG,CAAC,GAAG,MAAM,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC;KACxD,CAAC;CACH,CAAC;AA8DF;;;;;;;;;;;;;;;GAeG;AACH,wBAAsB,eAAe,CACnC,MAAM,EAAE,gBAAgB,EAExB,OAAO,EAAE,GAAG,EACZ,UAAU,EAAE;IACV,QAAQ,CAAC,MAAM,EAAE,gBAAgB,CAAC;IAClC,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC;CAC1B,EACD,uBAAuB,EAAE,yBAAyB,GACjD,OAAO,CAAC,MAAM,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC,CAehC;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,eAAe,CAC7B,MAAM,EAAE,gBAAgB,EAExB,OAAO,EAAE,GAAG,EACZ,UAAU,EAAE;IACV,QAAQ,CAAC,MAAM,EAAE,gBAAgB,CAAC;IAClC,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC;CAC1B,GACA,MAAM,CAAC,IAAI,EAAE,QAAQ,CAAC,CA0BxB;AAED,4EAA4E;AAC5E,wBAAgB,iBAAiB,CAC/B,MAAM,EAAE,gBAAgB,EACxB,IAAI,EAAE,oBAAoB,EAC1B,UAAU,EAAE,OAAO,EACnB,MAAM,EAAE,gBAAgB,GACvB,MAAM,CAAC,IAAI,EAAE,QAAQ,CAAC,CAkCxB"}
|
|
@@ -12,6 +12,8 @@ import { type ScenePublicationFence, type ScenePublicationFenceError } from './s
|
|
|
12
12
|
export interface SkinJointResolver {
|
|
13
13
|
resolveSkinAsset(skeletonHandleRaw: number): SkinAsset | undefined;
|
|
14
14
|
}
|
|
15
|
+
/** Derive a publication fence from the registry's unified live projections. */
|
|
16
|
+
export declare function scenePublicationFenceFromRegistry(registry: AssetRegistry, outputGuid: string): Result<ScenePublicationFence, ScenePublicationFenceError>;
|
|
15
17
|
/**
|
|
16
18
|
* Post-spawn hook contract (D-1). A hook runs after instantiate spawns the
|
|
17
19
|
* scene subtree; the shipped implementation is runtime's `postSpawnResolveJoints`
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"instantiate.d.ts","sourceRoot":"","sources":["../../src/registry/instantiate.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAAE,QAAQ,EAAE,YAAY,EAAE,KAAK,EAAE,MAAM,qBAAqB,CAAC;AACzE,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,6BAA6B,CAAC;AAE7D,OAAO,EAAW,KAAK,MAAM,EAAE,MAAM,qBAAqB,CAAC;AAO3D,OAAO,EACL,KAAK,KAAK,EAEV,UAAU,EAEV,KAAK,MAAM,EAGX,KAAK,UAAU,EACf,KAAK,kBAAkB,EAEvB,KAAK,SAAS,EACd,KAAK,KAAK,EAEX,MAAM,uBAAuB,CAAC;AAC/B,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAC;AAMvD,OAAO,EAGL,KAAK,qBAAqB,EAC1B,KAAK,0BAA0B,EAEhC,MAAM,2BAA2B,CAAC;AAEnC;;;;GAIG;AACH,MAAM,WAAW,iBAAiB;IAChC,gBAAgB,CAAC,iBAAiB,EAAE,MAAM,GAAG,SAAS,GAAG,SAAS,CAAC;CACpE;
|
|
1
|
+
{"version":3,"file":"instantiate.d.ts","sourceRoot":"","sources":["../../src/registry/instantiate.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,6 +1,31 @@
|
|
|
1
1
|
import type { CookedMaterialRecord } from '@forgeax/engine-pack';
|
|
2
2
|
import { AssetError, type MaterialAsset, type MaterialError } from '@forgeax/engine-types';
|
|
3
3
|
import type { AssetRegistry } from '../asset-registry';
|
|
4
|
+
export interface TexturePublicationStateSnapshot {
|
|
5
|
+
readonly guid: string;
|
|
6
|
+
readonly sourceKey: string;
|
|
7
|
+
readonly acceptedGeneration: number;
|
|
8
|
+
readonly acceptedDigest: string;
|
|
9
|
+
readonly candidateGeneration?: number;
|
|
10
|
+
readonly candidateFailure?: string;
|
|
11
|
+
}
|
|
12
|
+
export interface TexturePublicationState {
|
|
13
|
+
reject(candidate: {
|
|
14
|
+
readonly generation: number;
|
|
15
|
+
readonly reason: string;
|
|
16
|
+
}): TexturePublicationStateSnapshot;
|
|
17
|
+
accept(candidate: {
|
|
18
|
+
readonly generation: number;
|
|
19
|
+
readonly digest: string;
|
|
20
|
+
}): TexturePublicationStateSnapshot;
|
|
21
|
+
}
|
|
22
|
+
/** Candidate/accepted state that keeps the last known good publication honest. */
|
|
23
|
+
export declare function createTexturePublicationState(input: {
|
|
24
|
+
readonly guid: string;
|
|
25
|
+
readonly sourceKey: string;
|
|
26
|
+
readonly generation: number;
|
|
27
|
+
readonly digest: string;
|
|
28
|
+
}): TexturePublicationState;
|
|
4
29
|
/**
|
|
5
30
|
* Validate a MaterialAsset's passes[] against the ShaderRegistry's
|
|
6
31
|
* paramSchema (union semantics: all declared params across all passes
|
|
@@ -15,6 +40,7 @@ import type { AssetRegistry } from '../asset-registry';
|
|
|
15
40
|
* @returns AssetError on failure, null on success
|
|
16
41
|
*/
|
|
17
42
|
export declare function validateMaterialPasses(registry: AssetRegistry, asset: MaterialAsset): AssetError | null;
|
|
43
|
+
export declare function validateMaterialTransmissionContract(asset: MaterialAsset): MaterialError | null;
|
|
18
44
|
export interface MaterialEffectiveRootIdentity {
|
|
19
45
|
readonly guid: string;
|
|
20
46
|
readonly layoutIdentity: string;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"validate-material.d.ts","sourceRoot":"","sources":["../../src/registry/validate-material.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,sBAAsB,CAAC;AACjE,OAAO,EACL,UAAU,EAEV,KAAK,aAAa,EAClB,KAAK,aAAa,EAEnB,MAAM,uBAAuB,CAAC;AAC/B,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAC;AAEvD;;;;;;;;;;;;GAYG;AACH,wBAAgB,sBAAsB,CACpC,QAAQ,EAAE,aAAa,EACvB,KAAK,EAAE,aAAa,GACnB,UAAU,GAAG,IAAI,CAoFnB;AAED,MAAM,WAAW,6BAA6B;IAC5C,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,cAAc,EAAE,MAAM,CAAC;CACjC;AAED,wBAAgB,4BAA4B,CAC1C,MAAM,EAAE,IAAI,CAAC,oBAAoB,EAAE,MAAM,GAAG,SAAS,CAAC,EACtD,IAAI,EAAE,6BAA6B,GAClC,aAAa,GAAG,IAAI,CAiBtB;AAED;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,wBAAgB,oBAAoB,CAClC,SAAS,EAAE,aAAa,EACxB,KAAK,EAAE,aAAa,GACnB,UAAU,GAAG,IAAI,CA8GnB;AAED,wBAAgB,iBAAiB,CAC/B,SAAS,EAAE,aAAa,EACxB,KAAK,EAAE,MAAM,EACb,IAAI,EAAE,MAAM,EACZ,KAAK,EAAE,OAAO,GACb,OAAO,CAgCT;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,4BAA4B,CAAC,QAAQ,EAAE,aAAa,EAAE,KAAK,EAAE,aAAa,GAAG,IAAI,CA8BhG;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,+BAA+B,CAC7C,QAAQ,EAAE,aAAa,EACvB,QAAQ,EAAE,MAAM,GACf,WAAW,CAAC,MAAM,CAAC,GAAG,SAAS,CAIjC"}
|
|
1
|
+
{"version":3,"file":"validate-material.d.ts","sourceRoot":"","sources":["../../src/registry/validate-material.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,sBAAsB,CAAC;AACjE,OAAO,EACL,UAAU,EAEV,KAAK,aAAa,EAClB,KAAK,aAAa,EAEnB,MAAM,uBAAuB,CAAC;AAC/B,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAC;AAEvD,MAAM,WAAW,+BAA+B;IAC9C,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,kBAAkB,EAAE,MAAM,CAAC;IACpC,QAAQ,CAAC,cAAc,EAAE,MAAM,CAAC;IAChC,QAAQ,CAAC,mBAAmB,CAAC,EAAE,MAAM,CAAC;IACtC,QAAQ,CAAC,gBAAgB,CAAC,EAAE,MAAM,CAAC;CACpC;AAED,MAAM,WAAW,uBAAuB;IACtC,MAAM,CAAC,SAAS,EAAE;QAChB,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;QAC5B,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;KACzB,GAAG,+BAA+B,CAAC;IACpC,MAAM,CAAC,SAAS,EAAE;QAChB,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;QAC5B,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;KACzB,GAAG,+BAA+B,CAAC;CACrC;AAED,kFAAkF;AAClF,wBAAgB,6BAA6B,CAAC,KAAK,EAAE;IACnD,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;CACzB,GAAG,uBAAuB,CA0B1B;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,sBAAsB,CACpC,QAAQ,EAAE,aAAa,EACvB,KAAK,EAAE,aAAa,GACnB,UAAU,GAAG,IAAI,CAoFnB;AA4CD,wBAAgB,oCAAoC,CAAC,KAAK,EAAE,aAAa,GAAG,aAAa,GAAG,IAAI,CAkD/F;AAED,MAAM,WAAW,6BAA6B;IAC5C,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,cAAc,EAAE,MAAM,CAAC;CACjC;AAED,wBAAgB,4BAA4B,CAC1C,MAAM,EAAE,IAAI,CAAC,oBAAoB,EAAE,MAAM,GAAG,SAAS,CAAC,EACtD,IAAI,EAAE,6BAA6B,GAClC,aAAa,GAAG,IAAI,CAiBtB;AAED;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,wBAAgB,oBAAoB,CAClC,SAAS,EAAE,aAAa,EACxB,KAAK,EAAE,aAAa,GACnB,UAAU,GAAG,IAAI,CA8GnB;AAED,wBAAgB,iBAAiB,CAC/B,SAAS,EAAE,aAAa,EACxB,KAAK,EAAE,MAAM,EACb,IAAI,EAAE,MAAM,EACZ,KAAK,EAAE,OAAO,GACb,OAAO,CAgCT;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,4BAA4B,CAAC,QAAQ,EAAE,aAAa,EAAE,KAAK,EAAE,aAAa,GAAG,IAAI,CA8BhG;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,+BAA+B,CAC7C,QAAQ,EAAE,aAAa,EACvB,QAAQ,EAAE,MAAM,GACf,WAAW,CAAC,MAAM,CAAC,GAAG,SAAS,CAIjC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@forgeax/engine-assets-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,22 +26,22 @@
|
|
|
26
26
|
"LICENSE"
|
|
27
27
|
],
|
|
28
28
|
"dependencies": {
|
|
29
|
-
"@forgeax/engine-codec": "0.1.
|
|
30
|
-
"@forgeax/engine-ecs": "0.1.
|
|
31
|
-
"@forgeax/engine-geometry": "0.1.
|
|
32
|
-
"@forgeax/engine-graphics-extras": "0.1.
|
|
33
|
-
"@forgeax/engine-image": "0.1.
|
|
34
|
-
"@forgeax/engine-pack": "0.1.
|
|
35
|
-
"@forgeax/engine-plugin": "0.1.
|
|
36
|
-
"@forgeax/engine-rhi": "0.1.
|
|
37
|
-
"@forgeax/engine-scene": "0.1.
|
|
38
|
-
"@forgeax/engine-shader": "0.1.
|
|
39
|
-
"@forgeax/engine-types": "0.1.
|
|
40
|
-
"@forgeax/engine-ui": "0.1.
|
|
29
|
+
"@forgeax/engine-codec": "0.1.20",
|
|
30
|
+
"@forgeax/engine-ecs": "0.1.20",
|
|
31
|
+
"@forgeax/engine-geometry": "0.1.20",
|
|
32
|
+
"@forgeax/engine-graphics-extras": "0.1.20",
|
|
33
|
+
"@forgeax/engine-image": "0.1.20",
|
|
34
|
+
"@forgeax/engine-pack": "0.1.20",
|
|
35
|
+
"@forgeax/engine-plugin": "0.1.20",
|
|
36
|
+
"@forgeax/engine-rhi": "0.1.20",
|
|
37
|
+
"@forgeax/engine-scene": "0.1.20",
|
|
38
|
+
"@forgeax/engine-shader": "0.1.20",
|
|
39
|
+
"@forgeax/engine-types": "0.1.20",
|
|
40
|
+
"@forgeax/engine-ui": "0.1.20",
|
|
41
41
|
"@webgpu/types": "^0.1.71"
|
|
42
42
|
},
|
|
43
43
|
"devDependencies": {
|
|
44
|
-
"@forgeax/engine-skinning": "0.1.
|
|
44
|
+
"@forgeax/engine-skinning": "0.1.20",
|
|
45
45
|
"@webgpu/types": "^0.1.71"
|
|
46
46
|
},
|
|
47
47
|
"forgeax": {
|
|
@@ -193,4 +193,40 @@ describe('CatalogReplica', () => {
|
|
|
193
193
|
diagnostics: [{ code: 'catalog-revision-conflict', severity: 'blocking' }],
|
|
194
194
|
});
|
|
195
195
|
});
|
|
196
|
+
|
|
197
|
+
it('applies a failed lifecycle projection when the producer advances its observation revision', async () => {
|
|
198
|
+
const fixture = source();
|
|
199
|
+
const replica = new CatalogReplica(fixture.source as never);
|
|
200
|
+
await replica.start();
|
|
201
|
+
|
|
202
|
+
fixture.emit({
|
|
203
|
+
added: [],
|
|
204
|
+
changed: [
|
|
205
|
+
{
|
|
206
|
+
...base,
|
|
207
|
+
lifecycle: 'failed',
|
|
208
|
+
revision: {
|
|
209
|
+
digest: 'failure:source-package-ddc-failed:sha256:old',
|
|
210
|
+
observedAt: 2,
|
|
211
|
+
rootId: base.revision.rootId,
|
|
212
|
+
},
|
|
213
|
+
diagnostics: [
|
|
214
|
+
{
|
|
215
|
+
code: 'source-package-ddc-failed',
|
|
216
|
+
severity: 'blocking',
|
|
217
|
+
hint: 'repair and retry',
|
|
218
|
+
},
|
|
219
|
+
],
|
|
220
|
+
},
|
|
221
|
+
],
|
|
222
|
+
removed: [],
|
|
223
|
+
});
|
|
224
|
+
|
|
225
|
+
expect(replica.snapshot().entries[0]).toMatchObject({
|
|
226
|
+
guid: base.guid,
|
|
227
|
+
lifecycle: 'failed',
|
|
228
|
+
revision: { observedAt: 2 },
|
|
229
|
+
});
|
|
230
|
+
expect(replica.snapshot().stale).toBe(false);
|
|
231
|
+
});
|
|
196
232
|
});
|
|
@@ -30,7 +30,6 @@ import { World } from '@forgeax/engine-ecs';
|
|
|
30
30
|
import type { TextureAsset } from '@forgeax/engine-types';
|
|
31
31
|
import { describe, expect, it } from 'vitest';
|
|
32
32
|
import { decodeImageBytes } from '../decode-image-bytes';
|
|
33
|
-
import { numMipLevels } from '../mipmap-generator';
|
|
34
33
|
|
|
35
34
|
// 1x1 red PNG (RGBA 8-bit). Universally decodable by browser createImageBitmap.
|
|
36
35
|
const PNG_1X1_RED_BASE64 =
|
|
@@ -50,14 +49,13 @@ describe('decodeImageBytes browser real-PNG happy path (AC-01)', () => {
|
|
|
50
49
|
if (!result.ok) return;
|
|
51
50
|
const pod = result.value;
|
|
52
51
|
expect(pod.kind).toBe('texture');
|
|
53
|
-
expect(pod.width).toBeGreaterThan(0);
|
|
54
|
-
expect(pod.height).toBeGreaterThan(0);
|
|
52
|
+
expect(pod.shape.extent.width).toBeGreaterThan(0);
|
|
53
|
+
expect(pod.shape.extent.height).toBeGreaterThan(0);
|
|
55
54
|
// RGBA8 tight-packed: width * height * 4 bytes.
|
|
56
|
-
expect(pod.data.length).toBe(pod.width * pod.height * 4);
|
|
55
|
+
expect(pod.data.length).toBe(pod.shape.extent.width * pod.shape.extent.height * 4);
|
|
57
56
|
expect(pod.format).toBe('rgba8unorm-srgb');
|
|
58
57
|
expect(pod.colorSpace).toBe('srgb');
|
|
59
|
-
expect(pod.
|
|
60
|
-
expect(pod.mipLevelCount).toBe(numMipLevels({ width: pod.width, height: pod.height }));
|
|
58
|
+
expect(pod.mips).toEqual({ kind: 'generate' });
|
|
61
59
|
});
|
|
62
60
|
|
|
63
61
|
it('AC-01: opts.colorSpace="linear" + opts.mipmap=false narrows format + mipLevelCount', async () => {
|
|
@@ -70,8 +68,7 @@ describe('decodeImageBytes browser real-PNG happy path (AC-01)', () => {
|
|
|
70
68
|
const pod = result.value;
|
|
71
69
|
expect(pod.format).toBe('rgba8unorm');
|
|
72
70
|
expect(pod.colorSpace).toBe('linear');
|
|
73
|
-
expect(pod.
|
|
74
|
-
expect(pod.mipLevelCount).toBe(1);
|
|
71
|
+
expect(pod.mips).toEqual({ kind: 'none' });
|
|
75
72
|
});
|
|
76
73
|
});
|
|
77
74
|
|
|
@@ -279,6 +279,43 @@ describe('materialLoader', () => {
|
|
|
279
279
|
});
|
|
280
280
|
});
|
|
281
281
|
|
|
282
|
+
it('resolves transmission and thickness texture refs through authored contract', () => {
|
|
283
|
+
const out = materialLoader.load(
|
|
284
|
+
{
|
|
285
|
+
passes: [{ name: 'Forward', program: { module: 'forgeax::default-standard-pbr' } }],
|
|
286
|
+
parameters: [
|
|
287
|
+
{ name: 'transmissionTexture', type: 'texture' },
|
|
288
|
+
{ name: 'thicknessTexture', type: 'texture' },
|
|
289
|
+
],
|
|
290
|
+
values: {
|
|
291
|
+
transmission: 0.8,
|
|
292
|
+
ior: 1.45,
|
|
293
|
+
thickness: 0.25,
|
|
294
|
+
transmissionTexture: { texture: 0, sampler: 1, coordinates: { set: 2 } },
|
|
295
|
+
thicknessTexture: { texture: 2, sampler: 3, coordinates: { set: 3 } },
|
|
296
|
+
},
|
|
297
|
+
},
|
|
298
|
+
['texture-transmission', 'sampler-linear', 'texture-thickness', 'sampler-nearest'],
|
|
299
|
+
emptyCtx,
|
|
300
|
+
) as MaterialAsset;
|
|
301
|
+
|
|
302
|
+
expect(out.values).toMatchObject({
|
|
303
|
+
transmission: 0.8,
|
|
304
|
+
ior: 1.45,
|
|
305
|
+
thickness: 0.25,
|
|
306
|
+
transmissionTexture: {
|
|
307
|
+
texture: 'texture-transmission',
|
|
308
|
+
sampler: 'sampler-linear',
|
|
309
|
+
coordinates: { set: 2 },
|
|
310
|
+
},
|
|
311
|
+
thicknessTexture: {
|
|
312
|
+
texture: 'texture-thickness',
|
|
313
|
+
sampler: 'sampler-nearest',
|
|
314
|
+
coordinates: { set: 3 },
|
|
315
|
+
},
|
|
316
|
+
});
|
|
317
|
+
});
|
|
318
|
+
|
|
282
319
|
it('resolves nested texture values when the shader schema is present but empty', () => {
|
|
283
320
|
const out = materialLoader.load(
|
|
284
321
|
{
|
|
@@ -6,7 +6,7 @@ import {
|
|
|
6
6
|
} from '@forgeax/engine-types';
|
|
7
7
|
import { describe, expect, it } from 'vitest';
|
|
8
8
|
import type { AssetRegistry } from '../asset-registry';
|
|
9
|
-
import { resolveMountsRec } from '../registry/instantiate';
|
|
9
|
+
import { resolveMountsRec, scenePublicationFenceFromRegistry } from '../registry/instantiate';
|
|
10
10
|
import { createScenePublicationFence } from '../registry/scene-publication-fence';
|
|
11
11
|
|
|
12
12
|
const SCENE_GUID = '019ffdb4-1000-7000-8000-000000000008';
|
|
@@ -155,4 +155,62 @@ describe('resolveMountsRec publication fence identity', () => {
|
|
|
155
155
|
);
|
|
156
156
|
expect(result).toMatchObject({ ok: true, value: [{ source: 6 }] });
|
|
157
157
|
});
|
|
158
|
+
|
|
159
|
+
it('prefers the complete pack-index tuple during a CatalogReplica handoff', () => {
|
|
160
|
+
const world = new World();
|
|
161
|
+
const currentSourcePath = 'assets/current.glb';
|
|
162
|
+
const currentPublication = {
|
|
163
|
+
...publication(),
|
|
164
|
+
sourcePath: currentSourcePath,
|
|
165
|
+
receipt: { ...publication().receipt, sourcePath: currentSourcePath },
|
|
166
|
+
};
|
|
167
|
+
const fence = createScenePublicationFence(currentPublication);
|
|
168
|
+
expect(fence.ok).toBe(true);
|
|
169
|
+
if (!fence.ok) return;
|
|
170
|
+
const registry = {
|
|
171
|
+
assetCatalog: new Map(),
|
|
172
|
+
// The replica may still expose the prior complete tuple while the
|
|
173
|
+
// latest pack-index has already been hydrated after a source write.
|
|
174
|
+
catalogSnapshot: () => ({
|
|
175
|
+
entries: [
|
|
176
|
+
{
|
|
177
|
+
guid: SCENE_GUID,
|
|
178
|
+
kind: 'scene',
|
|
179
|
+
sourcePath: publication().sourcePath,
|
|
180
|
+
packageUrl: '/assets/scene.pack.json',
|
|
181
|
+
publication: publication(),
|
|
182
|
+
},
|
|
183
|
+
],
|
|
184
|
+
}),
|
|
185
|
+
packIndexCache: new Map([
|
|
186
|
+
[
|
|
187
|
+
SCENE_GUID,
|
|
188
|
+
{
|
|
189
|
+
guid: SCENE_GUID,
|
|
190
|
+
kind: 'scene',
|
|
191
|
+
sourcePath: currentSourcePath,
|
|
192
|
+
packageUrl: '/assets/current.pack.json',
|
|
193
|
+
publication: currentPublication,
|
|
194
|
+
},
|
|
195
|
+
],
|
|
196
|
+
]),
|
|
197
|
+
_guidForAsset: () => undefined,
|
|
198
|
+
} as unknown as AssetRegistry;
|
|
199
|
+
const result = resolveMountsRec(
|
|
200
|
+
registry,
|
|
201
|
+
[
|
|
202
|
+
{
|
|
203
|
+
localId: 0 as never,
|
|
204
|
+
source: 6,
|
|
205
|
+
memberFirst: 0 as never,
|
|
206
|
+
memberCount: 0,
|
|
207
|
+
publicationFence: fence.value,
|
|
208
|
+
},
|
|
209
|
+
],
|
|
210
|
+
world,
|
|
211
|
+
new Set(),
|
|
212
|
+
);
|
|
213
|
+
expect(result).toMatchObject({ ok: true, value: [{ source: 6 }] });
|
|
214
|
+
expect(scenePublicationFenceFromRegistry(registry, SCENE_GUID)).toEqual(fence);
|
|
215
|
+
});
|
|
158
216
|
});
|
|
@@ -5,6 +5,7 @@ import {
|
|
|
5
5
|
} from '@forgeax/engine-pack';
|
|
6
6
|
import { AssetGuid } from '@forgeax/engine-pack/guid';
|
|
7
7
|
import { ShaderRegistry } from '@forgeax/engine-shader';
|
|
8
|
+
import type { MaterialParameter } from '@forgeax/engine-types';
|
|
8
9
|
import { describe, expect, it, vi } from 'vitest';
|
|
9
10
|
import { AssetRegistry } from '../asset-registry';
|
|
10
11
|
import { MaterialGenerationCache } from '../material/generation-cache';
|
|
@@ -103,6 +104,70 @@ describe('material runtime readiness', () => {
|
|
|
103
104
|
]);
|
|
104
105
|
});
|
|
105
106
|
|
|
107
|
+
it('keeps the Standard transmission contract in the published snapshot', async () => {
|
|
108
|
+
const parameters: readonly MaterialParameter[] = [
|
|
109
|
+
{ name: 'transmission', type: 'f32', default: 0 },
|
|
110
|
+
{ name: 'ior', type: 'f32', default: 1.5 },
|
|
111
|
+
{ name: 'thickness', type: 'f32', default: 0 },
|
|
112
|
+
{ name: 'attenuationColor', type: 'vec3', default: [1, 1, 1] },
|
|
113
|
+
{ name: 'attenuationDistance', type: 'f32' },
|
|
114
|
+
{ name: 'transmissionTexture', type: 'texture' },
|
|
115
|
+
{ name: 'thicknessTexture', type: 'texture' },
|
|
116
|
+
];
|
|
117
|
+
expect(materialParametersToParamSchema(parameters, 'published::standard')).toEqual([
|
|
118
|
+
{ name: 'transmission', type: 'f32', default: 0 },
|
|
119
|
+
{ name: 'ior', type: 'f32', default: 1.5 },
|
|
120
|
+
{ name: 'thickness', type: 'f32', default: 0 },
|
|
121
|
+
{ name: 'attenuationColor', type: 'vec3', default: [1, 1, 1] },
|
|
122
|
+
{ name: 'attenuationDistance', type: 'f32' },
|
|
123
|
+
{ name: 'transmissionTexture', type: 'texture2d' },
|
|
124
|
+
{ name: 'thicknessTexture', type: 'texture2d' },
|
|
125
|
+
]);
|
|
126
|
+
const baseRecord = cookedRecord(PRODUCTION_GUID);
|
|
127
|
+
const record: CookedMaterialRecord = {
|
|
128
|
+
...baseRecord,
|
|
129
|
+
parameterContract: {
|
|
130
|
+
parameters,
|
|
131
|
+
values: {
|
|
132
|
+
transmission: 0.8,
|
|
133
|
+
ior: 1.45,
|
|
134
|
+
thickness: 0.25,
|
|
135
|
+
attenuationColor: [0.9, 0.95, 1],
|
|
136
|
+
attenuationDistance: 4,
|
|
137
|
+
transmissionTexture: { texture: 'texture/transmission' },
|
|
138
|
+
thicknessTexture: { texture: 'texture/thickness' },
|
|
139
|
+
},
|
|
140
|
+
},
|
|
141
|
+
resolved: {
|
|
142
|
+
...baseRecord.resolved,
|
|
143
|
+
parameters,
|
|
144
|
+
values: {
|
|
145
|
+
transmission: 0.8,
|
|
146
|
+
ior: 1.45,
|
|
147
|
+
thickness: 0.25,
|
|
148
|
+
attenuationColor: [0.9, 0.95, 1],
|
|
149
|
+
attenuationDistance: 4,
|
|
150
|
+
transmissionTexture: { texture: 'texture/transmission' },
|
|
151
|
+
thicknessTexture: { texture: 'texture/thickness' },
|
|
152
|
+
},
|
|
153
|
+
},
|
|
154
|
+
};
|
|
155
|
+
const loader = createMaterialLoader({
|
|
156
|
+
loadPublication: async () => ({ ...publication(), guid: PRODUCTION_GUID, record }),
|
|
157
|
+
loadReference: async () => true,
|
|
158
|
+
});
|
|
159
|
+
|
|
160
|
+
const result = await loader.load({
|
|
161
|
+
guid: PRODUCTION_GUID,
|
|
162
|
+
specializationKey: 'material-specialization/7/ready',
|
|
163
|
+
});
|
|
164
|
+
|
|
165
|
+
expect(result.status).toBe('Ready');
|
|
166
|
+
if (result.status !== 'Ready') return;
|
|
167
|
+
expect(result.parameterContract).toEqual(record.parameterContract);
|
|
168
|
+
expect(inspectMaterialRuntime(result).parameterContract).toEqual(record.parameterContract);
|
|
169
|
+
});
|
|
170
|
+
|
|
106
171
|
it('loads only a cooked record with its artifact and complete references', async () => {
|
|
107
172
|
const loader = createLoader(async () => publication());
|
|
108
173
|
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { createHash } from 'node:crypto';
|
|
1
2
|
import { existsSync } from 'node:fs';
|
|
2
3
|
import { fileURLToPath } from 'node:url';
|
|
3
4
|
import type { LoadContext, TextureAsset } from '@forgeax/engine-types';
|
|
@@ -7,7 +8,11 @@ import type {
|
|
|
7
8
|
BasisModuleFactory,
|
|
8
9
|
} from '../../../codec/src/wasm/basis-types.js';
|
|
9
10
|
import type { CodecContextFailure } from '../loaders/pack-artifact.js';
|
|
10
|
-
import {
|
|
11
|
+
import {
|
|
12
|
+
loadVerifiedTexturePack,
|
|
13
|
+
PACK_ARTIFACT_LOADERS,
|
|
14
|
+
textureLoader,
|
|
15
|
+
} from '../loaders/pack-artifact.js';
|
|
11
16
|
|
|
12
17
|
const TRANSCODER_GLUE = new URL('../../../codec/pkg/basis_transcoder.mjs', import.meta.url);
|
|
13
18
|
const ENCODER_GLUE = new URL('../../../codec/pkg/encode/basis_encoder.mjs', import.meta.url);
|
|
@@ -52,6 +57,10 @@ const context: LoadContext = {
|
|
|
52
57
|
device: undefined,
|
|
53
58
|
};
|
|
54
59
|
|
|
60
|
+
function digest(bytes: Uint8Array): string {
|
|
61
|
+
return `sha256:${createHash('sha256').update(bytes).digest('hex')}`;
|
|
62
|
+
}
|
|
63
|
+
|
|
55
64
|
describe.skipIf(!pkgBuilt)('Pack runtime raw Basis loader', () => {
|
|
56
65
|
it('keeps context failure code and detail correlated as a closed union', () => {
|
|
57
66
|
type ExpectedContextFailure =
|
|
@@ -79,7 +88,11 @@ describe.skipIf(!pkgBuilt)('Pack runtime raw Basis loader', () => {
|
|
|
79
88
|
{
|
|
80
89
|
guid: '019f0000-0000-7000-8000-000000000304',
|
|
81
90
|
kind: 'texture',
|
|
82
|
-
payload: {
|
|
91
|
+
payload: {
|
|
92
|
+
shape: { viewDimension: '2d', extent: { width: 4, height: 4 } },
|
|
93
|
+
colorSpace: 'linear',
|
|
94
|
+
mips: { kind: 'none' },
|
|
95
|
+
},
|
|
83
96
|
refs: [],
|
|
84
97
|
artifacts: {
|
|
85
98
|
body: {
|
|
@@ -101,12 +114,10 @@ describe.skipIf(!pkgBuilt)('Pack runtime raw Basis loader', () => {
|
|
|
101
114
|
if (!result.ok) return;
|
|
102
115
|
expect(result.value).toMatchObject({
|
|
103
116
|
kind: 'texture',
|
|
104
|
-
width: 4,
|
|
105
|
-
height: 4,
|
|
117
|
+
shape: { viewDimension: '2d', extent: { width: 4, height: 4 } },
|
|
106
118
|
format: 'rgba8unorm',
|
|
107
119
|
colorSpace: 'linear',
|
|
108
|
-
|
|
109
|
-
mipLevelCount: 1,
|
|
120
|
+
mips: { kind: 'packed', levelCount: 1 },
|
|
110
121
|
});
|
|
111
122
|
expect(result.value.data.byteLength).toBeGreaterThan(0);
|
|
112
123
|
});
|
|
@@ -119,7 +130,11 @@ describe.skipIf(!pkgBuilt)('Pack runtime raw Basis loader', () => {
|
|
|
119
130
|
{
|
|
120
131
|
guid: '019f0000-0000-7000-8000-000000000305',
|
|
121
132
|
kind: 'texture',
|
|
122
|
-
payload: {
|
|
133
|
+
payload: {
|
|
134
|
+
shape: { viewDimension: '2d', extent: { width: 4, height: 4 } },
|
|
135
|
+
colorSpace: 'srgb',
|
|
136
|
+
mips: { kind: 'none' },
|
|
137
|
+
},
|
|
123
138
|
refs: [],
|
|
124
139
|
artifacts: {
|
|
125
140
|
body: {
|
|
@@ -165,4 +180,48 @@ describe('Pack artifact loader matrix', () => {
|
|
|
165
180
|
['equirect', 'font', 'render-pipeline', 'texture', 'tileset'].sort(),
|
|
166
181
|
);
|
|
167
182
|
});
|
|
183
|
+
|
|
184
|
+
it('preserves array shape and generation provenance through verified loading', async () => {
|
|
185
|
+
const bytes = new Uint8Array(8 * 4 * 3).fill(91);
|
|
186
|
+
const artifactDigest = digest(bytes);
|
|
187
|
+
const result = await loadVerifiedTexturePack(
|
|
188
|
+
{
|
|
189
|
+
sourceKey: 'array/layers',
|
|
190
|
+
generation: 4,
|
|
191
|
+
expectedDigest: artifactDigest,
|
|
192
|
+
pack: {
|
|
193
|
+
guid: '019f0000-0000-7000-8000-000000000306',
|
|
194
|
+
kind: 'texture',
|
|
195
|
+
payload: {
|
|
196
|
+
shape: { viewDimension: '2d-array', extent: { width: 8, height: 4, layers: 3 } },
|
|
197
|
+
format: 'r8unorm',
|
|
198
|
+
colorSpace: 'linear',
|
|
199
|
+
mips: { kind: 'none' },
|
|
200
|
+
},
|
|
201
|
+
refs: [],
|
|
202
|
+
artifacts: {
|
|
203
|
+
body: {
|
|
204
|
+
bytes,
|
|
205
|
+
descriptor: {
|
|
206
|
+
path: 'array.raw',
|
|
207
|
+
mediaType: 'application/x-forgeax-r8',
|
|
208
|
+
byteLength: bytes.byteLength,
|
|
209
|
+
integrity: { algorithm: 'sha256', digest: artifactDigest },
|
|
210
|
+
},
|
|
211
|
+
},
|
|
212
|
+
},
|
|
213
|
+
},
|
|
214
|
+
},
|
|
215
|
+
context,
|
|
216
|
+
);
|
|
217
|
+
|
|
218
|
+
expect(result.ok).toBe(true);
|
|
219
|
+
if (!result.ok) return;
|
|
220
|
+
expect(result.value.asset.shape).toEqual({
|
|
221
|
+
viewDimension: '2d-array',
|
|
222
|
+
extent: { width: 8, height: 4, layers: 3 },
|
|
223
|
+
});
|
|
224
|
+
expect(result.value.generation).toBe(4);
|
|
225
|
+
expect(result.value.sourceKey).toBe('array/layers');
|
|
226
|
+
});
|
|
168
227
|
});
|