@luma.gl/webgpu 9.2.6 → 9.3.0-alpha.4
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/helpers/get-bind-group.d.ts.map +1 -1
- package/dist/adapter/helpers/get-bind-group.js +11 -5
- package/dist/adapter/helpers/get-bind-group.js.map +1 -1
- package/dist/adapter/resources/webgpu-buffer.d.ts +7 -0
- package/dist/adapter/resources/webgpu-buffer.d.ts.map +1 -1
- package/dist/adapter/resources/webgpu-buffer.js +39 -12
- package/dist/adapter/resources/webgpu-buffer.js.map +1 -1
- 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-pipeline-layout.d.ts.map +1 -1
- package/dist/adapter/resources/webgpu-pipeline-layout.js +1 -2
- package/dist/adapter/resources/webgpu-pipeline-layout.js.map +1 -1
- 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 +6485 -293
- package/dist/dist.min.js +10 -6
- package/dist/index.cjs +398 -114
- 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 +6 -5
- package/src/adapter/helpers/get-bind-group.ts +18 -5
- package/src/adapter/resources/webgpu-buffer.ts +43 -12
- package/src/adapter/resources/webgpu-fence.ts +30 -0
- package/src/adapter/resources/webgpu-pipeline-layout.ts +1 -2
- 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":"AAAA,UAAU;AACV,+BAA+B;AAC/B,oCAAoC;AAEpC,OAAO,EAA0D,GAAG,EAAC,MAAM,eAAe,CAAC;AAC3F,OAAO,EAAyB,WAAW,EAAE,YAAY,EAAC,MAAM,cAAc,CAAC;AAE/E;;;;GAIG;AACH,MAAM,UAAU,uBAAuB,CAAC,MAAc;IACpD,MAAM,YAAY,GAAiB,EAAC,UAAU,EAAE,EAAE,EAAE,QAAQ,EAAE,EAAE,EAAC,CAAC;IAElE,IAAI,UAAuB,CAAC;IAC5B,IAAI,CAAC;QACH,UAAU,GAAG,SAAS,CAAC,MAAM,CAAC,CAAC;IACjC,CAAC;IAAC,OAAO,KAAU,EAAE,CAAC;QACpB,GAAG,CAAC,KAAK,CAAC,KAAK,CAAC,OAAO,CAAC,EAAE,CAAC;QAC3B,OAAO,YAAY,CAAC;IACtB,CAAC;IAED,KAAK,MAAM,OAAO,IAAI,UAAU,CAAC,QAAQ,EAAE,CAAC;QAC1C,MAAM,OAAO,GAAG,EAAE,CAAC;QACnB,mBAAmB;QACnB,KAAK,MAAM,SAAS,IAAI,OAAO,CAAC,IAAI,EAAE,OAAO,IAAI,EAAE,EAAE,CAAC;YACpD,OAAO,CAAC,IAAI,CAAC;gBACX,IAAI,EAAE,SAAS,CAAC,IAAI;gBACpB,IAAI,EAAE,OAAO,CAAC,SAAS,CAAC,IAAI,CAAC;aAC9B,CAAC,CAAC;QACL,CAAC;QAED,YAAY,CAAC,QAAQ,CAAC,IAAI,CAAC;YACzB,IAAI,EAAE,SAAS;YACf,IAAI,EAAE,OAAO,CAAC,IAAI;YAClB,KAAK,EAAE,OAAO,CAAC,KAAK;YACpB,QAAQ,EAAE,OAAO,CAAC,OAAO;YACzB,0DAA0D;YAC1D,OAAO;SACR,CAAC,CAAC;IACL,CAAC;IAED,KAAK,MAAM,OAAO,IAAI,UAAU,CAAC,QAAQ,EAAE,CAAC;QAC1C,MAAM,kBAAkB,GAAyB;YAC/C,IAAI,EAAE,SAAS;YACf,IAAI,EAAE,OAAO,CAAC,IAAI;YAClB,KAAK,EAAE,OAAO,CAAC,KAAK;YACpB,QAAQ,EAAE,OAAO,CAAC,OAAO;YACzB,GAAG,4BAA4B,CAAC,OAAO,CAAC;SACzC,CAAC;QAEF,YAAY,CAAC,QAAQ,CAAC,IAAI,CAAC,kBAAkB,CAAC,CAAC;IACjD,CAAC;IAED,KAAK,MAAM,OAAO,IAAI,UAAU,CAAC,QAAQ,EAAE,CAAC;QAC1C,YAAY,CAAC,QAAQ,CAAC,IAAI,CAAC;YACzB,IAAI,EAAE,SAAS;YACf,IAAI,EAAE,OAAO,CAAC,IAAI;YAClB,KAAK,EAAE,OAAO,CAAC,KAAK;YACpB,QAAQ,EAAE,OAAO,CAAC,OAAO;SAC1B,CAAC,CAAC;IACL,CAAC;IAED,MAAM,MAAM,GAAG,UAAU,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,SAAS;IAEpD,uBAAuB;IACvB,MAAM,cAAc,GAAG,MAAM,EAAE,MAAM,CAAC,MAAM,IAAI,CAAC,CAAC,CAAC,mBAAmB;IACtE,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,cAAc,EAAE,CAAC,EAAE,EAAE,CAAC;QACxC,MAAM,aAAa,GAAG,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC;QAEvC,gCAAgC;QAChC,IAAI,aAAa,CAAC,YAAY,KAAK,UAAU,EAAE,CAAC;YAC9C,MAAM,IAAI,GAAG,OAAO,CAAC,aAAa,CAAC,IAAI,CAAC,CAAC;YAEzC,YAAY,CAAC,UAAU,CAAC,IAAI,CAAC;gBAC3B,IAAI,EAAE,aAAa,CAAC,IAAI;gBACxB,QAAQ,EAAE,MAAM,CAAC,aAAa,CAAC,QAAQ,CAAC;gBACxC,IAAI;aACL,CAAC,CAAC;QACL,CAAC;IACH,CAAC;IACD,OAAO,YAAY,CAAC;AACtB,CAAC;AAED,wEAAwE;AACxE,SAAS,OAAO,CAAC,IAAqB;IACpC,kDAAkD;IAClD,OAAO,IAAI,EAAE,MAAM,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC,IAAI,IAAI,IAAI,CAAC,MAAM,CAAC,IAAI,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC;AACxE,CAAC;AAED,SAAS,SAAS,CAAC,MAAc;IAC/B,IAAI,CAAC;QACH,OAAO,IAAI,WAAW,CAAC,MAAM,CAAC,CAAC;IACjC,CAAC;IAAC,OAAO,KAAU,EAAE,CAAC;QACpB,IAAI,KAAK,YAAY,KAAK,EAAE,CAAC;YAC3B,MAAM,KAAK,CAAC;QACd,CAAC;QACD,IAAI,OAAO,GAAG,kBAAkB,CAAC;QACjC,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,EAAE,OAAO,EAAE,CAAC;YAChD,OAAO,IAAI,KAAK,KAAK,CAAC,OAAO,GAAG,CAAC;QACnC,CAAC;QACD,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,EAAE,KAAK,EAAE,CAAC;YAC9C,OAAO,IAAI,KAAK,CAAC,KAAK,CAAC,IAAI,IAAI,EAAE,CAAC;QACpC,CAAC;QACD,MAAM,IAAI,KAAK,CAAC,OAAO,EAAE,EAAC,KAAK,EAAE,KAAK,EAAC,CAAC,CAAC;IAC3C,CAAC;AACH,CAAC;AAED,SAAS,4BAA4B,CACnC,CAAe,EAAE,6BAA6B;AAC9C,IAAkC,CAAC,2CAA2C;;IAO9E,IAAI,CAAC,CAAC,YAAY,KAAK,YAAY,CAAC,OAAO,EAAE,CAAC;QAC5C,MAAM,IAAI,KAAK,CAAC,uBAAuB,CAAC,CAAC;IAC3C,CAAC;IAED,MAAM,QAAQ,GAAG,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,qEAAqE;IACnG,uDAAuD;IACvD,MAAM,SAAS,GAAG,CAAC,CAAC,IAAI,CAAC,MAAM,EAAE,IAAyC,CAAC;IAE3E,gBAAgB;IAChB,MAAM,aAAa,GAA4B,QAAQ,CAAC,QAAQ,CAAC,YAAY,CAAC;QAC5E,CAAC,CAAC,YAAY;QACd,CAAC,CAAC,QAAQ,CAAC,QAAQ,CAAC,MAAM,CAAC;YACzB,CAAC,CAAC,MAAM;YACR,CAAC,CAAC,QAAQ,CAAC,QAAQ,CAAC,UAAU,CAAC;gBAC7B,CAAC,CAAC,UAAU;gBACZ,CAAC,CAAC,QAAQ,CAAC,QAAQ,CAAC,IAAI,CAAC;oBACvB,CAAC,CAAC,IAAI;oBACN,CAAC,CAAC,QAAQ,CAAC,QAAQ,CAAC,IAAI,CAAC;wBACvB,CAAC,CAAC,IAAI;wBACN,CAAC,CAAC,IAAI,CAAC;IAEjB,eAAe;IACf,MAAM,YAAY,GAAG,QAAQ,KAAK,yBAAyB,CAAC;IAE5D,aAAa;IACb,IAAI,UAAgC,CAAC;IACrC,IAAI,QAAQ,CAAC,UAAU,CAAC,eAAe,CAAC,EAAE,CAAC;QACzC,UAAU,GAAG,OAAO,CAAC;IACvB,CAAC;SAAM,IAAI,SAAS,KAAK,KAAK,EAAE,CAAC;QAC/B,UAAU,GAAG,MAAM,CAAC;IACtB,CAAC;SAAM,IAAI,SAAS,KAAK,KAAK,EAAE,CAAC;QAC/B,UAAU,GAAG,MAAM,CAAC;IACtB,CAAC;SAAM,CAAC;QACN,UAAU,GAAG,OAAO,CAAC,CAAC,mBAAmB;IAC3C,CAAC;IAED,OAAO,EAAC,aAAa,EAAE,UAAU,EAAE,YAAY,EAAC,CAAC;AACnD,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@luma.gl/webgpu",
|
|
3
|
-
"version": "9.
|
|
3
|
+
"version": "9.3.0-alpha.4",
|
|
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
|
-
"@probe.gl/env": "^4.
|
|
44
|
-
"@webgpu/types": "^0.1.34"
|
|
43
|
+
"@probe.gl/env": "^4.1.1",
|
|
44
|
+
"@webgpu/types": "^0.1.34",
|
|
45
|
+
"wgsl_reflect": "^1.2.1"
|
|
45
46
|
},
|
|
46
|
-
"gitHead": "
|
|
47
|
+
"gitHead": "7486e7b0377fb6ab961b4499828681bede60f3b1"
|
|
47
48
|
}
|
|
@@ -3,10 +3,11 @@
|
|
|
3
3
|
// Copyright (c) vis.gl contributors
|
|
4
4
|
|
|
5
5
|
import type {ComputeShaderLayout, BindingDeclaration, Binding} from '@luma.gl/core';
|
|
6
|
-
import {Buffer, Sampler, Texture, log} from '@luma.gl/core';
|
|
6
|
+
import {Buffer, Sampler, Texture, TextureView, log} from '@luma.gl/core';
|
|
7
7
|
import type {WebGPUBuffer} from '../resources/webgpu-buffer';
|
|
8
8
|
import type {WebGPUSampler} from '../resources/webgpu-sampler';
|
|
9
9
|
import type {WebGPUTexture} from '../resources/webgpu-texture';
|
|
10
|
+
import type {WebGPUTextureView} from '../resources/webgpu-texture-view';
|
|
10
11
|
|
|
11
12
|
/**
|
|
12
13
|
* Create a WebGPU "bind group layout" from an array of luma.gl bindings
|
|
@@ -76,7 +77,7 @@ function getBindGroupEntries(
|
|
|
76
77
|
for (const [bindingName, value] of Object.entries(bindings)) {
|
|
77
78
|
let bindingLayout = getShaderLayoutBinding(shaderLayout, bindingName);
|
|
78
79
|
if (bindingLayout) {
|
|
79
|
-
const entry = getBindGroupEntry(value, bindingLayout.location);
|
|
80
|
+
const entry = getBindGroupEntry(value, bindingLayout.location, undefined, bindingName);
|
|
80
81
|
if (entry) {
|
|
81
82
|
entries.push(entry);
|
|
82
83
|
}
|
|
@@ -88,7 +89,12 @@ function getBindGroupEntries(
|
|
|
88
89
|
ignoreWarnings: true
|
|
89
90
|
});
|
|
90
91
|
if (bindingLayout) {
|
|
91
|
-
const entry = getBindGroupEntry(
|
|
92
|
+
const entry = getBindGroupEntry(
|
|
93
|
+
value,
|
|
94
|
+
bindingLayout.location,
|
|
95
|
+
{sampler: true},
|
|
96
|
+
bindingName
|
|
97
|
+
);
|
|
92
98
|
if (entry) {
|
|
93
99
|
entries.push(entry);
|
|
94
100
|
}
|
|
@@ -102,7 +108,8 @@ function getBindGroupEntries(
|
|
|
102
108
|
function getBindGroupEntry(
|
|
103
109
|
binding: Binding,
|
|
104
110
|
index: number,
|
|
105
|
-
options?: {sampler?: boolean}
|
|
111
|
+
options?: {sampler?: boolean},
|
|
112
|
+
bindingName: string = 'unknown'
|
|
106
113
|
): GPUBindGroupEntry | null {
|
|
107
114
|
if (binding instanceof Buffer) {
|
|
108
115
|
return {
|
|
@@ -118,6 +125,12 @@ function getBindGroupEntry(
|
|
|
118
125
|
resource: (binding as WebGPUSampler).handle
|
|
119
126
|
};
|
|
120
127
|
}
|
|
128
|
+
if (binding instanceof TextureView) {
|
|
129
|
+
return {
|
|
130
|
+
binding: index,
|
|
131
|
+
resource: (binding as WebGPUTextureView).handle
|
|
132
|
+
};
|
|
133
|
+
}
|
|
121
134
|
if (binding instanceof Texture) {
|
|
122
135
|
if (options?.sampler) {
|
|
123
136
|
return {
|
|
@@ -130,6 +143,6 @@ function getBindGroupEntry(
|
|
|
130
143
|
resource: (binding as WebGPUTexture).view.handle
|
|
131
144
|
};
|
|
132
145
|
}
|
|
133
|
-
log.warn(`invalid binding ${
|
|
146
|
+
log.warn(`invalid binding ${bindingName}`, binding);
|
|
134
147
|
return null;
|
|
135
148
|
}
|
|
@@ -5,20 +5,28 @@
|
|
|
5
5
|
import {log, Buffer, type BufferProps, type BufferMapCallback} from '@luma.gl/core';
|
|
6
6
|
import {type WebGPUDevice} from '../webgpu-device';
|
|
7
7
|
|
|
8
|
+
/**
|
|
9
|
+
* WebGPU implementation of Buffer
|
|
10
|
+
* For byte alignment requirements see:
|
|
11
|
+
* @see https://www.w3.org/TR/webgpu/#dom-gpubuffer-mapasync
|
|
12
|
+
* @see https://developer.mozilla.org/en-US/docs/Web/API/GPUBuffer/mapAsync
|
|
13
|
+
*/
|
|
8
14
|
export class WebGPUBuffer extends Buffer {
|
|
9
15
|
readonly device: WebGPUDevice;
|
|
10
16
|
readonly handle: GPUBuffer;
|
|
11
17
|
readonly byteLength: number;
|
|
18
|
+
readonly paddedByteLength: number;
|
|
12
19
|
|
|
13
20
|
constructor(device: WebGPUDevice, props: BufferProps) {
|
|
14
21
|
super(device, props);
|
|
15
22
|
this.device = device;
|
|
16
23
|
|
|
17
24
|
this.byteLength = props.byteLength || props.data?.byteLength || 0;
|
|
25
|
+
this.paddedByteLength = Math.ceil(this.byteLength / 4) * 4;
|
|
18
26
|
const mappedAtCreation = Boolean(this.props.onMapped || props.data);
|
|
19
27
|
|
|
20
28
|
// WebGPU buffers must be aligned to 4 bytes
|
|
21
|
-
const size =
|
|
29
|
+
const size = this.paddedByteLength;
|
|
22
30
|
|
|
23
31
|
this.device.pushErrorScope('out-of-memory');
|
|
24
32
|
this.device.pushErrorScope('validation');
|
|
@@ -92,10 +100,11 @@ export class WebGPUBuffer extends Buffer {
|
|
|
92
100
|
byteOffset: number = 0,
|
|
93
101
|
byteLength: number = this.byteLength - byteOffset
|
|
94
102
|
): Promise<void> {
|
|
103
|
+
const alignedByteLength = Math.ceil(byteLength / 4) * 4;
|
|
95
104
|
// Unless the application created and supplied a mappable buffer, a staging buffer is needed
|
|
96
105
|
const isMappable = (this.usage & Buffer.MAP_WRITE) !== 0;
|
|
97
106
|
const mappableBuffer: WebGPUBuffer | null = !isMappable
|
|
98
|
-
? this._getMappableBuffer(Buffer.MAP_WRITE | Buffer.COPY_SRC, 0, this.
|
|
107
|
+
? this._getMappableBuffer(Buffer.MAP_WRITE | Buffer.COPY_SRC, 0, this.paddedByteLength)
|
|
99
108
|
: null;
|
|
100
109
|
|
|
101
110
|
const writeBuffer = mappableBuffer || this;
|
|
@@ -105,13 +114,15 @@ export class WebGPUBuffer extends Buffer {
|
|
|
105
114
|
this.device.pushErrorScope('validation');
|
|
106
115
|
try {
|
|
107
116
|
await this.device.handle.queue.onSubmittedWorkDone();
|
|
108
|
-
await writeBuffer.handle.mapAsync(GPUMapMode.WRITE, byteOffset,
|
|
109
|
-
const
|
|
117
|
+
await writeBuffer.handle.mapAsync(GPUMapMode.WRITE, byteOffset, alignedByteLength);
|
|
118
|
+
const mappedRange = writeBuffer.handle.getMappedRange(byteOffset, alignedByteLength);
|
|
119
|
+
const arrayBuffer = mappedRange.slice(0, byteLength);
|
|
110
120
|
// eslint-disable-next-line @typescript-eslint/await-thenable
|
|
111
121
|
await callback(arrayBuffer, 'mapped');
|
|
122
|
+
new Uint8Array(mappedRange).set(new Uint8Array(arrayBuffer), 0);
|
|
112
123
|
writeBuffer.handle.unmap();
|
|
113
124
|
if (mappableBuffer) {
|
|
114
|
-
this._copyBuffer(mappableBuffer, byteOffset,
|
|
125
|
+
this._copyBuffer(mappableBuffer, byteOffset, alignedByteLength);
|
|
115
126
|
}
|
|
116
127
|
} finally {
|
|
117
128
|
this.device.popErrorScope((error: GPUError) => {
|
|
@@ -138,17 +149,33 @@ export class WebGPUBuffer extends Buffer {
|
|
|
138
149
|
byteOffset = 0,
|
|
139
150
|
byteLength = this.byteLength - byteOffset
|
|
140
151
|
): Promise<T> {
|
|
152
|
+
const requestedEnd = byteOffset + byteLength;
|
|
153
|
+
if (requestedEnd > this.byteLength) {
|
|
154
|
+
throw new Error('Mapping range exceeds buffer size');
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
let mappedByteOffset = byteOffset;
|
|
158
|
+
let mappedByteLength = byteLength;
|
|
159
|
+
let sliceByteOffset = 0;
|
|
160
|
+
let lifetime: 'mapped' | 'copied' = 'mapped';
|
|
161
|
+
|
|
162
|
+
// WebGPU mapAsync requires 8-byte offsets and 4-byte lengths.
|
|
141
163
|
if (byteOffset % 8 !== 0 || byteLength % 4 !== 0) {
|
|
142
|
-
|
|
164
|
+
mappedByteOffset = Math.floor(byteOffset / 8) * 8;
|
|
165
|
+
const alignedEnd = Math.ceil(requestedEnd / 4) * 4;
|
|
166
|
+
mappedByteLength = alignedEnd - mappedByteOffset;
|
|
167
|
+
sliceByteOffset = byteOffset - mappedByteOffset;
|
|
168
|
+
lifetime = 'copied';
|
|
143
169
|
}
|
|
144
|
-
|
|
170
|
+
|
|
171
|
+
if (mappedByteOffset + mappedByteLength > this.paddedByteLength) {
|
|
145
172
|
throw new Error('Mapping range exceeds buffer size');
|
|
146
173
|
}
|
|
147
174
|
|
|
148
175
|
// Unless the application created and supplied a mappable buffer, a staging buffer is needed
|
|
149
176
|
const isMappable = (this.usage & Buffer.MAP_READ) !== 0;
|
|
150
177
|
const mappableBuffer: WebGPUBuffer | null = !isMappable
|
|
151
|
-
? this._getMappableBuffer(Buffer.MAP_READ | Buffer.COPY_DST, 0, this.
|
|
178
|
+
? this._getMappableBuffer(Buffer.MAP_READ | Buffer.COPY_DST, 0, this.paddedByteLength)
|
|
152
179
|
: null;
|
|
153
180
|
|
|
154
181
|
const readBuffer = mappableBuffer || this;
|
|
@@ -158,12 +185,16 @@ export class WebGPUBuffer extends Buffer {
|
|
|
158
185
|
try {
|
|
159
186
|
await this.device.handle.queue.onSubmittedWorkDone();
|
|
160
187
|
if (mappableBuffer) {
|
|
161
|
-
mappableBuffer._copyBuffer(this);
|
|
188
|
+
mappableBuffer._copyBuffer(this, mappedByteOffset, mappedByteLength);
|
|
162
189
|
}
|
|
163
|
-
await readBuffer.handle.mapAsync(GPUMapMode.READ,
|
|
164
|
-
const arrayBuffer = readBuffer.handle.getMappedRange(
|
|
190
|
+
await readBuffer.handle.mapAsync(GPUMapMode.READ, mappedByteOffset, mappedByteLength);
|
|
191
|
+
const arrayBuffer = readBuffer.handle.getMappedRange(mappedByteOffset, mappedByteLength);
|
|
192
|
+
const mappedRange =
|
|
193
|
+
lifetime === 'mapped'
|
|
194
|
+
? arrayBuffer
|
|
195
|
+
: arrayBuffer.slice(sliceByteOffset, sliceByteOffset + byteLength);
|
|
165
196
|
// eslint-disable-next-line @typescript-eslint/await-thenable
|
|
166
|
-
const result = await callback(
|
|
197
|
+
const result = await callback(mappedRange, lifetime);
|
|
167
198
|
readBuffer.handle.unmap();
|
|
168
199
|
return result;
|
|
169
200
|
} finally {
|
|
@@ -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
|
+
}
|
|
@@ -47,8 +47,7 @@ export class WebGPUPipelineLayout extends PipelineLayout {
|
|
|
47
47
|
// TODO (kaapp): This only supports the first group, but so does the rest of the code
|
|
48
48
|
const bindGroupEntries: GPUBindGroupLayoutEntry[] = [];
|
|
49
49
|
|
|
50
|
-
for (
|
|
51
|
-
const binding = this.props.shaderLayout.bindings[i];
|
|
50
|
+
for (const binding of this.props.shaderLayout.bindings) {
|
|
52
51
|
const bindingTypeInfo: Omit<GPUBindGroupLayoutEntry, 'binding' | 'visibility'> = {};
|
|
53
52
|
|
|
54
53
|
switch (binding.type) {
|