@flighthq/render-wgpu 0.5.1-next.1069.554a2ac → 0.5.1-next.1201.9b49dee

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 (105) hide show
  1. package/README.md +2 -2
  2. package/dist/contract.d.ts +9 -6
  3. package/dist/contract.d.ts.map +1 -1
  4. package/dist/contract.js +9 -6
  5. package/dist/contract.js.map +1 -1
  6. package/dist/index.d.ts +1 -1
  7. package/dist/index.d.ts.map +1 -1
  8. package/dist/index.js +1 -1
  9. package/dist/index.js.map +1 -1
  10. package/dist/wgpuDraw.js +1 -1
  11. package/dist/wgpuDraw.js.map +1 -1
  12. package/dist/wgpuFrame.d.ts +23 -0
  13. package/dist/wgpuFrame.d.ts.map +1 -0
  14. package/dist/{wgpuBackground.js → wgpuFrame.js} +67 -121
  15. package/dist/wgpuFrame.js.map +1 -0
  16. package/dist/wgpuFullscreenPass.d.ts +2 -2
  17. package/dist/wgpuFullscreenPass.d.ts.map +1 -1
  18. package/dist/wgpuFullscreenPass.js +1 -2
  19. package/dist/wgpuFullscreenPass.js.map +1 -1
  20. package/dist/wgpuHost.d.ts +6 -6
  21. package/dist/wgpuHost.d.ts.map +1 -1
  22. package/dist/wgpuHost.js +17 -3
  23. package/dist/wgpuHost.js.map +1 -1
  24. package/dist/wgpuRenderPass.d.ts +9 -0
  25. package/dist/wgpuRenderPass.d.ts.map +1 -0
  26. package/dist/wgpuRenderPass.js +222 -0
  27. package/dist/wgpuRenderPass.js.map +1 -0
  28. package/dist/wgpuRenderState.d.ts +3 -4
  29. package/dist/wgpuRenderState.d.ts.map +1 -1
  30. package/dist/wgpuRenderState.js +17 -88
  31. package/dist/wgpuRenderState.js.map +1 -1
  32. package/dist/wgpuRenderTarget.d.ts +12 -29
  33. package/dist/wgpuRenderTarget.d.ts.map +1 -1
  34. package/dist/wgpuRenderTarget.js +19 -252
  35. package/dist/wgpuRenderTarget.js.map +1 -1
  36. package/dist/wgpuRenderTargetPool.d.ts +5 -5
  37. package/dist/wgpuRenderTargetPool.d.ts.map +1 -1
  38. package/dist/wgpuRenderTargetPool.js +7 -7
  39. package/dist/wgpuRenderTargetPool.js.map +1 -1
  40. package/dist/wgpuRenderTexture.d.ts +5 -4
  41. package/dist/wgpuRenderTexture.d.ts.map +1 -1
  42. package/dist/wgpuRenderTexture.js +14 -16
  43. package/dist/wgpuRenderTexture.js.map +1 -1
  44. package/dist/wgpuRenderTexturePool.js +1 -3
  45. package/dist/wgpuRenderTexturePool.js.map +1 -1
  46. package/dist/wgpuScissor.d.ts +1 -1
  47. package/dist/wgpuScissor.d.ts.map +1 -1
  48. package/dist/wgpuScissor.js +7 -4
  49. package/dist/wgpuScissor.js.map +1 -1
  50. package/dist/wgpuScreenAntialias.d.ts +3 -0
  51. package/dist/wgpuScreenAntialias.d.ts.map +1 -0
  52. package/dist/wgpuScreenAntialias.js +119 -0
  53. package/dist/wgpuScreenAntialias.js.map +1 -0
  54. package/dist/wgpuScreenCapture.d.ts +5 -0
  55. package/dist/wgpuScreenCapture.d.ts.map +1 -0
  56. package/dist/{wgpuSurface.js → wgpuScreenCapture.js} +55 -73
  57. package/dist/wgpuScreenCapture.js.map +1 -0
  58. package/dist/wgpuScreenRenderTarget.d.ts +9 -0
  59. package/dist/wgpuScreenRenderTarget.d.ts.map +1 -0
  60. package/dist/wgpuScreenRenderTarget.js +123 -0
  61. package/dist/wgpuScreenRenderTarget.js.map +1 -0
  62. package/dist/wgpuShader.js +2 -2
  63. package/dist/wgpuShader.js.map +1 -1
  64. package/dist/wgpuTestHelper.d.ts +8 -2
  65. package/dist/wgpuTestHelper.d.ts.map +1 -1
  66. package/dist/wgpuTestHelper.js +38 -3
  67. package/dist/wgpuTestHelper.js.map +1 -1
  68. package/dist/wgpuTextureRenderTarget.d.ts +18 -0
  69. package/dist/wgpuTextureRenderTarget.d.ts.map +1 -0
  70. package/dist/wgpuTextureRenderTarget.js +122 -0
  71. package/dist/wgpuTextureRenderTarget.js.map +1 -0
  72. package/package.json +11 -11
  73. package/src/wgpuDraw.test.ts +8 -8
  74. package/src/{wgpuBackground.test.ts → wgpuFrame.test.ts} +34 -20
  75. package/src/wgpuFullscreenPass.test.ts +7 -7
  76. package/src/wgpuHost.test.ts +28 -82
  77. package/src/wgpuRenderPass.test.ts +258 -0
  78. package/src/wgpuRenderState.test.ts +34 -313
  79. package/src/wgpuRenderTarget.test.ts +44 -219
  80. package/src/wgpuRenderTargetPool.test.ts +21 -21
  81. package/src/wgpuRenderTexture.test.ts +17 -15
  82. package/src/wgpuScissor.test.ts +43 -13
  83. package/src/wgpuScreenAntialias.test.ts +60 -0
  84. package/src/wgpuScreenCapture.test.ts +156 -0
  85. package/src/wgpuScreenRenderTarget.test.ts +152 -0
  86. package/src/wgpuShader.test.ts +5 -6
  87. package/src/wgpuTextureRenderTarget.test.ts +129 -0
  88. package/src/wgpuTextureResolver.test.ts +5 -5
  89. package/dist/wgpuAntialias.d.ts +0 -14
  90. package/dist/wgpuAntialias.d.ts.map +0 -1
  91. package/dist/wgpuAntialias.js +0 -155
  92. package/dist/wgpuAntialias.js.map +0 -1
  93. package/dist/wgpuBackground.d.ts +0 -20
  94. package/dist/wgpuBackground.d.ts.map +0 -1
  95. package/dist/wgpuBackground.js.map +0 -1
  96. package/dist/wgpuElement.d.ts +0 -7
  97. package/dist/wgpuElement.d.ts.map +0 -1
  98. package/dist/wgpuElement.js +0 -20
  99. package/dist/wgpuElement.js.map +0 -1
  100. package/dist/wgpuSurface.d.ts +0 -6
  101. package/dist/wgpuSurface.d.ts.map +0 -1
  102. package/dist/wgpuSurface.js.map +0 -1
  103. package/src/wgpuAntialias.test.ts +0 -239
  104. package/src/wgpuElement.test.ts +0 -145
  105. package/src/wgpuSurface.test.ts +0 -141
@@ -1,145 +0,0 @@
1
- import {
2
- createWgpuCanvasElement,
3
- createWgpuRenderSurface,
4
- getWgpuRenderSurfaceProvider,
5
- resetWgpuRenderSurfaceProviderForTest,
6
- setWgpuRenderSurfaceProvider,
7
- } from './wgpuElement';
8
-
9
- function entityProvider(fields: Omit<WgpuRenderSurfaceProvider, keyof Entity>): WgpuRenderSurfaceProvider {
10
- return (() => {
11
- const out = allocateEntity<any>();
12
- Object.assign(out, fields);
13
- return finishEntity(out);
14
- })();
15
- }
16
-
17
- describe('createWgpuCanvasElement', () => {
18
- afterEach(() => resetWgpuRenderSurfaceProviderForTest());
19
-
20
- it('preserves the canonical provider result identity', () => {
21
- const surface = {} as HTMLCanvasElement;
22
- setWgpuRenderSurfaceProvider(entityProvider({ createRenderSurface: () => surface }));
23
- expect(createWgpuCanvasElement(100, 200, 2)).toBe(surface);
24
- });
25
-
26
- it('throws an actionable Web-only setup error when the provider is absent', () => {
27
- expect(() => createWgpuCanvasElement(100, 200)).toThrowError(
28
- /enableHostWebWgpuRenderSurface\(\).*inject a WgpuRenderSurfaceProvider/,
29
- );
30
- });
31
-
32
- it('throws the same setup error when the provider refuses', () => {
33
- setWgpuRenderSurfaceProvider(entityProvider({ createRenderSurface: () => null }));
34
- expect(() => createWgpuCanvasElement(100, 200)).toThrowError(/enableHostWebWgpuRenderSurface\(\)/);
35
- });
36
- });
37
-
38
- describe('createWgpuRenderSurface', () => {
39
- afterEach(() => resetWgpuRenderSurfaceProviderForTest());
40
-
41
- it('returns null when no provider is selected', () => {
42
- expect(createWgpuRenderSurface(100, 200)).toBeNull();
43
- });
44
-
45
- it('passes exact dimensions and the default pixel ratio to the selected provider', () => {
46
- const surface = {} as HTMLCanvasElement;
47
- const createRenderSurface = vi.fn(() => surface);
48
- setWgpuRenderSurfaceProvider(entityProvider({ createRenderSurface }));
49
- expect(createWgpuRenderSurface(100, 200)).toBe(surface);
50
- expect(createRenderSurface).toHaveBeenCalledOnce();
51
- expect(createRenderSurface).toHaveBeenCalledWith(100, 200, 1);
52
- });
53
-
54
- it('passes an explicit pixel ratio and preserves the provider result identity', () => {
55
- const surface = {} as HTMLCanvasElement;
56
- const createRenderSurface = vi.fn(() => surface);
57
- setWgpuRenderSurfaceProvider(entityProvider({ createRenderSurface }));
58
- expect(createWgpuRenderSurface(300, 150, 2.5)).toBe(surface);
59
- expect(createRenderSurface).toHaveBeenCalledWith(300, 150, 2.5);
60
- });
61
-
62
- it('selects replacements and reset restores omission', () => {
63
- const first = {} as HTMLCanvasElement;
64
- const second = {} as HTMLCanvasElement;
65
- const firstProvider = entityProvider({ createRenderSurface: vi.fn(() => first) });
66
- const secondProvider = entityProvider({ createRenderSurface: vi.fn(() => second) });
67
- setWgpuRenderSurfaceProvider(firstProvider);
68
- expect(getWgpuRenderSurfaceProvider()).toBe(firstProvider);
69
- expect(createWgpuRenderSurface(1, 2)).toBe(first);
70
- setWgpuRenderSurfaceProvider(secondProvider);
71
- expect(getWgpuRenderSurfaceProvider()).toBe(secondProvider);
72
- expect(createWgpuRenderSurface(3, 4)).toBe(second);
73
- resetWgpuRenderSurfaceProviderForTest();
74
- expect(getWgpuRenderSurfaceProvider()).toBeNull();
75
- expect(createWgpuRenderSurface(5, 6)).toBeNull();
76
- });
77
-
78
- it('preserves provider refusal as null', () => {
79
- setWgpuRenderSurfaceProvider(entityProvider({ createRenderSurface: () => null }));
80
- expect(createWgpuRenderSurface(100, 200)).toBeNull();
81
- });
82
-
83
- it('lets a native host provide a surface without reading document', () => {
84
- const surface = {} as HTMLCanvasElement;
85
- setWgpuRenderSurfaceProvider(entityProvider({ createRenderSurface: () => surface }));
86
- withThrowingDocument(() => expect(createWgpuRenderSurface(100, 200)).toBe(surface));
87
- });
88
-
89
- it('returns null for omission and refusal without reading document', () => {
90
- withThrowingDocument(() => {
91
- expect(createWgpuRenderSurface(100, 200)).toBeNull();
92
- setWgpuRenderSurfaceProvider(entityProvider({ createRenderSurface: () => null }));
93
- expect(createWgpuRenderSurface(100, 200)).toBeNull();
94
- });
95
- });
96
- });
97
-
98
- describe('getWgpuRenderSurfaceProvider', () => {
99
- afterEach(() => resetWgpuRenderSurfaceProviderForTest());
100
-
101
- it('returns the exact selected provider', () => {
102
- const provider = entityProvider({ createRenderSurface: () => ({}) as HTMLCanvasElement });
103
- setWgpuRenderSurfaceProvider(provider);
104
- expect(getWgpuRenderSurfaceProvider()).toBe(provider);
105
- });
106
- });
107
-
108
- describe('resetWgpuRenderSurfaceProviderForTest', () => {
109
- it('restores provider omission', () => {
110
- setWgpuRenderSurfaceProvider(entityProvider({ createRenderSurface: () => ({}) as HTMLCanvasElement }));
111
- resetWgpuRenderSurfaceProviderForTest();
112
- expect(getWgpuRenderSurfaceProvider()).toBeNull();
113
- expect(createWgpuRenderSurface(1, 1)).toBeNull();
114
- });
115
- });
116
-
117
- describe('setWgpuRenderSurfaceProvider', () => {
118
- afterEach(() => resetWgpuRenderSurfaceProviderForTest());
119
-
120
- it('replaces the selected provider', () => {
121
- const first = entityProvider({ createRenderSurface: () => ({}) as HTMLCanvasElement });
122
- const second = entityProvider({ createRenderSurface: () => ({}) as HTMLCanvasElement });
123
- setWgpuRenderSurfaceProvider(first);
124
- setWgpuRenderSurfaceProvider(second);
125
- expect(getWgpuRenderSurfaceProvider()).toBe(second);
126
- });
127
- });
128
-
129
- function withThrowingDocument(run: () => void): void {
130
- const descriptor = Object.getOwnPropertyDescriptor(globalThis, 'document');
131
- Object.defineProperty(globalThis, 'document', {
132
- configurable: true,
133
- get(): never {
134
- throw new Error('portable WGPU code read document');
135
- },
136
- });
137
- try {
138
- run();
139
- } finally {
140
- if (descriptor === undefined) delete (globalThis as { document?: Document }).document;
141
- else Object.defineProperty(globalThis, 'document', descriptor);
142
- }
143
- }
144
- import { allocateEntity, finishEntity } from '@flighthq/entity/contract';
145
- import type { Entity, WgpuRenderSurfaceProvider } from '@flighthq/types/contract';
@@ -1,141 +0,0 @@
1
- import type { WgpuRenderState } from '@flighthq/types/contract';
2
- import { beforeAll, describe, expect, it } from 'vitest';
3
-
4
- import { getWgpuRenderStateRuntime } from './wgpuRenderState';
5
- import {
6
- acquireWgpuFrameCaptureTexture,
7
- createBitmapFromWgpuRenderState,
8
- enableWgpuFrameCapture,
9
- encodeWgpuFrameCapture,
10
- } from './wgpuSurface';
11
- import { createWgpuRenderStateForTest, installWgpuMock } from './wgpuTestHelper';
12
-
13
- beforeAll(() => {
14
- installWgpuMock();
15
- });
16
-
17
- describe('acquireWgpuFrameCaptureTexture', () => {
18
- it('returns null until capture is enabled, then an offscreen texture', async () => {
19
- const state = await createWgpuRenderStateForTest();
20
- expect(acquireWgpuFrameCaptureTexture(state)).toBeNull();
21
- enableWgpuFrameCapture(state);
22
- expect(acquireWgpuFrameCaptureTexture(state)).not.toBeNull();
23
- });
24
- });
25
-
26
- describe('createBitmapFromWgpuRenderState', () => {
27
- it('throws when frame capture was never enabled (no buffer to read)', async () => {
28
- const state = await createWgpuRenderStateForTest();
29
- await expect(createBitmapFromWgpuRenderState(state)).rejects.toThrow(/enableWgpuFrameCapture/);
30
- });
31
-
32
- it('reads the mapped buffer within the bound', async () => {
33
- const state = await createWgpuRenderStateForTest();
34
- installCaptureBuffer(state, () => Promise.resolve());
35
-
36
- const bitmap = await createBitmapFromWgpuRenderState(state, 1_000);
37
-
38
- expect(bitmap.width).toBe(1);
39
- expect(bitmap.height).toBe(1);
40
- });
41
-
42
- it('fails by name when the buffer never maps, instead of awaiting forever', async () => {
43
- // The driver failure this bounds: mapAsync neither resolves nor rejects. Before the bound, the
44
- // caller sat here until something outside it gave up and reported a stall with no location.
45
- const state = await createWgpuRenderStateForTest();
46
- installCaptureBuffer(state, () => new Promise<void>(() => {}));
47
-
48
- await expect(createBitmapFromWgpuRenderState(state, 25)).rejects.toThrow(/did not map within 25ms/);
49
- });
50
-
51
- it('leaves the wait unbounded when the caller passes 0', async () => {
52
- const state = await createWgpuRenderStateForTest();
53
- let settle = (): void => {};
54
- installCaptureBuffer(state, () => new Promise<void>((resolve) => (settle = resolve)));
55
-
56
- let done = false;
57
- const pending = createBitmapFromWgpuRenderState(state, 0).then(() => (done = true));
58
- await new Promise((resolve) => setTimeout(resolve, 40));
59
- expect(done).toBe(false);
60
-
61
- settle();
62
- await pending;
63
- expect(done).toBe(true);
64
- });
65
- });
66
-
67
- // Installs a 1×1 retained capture buffer whose map step the caller controls, so the map bound can be
68
- // exercised without a GPU. The mock device's buffers carry no map surface of their own.
69
- function installCaptureBuffer(state: WgpuRenderState, mapAsync: () => Promise<void>): void {
70
- const runtime = getWgpuRenderStateRuntime(state);
71
- runtime.frameCaptureBuffer = {
72
- mapAsync,
73
- getMappedRange: () => new ArrayBuffer(256),
74
- unmap: () => {},
75
- destroy: () => {},
76
- } as unknown as GPUBuffer;
77
- runtime.frameCaptureWidth = 1;
78
- runtime.frameCaptureHeight = 1;
79
- runtime.frameCaptureBytesPerRow = 256;
80
- }
81
-
82
- describe('enableWgpuFrameCapture', () => {
83
- it('sets the capture flag on the render state runtime', async () => {
84
- const state = await createWgpuRenderStateForTest();
85
- expect(getWgpuRenderStateRuntime(state).frameCaptureEnabled).toBeFalsy();
86
- enableWgpuFrameCapture(state);
87
- expect(getWgpuRenderStateRuntime(state).frameCaptureEnabled).toBe(true);
88
- });
89
- });
90
-
91
- describe('encodeWgpuFrameCapture', () => {
92
- it('is a no-op when capture is disabled', async () => {
93
- const state = await createWgpuRenderStateForTest();
94
- let copied = false;
95
- const encoder = { copyTextureToBuffer: () => (copied = true) } as unknown as GPUCommandEncoder;
96
- encodeWgpuFrameCapture(state, encoder);
97
- expect(copied).toBe(false);
98
- });
99
-
100
- it('skips the copy while a readback holds the buffer, and resumes once it lets go', async () => {
101
- // The writer/reader handshake over the single retained buffer: an animating scene must not keep
102
- // enqueueing copies into a buffer a readback has mapped or is waiting to map.
103
- const state = await createWgpuRenderStateForTest();
104
- enableWgpuFrameCapture(state);
105
- acquireWgpuFrameCaptureTexture(state);
106
- const runtime = getWgpuRenderStateRuntime(state);
107
- let mapState: GPUBufferMapState = 'unmapped';
108
- installCaptureBuffer(state, () => Promise.resolve());
109
- Object.defineProperty(runtime.frameCaptureBuffer, 'mapState', { get: () => mapState });
110
-
111
- let copies = 0;
112
- const encoder = { copyTextureToBuffer: () => copies++ } as unknown as GPUCommandEncoder;
113
-
114
- mapState = 'pending';
115
- encodeWgpuFrameCapture(state, encoder);
116
- mapState = 'mapped';
117
- encodeWgpuFrameCapture(state, encoder);
118
- expect(copies).toBe(0);
119
-
120
- mapState = 'unmapped';
121
- encodeWgpuFrameCapture(state, encoder);
122
- expect(copies).toBe(1);
123
- });
124
-
125
- it('still copies when the implementation reports no map state at all', async () => {
126
- // Fails safe in the direction that keeps capturing: an undefined mapState must not read as "busy"
127
- // and silence every copy for the rest of the run.
128
- const state = await createWgpuRenderStateForTest();
129
- enableWgpuFrameCapture(state);
130
- acquireWgpuFrameCaptureTexture(state);
131
- installCaptureBuffer(state, () => Promise.resolve());
132
- Object.defineProperty(getWgpuRenderStateRuntime(state).frameCaptureBuffer, 'mapState', {
133
- get: () => undefined,
134
- });
135
-
136
- let copies = 0;
137
- encodeWgpuFrameCapture(state, { copyTextureToBuffer: () => copies++ } as unknown as GPUCommandEncoder);
138
-
139
- expect(copies).toBe(1);
140
- });
141
- });