@luma.gl/webgpu 9.2.5 → 9.3.0-alpha.2
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/adapter/resources/webgpu-fence.d.ts +13 -0
- package/dist/adapter/resources/webgpu-fence.d.ts.map +1 -0
- package/dist/adapter/resources/webgpu-fence.js +25 -0
- package/dist/adapter/resources/webgpu-fence.js.map +1 -0
- package/dist/adapter/resources/webgpu-texture.d.ts +12 -3
- package/dist/adapter/resources/webgpu-texture.d.ts.map +1 -1
- package/dist/adapter/resources/webgpu-texture.js +143 -26
- package/dist/adapter/resources/webgpu-texture.js.map +1 -1
- package/dist/adapter/webgpu-adapter.d.ts.map +1 -1
- package/dist/adapter/webgpu-adapter.js +34 -34
- package/dist/adapter/webgpu-adapter.js.map +1 -1
- package/dist/adapter/webgpu-canvas-context.d.ts +4 -3
- package/dist/adapter/webgpu-canvas-context.d.ts.map +1 -1
- package/dist/adapter/webgpu-canvas-context.js +22 -21
- package/dist/adapter/webgpu-canvas-context.js.map +1 -1
- package/dist/adapter/webgpu-device.d.ts +3 -1
- package/dist/adapter/webgpu-device.d.ts.map +1 -1
- package/dist/adapter/webgpu-device.js +14 -3
- package/dist/adapter/webgpu-device.js.map +1 -1
- package/dist/dist.dev.js +6438 -274
- package/dist/dist.min.js +10 -6
- package/dist/index.cjs +347 -86
- package/dist/index.cjs.map +4 -4
- package/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -0
- package/dist/index.js.map +1 -1
- package/dist/wgsl/get-shader-layout-wgsl.d.ts +8 -0
- package/dist/wgsl/get-shader-layout-wgsl.d.ts.map +1 -0
- package/dist/wgsl/get-shader-layout-wgsl.js +136 -0
- package/dist/wgsl/get-shader-layout-wgsl.js.map +1 -0
- package/package.json +5 -4
- package/src/adapter/resources/webgpu-fence.ts +30 -0
- package/src/adapter/resources/webgpu-texture.ts +202 -88
- package/src/adapter/webgpu-adapter.ts +40 -42
- package/src/adapter/webgpu-canvas-context.ts +25 -23
- package/src/adapter/webgpu-device.ts +19 -4
- package/src/index.ts +3 -0
- package/src/wgsl/get-shader-layout-wgsl.ts +156 -0
package/dist/index.d.ts
CHANGED
|
@@ -5,4 +5,6 @@ export { WebGPUBuffer } from "./adapter/resources/webgpu-buffer.js";
|
|
|
5
5
|
export { WebGPUTexture } from "./adapter/resources/webgpu-texture.js";
|
|
6
6
|
export { WebGPUSampler } from "./adapter/resources/webgpu-sampler.js";
|
|
7
7
|
export { WebGPUShader } from "./adapter/resources/webgpu-shader.js";
|
|
8
|
+
export { WebGPUFence } from "./adapter/resources/webgpu-fence.js";
|
|
9
|
+
export { getShaderLayoutFromWGSL } from "./wgsl/get-shader-layout-wgsl.js";
|
|
8
10
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAKA,YAAY,EAAC,aAAa,EAAC,oCAAiC;AAC5D,OAAO,EAAC,aAAa,EAAC,oCAAiC;AAGvD,OAAO,EAAC,YAAY,EAAC,mCAAgC;AACrD,OAAO,EAAC,YAAY,EAAC,6CAA0C;AAC/D,OAAO,EAAC,aAAa,EAAC,8CAA2C;AACjE,OAAO,EAAC,aAAa,EAAC,8CAA2C;AACjE,OAAO,EAAC,YAAY,EAAC,6CAA0C"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAKA,YAAY,EAAC,aAAa,EAAC,oCAAiC;AAC5D,OAAO,EAAC,aAAa,EAAC,oCAAiC;AAGvD,OAAO,EAAC,YAAY,EAAC,mCAAgC;AACrD,OAAO,EAAC,YAAY,EAAC,6CAA0C;AAC/D,OAAO,EAAC,aAAa,EAAC,8CAA2C;AACjE,OAAO,EAAC,aAAa,EAAC,8CAA2C;AACjE,OAAO,EAAC,YAAY,EAAC,6CAA0C;AAC/D,OAAO,EAAC,WAAW,EAAC,4CAAyC;AAE7D,OAAO,EAAC,uBAAuB,EAAC,yCAAsC"}
|
package/dist/index.js
CHANGED
|
@@ -8,4 +8,6 @@ export { WebGPUBuffer } from "./adapter/resources/webgpu-buffer.js";
|
|
|
8
8
|
export { WebGPUTexture } from "./adapter/resources/webgpu-texture.js";
|
|
9
9
|
export { WebGPUSampler } from "./adapter/resources/webgpu-sampler.js";
|
|
10
10
|
export { WebGPUShader } from "./adapter/resources/webgpu-shader.js";
|
|
11
|
+
export { WebGPUFence } from "./adapter/resources/webgpu-fence.js";
|
|
12
|
+
export { getShaderLayoutFromWGSL } from "./wgsl/get-shader-layout-wgsl.js";
|
|
11
13
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,UAAU;AACV,+BAA+B;AAC/B,oCAAoC;AAIpC,OAAO,EAAC,aAAa,EAAC,oCAAiC;AAEvD,mDAAmD;AACnD,OAAO,EAAC,YAAY,EAAC,mCAAgC;AACrD,OAAO,EAAC,YAAY,EAAC,6CAA0C;AAC/D,OAAO,EAAC,aAAa,EAAC,8CAA2C;AACjE,OAAO,EAAC,aAAa,EAAC,8CAA2C;AACjE,OAAO,EAAC,YAAY,EAAC,6CAA0C"}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,UAAU;AACV,+BAA+B;AAC/B,oCAAoC;AAIpC,OAAO,EAAC,aAAa,EAAC,oCAAiC;AAEvD,mDAAmD;AACnD,OAAO,EAAC,YAAY,EAAC,mCAAgC;AACrD,OAAO,EAAC,YAAY,EAAC,6CAA0C;AAC/D,OAAO,EAAC,aAAa,EAAC,8CAA2C;AACjE,OAAO,EAAC,aAAa,EAAC,8CAA2C;AACjE,OAAO,EAAC,YAAY,EAAC,6CAA0C;AAC/D,OAAO,EAAC,WAAW,EAAC,4CAAyC;AAE7D,OAAO,EAAC,uBAAuB,EAAC,yCAAsC"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { ShaderLayout } from '@luma.gl/core';
|
|
2
|
+
/**
|
|
3
|
+
* Parse a ShaderLayout from WGSL shader source code.
|
|
4
|
+
* @param source WGSL source code (can contain both @vertex and @fragment entry points)
|
|
5
|
+
* @returns
|
|
6
|
+
*/
|
|
7
|
+
export declare function getShaderLayoutFromWGSL(source: string): ShaderLayout;
|
|
8
|
+
//# sourceMappingURL=get-shader-layout-wgsl.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"get-shader-layout-wgsl.d.ts","sourceRoot":"","sources":["../../src/wgsl/get-shader-layout-wgsl.ts"],"names":[],"mappings":"AAIA,OAAO,EAAsB,YAAY,EAA4B,MAAM,eAAe,CAAC;AAG3F;;;;GAIG;AACH,wBAAgB,uBAAuB,CAAC,MAAM,EAAE,MAAM,GAAG,YAAY,CAuEpE"}
|
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
// luma.gl
|
|
2
|
+
// SPDX-License-Identifier: MIT
|
|
3
|
+
// Copyright (c) vis.gl contributors
|
|
4
|
+
import { log } from '@luma.gl/core';
|
|
5
|
+
import { WgslReflect, ResourceType } from 'wgsl_reflect';
|
|
6
|
+
/**
|
|
7
|
+
* Parse a ShaderLayout from WGSL shader source code.
|
|
8
|
+
* @param source WGSL source code (can contain both @vertex and @fragment entry points)
|
|
9
|
+
* @returns
|
|
10
|
+
*/
|
|
11
|
+
export function getShaderLayoutFromWGSL(source) {
|
|
12
|
+
const shaderLayout = { attributes: [], bindings: [] };
|
|
13
|
+
let parsedWGSL;
|
|
14
|
+
try {
|
|
15
|
+
parsedWGSL = parseWGSL(source);
|
|
16
|
+
}
|
|
17
|
+
catch (error) {
|
|
18
|
+
log.error(error.message)();
|
|
19
|
+
return shaderLayout;
|
|
20
|
+
}
|
|
21
|
+
for (const uniform of parsedWGSL.uniforms) {
|
|
22
|
+
const members = [];
|
|
23
|
+
// @ts-expect-error
|
|
24
|
+
for (const attribute of uniform.type?.members || []) {
|
|
25
|
+
members.push({
|
|
26
|
+
name: attribute.name,
|
|
27
|
+
type: getType(attribute.type)
|
|
28
|
+
});
|
|
29
|
+
}
|
|
30
|
+
shaderLayout.bindings.push({
|
|
31
|
+
type: 'uniform',
|
|
32
|
+
name: uniform.name,
|
|
33
|
+
group: uniform.group,
|
|
34
|
+
location: uniform.binding,
|
|
35
|
+
// @ts-expect-error TODO - unused for now but needs fixing
|
|
36
|
+
members
|
|
37
|
+
});
|
|
38
|
+
}
|
|
39
|
+
for (const texture of parsedWGSL.textures) {
|
|
40
|
+
const bindingDeclaration = {
|
|
41
|
+
type: 'texture',
|
|
42
|
+
name: texture.name,
|
|
43
|
+
group: texture.group,
|
|
44
|
+
location: texture.binding,
|
|
45
|
+
...getTextureBindingFromReflect(texture)
|
|
46
|
+
};
|
|
47
|
+
shaderLayout.bindings.push(bindingDeclaration);
|
|
48
|
+
}
|
|
49
|
+
for (const sampler of parsedWGSL.samplers) {
|
|
50
|
+
shaderLayout.bindings.push({
|
|
51
|
+
type: 'sampler',
|
|
52
|
+
name: sampler.name,
|
|
53
|
+
group: sampler.group,
|
|
54
|
+
location: sampler.binding
|
|
55
|
+
});
|
|
56
|
+
}
|
|
57
|
+
const vertex = parsedWGSL.entry.vertex[0]; // "main"
|
|
58
|
+
// Vertex shader inputs
|
|
59
|
+
const attributeCount = vertex?.inputs.length || 0; // inputs to "main"
|
|
60
|
+
for (let i = 0; i < attributeCount; i++) {
|
|
61
|
+
const wgslAttribute = vertex.inputs[i];
|
|
62
|
+
// locationType can be "builtin"
|
|
63
|
+
if (wgslAttribute.locationType === 'location') {
|
|
64
|
+
const type = getType(wgslAttribute.type);
|
|
65
|
+
shaderLayout.attributes.push({
|
|
66
|
+
name: wgslAttribute.name,
|
|
67
|
+
location: Number(wgslAttribute.location),
|
|
68
|
+
type
|
|
69
|
+
});
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
return shaderLayout;
|
|
73
|
+
}
|
|
74
|
+
/** Get a valid shader attribute type string from a wgsl-reflect type */
|
|
75
|
+
function getType(type) {
|
|
76
|
+
// @ts-expect-error WgslReflect type checks needed
|
|
77
|
+
return type?.format ? `${type.name}<${type.format.name}>` : type.name;
|
|
78
|
+
}
|
|
79
|
+
function parseWGSL(source) {
|
|
80
|
+
try {
|
|
81
|
+
return new WgslReflect(source);
|
|
82
|
+
}
|
|
83
|
+
catch (error) {
|
|
84
|
+
if (error instanceof Error) {
|
|
85
|
+
throw error;
|
|
86
|
+
}
|
|
87
|
+
let message = 'WGSL parse error';
|
|
88
|
+
if (typeof error === 'object' && error?.message) {
|
|
89
|
+
message += `: ${error.message} `;
|
|
90
|
+
}
|
|
91
|
+
if (typeof error === 'object' && error?.token) {
|
|
92
|
+
message += error.token.line || '';
|
|
93
|
+
}
|
|
94
|
+
throw new Error(message, { cause: error });
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
function getTextureBindingFromReflect(v, // VariableInfo for a texture
|
|
98
|
+
opts // optional: if you know the runtime format
|
|
99
|
+
) {
|
|
100
|
+
if (v.resourceType !== ResourceType.Texture) {
|
|
101
|
+
throw new Error('Not a texture binding');
|
|
102
|
+
}
|
|
103
|
+
const typeName = v.type.name; // e.g. "texture_2d", "texture_cube_array", "texture_multisampled_2d"
|
|
104
|
+
// @ts-expect-error v.type.format is not always defined
|
|
105
|
+
const component = v.type.format?.name;
|
|
106
|
+
// viewDimension
|
|
107
|
+
const viewDimension = typeName.includes('cube_array')
|
|
108
|
+
? 'cube-array'
|
|
109
|
+
: typeName.includes('cube')
|
|
110
|
+
? 'cube'
|
|
111
|
+
: typeName.includes('2d_array')
|
|
112
|
+
? '2d-array'
|
|
113
|
+
: typeName.includes('3d')
|
|
114
|
+
? '3d'
|
|
115
|
+
: typeName.includes('1d')
|
|
116
|
+
? '1d'
|
|
117
|
+
: '2d';
|
|
118
|
+
// multisampled
|
|
119
|
+
const multisampled = typeName === 'texture_multisampled_2d';
|
|
120
|
+
// sampleType
|
|
121
|
+
let sampleType;
|
|
122
|
+
if (typeName.startsWith('texture_depth')) {
|
|
123
|
+
sampleType = 'depth';
|
|
124
|
+
}
|
|
125
|
+
else if (component === 'i32') {
|
|
126
|
+
sampleType = 'sint';
|
|
127
|
+
}
|
|
128
|
+
else if (component === 'u32') {
|
|
129
|
+
sampleType = 'uint';
|
|
130
|
+
}
|
|
131
|
+
else {
|
|
132
|
+
sampleType = 'float'; // default to float
|
|
133
|
+
}
|
|
134
|
+
return { viewDimension, sampleType, multisampled };
|
|
135
|
+
}
|
|
136
|
+
//# sourceMappingURL=get-shader-layout-wgsl.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"get-shader-layout-wgsl.js","sourceRoot":"","sources":["../../src/wgsl/get-shader-layout-wgsl.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@luma.gl/webgpu",
|
|
3
|
-
"version": "9.2
|
|
3
|
+
"version": "9.3.0-alpha.2",
|
|
4
4
|
"description": "WebGPU adapter for the luma.gl core API",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|
|
@@ -37,11 +37,12 @@
|
|
|
37
37
|
"prepublishOnly": "npm run build-minified-bundle && npm run build-dev-bundle"
|
|
38
38
|
},
|
|
39
39
|
"peerDependencies": {
|
|
40
|
-
"@luma.gl/core": "
|
|
40
|
+
"@luma.gl/core": "9.2.0-alpha.6"
|
|
41
41
|
},
|
|
42
42
|
"dependencies": {
|
|
43
43
|
"@probe.gl/env": "^4.0.8",
|
|
44
|
-
"@webgpu/types": "^0.1.34"
|
|
44
|
+
"@webgpu/types": "^0.1.34",
|
|
45
|
+
"wgsl_reflect": "^1.2.1"
|
|
45
46
|
},
|
|
46
|
-
"gitHead": "
|
|
47
|
+
"gitHead": "7fedf8d8902f58490a4ffca9a873daee3c732f24"
|
|
47
48
|
}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
// luma.gl
|
|
2
|
+
// SPDX-License-Identifier: MIT
|
|
3
|
+
// Copyright (c) vis.gl contributors
|
|
4
|
+
|
|
5
|
+
import {Fence, type FenceProps} from '@luma.gl/core';
|
|
6
|
+
import {WebGPUDevice} from '../webgpu-device';
|
|
7
|
+
|
|
8
|
+
/** WebGPU fence implemented by waiting for submitted work */
|
|
9
|
+
export class WebGPUFence extends Fence {
|
|
10
|
+
readonly device: WebGPUDevice;
|
|
11
|
+
readonly handle: null = null;
|
|
12
|
+
readonly signaled: Promise<void>;
|
|
13
|
+
private _signaled = false;
|
|
14
|
+
|
|
15
|
+
constructor(device: WebGPUDevice, props: FenceProps = {}) {
|
|
16
|
+
super(device, {});
|
|
17
|
+
this.device = device;
|
|
18
|
+
this.signaled = device.handle.queue.onSubmittedWorkDone().then(() => {
|
|
19
|
+
this._signaled = true;
|
|
20
|
+
});
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
isSignaled(): boolean {
|
|
24
|
+
return this._signaled;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
override destroy(): void {
|
|
28
|
+
// Nothing to release for WebGPU fence
|
|
29
|
+
}
|
|
30
|
+
}
|
|
@@ -1,18 +1,24 @@
|
|
|
1
1
|
// luma.gl, MIT license
|
|
2
|
-
import
|
|
3
|
-
TextureProps,
|
|
4
|
-
TextureViewProps,
|
|
5
|
-
CopyExternalImageOptions,
|
|
6
|
-
CopyImageDataOptions,
|
|
7
|
-
|
|
2
|
+
import {
|
|
3
|
+
type TextureProps,
|
|
4
|
+
type TextureViewProps,
|
|
5
|
+
type CopyExternalImageOptions,
|
|
6
|
+
type CopyImageDataOptions,
|
|
7
|
+
type TextureReadOptions,
|
|
8
|
+
type TextureWriteOptions,
|
|
9
|
+
type SamplerProps,
|
|
10
|
+
Buffer,
|
|
11
|
+
Texture,
|
|
12
|
+
log,
|
|
13
|
+
textureFormatDecoder
|
|
8
14
|
} from '@luma.gl/core';
|
|
9
|
-
import {Texture, log} from '@luma.gl/core';
|
|
10
15
|
|
|
11
16
|
import {getWebGPUTextureFormat} from '../helpers/convert-texture-format';
|
|
12
17
|
import type {WebGPUDevice} from '../webgpu-device';
|
|
13
18
|
import {WebGPUSampler} from './webgpu-sampler';
|
|
14
19
|
import {WebGPUTextureView} from './webgpu-texture-view';
|
|
15
20
|
|
|
21
|
+
/** WebGPU implementation of the luma.gl core Texture resource */
|
|
16
22
|
export class WebGPUTexture extends Texture {
|
|
17
23
|
readonly device: WebGPUDevice;
|
|
18
24
|
readonly handle: GPUTexture;
|
|
@@ -20,13 +26,9 @@ export class WebGPUTexture extends Texture {
|
|
|
20
26
|
view: WebGPUTextureView;
|
|
21
27
|
|
|
22
28
|
constructor(device: WebGPUDevice, props: TextureProps) {
|
|
23
|
-
super(device, props);
|
|
29
|
+
super(device, props, {byteAlignment: 256}); // WebGPU requires row width to be a multiple of 256 bytes
|
|
24
30
|
this.device = device;
|
|
25
31
|
|
|
26
|
-
if (this.dimension === 'cube') {
|
|
27
|
-
this.depth = 6;
|
|
28
|
-
}
|
|
29
|
-
|
|
30
32
|
this.device.pushErrorScope('out-of-memory');
|
|
31
33
|
this.device.pushErrorScope('validation');
|
|
32
34
|
|
|
@@ -58,7 +60,9 @@ export class WebGPUTexture extends Texture {
|
|
|
58
60
|
// TODO - Read all properties directly from the supplied handle?
|
|
59
61
|
if (this.props.handle) {
|
|
60
62
|
this.handle.label ||= this.id;
|
|
63
|
+
// @ts-expect-error readonly
|
|
61
64
|
this.width = this.handle.width;
|
|
65
|
+
// @ts-expect-error readonly
|
|
62
66
|
this.height = this.handle.height;
|
|
63
67
|
}
|
|
64
68
|
|
|
@@ -90,10 +94,43 @@ export class WebGPUTexture extends Texture {
|
|
|
90
94
|
return new WebGPUTextureView(this.device, {...props, texture: this});
|
|
91
95
|
}
|
|
92
96
|
|
|
97
|
+
copyExternalImage(options_: CopyExternalImageOptions): {width: number; height: number} {
|
|
98
|
+
const options = this._normalizeCopyExternalImageOptions(options_);
|
|
99
|
+
|
|
100
|
+
this.device.pushErrorScope('validation');
|
|
101
|
+
this.device.handle.queue.copyExternalImageToTexture(
|
|
102
|
+
// source: GPUImageCopyExternalImage
|
|
103
|
+
{
|
|
104
|
+
source: options.image,
|
|
105
|
+
origin: [options.sourceX, options.sourceY],
|
|
106
|
+
flipY: false // options.flipY
|
|
107
|
+
},
|
|
108
|
+
// destination: GPUImageCopyTextureTagged
|
|
109
|
+
{
|
|
110
|
+
texture: this.handle,
|
|
111
|
+
origin: [options.x, options.y, options.z],
|
|
112
|
+
mipLevel: options.mipLevel,
|
|
113
|
+
aspect: options.aspect,
|
|
114
|
+
colorSpace: options.colorSpace,
|
|
115
|
+
premultipliedAlpha: options.premultipliedAlpha
|
|
116
|
+
},
|
|
117
|
+
// copySize: GPUExtent3D
|
|
118
|
+
[options.width, options.height, options.depth] // depth is always 1 for 2D textures
|
|
119
|
+
);
|
|
120
|
+
this.device.popErrorScope((error: GPUError) => {
|
|
121
|
+
this.device.reportError(new Error(`copyExternalImage: ${error.message}`), this)();
|
|
122
|
+
this.device.debug();
|
|
123
|
+
});
|
|
124
|
+
|
|
125
|
+
// TODO - should these be clipped to the texture size minus x,y,z?
|
|
126
|
+
return {width: options.width, height: options.height};
|
|
127
|
+
}
|
|
128
|
+
|
|
93
129
|
copyImageData(options_: CopyImageDataOptions): void {
|
|
94
130
|
const {width, height, depth} = this;
|
|
95
131
|
const options = this._normalizeCopyImageDataOptions(options_);
|
|
96
132
|
this.device.pushErrorScope('validation');
|
|
133
|
+
|
|
97
134
|
this.device.handle.queue.writeTexture(
|
|
98
135
|
// destination: GPUImageCopyTexture
|
|
99
136
|
{
|
|
@@ -121,108 +158,185 @@ export class WebGPUTexture extends Texture {
|
|
|
121
158
|
});
|
|
122
159
|
}
|
|
123
160
|
|
|
124
|
-
|
|
125
|
-
|
|
161
|
+
override generateMipmapsWebGL(): void {
|
|
162
|
+
log.warn(`${this}: generateMipmaps not supported in WebGPU`)();
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
getImageDataLayout(options: TextureReadOptions): {
|
|
166
|
+
byteLength: number;
|
|
167
|
+
bytesPerRow: number;
|
|
168
|
+
rowsPerImage: number;
|
|
169
|
+
} {
|
|
170
|
+
return {
|
|
171
|
+
byteLength: 0,
|
|
172
|
+
bytesPerRow: 0,
|
|
173
|
+
rowsPerImage: 0
|
|
174
|
+
};
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
override readBuffer(options: TextureReadOptions = {}, buffer?: Buffer): Buffer {
|
|
178
|
+
const {
|
|
179
|
+
x = 0,
|
|
180
|
+
y = 0,
|
|
181
|
+
z = 0,
|
|
182
|
+
width = this.width,
|
|
183
|
+
height = this.height,
|
|
184
|
+
depthOrArrayLayers = this.depth,
|
|
185
|
+
mipLevel = 0,
|
|
186
|
+
aspect = 'all'
|
|
187
|
+
} = options;
|
|
188
|
+
|
|
189
|
+
const layout = this.computeMemoryLayout(options);
|
|
190
|
+
|
|
191
|
+
const {bytesPerRow, rowsPerImage, byteLength} = layout;
|
|
192
|
+
|
|
193
|
+
// Create a GPUBuffer to hold the copied pixel data.
|
|
194
|
+
const readBuffer =
|
|
195
|
+
buffer ||
|
|
196
|
+
this.device.createBuffer({
|
|
197
|
+
byteLength,
|
|
198
|
+
usage: Buffer.COPY_DST | Buffer.MAP_READ
|
|
199
|
+
});
|
|
200
|
+
const gpuReadBuffer = readBuffer.handle as GPUBuffer;
|
|
201
|
+
|
|
202
|
+
// Record commands to copy from the texture to the buffer.
|
|
203
|
+
const gpuDevice = this.device.handle;
|
|
126
204
|
|
|
127
205
|
this.device.pushErrorScope('validation');
|
|
128
|
-
|
|
129
|
-
|
|
206
|
+
const commandEncoder = gpuDevice.createCommandEncoder();
|
|
207
|
+
commandEncoder.copyTextureToBuffer(
|
|
208
|
+
// source
|
|
130
209
|
{
|
|
131
|
-
|
|
132
|
-
origin:
|
|
133
|
-
|
|
210
|
+
texture: this.handle,
|
|
211
|
+
origin: {x, y, z},
|
|
212
|
+
// origin: [options.x, options.y, 0], // options.depth],
|
|
213
|
+
mipLevel,
|
|
214
|
+
aspect
|
|
215
|
+
// colorSpace: options.colorSpace,
|
|
216
|
+
// premultipliedAlpha: options.premultipliedAlpha
|
|
134
217
|
},
|
|
135
|
-
// destination
|
|
218
|
+
// destination
|
|
136
219
|
{
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
colorSpace: options.colorSpace,
|
|
142
|
-
premultipliedAlpha: options.premultipliedAlpha
|
|
220
|
+
buffer: gpuReadBuffer,
|
|
221
|
+
offset: 0,
|
|
222
|
+
bytesPerRow,
|
|
223
|
+
rowsPerImage
|
|
143
224
|
},
|
|
144
|
-
//
|
|
145
|
-
|
|
225
|
+
// copy size
|
|
226
|
+
{
|
|
227
|
+
width,
|
|
228
|
+
height,
|
|
229
|
+
depthOrArrayLayers
|
|
230
|
+
}
|
|
146
231
|
);
|
|
232
|
+
|
|
233
|
+
// Submit the command.
|
|
234
|
+
const commandBuffer = commandEncoder.finish();
|
|
235
|
+
this.device.handle.queue.submit([commandBuffer]);
|
|
147
236
|
this.device.popErrorScope((error: GPUError) => {
|
|
148
|
-
this.device.reportError(new Error(
|
|
237
|
+
this.device.reportError(new Error(`${this} readBuffer: ${error.message}`), this)();
|
|
149
238
|
this.device.debug();
|
|
150
239
|
});
|
|
151
240
|
|
|
152
|
-
|
|
153
|
-
return {width: options.width, height: options.height};
|
|
241
|
+
return readBuffer;
|
|
154
242
|
}
|
|
155
243
|
|
|
156
|
-
override
|
|
157
|
-
|
|
244
|
+
override async readDataAsync(options: TextureReadOptions = {}): Promise<ArrayBuffer> {
|
|
245
|
+
const buffer = this.readBuffer(options);
|
|
246
|
+
const data = await buffer.readAsync();
|
|
247
|
+
buffer.destroy();
|
|
248
|
+
return data.buffer as ArrayBuffer;
|
|
158
249
|
}
|
|
159
250
|
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
251
|
+
override writeBuffer(buffer: Buffer, options: TextureWriteOptions = {}) {
|
|
252
|
+
const {
|
|
253
|
+
x = 0,
|
|
254
|
+
y = 0,
|
|
255
|
+
z = 0,
|
|
256
|
+
width = this.width,
|
|
257
|
+
height = this.height,
|
|
258
|
+
depthOrArrayLayers = this.depth,
|
|
259
|
+
mipLevel = 0,
|
|
260
|
+
aspect = 'all'
|
|
261
|
+
} = options;
|
|
168
262
|
|
|
169
|
-
|
|
170
|
-
const encoder = device.createCommandEncoder();
|
|
171
|
-
encoder.copyTextureToBuffer(
|
|
172
|
-
{ texture },
|
|
173
|
-
{ buffer, rowPitch: textureWidth * 4 },
|
|
174
|
-
[textureWidth, textureHeight],
|
|
175
|
-
);
|
|
176
|
-
device.submit([encoder.finish()]);
|
|
263
|
+
const layout = this.computeMemoryLayout(options);
|
|
177
264
|
|
|
178
265
|
// Get the data on the CPU.
|
|
179
|
-
await buffer.mapAndReadAsync(
|
|
180
|
-
saveScreenshot(buffer.getMappedRange());
|
|
181
|
-
buffer.unmap();
|
|
182
|
-
}
|
|
266
|
+
// await buffer.mapAndReadAsync();
|
|
183
267
|
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
const bytesPerRow = Math.ceil((img.width * 4) / 256) * 256;
|
|
188
|
-
if (bytesPerRow == img.width * 4) {
|
|
189
|
-
data = imageData.data;
|
|
190
|
-
} else {
|
|
191
|
-
data = new Uint8Array(bytesPerRow * img.height);
|
|
192
|
-
let imagePixelIndex = 0;
|
|
193
|
-
for (let y = 0; y < img.height; ++y) {
|
|
194
|
-
for (let x = 0; x < img.width; ++x) {
|
|
195
|
-
const i = x * 4 + y * bytesPerRow;
|
|
196
|
-
data[i] = imageData.data[imagePixelIndex];
|
|
197
|
-
data[i + 1] = imageData.data[imagePixelIndex + 1];
|
|
198
|
-
data[i + 2] = imageData.data[imagePixelIndex + 2];
|
|
199
|
-
data[i + 3] = imageData.data[imagePixelIndex + 3];
|
|
200
|
-
imagePixelIndex += 4;
|
|
201
|
-
}
|
|
202
|
-
}
|
|
203
|
-
}
|
|
204
|
-
return this;
|
|
205
|
-
}
|
|
268
|
+
const {bytesPerRow, rowsPerImage} = layout;
|
|
269
|
+
|
|
270
|
+
const gpuDevice = this.device.handle;
|
|
206
271
|
|
|
207
|
-
|
|
208
|
-
const commandEncoder =
|
|
272
|
+
this.device.pushErrorScope('validation');
|
|
273
|
+
const commandEncoder = gpuDevice.createCommandEncoder();
|
|
209
274
|
commandEncoder.copyBufferToTexture(
|
|
210
275
|
{
|
|
211
|
-
buffer:
|
|
212
|
-
|
|
276
|
+
buffer: buffer.handle as GPUBuffer,
|
|
277
|
+
offset: 0,
|
|
278
|
+
bytesPerRow,
|
|
279
|
+
rowsPerImage
|
|
213
280
|
},
|
|
214
281
|
{
|
|
215
|
-
texture: this.handle
|
|
282
|
+
texture: this.handle,
|
|
283
|
+
origin: {x, y, z},
|
|
284
|
+
mipLevel,
|
|
285
|
+
aspect
|
|
216
286
|
},
|
|
217
|
-
{
|
|
218
|
-
width,
|
|
219
|
-
height,
|
|
220
|
-
depth
|
|
221
|
-
}
|
|
287
|
+
{width, height, depthOrArrayLayers}
|
|
222
288
|
);
|
|
289
|
+
const commandBuffer = commandEncoder.finish();
|
|
290
|
+
this.device.handle.queue.submit([commandBuffer]);
|
|
291
|
+
this.device.popErrorScope((error: GPUError) => {
|
|
292
|
+
this.device.reportError(new Error(`${this} writeBuffer: ${error.message}`), this)();
|
|
293
|
+
this.device.debug();
|
|
294
|
+
});
|
|
295
|
+
}
|
|
223
296
|
|
|
224
|
-
|
|
225
|
-
|
|
297
|
+
override writeData(data: ArrayBuffer | ArrayBufferView, options: TextureWriteOptions = {}): void {
|
|
298
|
+
const device = this.device;
|
|
299
|
+
|
|
300
|
+
const {
|
|
301
|
+
x = 0,
|
|
302
|
+
y = 0,
|
|
303
|
+
z = 0,
|
|
304
|
+
width = this.width,
|
|
305
|
+
height = this.height,
|
|
306
|
+
depthOrArrayLayers = this.depth,
|
|
307
|
+
mipLevel = 0,
|
|
308
|
+
aspect = 'all'
|
|
309
|
+
} = options;
|
|
310
|
+
|
|
311
|
+
const layout = textureFormatDecoder.computeMemoryLayout({
|
|
312
|
+
format: this.format,
|
|
313
|
+
width: this.width,
|
|
314
|
+
height: this.height,
|
|
315
|
+
depth: this.depth,
|
|
316
|
+
byteAlignment: this.byteAlignment
|
|
317
|
+
});
|
|
318
|
+
|
|
319
|
+
const {bytesPerRow, rowsPerImage} = layout;
|
|
320
|
+
|
|
321
|
+
this.device.pushErrorScope('validation');
|
|
322
|
+
device.handle.queue.writeTexture(
|
|
323
|
+
{
|
|
324
|
+
texture: this.handle,
|
|
325
|
+
mipLevel,
|
|
326
|
+
aspect,
|
|
327
|
+
origin: {x, y, z}
|
|
328
|
+
},
|
|
329
|
+
data,
|
|
330
|
+
{
|
|
331
|
+
offset: 0,
|
|
332
|
+
bytesPerRow,
|
|
333
|
+
rowsPerImage
|
|
334
|
+
},
|
|
335
|
+
{width, height, depthOrArrayLayers}
|
|
336
|
+
);
|
|
337
|
+
this.device.popErrorScope((error: GPUError) => {
|
|
338
|
+
this.device.reportError(new Error(`${this} writeData: ${error.message}`), this)();
|
|
339
|
+
this.device.debug();
|
|
340
|
+
});
|
|
226
341
|
}
|
|
227
|
-
*/
|
|
228
342
|
}
|