@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.
- package/dist/contract.d.ts +2 -1
- package/dist/contract.d.ts.map +1 -1
- package/dist/contract.js +2 -1
- package/dist/contract.js.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/wgpuDraw.d.ts +3 -3
- package/dist/wgpuDraw.d.ts.map +1 -1
- package/dist/wgpuDraw.js +10 -1
- package/dist/wgpuDraw.js.map +1 -1
- package/dist/wgpuExternalImageSource.d.ts +2 -0
- package/dist/wgpuExternalImageSource.d.ts.map +1 -0
- package/dist/wgpuExternalImageSource.js +34 -0
- package/dist/wgpuExternalImageSource.js.map +1 -0
- package/dist/wgpuRenderState.d.ts +10 -1
- package/dist/wgpuRenderState.d.ts.map +1 -1
- package/dist/wgpuRenderState.js +182 -3
- package/dist/wgpuRenderState.js.map +1 -1
- package/dist/wgpuRenderTexture.d.ts +6 -1
- package/dist/wgpuRenderTexture.d.ts.map +1 -1
- package/dist/wgpuRenderTexture.js +70 -13
- package/dist/wgpuRenderTexture.js.map +1 -1
- package/dist/wgpuRenderTexturePool.d.ts +7 -0
- package/dist/wgpuRenderTexturePool.d.ts.map +1 -0
- package/dist/wgpuRenderTexturePool.js +85 -0
- package/dist/wgpuRenderTexturePool.js.map +1 -0
- package/dist/wgpuTestHelper.d.ts +1 -0
- package/dist/wgpuTestHelper.d.ts.map +1 -1
- package/dist/wgpuTestHelper.js +15 -1
- package/dist/wgpuTestHelper.js.map +1 -1
- package/dist/wgpuTextureUpload.d.ts.map +1 -1
- package/dist/wgpuTextureUpload.js +3 -0
- package/dist/wgpuTextureUpload.js.map +1 -1
- package/package.json +11 -11
- package/src/wgpuDraw.test.ts +53 -8
- package/src/wgpuExternalImageSource.test.ts +40 -0
- package/src/wgpuRenderState.test.ts +123 -0
- package/src/wgpuRenderTexture.test.ts +69 -0
- package/src/wgpuRenderTexturePool.test.ts +121 -0
- 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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
26
|
-
|
|
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,
|
|
53
|
-
target.clearColors = [...
|
|
54
|
-
target.clearDepth =
|
|
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
|
-
|
|
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":"
|
|
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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"}
|
package/dist/wgpuTestHelper.d.ts
CHANGED
|
@@ -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;
|
|
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"}
|
package/dist/wgpuTestHelper.js
CHANGED
|
@@ -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":"AAEA,OAAO,EAAE,qBAAqB,EAAE,MAAM,mBAAmB,CAAC;AAE1D,8FAA8F;AAC9F,SAAS,oBAAoB;IAC3B,MAAM,CAAC,GAAG,UAAqC,CAAC;IAEhD,IAAI,CAAC,CAAC,CAAC,gBAAgB,CAAC,EAAE,CAAC;QACzB,CAAC,CAAC,gBAAgB,CAAC,GAAG;YACpB,QAAQ,EAAE,CAAC;YACX,SAAS,EAAE,CAAC;YACZ,QAAQ,EAAE,CAAC;YACX,QAAQ,EAAE,CAAC;YACX,KAAK,EAAE,EAAE;YACT,MAAM,EAAE,EAAE;YACV,OAAO,EAAE,EAAE;YACX,OAAO,EAAE,GAAG;YACZ,QAAQ,EAAE,GAAG;YACb,aAAa,EAAE,GAAG;SACnB,CAAC;IACJ,CAAC;IACD,IAAI,CAAC,CAAC,CAAC,iBAAiB,CAAC,EAAE,CAAC;QAC1B,CAAC,CAAC,iBAAiB,CAAC,GAAG,EAAE,QAAQ,EAAE,CAAC,EAAE,QAAQ,EAAE,CAAC,EAAE,eAAe,EAAE,CAAC,EAAE,eAAe,EAAE,CAAC,EAAE,iBAAiB,EAAE,EAAE,EAAE,CAAC;IACrH,CAAC;IACD,IAAI,CAAC,CAAC,CAAC,gBAAgB,CAAC,EAAE,CAAC;QACzB,CAAC,CAAC,gBAAgB,CAAC,GAAG,EAAE,MAAM,EAAE,CAAC,EAAE,QAAQ,EAAE,CAAC,EAAE,OAAO,EAAE,CAAC,EAAE,CAAC;IAC/D,CAAC;IACD,IAAI,CAAC,CAAC,CAAC,eAAe,CAAC,EAAE,CAAC;QACxB,CAAC,CAAC,eAAe,CAAC,GAAG,EAAE,GAAG,EAAE,CAAC,EAAE,KAAK,EAAE,CAAC,EAAE,IAAI,EAAE,CAAC,EAAE,KAAK,EAAE,CAAC,EAAE,GAAG,EAAE,EAAE,EAAE,CAAC;IACxE,CAAC;IACD,IAAI,CAAC,CAAC,CAAC,YAAY,CAAC,EAAE,CAAC;QACrB,CAAC,CAAC,YAAY,CAAC,GAAG,EAAE,IAAI,EAAE,CAAC,EAAE,KAAK,EAAE,CAAC,EAAE,CAAC;IAC1C,CAAC;AACH,CAAC;AAED,iDAAiD;AACjD,iFAAiF;AAEjF,SAAS,aAAa;IACpB,OAAO,EAAkB,CAAC;AAC5B,CAAC;AAED,SAAS,mBAAmB;IAC1B,OAAO,EAAwB,CAAC;AAClC,CAAC;AAED,SAAS,UAAU;IACjB,OAAO,EAAE,OAAO,EAAE,GAAG,EAAE,GAAE,CAAC,EAA0B,CAAC;AACvD,CAAC;AAED,SAAS,WAAW;IAClB,OAAO;QACL,UAAU,EAAE,GAAG,EAAE,CAAC,CAAC,EAAE,CAAmB;QACxC,OAAO,EAAE,GAAG,EAAE,GAAE,CAAC;KACO,CAAC;AAC7B,CAAC;AAED,SAAS,qBAAqB;IAC5B,OAAO;QACL,IAAI,EAAE,GAAG,EAAE,GAAE,CAAC;QACd,GAAG,EAAE,GAAG,EAAE,GAAE,CAAC;QACb,YAAY,EAAE,GAAG,EAAE,GAAE,CAAC;QACtB,WAAW,EAAE,GAAG,EAAE,GAAE,CAAC;QACrB,cAAc,EAAE,GAAG,EAAE,GAAE,CAAC;QACxB,mBAAmB,EAAE,GAAG,EAAE,GAAE,CAAC;QAC7B,WAAW,EAAE,GAAG,EAAE,GAAE,CAAC;KACa,CAAC;AACvC,CAAC;AAED,SAAS,kBAAkB;IACzB,OAAO;QACL,eAAe,EAAE,GAAG,EAAE,CAAC,qBAAqB,EAAE;QAC9C,MAAM,EAAE,GAAG,EAAE,CAAC,CAAC,EAAE,CAAqB;KACP,CAAC;AACpC,CAAC;AAED,gGAAgG;AAChG,6DAA6D;AAC7D,SAAS,YAAY,CAAC,UAAwC;IAC5D,OAAO,EAAE,YAAY,EAAE,UAAU,EAAkC,CAAC;AACtE,CAAC;AAED,SAAS,gBAAgB;IACvB,OAAO,EAAqB,CAAC;AAC/B,CAAC;AAED,SAAS,WAAW;IAClB,OAAO,EAAgB,CAAC;AAC1B,CAAC;AAED,SAAS,kBAAkB;IACzB,OAAO,EAAuB,CAAC;AACjC,CAAC;AAED,SAAS,UAAU;IACjB,OAAO;QACL,QAAQ,EAAE,IAAI,GAAG,EAAE;QACnB,MAAM,EAAE,EAAE,qBAAqB,EAAE,IAAI,EAAE,+BAA+B,EAAE,GAAG,EAAE;QAC7E,eAAe,EAAE,GAAG,EAAE,CAAC,aAAa,EAAE;QACtC,qBAAqB,EAAE,GAAG,EAAE,CAAC,mBAAmB,EAAE;QAClD,YAAY,EAAE,GAAG,EAAE,CAAC,UAAU,EAAE;QAChC,oBAAoB,EAAE,GAAG,EAAE,CAAC,kBAAkB,EAAE;QAChD,oBAAoB,EAAE,GAAG,EAAE,CAAC,kBAAkB,EAAE;QAChD,oBAAoB,EAAE,CAAC,UAAuC,EAAE,EAAE,CAAC,YAAY,CAAC,UAAU,CAAC;QAC3F,aAAa,EAAE,GAAG,EAAE,CAAC,WAAW,EAAE;QAClC,kBAAkB,EAAE,GAAG,EAAE,CAAC,gBAAgB,EAAE;QAC5C,aAAa,EAAE,GAAG,EAAE,CAAC,WAAW,EAAE;QAClC,KAAK,EAAE;YACL,0BAA0B,EAAE,GAAG,EAAE,GAAE,CAAC;YACpC,MAAM,EAAE,GAAG,EAAE,GAAE,CAAC;YAChB,WAAW,EAAE,GAAG,EAAE,GAAE,CAAC;YACrB,YAAY,EAAE,GAAG,EAAE,GAAE,CAAC;SACvB;KACsB,CAAC;AAC5B,CAAC;AAED,SAAS,WAAW;IAClB,OAAO;QACL,8FAA8F;QAC9F,oGAAoG;QACpG,MAAM,EAAE,EAAE,aAAa,EAAE,CAAC,EAAE,+BAA+B,EAAE,GAAG,EAAE;QAClE,QAAQ,EAAE,IAAI,GAAG,EAAE;QACnB,aAAa,EAAE,GAAG,EAAE,CAAC,OAAO,CAAC,OAAO,CAAC,UAAU,EAAE,CAAC;KAC1B,CAAC;AAC7B,CAAC;AAED,gGAAgG;AAChG,sGAAsG;AACtG,kGAAkG;AAClG,MAAM,UAAU,8BAA8B,CAAC,KAAK,GAAG,CAAC,EAAE,MAAM,GAAG,CAAC;IAClE,MAAM,KAAK,GAAG,QAAQ,CAAC,aAAa,CAAC,KAAK,CAAC,CAAC;IAC5C,KAAK,CAAC,KAAK,GAAG,KAAK,CAAC;IACpB,KAAK,CAAC,MAAM,GAAG,MAAM,CAAC;IACtB,MAAM,CAAC,gBAAgB,CAAC,KAAK,EAAE;QAC7B,QAAQ,EAAE,EAAE,YAAY,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE;QAC7C,aAAa,EAAE,EAAE,YAAY,EAAE,IAAI,EAAE,KAAK,EAAE,MAAM,EAAE;QACpD,YAAY,EAAE,EAAE,YAAY,EAAE,IAAI,EAAE,KAAK,EAAE,KAAK,EAAE;KACnD,CAAC,CAAC;IACH,OAAO,KAAK,CAAC;AACf,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,4BAA4B;IAChD,MAAM,MAAM,GAAG,QAAQ,CAAC,aAAa,CAAC,QAAQ,CAAC,CAAC;IAChD,MAAM,CAAC,KAAK,GAAG,GAAG,CAAC;IACnB,MAAM,CAAC,MAAM,GAAG,GAAG,CAAC;IACpB,OAAO,qBAAqB,CAAC,MAAM,CAAC,CAAC;AACvC,CAAC;AAED,MAAM,UAAU,eAAe;IAC7B,oBAAoB,EAAE,CAAC;IACvB,MAAM,GAAG,GAAQ;QACf,wBAAwB,EAAE,GAAG,EAAE,CAAC,YAAgC;QAChE,cAAc,EAAE,GAAG,EAAE,CAAC,OAAO,CAAC,OAAO,CAAC,WAAW,EAAE,CAAC;KACnC,CAAC;IAEpB,kGAAkG;IAClG,qFAAqF;IACrF,IAAI,UAAU,CAAC,SAAS,IAAI,IAAI,EAAE,CAAC;QACjC,MAAM,CAAC,cAAc,CAAC,UAAU,EAAE,WAAW,EAAE,EAAE,KAAK,EAAE,EAAE,EAAE,YAAY,EAAE,IAAI,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC,CAAC;IACpG,CAAC;IACD,MAAM,CAAC,cAAc,CAAC,UAAU,CAAC,SAAS,EAAE,KAAK,EAAE;QACjD,KAAK,EAAE,GAAG;QACV,YAAY,EAAE,IAAI;QAClB,QAAQ,EAAE,IAAI;KACf,CAAC,CAAC;IAEH,MAAM,cAAc,GAAG,iBAAiB,CAAC,SAAS,CAAC,UAAU,CAAC;IAC7D,iBAAiB,CAAC,SAAqC,CAAC,UAAU,GAAG,UAEpE,SAAiB,EACjB,OAAiB;QAEjB,IAAI,SAAS,KAAK,QAAQ,EAAE,CAAC;YAC3B,OAAO;gBACL,SAAS,EAAE,GAAG,EAAE,GAAE,CAAC;gBACnB,iBAAiB,EAAE,GAAG,EAAE,CAAC,WAAW,EAAE;aACR,CAAC;QACnC,CAAC;QACD,8DAA8D;QAC9D,OAAQ,cAAsB,CAAC,IAAI,CAAC,IAAI,EAAE,SAAS,EAAE,OAAO,CAAC,CAAC;IAChE,CAAC,CAAC;AACJ,CAAC"}
|
|
@@ -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;
|
|
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.
|
|
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.
|
|
40
|
-
"@flighthq/entity": "0.3.0-next.
|
|
41
|
-
"@flighthq/scene2d": "0.3.0-next.
|
|
42
|
-
"@flighthq/geometry": "0.3.0-next.
|
|
43
|
-
"@flighthq/log": "0.3.0-next.
|
|
44
|
-
"@flighthq/render": "0.3.0-next.
|
|
45
|
-
"@flighthq/signals": "0.3.0-next.
|
|
46
|
-
"@flighthq/bitmap": "0.3.0-next.
|
|
47
|
-
"@flighthq/texture": "0.3.0-next.
|
|
48
|
-
"@flighthq/types": "0.3.0-next.
|
|
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": "*",
|
package/src/wgpuDraw.test.ts
CHANGED
|
@@ -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
|
+
});
|