@flighthq/render-wgpu 0.3.0-next.1220.6982c21 → 0.3.0-next.1272.222de94

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.
Files changed (42) hide show
  1. package/dist/contract.d.ts +2 -1
  2. package/dist/contract.d.ts.map +1 -1
  3. package/dist/contract.js +2 -1
  4. package/dist/contract.js.map +1 -1
  5. package/dist/index.d.ts +1 -1
  6. package/dist/index.d.ts.map +1 -1
  7. package/dist/index.js +1 -1
  8. package/dist/index.js.map +1 -1
  9. package/dist/wgpuDraw.d.ts +3 -3
  10. package/dist/wgpuDraw.d.ts.map +1 -1
  11. package/dist/wgpuDraw.js +10 -1
  12. package/dist/wgpuDraw.js.map +1 -1
  13. package/dist/wgpuExternalImageSource.d.ts +2 -0
  14. package/dist/wgpuExternalImageSource.d.ts.map +1 -0
  15. package/dist/wgpuExternalImageSource.js +34 -0
  16. package/dist/wgpuExternalImageSource.js.map +1 -0
  17. package/dist/wgpuRenderState.d.ts +10 -1
  18. package/dist/wgpuRenderState.d.ts.map +1 -1
  19. package/dist/wgpuRenderState.js +182 -3
  20. package/dist/wgpuRenderState.js.map +1 -1
  21. package/dist/wgpuRenderTexture.d.ts +6 -1
  22. package/dist/wgpuRenderTexture.d.ts.map +1 -1
  23. package/dist/wgpuRenderTexture.js +70 -13
  24. package/dist/wgpuRenderTexture.js.map +1 -1
  25. package/dist/wgpuRenderTexturePool.d.ts +7 -0
  26. package/dist/wgpuRenderTexturePool.d.ts.map +1 -0
  27. package/dist/wgpuRenderTexturePool.js +85 -0
  28. package/dist/wgpuRenderTexturePool.js.map +1 -0
  29. package/dist/wgpuTestHelper.d.ts +1 -0
  30. package/dist/wgpuTestHelper.d.ts.map +1 -1
  31. package/dist/wgpuTestHelper.js +15 -1
  32. package/dist/wgpuTestHelper.js.map +1 -1
  33. package/dist/wgpuTextureUpload.d.ts.map +1 -1
  34. package/dist/wgpuTextureUpload.js +3 -0
  35. package/dist/wgpuTextureUpload.js.map +1 -1
  36. package/package.json +11 -11
  37. package/src/wgpuDraw.test.ts +53 -8
  38. package/src/wgpuExternalImageSource.test.ts +40 -0
  39. package/src/wgpuRenderState.test.ts +123 -0
  40. package/src/wgpuRenderTexture.test.ts +69 -0
  41. package/src/wgpuRenderTexturePool.test.ts +121 -0
  42. package/src/wgpuTextureUpload.test.ts +19 -0
@@ -1,10 +1,14 @@
1
+ import { resolveRenderTargetDescriptor } from '@flighthq/render/contract';
1
2
  import { getWgpuRenderStateRuntime } from './wgpuRenderState';
2
3
  import { beginWgpuRenderPass, createWgpuRenderTarget, destroyWgpuRenderTarget, endWgpuRenderPass, resizeWgpuRenderTarget, } from './wgpuRenderTarget';
3
4
  // Returns a populated render texture's state-owned allocation without copying pixels through the
4
5
  // CPU. An unrendered or currently-written Texture returns null.
5
6
  export function bindWgpuRenderTexture(state, renderTexture) {
6
7
  const entry = getWgpuRenderTextureEntry(state, renderTexture);
7
- return entry?.status === 'ready' ? entry.target : null;
8
+ if (entry?.status === 'ready')
9
+ return entry.target;
10
+ notifyGuard(state, renderTexture);
11
+ return null;
8
12
  }
9
13
  export function destroyWgpuRenderTexture(state, renderTexture) {
10
14
  const runtime = getWgpuRenderStateRuntime(state);
@@ -14,29 +18,66 @@ export function destroyWgpuRenderTexture(state, renderTexture) {
14
18
  destroyWgpuRenderTarget(state, entry.target);
15
19
  runtime.wgpuRenderTextureCache.delete(renderTexture);
16
20
  }
21
+ export function explainWgpuRenderTexture(state, renderTexture) {
22
+ const entry = getWgpuRenderTextureEntry(state, renderTexture);
23
+ return {
24
+ height: entry?.target.height ?? renderTexture.source.height,
25
+ status: entry?.status ?? 'unrendered',
26
+ width: entry?.target.width ?? renderTexture.source.width,
27
+ };
28
+ }
29
+ // Resolves the hidden target only while its public handle owns completed content. Effect recipes use
30
+ // this bridge; display composition continues to sample the RenderTexture.
31
+ export function getWgpuRenderTextureTarget(state, renderTexture) {
32
+ const entry = getWgpuRenderTextureEntry(state, renderTexture);
33
+ if (entry?.status === 'ready')
34
+ return entry.target;
35
+ notifyGuard(state, renderTexture);
36
+ return null;
37
+ }
38
+ export function invalidateWgpuRenderTexture(state, renderTexture, status = 'unrendered') {
39
+ const entry = getWgpuRenderTextureEntry(state, renderTexture);
40
+ if (entry !== undefined)
41
+ entry.status = status;
42
+ }
17
43
  export function isWgpuRenderTextureReady(state, renderTexture) {
18
- return getWgpuRenderTextureEntry(state, renderTexture)?.status === 'ready';
44
+ const ready = getWgpuRenderTextureEntry(state, renderTexture)?.status === 'ready';
45
+ if (!ready)
46
+ notifyGuard(state, renderTexture);
47
+ return ready;
19
48
  }
20
49
  /**
21
50
  * Clears and populates a render texture's hidden WebGPU target. The caller must have opened the
22
51
  * frame command encoder; the enclosing render pass is restored even when the callback throws.
23
52
  */
24
53
  export function renderIntoWgpuRenderTexture(state, renderTexture, callback) {
25
- const entry = ensureWgpuRenderTextureEntry(state, renderTexture);
26
- entry.status = 'writing';
27
- let rendered = false;
28
- try {
29
- beginWgpuRenderPass(state, entry.target);
54
+ writeWgpuRenderTextureTarget(state, renderTexture, (target) => {
55
+ beginWgpuRenderPass(state, target);
30
56
  try {
31
57
  callback(state);
32
- rendered = true;
33
58
  }
34
59
  finally {
35
60
  endWgpuRenderPass(state);
36
61
  }
62
+ });
63
+ }
64
+ export function setWgpuRenderTextureGuard(state, guard) {
65
+ getWgpuRenderStateRuntime(state).wgpuRenderTextureGuard = guard;
66
+ }
67
+ // Gives a backend recipe the hidden destination without opening a render pass. The recipe may encode
68
+ // several passes; success atomically publishes the handle, while failure restores an honest status.
69
+ export function writeWgpuRenderTextureTarget(state, renderTexture, callback) {
70
+ const entry = ensureWgpuRenderTextureEntry(state, renderTexture);
71
+ const previousStatus = entry.status;
72
+ entry.status = 'writing';
73
+ let rendered = false;
74
+ try {
75
+ const result = callback(entry.target);
76
+ rendered = true;
77
+ return result;
37
78
  }
38
79
  finally {
39
- entry.status = rendered ? 'ready' : 'unrendered';
80
+ entry.status = rendered ? 'ready' : previousStatus === 'writing' ? 'writing' : 'unrendered';
40
81
  if (rendered) {
41
82
  renderTexture.colorSpace = entry.target.colorSpace;
42
83
  renderTexture.version = (renderTexture.version + 1) >>> 0;
@@ -45,18 +86,31 @@ export function renderIntoWgpuRenderTexture(state, renderTexture, callback) {
45
86
  }
46
87
  function ensureWgpuRenderTextureEntry(state, renderTexture) {
47
88
  const descriptor = renderTexture.source;
89
+ const requested = resolveRenderTargetDescriptor(descriptor);
90
+ const format = getWgpuRenderTextureFormat(state, requested.format);
91
+ const colorSpace = descriptor.colorSpace ?? renderTexture.colorSpace;
48
92
  const runtime = getWgpuRenderStateRuntime(state);
49
93
  const entries = (runtime.wgpuRenderTextureCache ??= new WeakMap());
50
94
  let entry = entries.get(renderTexture);
51
95
  if (entry === undefined) {
52
- const target = createWgpuRenderTarget(state, descriptor.width, descriptor.height, getWgpuRenderTextureFormat(state, descriptor.format), descriptor.colorSpace ?? renderTexture.colorSpace);
53
- target.clearColors = [...(descriptor.clearColors ?? [])];
54
- target.clearDepth = descriptor.clearDepth ?? 1;
96
+ const target = createWgpuRenderTarget(state, requested.width, requested.height, format, colorSpace);
97
+ target.clearColors = [...requested.clearColors];
98
+ target.clearDepth = requested.clearDepth;
55
99
  entry = { status: 'unrendered', target };
56
100
  entries.set(renderTexture, entry);
57
101
  }
58
102
  else {
59
- resizeWgpuRenderTarget(state, entry.target, descriptor.width, descriptor.height);
103
+ if (entry.target.format !== format) {
104
+ destroyWgpuRenderTarget(state, entry.target);
105
+ entry.target = createWgpuRenderTarget(state, requested.width, requested.height, format, colorSpace);
106
+ entry.status = 'unrendered';
107
+ }
108
+ else {
109
+ resizeWgpuRenderTarget(state, entry.target, requested.width, requested.height);
110
+ entry.target.colorSpace = colorSpace;
111
+ }
112
+ entry.target.clearColors = [...requested.clearColors];
113
+ entry.target.clearDepth = requested.clearDepth;
60
114
  }
61
115
  return entry;
62
116
  }
@@ -70,4 +124,7 @@ function getWgpuRenderTextureFormat(state, format) {
70
124
  return 'rgba32float';
71
125
  return format === 'rgba8' ? 'rgba8unorm' : state.format;
72
126
  }
127
+ function notifyGuard(state, renderTexture) {
128
+ getWgpuRenderStateRuntime(state).wgpuRenderTextureGuard?.(state, renderTexture, explainWgpuRenderTexture(state, renderTexture));
129
+ }
73
130
  //# sourceMappingURL=wgpuRenderTexture.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"wgpuRenderTexture.js","sourceRoot":"","sources":["../src/wgpuRenderTexture.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"wgpuRenderTexture.js","sourceRoot":"","sources":["../src/wgpuRenderTexture.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,7 @@
1
+ import type { RenderTargetDescriptor, RenderTexture, WgpuRenderState, WgpuRenderTexturePool } from '@flighthq/types/contract';
2
+ export declare function acquireWgpuRenderTexture(state: WgpuRenderState, pool: WgpuRenderTexturePool, descriptor: Readonly<RenderTargetDescriptor>): RenderTexture;
3
+ export declare function createWgpuRenderTexturePool(): WgpuRenderTexturePool;
4
+ export declare function destroyWgpuRenderTexturePool(state: WgpuRenderState, pool: WgpuRenderTexturePool): void;
5
+ export declare function releaseWgpuRenderTexture(state: WgpuRenderState, pool: WgpuRenderTexturePool, renderTexture: RenderTexture): void;
6
+ export declare function withWgpuRenderTextures<T>(state: WgpuRenderState, pool: WgpuRenderTexturePool, descriptors: ReadonlyArray<Readonly<RenderTargetDescriptor>>, callback: (textures: ReadonlyArray<RenderTexture>) => T): T;
7
+ //# sourceMappingURL=wgpuRenderTexturePool.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"wgpuRenderTexturePool.d.ts","sourceRoot":"","sources":["../src/wgpuRenderTexturePool.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAEV,sBAAsB,EACtB,aAAa,EACb,eAAe,EACf,qBAAqB,EACtB,MAAM,0BAA0B,CAAC;AAKlC,wBAAgB,wBAAwB,CACtC,KAAK,EAAE,eAAe,EACtB,IAAI,EAAE,qBAAqB,EAC3B,UAAU,EAAE,QAAQ,CAAC,sBAAsB,CAAC,GAC3C,aAAa,CAQf;AAED,wBAAgB,2BAA2B,IAAI,qBAAqB,CAQnE;AAID,wBAAgB,4BAA4B,CAAC,KAAK,EAAE,eAAe,EAAE,IAAI,EAAE,qBAAqB,GAAG,IAAI,CAStG;AAED,wBAAgB,wBAAwB,CACtC,KAAK,EAAE,eAAe,EACtB,IAAI,EAAE,qBAAqB,EAC3B,aAAa,EAAE,aAAa,GAC3B,IAAI,CAON;AAED,wBAAgB,sBAAsB,CAAC,CAAC,EACtC,KAAK,EAAE,eAAe,EACtB,IAAI,EAAE,qBAAqB,EAC3B,WAAW,EAAE,aAAa,CAAC,QAAQ,CAAC,sBAAsB,CAAC,CAAC,EAC5D,QAAQ,EAAE,CAAC,QAAQ,EAAE,aAAa,CAAC,aAAa,CAAC,KAAK,CAAC,GACtD,CAAC,CAWH"}
@@ -0,0 +1,85 @@
1
+ import { createRenderTexture } from '@flighthq/texture/contract';
2
+ import { createWgpuRenderTargetPool, destroyWgpuRenderTargetPool } from './wgpuRenderTargetPool';
3
+ import { destroyWgpuRenderTexture, invalidateWgpuRenderTexture } from './wgpuRenderTexture';
4
+ export function acquireWgpuRenderTexture(state, pool, descriptor) {
5
+ assertUsablePool(state, pool);
6
+ const renderTexture = pool.free.pop() ?? createRenderTexture(descriptor);
7
+ applyRenderTargetDescriptor(renderTexture.source, descriptor);
8
+ renderTexture.colorSpace = descriptor.colorSpace ?? 'srgb';
9
+ invalidateWgpuRenderTexture(state, renderTexture);
10
+ pool.leased.add(renderTexture);
11
+ return renderTexture;
12
+ }
13
+ export function createWgpuRenderTexturePool() {
14
+ return {
15
+ device: null,
16
+ destroyed: false,
17
+ effectTargets: createWgpuRenderTargetPool(),
18
+ free: [],
19
+ leased: new Set(),
20
+ };
21
+ }
22
+ // Destroys both free and outstanding handles. Shutdown does not require callers to recover every
23
+ // displayed lease first; the pool becomes permanently unusable afterward.
24
+ export function destroyWgpuRenderTexturePool(state, pool) {
25
+ if (pool.destroyed)
26
+ return;
27
+ assertPoolDevice(state, pool);
28
+ const textures = new Set([...pool.free, ...pool.leased]);
29
+ for (const renderTexture of textures)
30
+ destroyWgpuRenderTexture(state, renderTexture);
31
+ pool.free.length = 0;
32
+ pool.leased.clear();
33
+ destroyWgpuRenderTargetPool(state, pool.effectTargets);
34
+ pool.destroyed = true;
35
+ }
36
+ export function releaseWgpuRenderTexture(state, pool, renderTexture) {
37
+ assertUsablePool(state, pool);
38
+ if (!pool.leased.delete(renderTexture)) {
39
+ throw new Error('releaseWgpuRenderTexture: texture is not leased from this pool');
40
+ }
41
+ invalidateWgpuRenderTexture(state, renderTexture, 'released');
42
+ pool.free.push(renderTexture);
43
+ }
44
+ export function withWgpuRenderTextures(state, pool, descriptors, callback) {
45
+ const textures = [];
46
+ try {
47
+ for (const descriptor of descriptors)
48
+ textures.push(acquireWgpuRenderTexture(state, pool, descriptor));
49
+ return callback(textures);
50
+ }
51
+ finally {
52
+ for (let i = textures.length - 1; i >= 0; i--) {
53
+ const texture = textures[i];
54
+ if (pool.leased.has(texture))
55
+ releaseWgpuRenderTexture(state, pool, texture);
56
+ }
57
+ }
58
+ }
59
+ function applyRenderTargetDescriptor(target, descriptor) {
60
+ target.width = descriptor.width;
61
+ target.height = descriptor.height;
62
+ target.format = descriptor.format;
63
+ target.colorAttachments = descriptor.colorAttachments;
64
+ target.colorFormats = descriptor.colorFormats === undefined ? undefined : [...descriptor.colorFormats];
65
+ target.sampleCount = descriptor.sampleCount;
66
+ target.depth = descriptor.depth;
67
+ target.colorSpace = descriptor.colorSpace ?? 'srgb';
68
+ target.clearColors = descriptor.clearColors === undefined ? undefined : [...descriptor.clearColors];
69
+ target.clearDepth = descriptor.clearDepth;
70
+ target.version = (target.version + 1) >>> 0;
71
+ }
72
+ function assertUsablePool(state, pool) {
73
+ if (pool.destroyed)
74
+ throw new Error('WgpuRenderTexturePool has been destroyed');
75
+ assertPoolDevice(state, pool);
76
+ }
77
+ function assertPoolDevice(state, pool) {
78
+ if (pool.device === null) {
79
+ pool.device = state.device;
80
+ }
81
+ else if (pool.device !== state.device) {
82
+ throw new Error('WgpuRenderTexturePool cannot cross GPU devices');
83
+ }
84
+ }
85
+ //# sourceMappingURL=wgpuRenderTexturePool.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"wgpuRenderTexturePool.js","sourceRoot":"","sources":["../src/wgpuRenderTexturePool.ts"],"names":[],"mappings":"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"}
@@ -1,4 +1,5 @@
1
1
  import type { WgpuRenderState } from '@flighthq/types/contract';
2
+ export declare function createReadyImageElementForTest(width?: number, height?: number): HTMLImageElement;
2
3
  export declare function createWgpuRenderStateForTest(): Promise<WgpuRenderState>;
3
4
  export declare function installWgpuMock(): void;
4
5
  //# sourceMappingURL=wgpuTestHelper.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"wgpuTestHelper.d.ts","sourceRoot":"","sources":["../src/wgpuTestHelper.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,0BAA0B,CAAC;AA+HhE,wBAAsB,4BAA4B,IAAI,OAAO,CAAC,eAAe,CAAC,CAK7E;AAED,wBAAgB,eAAe,IAAI,IAAI,CAiCtC"}
1
+ {"version":3,"file":"wgpuTestHelper.d.ts","sourceRoot":"","sources":["../src/wgpuTestHelper.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,0BAA0B,CAAC;AAkIhE,wBAAgB,8BAA8B,CAAC,KAAK,SAAI,EAAE,MAAM,SAAI,GAAG,gBAAgB,CAUtF;AAED,wBAAsB,4BAA4B,IAAI,OAAO,CAAC,eAAe,CAAC,CAK7E;AAED,wBAAgB,eAAe,IAAI,IAAI,CAiCtC"}
@@ -80,7 +80,7 @@ function makePipelineLayout() {
80
80
  function makeDevice() {
81
81
  return {
82
82
  features: new Set(),
83
- limits: { minUniformBufferOffsetAlignment: 256 },
83
+ limits: { maxTextureDimension2D: 8192, minUniformBufferOffsetAlignment: 256 },
84
84
  createBindGroup: () => makeBindGroup(),
85
85
  createBindGroupLayout: () => makeBindGroupLayout(),
86
86
  createBuffer: () => makeBuffer(),
@@ -107,6 +107,20 @@ function makeAdapter() {
107
107
  requestDevice: () => Promise.resolve(makeDevice()),
108
108
  };
109
109
  }
110
+ // JSDOM does not decode image elements, so a bare <img> remains incomplete even when its layout
111
+ // width and height are assigned. Use this fixture when a test needs to exercise a successful external
112
+ // image upload; readiness-failure tests should keep constructing the incomplete element directly.
113
+ export function createReadyImageElementForTest(width = 1, height = 1) {
114
+ const image = document.createElement('img');
115
+ image.width = width;
116
+ image.height = height;
117
+ Object.defineProperties(image, {
118
+ complete: { configurable: true, value: true },
119
+ naturalHeight: { configurable: true, value: height },
120
+ naturalWidth: { configurable: true, value: width },
121
+ });
122
+ return image;
123
+ }
110
124
  export async function createWgpuRenderStateForTest() {
111
125
  const canvas = document.createElement('canvas');
112
126
  canvas.width = 800;
@@ -1 +1 @@
1
- {"version":3,"file":"wgpuTestHelper.js","sourceRoot":"","sources":["../src/wgpuTestHelper.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"wgpuTestHelper.js","sourceRoot":"","sources":["../src/wgpuTestHelper.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"wgpuTextureUpload.d.ts","sourceRoot":"","sources":["../src/wgpuTextureUpload.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,0BAA0B,CAAC;AAStD,wBAAgB,qBAAqB,CACnC,MAAM,EAAE,SAAS,EACjB,OAAO,EAAE,UAAU,EACnB,MAAM,EAAE,WAAW,EACnB,KAAK,EAAE,MAAM,EACb,MAAM,EAAE,MAAM,EACd,IAAI,EAAE,QAAQ,CAAC,iBAAiB,CAAC,WAAW,CAAC,CAAC,GAC7C,IAAI,CAON;AAID,wBAAgB,wBAAwB,CACtC,MAAM,EAAE,SAAS,EACjB,OAAO,EAAE,UAAU,EACnB,MAAM,EAAE,WAAW,EACnB,KAAK,EAAE,MAAM,EACb,MAAM,EAAE,MAAM,EACd,MAAM,EAAE,0BAA0B,GACjC,IAAI,CAEN;AAGD,wBAAgB,8BAA8B,CAC5C,MAAM,EAAE,SAAS,EACjB,OAAO,EAAE,UAAU,EACnB,MAAM,EAAE,WAAW,EACnB,KAAK,EAAE,QAAQ,CAAC,KAAK,CAAC,GACrB,IAAI,CASN"}
1
+ {"version":3,"file":"wgpuTextureUpload.d.ts","sourceRoot":"","sources":["../src/wgpuTextureUpload.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,0BAA0B,CAAC;AAWtD,wBAAgB,qBAAqB,CACnC,MAAM,EAAE,SAAS,EACjB,OAAO,EAAE,UAAU,EACnB,MAAM,EAAE,WAAW,EACnB,KAAK,EAAE,MAAM,EACb,MAAM,EAAE,MAAM,EACd,IAAI,EAAE,QAAQ,CAAC,iBAAiB,CAAC,WAAW,CAAC,CAAC,GAC7C,IAAI,CAON;AAID,wBAAgB,wBAAwB,CACtC,MAAM,EAAE,SAAS,EACjB,OAAO,EAAE,UAAU,EACnB,MAAM,EAAE,WAAW,EACnB,KAAK,EAAE,MAAM,EACb,MAAM,EAAE,MAAM,EACd,MAAM,EAAE,0BAA0B,GACjC,IAAI,CAGN;AAGD,wBAAgB,8BAA8B,CAC5C,MAAM,EAAE,SAAS,EACjB,OAAO,EAAE,UAAU,EACnB,MAAM,EAAE,WAAW,EACnB,KAAK,EAAE,QAAQ,CAAC,KAAK,CAAC,GACrB,IAAI,CASN"}
@@ -1,3 +1,4 @@
1
+ import { isWgpuExternalImageSourceReady } from './wgpuExternalImageSource';
1
2
  // Texel-upload primitives for one texture region. Each writes into `texture` at `origin` (the [x, y, z]
2
3
  // where z selects a cube-array layer / cube face). The wgpu mirror of render-gl's glTextureUpload; the
3
4
  // caller owns texture creation and format.
@@ -10,6 +11,8 @@ export function uploadWgpuTextureData(device, texture, origin, width, height, da
10
11
  // Uploads a decoded DOM element through queue.copyExternalImageToTexture — the web fast-path (GPU-side
11
12
  // copy, no CPU staging). Absent on non-web hosts.
12
13
  export function uploadWgpuTextureElement(device, texture, origin, width, height, source) {
14
+ if (!isWgpuExternalImageSourceReady(source, width, height))
15
+ return;
13
16
  device.queue.copyExternalImageToTexture({ source }, { texture, origin }, [width, height, 1]);
14
17
  }
15
18
  // Uploads a host-backed Image through the decoded-element fast path.
@@ -1 +1 @@
1
- {"version":3,"file":"wgpuTextureUpload.js","sourceRoot":"","sources":["../src/wgpuTextureUpload.ts"],"names":[],"mappings":"AAEA,wGAAwG;AACxG,uGAAuG;AACvG,2CAA2C;AAE3C,0GAA0G;AAC1G,2GAA2G;AAC3G,wCAAwC;AACxC,MAAM,UAAU,qBAAqB,CACnC,MAAiB,EACjB,OAAmB,EACnB,MAAmB,EACnB,KAAa,EACb,MAAc,EACd,IAA8C;IAE9C,MAAM,CAAC,KAAK,CAAC,YAAY,CACvB,EAAE,OAAO,EAAE,MAAM,EAAE,EACnB,IAAsC,EACtC,EAAE,WAAW,EAAE,KAAK,GAAG,CAAC,EAAE,YAAY,EAAE,MAAM,EAAE,EAChD,CAAC,KAAK,EAAE,MAAM,EAAE,CAAC,CAAC,CACnB,CAAC;AACJ,CAAC;AAED,uGAAuG;AACvG,kDAAkD;AAClD,MAAM,UAAU,wBAAwB,CACtC,MAAiB,EACjB,OAAmB,EACnB,MAAmB,EACnB,KAAa,EACb,MAAc,EACd,MAAkC;IAElC,MAAM,CAAC,KAAK,CAAC,0BAA0B,CAAC,EAAE,MAAM,EAAE,EAAE,EAAE,OAAO,EAAE,MAAM,EAAE,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,CAAC,CAAC,CAAC,CAAC;AAC/F,CAAC;AAED,qEAAqE;AACrE,MAAM,UAAU,8BAA8B,CAC5C,MAAiB,EACjB,OAAmB,EACnB,MAAmB,EACnB,KAAsB;IAEtB,wBAAwB,CACtB,MAAM,EACN,OAAO,EACP,MAAM,EACN,KAAK,CAAC,KAAK,EACX,KAAK,CAAC,MAAM,EACZ,KAAK,CAAC,MAAoC,CAC3C,CAAC;AACJ,CAAC"}
1
+ {"version":3,"file":"wgpuTextureUpload.js","sourceRoot":"","sources":["../src/wgpuTextureUpload.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,8BAA8B,EAAE,MAAM,2BAA2B,CAAC;AAE3E,wGAAwG;AACxG,uGAAuG;AACvG,2CAA2C;AAE3C,0GAA0G;AAC1G,2GAA2G;AAC3G,wCAAwC;AACxC,MAAM,UAAU,qBAAqB,CACnC,MAAiB,EACjB,OAAmB,EACnB,MAAmB,EACnB,KAAa,EACb,MAAc,EACd,IAA8C;IAE9C,MAAM,CAAC,KAAK,CAAC,YAAY,CACvB,EAAE,OAAO,EAAE,MAAM,EAAE,EACnB,IAAsC,EACtC,EAAE,WAAW,EAAE,KAAK,GAAG,CAAC,EAAE,YAAY,EAAE,MAAM,EAAE,EAChD,CAAC,KAAK,EAAE,MAAM,EAAE,CAAC,CAAC,CACnB,CAAC;AACJ,CAAC;AAED,uGAAuG;AACvG,kDAAkD;AAClD,MAAM,UAAU,wBAAwB,CACtC,MAAiB,EACjB,OAAmB,EACnB,MAAmB,EACnB,KAAa,EACb,MAAc,EACd,MAAkC;IAElC,IAAI,CAAC,8BAA8B,CAAC,MAAM,EAAE,KAAK,EAAE,MAAM,CAAC;QAAE,OAAO;IACnE,MAAM,CAAC,KAAK,CAAC,0BAA0B,CAAC,EAAE,MAAM,EAAE,EAAE,EAAE,OAAO,EAAE,MAAM,EAAE,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,CAAC,CAAC,CAAC,CAAC;AAC/F,CAAC;AAED,qEAAqE;AACrE,MAAM,UAAU,8BAA8B,CAC5C,MAAiB,EACjB,OAAmB,EACnB,MAAmB,EACnB,KAAsB;IAEtB,wBAAwB,CACtB,MAAM,EACN,OAAO,EACP,MAAM,EACN,KAAK,CAAC,KAAK,EACX,KAAK,CAAC,MAAM,EACZ,KAAK,CAAC,MAAoC,CAC3C,CAAC;AACJ,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@flighthq/render-wgpu",
3
- "version": "0.3.0-next.1220.6982c21",
3
+ "version": "0.3.0-next.1272.222de94",
4
4
  "repository": {
5
5
  "type": "git",
6
6
  "url": "https://github.com/flighthq/flight.git",
@@ -36,16 +36,16 @@
36
36
  "clean:dist": "tsx ../../scripts/clean-package-dist.ts"
37
37
  },
38
38
  "dependencies": {
39
- "@flighthq/color": "0.3.0-next.1220.6982c21",
40
- "@flighthq/entity": "0.3.0-next.1220.6982c21",
41
- "@flighthq/scene2d": "0.3.0-next.1220.6982c21",
42
- "@flighthq/geometry": "0.3.0-next.1220.6982c21",
43
- "@flighthq/log": "0.3.0-next.1220.6982c21",
44
- "@flighthq/render": "0.3.0-next.1220.6982c21",
45
- "@flighthq/signals": "0.3.0-next.1220.6982c21",
46
- "@flighthq/bitmap": "0.3.0-next.1220.6982c21",
47
- "@flighthq/texture": "0.3.0-next.1220.6982c21",
48
- "@flighthq/types": "0.3.0-next.1220.6982c21"
39
+ "@flighthq/color": "0.3.0-next.1272.222de94",
40
+ "@flighthq/entity": "0.3.0-next.1272.222de94",
41
+ "@flighthq/scene2d": "0.3.0-next.1272.222de94",
42
+ "@flighthq/geometry": "0.3.0-next.1272.222de94",
43
+ "@flighthq/log": "0.3.0-next.1272.222de94",
44
+ "@flighthq/render": "0.3.0-next.1272.222de94",
45
+ "@flighthq/signals": "0.3.0-next.1272.222de94",
46
+ "@flighthq/bitmap": "0.3.0-next.1272.222de94",
47
+ "@flighthq/texture": "0.3.0-next.1272.222de94",
48
+ "@flighthq/types": "0.3.0-next.1272.222de94"
49
49
  },
50
50
  "devDependencies": {
51
51
  "@webgpu/types": "*",
@@ -1,7 +1,7 @@
1
1
  import { getOrCreateRenderProxy2D, prepareScene2DRender } from '@flighthq/render/contract';
2
2
  import { createSprite } from '@flighthq/scene2d/contract';
3
3
  import { getTextureSource } from '@flighthq/texture/contract';
4
- import type { Bitmap, CompressedImage, Image, Texture } from '@flighthq/types/contract';
4
+ import type { Bitmap, CompressedImage, Image, Texture, WgpuTextureEntry } from '@flighthq/types/contract';
5
5
  import {
6
6
  BitmapTextureSourceKind,
7
7
  BlendMode,
@@ -37,6 +37,11 @@ beforeAll(() => {
37
37
  installWgpuMock();
38
38
  });
39
39
 
40
+ function requireTextureEntry(entry: WgpuTextureEntry | null): WgpuTextureEntry {
41
+ if (entry === null) throw new Error('Expected a ready WebGPU texture entry');
42
+ return entry;
43
+ }
44
+
40
45
  function bitmap(size: number, version: number): Bitmap {
41
46
  return {
42
47
  alphaType: 'straight',
@@ -142,6 +147,46 @@ describe('bindWgpuImageResourceTexture', () => {
142
147
  bindWgpuImageResourceTexture(state, image);
143
148
  expect(copy).toHaveBeenCalled();
144
149
  });
150
+
151
+ it('skips an initial upload when the canvas has no pixels', async () => {
152
+ const state = await createWgpuRenderStateForTest();
153
+ const copy = vi.spyOn(state.device.queue, 'copyExternalImageToTexture');
154
+ const canvas = document.createElement('canvas');
155
+ canvas.width = 0;
156
+ canvas.height = 4;
157
+ const image = {
158
+ source: canvas,
159
+ width: 0,
160
+ height: 4,
161
+ kind: ImageTextureSourceKind,
162
+ version: 1,
163
+ } as unknown as Image;
164
+ expect(bindWgpuImageResourceTexture(state, image)).toBeNull();
165
+ expect(copy).not.toHaveBeenCalled();
166
+ });
167
+
168
+ it('keeps the previous upload while a 2D canvas context is lost', async () => {
169
+ const state = await createWgpuRenderStateForTest();
170
+ const copy = vi.spyOn(state.device.queue, 'copyExternalImageToTexture');
171
+ const canvas = document.createElement('canvas');
172
+ canvas.width = 4;
173
+ canvas.height = 4;
174
+ const image = {
175
+ source: canvas,
176
+ width: 4,
177
+ height: 4,
178
+ kind: ImageTextureSourceKind,
179
+ version: 1,
180
+ } as unknown as Image;
181
+ const entry = requireTextureEntry(bindWgpuImageResourceTexture(state, image));
182
+ const getContext = vi
183
+ .spyOn(canvas, 'getContext')
184
+ .mockReturnValue({ isContextLost: () => true } as unknown as GPUCanvasContext);
185
+ image.version = 2;
186
+ expect(bindWgpuImageResourceTexture(state, image)).toBe(entry);
187
+ expect(copy).toHaveBeenCalledTimes(1);
188
+ getContext.mockRestore();
189
+ });
145
190
  });
146
191
 
147
192
  describe('bindWgpuTexture', () => {
@@ -150,7 +195,7 @@ describe('bindWgpuTexture', () => {
150
195
  const canvas = document.createElement('canvas');
151
196
  canvas.width = 8;
152
197
  canvas.height = 8;
153
- const entry = bindWgpuTexture(state, canvas);
198
+ const entry = requireTextureEntry(bindWgpuTexture(state, canvas));
154
199
  expect(entry).toBeDefined();
155
200
  expect(entry.texture).toBeDefined();
156
201
  expect(bindWgpuTexture(state, canvas)).toBe(entry);
@@ -254,7 +299,7 @@ describe('createWgpuTextureEntry', () => {
254
299
  const canvas = document.createElement('canvas');
255
300
  canvas.width = 4;
256
301
  canvas.height = 4;
257
- const entry = createWgpuTextureEntry(state, 4, 4, canvas);
302
+ const entry = requireTextureEntry(createWgpuTextureEntry(state, 4, 4, canvas));
258
303
  expect(entry.texture).toBeDefined();
259
304
  expect(entry.bindGroup).toBeDefined();
260
305
  });
@@ -276,7 +321,7 @@ describe('drawWgpuQuad', () => {
276
321
  const canvas = document.createElement('canvas');
277
322
  canvas.width = 4;
278
323
  canvas.height = 4;
279
- const entry = bindWgpuTexture(state, canvas);
324
+ const entry = requireTextureEntry(bindWgpuTexture(state, canvas));
280
325
  expect(() => drawWgpuQuad(state, renderProxy, entry, 0, 0, 4, 4, 0, 0, 1, 1)).not.toThrow();
281
326
  submitWgpuRenderPass(state);
282
327
  });
@@ -292,7 +337,7 @@ describe('drawWgpuQuadWithTransform', () => {
292
337
  const canvas = document.createElement('canvas');
293
338
  canvas.width = 4;
294
339
  canvas.height = 4;
295
- const entry = bindWgpuTexture(state, canvas);
340
+ const entry = requireTextureEntry(bindWgpuTexture(state, canvas));
296
341
  const t = { a: 1, b: 0, c: 0, d: 1, tx: 0, ty: 0 };
297
342
  expect(() => drawWgpuQuadWithTransform(state, renderProxy, t, entry, 0, 0, 4, 4, 0, 0, 1, 1)).not.toThrow();
298
343
  submitWgpuRenderPass(state);
@@ -368,7 +413,7 @@ describe('submitWgpuQuadDraw', () => {
368
413
  const canvas = document.createElement('canvas');
369
414
  canvas.width = 4;
370
415
  canvas.height = 4;
371
- const entry = bindWgpuTexture(state, canvas);
416
+ const entry = requireTextureEntry(bindWgpuTexture(state, canvas));
372
417
  expect(() => submitWgpuQuadDraw(state, 0, entry.bindGroup)).not.toThrow();
373
418
  submitWgpuRenderPass(state);
374
419
  });
@@ -378,7 +423,7 @@ describe('submitWgpuQuadDraw', () => {
378
423
  const canvas = document.createElement('canvas');
379
424
  canvas.width = 4;
380
425
  canvas.height = 4;
381
- const entry = bindWgpuTexture(state, canvas);
426
+ const entry = requireTextureEntry(bindWgpuTexture(state, canvas));
382
427
  expect(() => submitWgpuQuadDraw(state, 0, entry.bindGroup)).not.toThrow();
383
428
  });
384
429
  });
@@ -389,7 +434,7 @@ describe('updateWgpuTextureEntry', () => {
389
434
  const canvas = document.createElement('canvas');
390
435
  canvas.width = 4;
391
436
  canvas.height = 4;
392
- const entry = createWgpuTextureEntry(state, 4, 4, canvas);
437
+ const entry = requireTextureEntry(createWgpuTextureEntry(state, 4, 4, canvas));
393
438
  expect(() => updateWgpuTextureEntry(state, entry, canvas)).not.toThrow();
394
439
  });
395
440
  });
@@ -0,0 +1,40 @@
1
+ import { isWgpuExternalImageSourceReady } from './wgpuExternalImageSource';
2
+ import { createReadyImageElementForTest } from './wgpuTestHelper';
3
+
4
+ describe('isWgpuExternalImageSourceReady', () => {
5
+ it('accepts a readable canvas with enough pixels', () => {
6
+ const canvas = document.createElement('canvas');
7
+ canvas.width = 4;
8
+ canvas.height = 4;
9
+ expect(isWgpuExternalImageSourceReady(canvas, 4, 4)).toBe(true);
10
+ });
11
+
12
+ it('accepts a decoded image with enough pixels', () => {
13
+ const image = createReadyImageElementForTest(4, 4);
14
+ expect(isWgpuExternalImageSourceReady(image, 4, 4)).toBe(true);
15
+ });
16
+
17
+ it('rejects zero extents and undersized sources', () => {
18
+ const canvas = document.createElement('canvas');
19
+ canvas.width = 4;
20
+ canvas.height = 4;
21
+ expect(isWgpuExternalImageSourceReady(canvas, 0, 4)).toBe(false);
22
+ expect(isWgpuExternalImageSourceReady(canvas, 5, 4)).toBe(false);
23
+ });
24
+
25
+ it('rejects a lost 2D canvas context', () => {
26
+ const canvas = document.createElement('canvas');
27
+ canvas.width = 4;
28
+ canvas.height = 4;
29
+ const getContext = vi
30
+ .spyOn(canvas, 'getContext')
31
+ .mockReturnValue({ isContextLost: () => true } as unknown as GPUCanvasContext);
32
+ expect(isWgpuExternalImageSourceReady(canvas, 4, 4)).toBe(false);
33
+ getContext.mockRestore();
34
+ });
35
+
36
+ it('rejects an undecoded image element', () => {
37
+ const image = document.createElement('img');
38
+ expect(isWgpuExternalImageSourceReady(image, 1, 1)).toBe(false);
39
+ });
40
+ });