@forgeax/engine-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/README.md +45 -0
- package/dist/.tsbuildinfo +1 -1
- package/dist/__tests__/helpers/standard-material-manifest.d.ts +12 -0
- package/dist/__tests__/helpers/standard-material-manifest.d.ts.map +1 -0
- 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-environment-consumer.integration.test.d.ts +2 -0
- package/dist/__tests__/render-environment-consumer.integration.test.d.ts.map +1 -0
- package/dist/__tests__/render-error-exhaustive.test-d.d.ts.map +1 -1
- package/dist/__tests__/render-feature-prepared-graphics.fixture.d.ts.map +1 -1
- package/dist/__tests__/renderer-host-fallback.unit.test.d.ts +2 -0
- package/dist/__tests__/renderer-host-fallback.unit.test.d.ts.map +1 -0
- package/dist/__tests__/skinned-shadow-mixed.dawn.test.d.ts +2 -0
- package/dist/__tests__/skinned-shadow-mixed.dawn.test.d.ts.map +1 -0
- 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/backend-selection.d.ts.map +1 -1
- package/dist/createRenderer.d.ts.map +1 -1
- package/dist/index.mjs +21 -1
- package/dist/index.mjs.map +1 -1
- package/dist/renderer-host.d.ts +2 -1
- package/dist/renderer-host.d.ts.map +1 -1
- package/dist/renderer-host.mjs +21 -2
- package/dist/renderer-host.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/instances-per-instance-pbr.dawn.test.ts +12 -11
- 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 +56 -0
- package/src/__tests__/extract-record-no-hardcoded-texture-fields.test.ts +4 -5
- package/src/__tests__/four-path-compression.integration.test.ts +2 -2
- package/src/__tests__/fullscreen-post-process-pass.dawn.test.ts +461 -18
- package/src/__tests__/geometry.unit.test.ts +3 -1
- package/src/__tests__/gpu-resource-cow-survivor.test.ts +2 -3
- package/src/__tests__/helpers/standard-material-manifest.ts +45 -0
- 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 +18 -16
- package/src/__tests__/materials.unit.test.ts +2 -0
- 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 +31 -12
- package/src/__tests__/pipeline-cache-keying.unit.test.ts +6 -4
- package/src/__tests__/pipeline.unit.test.ts +23 -21
- package/src/__tests__/point-light-shadow.unit.test.ts +6 -5
- package/src/__tests__/render-environment-consumer.integration.test.ts +33 -0
- package/src/__tests__/render-error-exhaustive.test-d.ts +86 -0
- package/src/__tests__/render-feature-prepared-graphics.fixture.ts +10 -0
- package/src/__tests__/render-system-extract.test.ts +4 -6
- package/src/__tests__/render-system-mega.test.ts +3 -1
- package/src/__tests__/render-system-record-multi-material-textureview.test.ts +7 -7
- package/src/__tests__/render-system-record-per-submesh-transparency.test.ts +5 -4
- package/src/__tests__/render-system-record.test.ts +8 -6
- package/src/__tests__/renderer-host-fallback.unit.test.ts +112 -0
- package/src/__tests__/renderer-lifecycle.integration.test.ts +10 -0
- package/src/__tests__/renderer-surface.unit.test.ts +66 -0
- package/src/__tests__/shadow-csm-cascade-loadop.test.ts +5 -1
- package/src/__tests__/shadow-csm-tile-consistency.test.ts +5 -1
- package/src/__tests__/shadow-fields-observable.dawn.test.ts +56 -39
- package/src/__tests__/skinned-shadow-mixed.dawn.test.ts +385 -0
- package/src/__tests__/sprite-cullmode-flip.dawn.test.ts +4 -6
- package/src/__tests__/sprite-lit-bgl-byte-identical.test.ts +11 -9
- package/src/__tests__/ssao-passes.test.ts +28 -12
- package/src/__tests__/systems.unit.test.ts +63 -33
- 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/backend-selection.ts +4 -0
- package/src/createRenderer.ts +3 -0
- package/src/renderer-host.ts +30 -3
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/backend-selection.ts","../src/renderer-host.ts"],"names":[],"mappings":";;;;;AAKO,SAAS,WAAA,CACd,KACA,eAAA,EACgB;AAChB,EAAA,MAAM,MAAM,GAAA,CAAI,GAAA;AAChB,EAAA,MAAM,qBAAqB,GAAA,CAAI,kBAAA;AAG/B,EAAA,MAAM,gCAAgC,GAAA,CAAI,6BAAA;AAG1C,EAAA,MAAM,oBAAoB,GAAA,CAAI,sBAAA;AAG9B,EAAA,MAAM,yBAAyB,GAAA,CAAI,eAAA;AAGnC,EAAA,MAAM,IAAA,GAAuB;AAAA,IAC3B,GAAA;AAAA,IACA,GAAI,kBAAA,KAAuB,MAAA,GAAY,EAAC,GAAI,EAAE,kBAAA,EAAmB;AAAA,IACjE,GAAI,6BAAA,KAAkC,MAAA,GAAY,EAAC,GAAI,EAAE,6BAAA,EAA8B;AAAA,IACvF,GAAI,iBAAA,KAAsB,MAAA,GAAY,EAAC,GAAI,EAAE,wBAAwB,iBAAA;AAAkB,GACzF;AACA,EAAA,MAAM,0BAA0B,eAAA,IAAmB,sBAAA;AACnD,EAAA,OAAO,4BAA4B,MAAA,GAC/B,IAAA,GACA,EAAE,GAAG,IAAA,EAAM,iBAAiB,uBAAA,EAAwB;AAC1D;AAGA,eAAsB,eAAA,CACpB,OAAA,EACA,UAAA,GAAa,KAAA,EAIb;AACA,EAAA,MAAM,WAAW,OAAA,EAAS,GAAA;AAC1B,EAAA,IAAI,QAAA,KAAa,MAAA,IAAa,QAAA,KAAa,IAAA,EAAM;AAC/C,IAAA,OAAO,EAAA,CAAG,WAAA,CAAY,EAAE,GAAA,EAAK,QAAA,EAAU,GAAI,QAAA,EAAoB,EAAG,OAAA,EAAS,kBAAkB,CAAC,CAAA;AAAA,EAChG;AACA,EAAA,MAAM,GAAA,GACJ,OAAO,UAAA,KAAe,WAAA,GAClB,SACC,UAAA,CAAiD,SAAA;AACxD,EAAA,IAAI,CAAC,UAAA,IAAc,GAAA,EAAK,QAAQ,MAAA,IAAa,GAAA,CAAI,QAAQ,IAAA,EAAM;AAC7D,IAAA,OAAO,EAAA;AAAA,MACL,WAAA,CAAY,SAAA,EAAiD,OAAA,EAAS,kBAAkB;AAAA,KAC1F;AAAA,EACF;AACA,EAAA,IAAI;AACF,IAAA,MAAM,GAAA,GAAO,MAAM,OAAO,0BAA0B,CAAA;AACpD,IAAA,MAAO,IAAI,WAAA,EAAuC;AAClD,IAAA,OAAO,EAAA,CAAG,WAAA,CAAY,GAAA,EAAK,OAAA,EAAS,kBAAkB,CAAC,CAAA;AAAA,EACzD,SAAS,KAAA,EAAO;AACd,IAAA,OAAO,GAAA;AAAA,MACL,IAAI,QAAA,CAAS;AAAA,QACX,IAAA,EAAM,mBAAA;AAAA,QACN,QAAA,EAAU,mCAAA;AAAA,QACV,IAAA,EAAM,CAAA,6BAAA,EAAgC,MAAA,CAAO,KAAK,CAAC,CAAA;AAAA,OACpD;AAAA,KACH;AAAA,EACF;AACF;;;
|
|
1
|
+
{"version":3,"sources":["../src/backend-selection.ts","../src/renderer-host.ts"],"names":[],"mappings":"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","file":"renderer-host.mjs","sourcesContent":["import type { RendererOptions } from '@forgeax/engine-render';\nimport type { RhiBackendPack } from '@forgeax/engine-render/internal/construct-renderer';\nimport { err, ok, RhiError } from '@forgeax/engine-rhi';\nimport * as rhiWebgpu from '@forgeax/engine-rhi-webgpu';\n\nexport function loadRhiPack(\n mod: Record<string, unknown>,\n instrumentation?: RhiBackendPack['instrumentation'],\n): RhiBackendPack {\n const rhi = mod.rhi as unknown as RhiBackendPack['rhi'];\n const createShaderModule = mod.createShaderModule as\n | RhiBackendPack['createShaderModule']\n | undefined;\n const createShaderModuleImmediate = mod.createShaderModuleImmediate as\n | RhiBackendPack['createShaderModuleImmediate']\n | undefined;\n const translateErrorEventToRhiError = mod.translateErrorEventToRhiError as\n | RhiBackendPack['translateErrorEventToRhiError']\n | undefined;\n const rawDeviceAccessor = mod._internal_getRawDevice as unknown as\n | RhiBackendPack['_internal_getRawDevice']\n | undefined;\n const backendInstrumentation = mod.instrumentation as\n | RhiBackendPack['instrumentation']\n | undefined;\n const pack: RhiBackendPack = {\n rhi,\n ...(createShaderModule === undefined ? {} : { createShaderModule }),\n ...(createShaderModuleImmediate === undefined ? {} : { createShaderModuleImmediate }),\n ...(translateErrorEventToRhiError === undefined ? {} : { translateErrorEventToRhiError }),\n ...(rawDeviceAccessor === undefined ? {} : { _internal_getRawDevice: rawDeviceAccessor }),\n };\n const resolvedInstrumentation = instrumentation ?? backendInstrumentation;\n return resolvedInstrumentation === undefined\n ? pack\n : { ...pack, instrumentation: resolvedInstrumentation };\n}\n\n/** Selects one backend pack; render receives only this typed owner contract. */\nexport async function loadBackendPack(\n options: RendererOptions | undefined,\n preferWgpu = false,\n): Promise<\n | { readonly ok: true; readonly value: RhiBackendPack }\n | { readonly ok: false; readonly error: RhiError }\n> {\n const explicit = options?.rhi;\n if (explicit !== undefined && explicit !== null) {\n return ok(loadRhiPack({ rhi: explicit, ...(explicit as object) }, options?.rhiInstrumentation));\n }\n const nav =\n typeof globalThis === 'undefined'\n ? undefined\n : (globalThis as { navigator?: { gpu?: unknown } }).navigator;\n if (!preferWgpu && nav?.gpu !== undefined && nav.gpu !== null) {\n return ok(\n loadRhiPack(rhiWebgpu as unknown as Record<string, unknown>, options?.rhiInstrumentation),\n );\n }\n try {\n const mod = (await import('@forgeax/engine-rhi-wgpu')) as Record<string, unknown>;\n await (mod.ensureReady as () => Promise<unknown>)();\n return ok(loadRhiPack(mod, options?.rhiInstrumentation));\n } catch (cause) {\n return err(\n new RhiError({\n code: 'rhi-not-available',\n expected: 'a usable RHI backend is available',\n hint: `failed to load wgpu backend: ${String(cause)}`,\n }),\n );\n }\n}\n","import type { AssetRegistry } from '@forgeax/engine-assets-runtime';\nimport type { RenderError, RendererOptions, RenderResult } from '@forgeax/engine-render';\nimport type {\n BundlerOptions,\n RendererHostAssembly,\n} from '@forgeax/engine-render/internal/construct-renderer';\nimport {\n constructRendererHost,\n EngineEnvironmentError,\n} from '@forgeax/engine-render/internal/construct-renderer';\nimport { loadBackendPack } from './backend-selection';\n\nexport type {\n BundlerOptions,\n RendererHostAssembly,\n} from '@forgeax/engine-render/internal/construct-renderer';\n\nconst FALLBACK_ERROR_CODES = new Set([\n 'adapter-unavailable',\n 'request-adapter-threw',\n 'feature-not-enabled',\n 'limit-exceeded',\n 'rhi-not-available',\n 'device-lost',\n 'oom',\n]);\n\nfunction canFallbackToWgpu(error: unknown): boolean {\n if (!(error instanceof EngineEnvironmentError)) return false;\n const webgpuError = error.detail.webgpuError;\n if (webgpuError === undefined || typeof webgpuError !== 'object') return false;\n if (!('code' in webgpuError)) return false;\n const code = webgpuError.code;\n return typeof code === 'string' && FALLBACK_ERROR_CODES.has(code);\n}\n\n/** Assemble renderer plus asset services in the Runtime-owned backend host. */\nexport async function constructRuntimeRendererHost(\n canvas: unknown,\n options?: RendererOptions,\n bundler?: BundlerOptions,\n): Promise<RenderResult<RendererHostAssembly, RenderError | EngineEnvironmentError>> {\n const first = await loadBackendPack(options);\n if (!first.ok) throw first.error;\n const constructed = await constructRendererHost(canvas, options, bundler, first.value);\n if (\n constructed.ok ||\n options?.rhi !== undefined ||\n typeof globalThis === 'undefined' ||\n !canFallbackToWgpu(constructed.error)\n ) {\n return constructed;\n }\n const fallback = await loadBackendPack(options, true);\n if (!fallback.ok) return constructed;\n return constructRendererHost(canvas, options, bundler, fallback.value);\n}\n\nexport { loadRhiPack } from './backend-selection';\nexport type { AssetRegistry };\n"]}
|
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
|
}
|
|
@@ -10,11 +10,8 @@
|
|
|
10
10
|
// AC-01: PBR instances=N vs instances=1 frames differ (diffCount>0).
|
|
11
11
|
// AC-06: single entity + N instance reads meshes[0] (not meshes[instance_index]).
|
|
12
12
|
//
|
|
13
|
-
//
|
|
14
|
-
//
|
|
15
|
-
// (diffCount===0) because instance=1 at origin and instances=N all at origin
|
|
16
|
-
// produce the same pixel pattern. GREEN after w4 lands (PBR vs_main reads
|
|
17
|
-
// meshes[0] + instances[idx]).
|
|
13
|
+
// The PBR vertex path must combine the entity transform from meshes[0] with
|
|
14
|
+
// the per-instance transform selected by instance_index.
|
|
18
15
|
//
|
|
19
16
|
// Dual-state methodology: render to two textures (instances=N vs instances=1),
|
|
20
17
|
// read back both, count pixels that differ by more than epsilon. The
|
|
@@ -52,6 +49,11 @@ const INSTANCE_GRID_Y = 3;
|
|
|
52
49
|
const INSTANCE_GRID_Z = 2;
|
|
53
50
|
const INSTANCE_COUNT = INSTANCE_GRID_X * INSTANCE_GRID_Y * INSTANCE_GRID_Z; // 30
|
|
54
51
|
const SPACING = 2.5;
|
|
52
|
+
// Windows Dawn first-touch attempts have reached about 80 seconds for this
|
|
53
|
+
// two-renderer PBR/readback probe. Keep the test bounded, but above the
|
|
54
|
+
// project-wide 30-second budget so retries do not turn a slow valid probe into
|
|
55
|
+
// a cancelled nightly job.
|
|
56
|
+
const PBR_DAWN_TEST_TIMEOUT_MS = 120_000;
|
|
55
57
|
|
|
56
58
|
function buildTranslationGrid(): Float32Array {
|
|
57
59
|
const out = new Float32Array(INSTANCE_COUNT * 16);
|
|
@@ -85,8 +87,10 @@ const ENGINE_MANIFEST_URL = `data:application/json,${encodeURIComponent(
|
|
|
85
87
|
JSON.stringify(ENGINE_MANIFEST),
|
|
86
88
|
)}`;
|
|
87
89
|
|
|
88
|
-
describe('w2 -- PBR dual-state dawn smoke (AC-01 / AC-06
|
|
89
|
-
it('instances=N vs instances=1: frames differ in pixel diff count
|
|
90
|
+
describe('w2 -- PBR dual-state dawn smoke (AC-01 / AC-06)', () => {
|
|
91
|
+
it('instances=N vs instances=1: frames differ in pixel diff count', {
|
|
92
|
+
timeout: PBR_DAWN_TEST_TIMEOUT_MS,
|
|
93
|
+
}, async () => {
|
|
90
94
|
const dawnAvailable = typeof globalThis.navigator?.gpu?.requestAdapter === 'function';
|
|
91
95
|
if (!dawnAvailable) {
|
|
92
96
|
throw new Error('dawn-node navigator.gpu not injected; vitest.setup-webgpu.ts regressed');
|
|
@@ -366,9 +370,6 @@ describe('w2 -- PBR dual-state dawn smoke (AC-01 / AC-06, RED before w4)', () =>
|
|
|
366
370
|
|
|
367
371
|
// AC-01: diffCount>0 -- the two frames must differ (instances=N spreads
|
|
368
372
|
// to distinct positions, instances=1 renders at entity origin only).
|
|
369
|
-
// RED before w4: all N copies collapse to entity origin, so both frames
|
|
370
|
-
// render the same cube at the same position -> diffCount===0.
|
|
371
|
-
// Currently RED: diffCount===0 because shader doesn't read @group(3)
|
|
372
373
|
expect(diffCount).toBeGreaterThan(0);
|
|
373
374
|
// Also verify the N-instance frame has substantial non-clear pixels
|
|
374
375
|
// (proves instances rendered, not just an empty frame)
|
|
@@ -377,7 +378,7 @@ describe('w2 -- PBR dual-state dawn smoke (AC-01 / AC-06, RED before w4)', () =>
|
|
|
377
378
|
});
|
|
378
379
|
|
|
379
380
|
// w5 -- unlit dual-state: N unlit instances at distinct NDC positions (AC-02)
|
|
380
|
-
it('unlit Instances=N vs instances=1: frames differ
|
|
381
|
+
it('unlit Instances=N vs instances=1: frames differ', async () => {
|
|
381
382
|
const dawnAvailable_2 = typeof globalThis.navigator?.gpu?.requestAdapter === 'function';
|
|
382
383
|
if (!dawnAvailable_2) {
|
|
383
384
|
throw new Error('dawn-node navigator.gpu not injected');
|
|
@@ -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);
|