@luma.gl/webgpu 9.0.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/README.md +1 -0
- package/dist/adapter/helpers/accessor-to-format.d.ts +1 -0
- package/dist/adapter/helpers/accessor-to-format.d.ts.map +1 -0
- package/dist/adapter/helpers/accessor-to-format.js +2 -0
- package/dist/adapter/helpers/accessor-to-format.js.map +1 -0
- package/dist/adapter/helpers/convert-texture-format.d.ts +5 -0
- package/dist/adapter/helpers/convert-texture-format.d.ts.map +1 -0
- package/dist/adapter/helpers/convert-texture-format.js +8 -0
- package/dist/adapter/helpers/convert-texture-format.js.map +1 -0
- package/dist/adapter/helpers/generate-mipmaps.d.ts +10 -0
- package/dist/adapter/helpers/generate-mipmaps.d.ts.map +1 -0
- package/dist/adapter/helpers/generate-mipmaps.js +95 -0
- package/dist/adapter/helpers/generate-mipmaps.js.map +1 -0
- package/dist/adapter/helpers/get-bind-group.d.ts +13 -0
- package/dist/adapter/helpers/get-bind-group.d.ts.map +1 -0
- package/dist/adapter/helpers/get-bind-group.js +60 -0
- package/dist/adapter/helpers/get-bind-group.js.map +1 -0
- package/dist/adapter/helpers/get-vertex-buffer-layout.d.ts +12 -0
- package/dist/adapter/helpers/get-vertex-buffer-layout.d.ts.map +1 -0
- package/dist/adapter/helpers/get-vertex-buffer-layout.js +98 -0
- package/dist/adapter/helpers/get-vertex-buffer-layout.js.map +1 -0
- package/dist/adapter/helpers/webgpu-parameters.d.ts +9 -0
- package/dist/adapter/helpers/webgpu-parameters.d.ts.map +1 -0
- package/dist/adapter/helpers/webgpu-parameters.js +134 -0
- package/dist/adapter/helpers/webgpu-parameters.js.map +1 -0
- package/dist/adapter/resources/webgpu-buffer.d.ts +18 -0
- package/dist/adapter/resources/webgpu-buffer.d.ts.map +1 -0
- package/dist/adapter/resources/webgpu-buffer.js +84 -0
- package/dist/adapter/resources/webgpu-buffer.js.map +1 -0
- package/dist/adapter/resources/webgpu-command-encoder.d.ts +45 -0
- package/dist/adapter/resources/webgpu-command-encoder.d.ts.map +1 -0
- package/dist/adapter/resources/webgpu-command-encoder.js +66 -0
- package/dist/adapter/resources/webgpu-command-encoder.js.map +1 -0
- package/dist/adapter/resources/webgpu-compute-pass.d.ts +32 -0
- package/dist/adapter/resources/webgpu-compute-pass.d.ts.map +1 -0
- package/dist/adapter/resources/webgpu-compute-pass.js +56 -0
- package/dist/adapter/resources/webgpu-compute-pass.js.map +1 -0
- package/dist/adapter/resources/webgpu-compute-pipeline.d.ts +12 -0
- package/dist/adapter/resources/webgpu-compute-pipeline.d.ts.map +1 -0
- package/dist/adapter/resources/webgpu-compute-pipeline.js +27 -0
- package/dist/adapter/resources/webgpu-compute-pipeline.js.map +1 -0
- package/dist/adapter/resources/webgpu-external-texture.d.ts +18 -0
- package/dist/adapter/resources/webgpu-external-texture.d.ts.map +1 -0
- package/dist/adapter/resources/webgpu-external-texture.js +30 -0
- package/dist/adapter/resources/webgpu-external-texture.js.map +1 -0
- package/dist/adapter/resources/webgpu-framebuffer.d.ts +29 -0
- package/dist/adapter/resources/webgpu-framebuffer.d.ts.map +1 -0
- package/dist/adapter/resources/webgpu-framebuffer.js +111 -0
- package/dist/adapter/resources/webgpu-framebuffer.js.map +1 -0
- package/dist/adapter/resources/webgpu-query.d.ts +1 -0
- package/dist/adapter/resources/webgpu-query.d.ts.map +1 -0
- package/dist/adapter/resources/webgpu-query.js +2 -0
- package/dist/adapter/resources/webgpu-query.js.map +1 -0
- package/dist/adapter/resources/webgpu-render-pass.d.ts +34 -0
- package/dist/adapter/resources/webgpu-render-pass.d.ts.map +1 -0
- package/dist/adapter/resources/webgpu-render-pass.js +92 -0
- package/dist/adapter/resources/webgpu-render-pass.js.map +1 -0
- package/dist/adapter/resources/webgpu-render-pipeline.d.ts +41 -0
- package/dist/adapter/resources/webgpu-render-pipeline.d.ts.map +1 -0
- package/dist/adapter/resources/webgpu-render-pipeline.js +148 -0
- package/dist/adapter/resources/webgpu-render-pipeline.js.map +1 -0
- package/dist/adapter/resources/webgpu-sampler.d.ts +16 -0
- package/dist/adapter/resources/webgpu-sampler.d.ts.map +1 -0
- package/dist/adapter/resources/webgpu-sampler.js +19 -0
- package/dist/adapter/resources/webgpu-sampler.js.map +1 -0
- package/dist/adapter/resources/webgpu-shader.d.ts +21 -0
- package/dist/adapter/resources/webgpu-shader.d.ts.map +1 -0
- package/dist/adapter/resources/webgpu-shader.js +64 -0
- package/dist/adapter/resources/webgpu-shader.js.map +1 -0
- package/dist/adapter/resources/webgpu-texture.d.ts +39 -0
- package/dist/adapter/resources/webgpu-texture.d.ts.map +1 -0
- package/dist/adapter/resources/webgpu-texture.js +111 -0
- package/dist/adapter/resources/webgpu-texture.js.map +1 -0
- package/dist/adapter/webgpu-canvas-context.d.ts +32 -0
- package/dist/adapter/webgpu-canvas-context.d.ts.map +1 -0
- package/dist/adapter/webgpu-canvas-context.js +95 -0
- package/dist/adapter/webgpu-canvas-context.js.map +1 -0
- package/dist/adapter/webgpu-device.d.ts +67 -0
- package/dist/adapter/webgpu-device.d.ts.map +1 -0
- package/dist/adapter/webgpu-device.js +225 -0
- package/dist/adapter/webgpu-device.js.map +1 -0
- package/dist/adapter/webgpu-types.d.ts +1 -0
- package/dist/adapter/webgpu-types.d.ts.map +1 -0
- package/dist/adapter/webgpu-types.js +2 -0
- package/dist/adapter/webgpu-types.js.map +1 -0
- package/dist/bundle.d.ts +2 -0
- package/dist/bundle.d.ts.map +1 -0
- package/dist/bundle.js +5 -0
- package/dist/bundle.js.map +1 -0
- package/dist/glsl/glsllang.d.ts +3 -0
- package/dist/glsl/glsllang.d.ts.map +1 -0
- package/dist/glsl/glsllang.js +10 -0
- package/dist/glsl/glsllang.js.map +1 -0
- package/dist/index.d.ts +8 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +8 -0
- package/dist/index.js.map +1 -0
- package/dist/init.d.ts +2 -0
- package/dist/init.d.ts.map +1 -0
- package/dist/init.js +4 -0
- package/dist/init.js.map +1 -0
- package/package.json +36 -0
- package/src/adapter/helpers/accessor-to-format.ts +101 -0
- package/src/adapter/helpers/convert-texture-format.ts +10 -0
- package/src/adapter/helpers/generate-mipmaps.ts +107 -0
- package/src/adapter/helpers/get-bind-group.ts +82 -0
- package/src/adapter/helpers/get-vertex-buffer-layout.ts +123 -0
- package/src/adapter/helpers/webgpu-parameters.ts +226 -0
- package/src/adapter/resources/webgpu-buffer.ts +96 -0
- package/src/adapter/resources/webgpu-command-encoder.ts +111 -0
- package/src/adapter/resources/webgpu-compute-pass.ts +74 -0
- package/src/adapter/resources/webgpu-compute-pipeline.ts +34 -0
- package/src/adapter/resources/webgpu-external-texture.ts +37 -0
- package/src/adapter/resources/webgpu-framebuffer.ts +120 -0
- package/src/adapter/resources/webgpu-query.ts +43 -0
- package/src/adapter/resources/webgpu-render-pass.ts +128 -0
- package/src/adapter/resources/webgpu-render-pipeline.ts +231 -0
- package/src/adapter/resources/webgpu-sampler.ts +25 -0
- package/src/adapter/resources/webgpu-shader.ts +72 -0
- package/src/adapter/resources/webgpu-texture.ts +243 -0
- package/src/adapter/webgpu-canvas-context.ts +102 -0
- package/src/adapter/webgpu-device.ts +282 -0
- package/src/adapter/webgpu-types.ts +0 -0
- package/src/bundle.ts +4 -0
- package/src/glsl/glsllang.ts +14 -0
- package/src/index.ts +13 -0
- package/src/init.ts +4 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"glsllang.d.ts","sourceRoot":"","sources":["../../src/glsl/glsllang.ts"],"names":[],"mappings":"AAKA,yCAAyC;AACzC,wBAAsB,iBAAiB,qBAOtC"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
let glslang;
|
|
2
|
+
export async function loadGlslangModule() {
|
|
3
|
+
if (!glslang) {
|
|
4
|
+
const glslangModule = await import('https://unpkg.com/@webgpu/glslang@0.0.15/dist/web-devel/glslang.js');
|
|
5
|
+
glslang = await glslangModule.default();
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
return glslang;
|
|
9
|
+
}
|
|
10
|
+
//# sourceMappingURL=glsllang.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/glsl/glsllang.ts"],"names":["glslang","loadGlslangModule","glslangModule","default"],"mappings":"AAGA,IAAIA,OAAJ;AAGA,OAAO,eAAeC,iBAAf,GAAmC;AACxC,MAAI,CAACD,OAAL,EAAc;AAEZ,UAAME,aAAa,GAAG,MAAM,OAAiC,oEAAjC,CAA5B;AACAF,IAAAA,OAAO,GAAG,MAAME,aAAa,CAACC,OAAd,EAAhB;AACD;;AACD,SAAOH,OAAP;AACD","sourcesContent":["// Inspired by webgpu samples at https://github.com/austinEng/webgpu-samples/blob/master/src/glslang.ts\n// under BSD 3-clause license\n\nlet glslang: unknown;\n\n/** Dynamically load the GLSL compiler */\nexport async function loadGlslangModule() {\n if (!glslang) {\n // @ts-ignore\n const glslangModule = await import(/* webpackIgnore: true */ 'https://unpkg.com/@webgpu/glslang@0.0.15/dist/web-devel/glslang.js');\n glslang = await glslangModule.default();\n }\n return glslang;\n}\n"],"file":"glsllang.js"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import '@luma.gl/api';
|
|
2
|
+
import './init';
|
|
3
|
+
export { default as WebGPUDevice } from './adapter/webgpu-device';
|
|
4
|
+
export { default as WebGPUBuffer } from './adapter/resources/webgpu-buffer';
|
|
5
|
+
export { default as WebGPUTexture } from './adapter/resources/webgpu-texture';
|
|
6
|
+
export { default as WebGPUSampler } from './adapter/resources/webgpu-sampler';
|
|
7
|
+
export { default as WebGPUShader } from './adapter/resources/webgpu-shader';
|
|
8
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAEA,OAAO,cAAc,CAAC;AACtB,OAAO,QAAQ,CAAA;AAGf,OAAO,EAAC,OAAO,IAAI,YAAY,EAAC,MAAM,yBAAyB,CAAC;AAGhE,OAAO,EAAC,OAAO,IAAI,YAAY,EAAC,MAAM,mCAAmC,CAAC;AAC1E,OAAO,EAAC,OAAO,IAAI,aAAa,EAAC,MAAM,oCAAoC,CAAC;AAC5E,OAAO,EAAC,OAAO,IAAI,aAAa,EAAC,MAAM,oCAAoC,CAAC;AAC5E,OAAO,EAAC,OAAO,IAAI,YAAY,EAAC,MAAM,mCAAmC,CAAC"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import '@luma.gl/api';
|
|
2
|
+
import './init';
|
|
3
|
+
export { default as WebGPUDevice } from './adapter/webgpu-device';
|
|
4
|
+
export { default as WebGPUBuffer } from './adapter/resources/webgpu-buffer';
|
|
5
|
+
export { default as WebGPUTexture } from './adapter/resources/webgpu-texture';
|
|
6
|
+
export { default as WebGPUSampler } from './adapter/resources/webgpu-sampler';
|
|
7
|
+
export { default as WebGPUShader } from './adapter/resources/webgpu-shader';
|
|
8
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/index.ts"],"names":["default","WebGPUDevice","WebGPUBuffer","WebGPUTexture","WebGPUSampler","WebGPUShader"],"mappings":"AAEA,OAAO,cAAP;AACA,OAAO,QAAP;AAGA,SAAQA,OAAO,IAAIC,YAAnB,QAAsC,yBAAtC;AAGA,SAAQD,OAAO,IAAIE,YAAnB,QAAsC,mCAAtC;AACA,SAAQF,OAAO,IAAIG,aAAnB,QAAuC,oCAAvC;AACA,SAAQH,OAAO,IAAII,aAAnB,QAAuC,oCAAvC;AACA,SAAQJ,OAAO,IAAIK,YAAnB,QAAsC,mCAAtC","sourcesContent":["\n// Initialize any global state\nimport '@luma.gl/api';\nimport './init'\n\n// WEBGPU ADAPTER\nexport {default as WebGPUDevice} from './adapter/webgpu-device';\n\n// WEBGPU CLASSES (typically not accessed directly)\nexport {default as WebGPUBuffer} from './adapter/resources/webgpu-buffer';\nexport {default as WebGPUTexture} from './adapter/resources/webgpu-texture';\nexport {default as WebGPUSampler} from './adapter/resources/webgpu-sampler';\nexport {default as WebGPUShader} from './adapter/resources/webgpu-shader';\n"],"file":"index.js"}
|
package/dist/init.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"init.d.ts","sourceRoot":"","sources":["../src/init.ts"],"names":[],"mappings":""}
|
package/dist/init.js
ADDED
package/dist/init.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/init.ts"],"names":["luma","WebGPUDevice","registerDevices"],"mappings":"AAAA,SAAQA,IAAR,QAAmB,cAAnB;AACA,OAAOC,YAAP,MAAyB,yBAAzB;AAEAD,IAAI,CAACE,eAAL,CAAqB,CAACD,YAAD,CAArB","sourcesContent":["import {luma} from '@luma.gl/api';\nimport WebGPUDevice from './adapter/webgpu-device';\n\nluma.registerDevices([WebGPUDevice]);\n"],"file":"init.js"}
|
package/package.json
ADDED
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@luma.gl/webgpu",
|
|
3
|
+
"version": "9.0.0-alpha.2",
|
|
4
|
+
"description": "WebGPU adapter for the luma.gl API",
|
|
5
|
+
"license": "MIT",
|
|
6
|
+
"repository": {
|
|
7
|
+
"type": "git",
|
|
8
|
+
"url": "https://github.com/visgl/luma.gl"
|
|
9
|
+
},
|
|
10
|
+
"keywords": [
|
|
11
|
+
"webgpu",
|
|
12
|
+
"visualization",
|
|
13
|
+
"animation",
|
|
14
|
+
"3d"
|
|
15
|
+
],
|
|
16
|
+
"types": "src/index.ts",
|
|
17
|
+
"main": "dist/index.js",
|
|
18
|
+
"module": "dist/index.js",
|
|
19
|
+
"files": [
|
|
20
|
+
"src",
|
|
21
|
+
"dist",
|
|
22
|
+
"README.md"
|
|
23
|
+
],
|
|
24
|
+
"sideEffects": false,
|
|
25
|
+
"scripts": {
|
|
26
|
+
"pre-build": "npm run build-bundle && npm run build-bundle -- --env.dev",
|
|
27
|
+
"build-bundle": "webpack --display=minimal --config ../../scripts/bundle.config.js"
|
|
28
|
+
},
|
|
29
|
+
"dependencies": {
|
|
30
|
+
"@babel/runtime": "^7.0.0",
|
|
31
|
+
"@luma.gl/api": "9.0.0-alpha.2",
|
|
32
|
+
"@webgpu/types": "^0.1.9",
|
|
33
|
+
"probe.gl": "^3.2.1"
|
|
34
|
+
},
|
|
35
|
+
"gitHead": "81e93840f31f0e32f86dfea6b576acf2c2d9caec"
|
|
36
|
+
}
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
/*
|
|
2
|
+
import {assert} from '@luma.gl/api';
|
|
3
|
+
import GL from '@luma.gl/constants';
|
|
4
|
+
|
|
5
|
+
type Accessor = Record<string, any>;
|
|
6
|
+
|
|
7
|
+
const FORMAT_TO_ACCESSOR: Record<GPUVertexFormat, Accessor> = {
|
|
8
|
+
uchar2: {type: 'uchar', size: 2},
|
|
9
|
+
uchar4: {type: 'uchar', size: 4},
|
|
10
|
+
char2: {type: 'char', size: 2},
|
|
11
|
+
char4: {type: 'char', size: 4},
|
|
12
|
+
uchar2norm: {type: 'uchar', size: 2, normalized: true},
|
|
13
|
+
uchar4norm: {type: 'uchar', size: 4, normalized: true},
|
|
14
|
+
char2norm: {type: 'char', size: 2, normalized: true},
|
|
15
|
+
char4norm: {type: 'char', size: 4, normalized: true},
|
|
16
|
+
ushort2: {type: 'ushort', size: 2},
|
|
17
|
+
ushort4: {type: 'ushort', size: 4},
|
|
18
|
+
short2: {type: 'short', size: 2},
|
|
19
|
+
short4: {type: 'short', size: 4},
|
|
20
|
+
ushort2norm: {type: 'ushort', size: 2, normalized: true},
|
|
21
|
+
ushort4norm: {type: 'ushort', size: 4, normalized: true},
|
|
22
|
+
short2norm: {type: 'short', size: 1, normalized: true},
|
|
23
|
+
short4norm: {type: 'short', size: 1, normalized: true},
|
|
24
|
+
half2: {type: 'half', size: 2},
|
|
25
|
+
half4: {type: 'half', size: 4},
|
|
26
|
+
float: {type: 'float', size: 1},
|
|
27
|
+
float2: {type: 'float', size: 2},
|
|
28
|
+
float3: {type: 'float', size: 3},
|
|
29
|
+
float4: {type: 'float', size: 4},
|
|
30
|
+
uint: {type: 'uint', size: 1, integer: true},
|
|
31
|
+
uint2: {type: 'uint', size: 2, integer: true},
|
|
32
|
+
uint3: {type: 'uint', size: 3, integer: true},
|
|
33
|
+
uint4: {type: 'uint', size: 4, integer: true},
|
|
34
|
+
int: {type: 'int', size: 1, integer: true},
|
|
35
|
+
int2: {type: 'int', size: 2, integer: true},
|
|
36
|
+
int3: {type: 'int', size: 3, integer: true},
|
|
37
|
+
int4: {type: 'int', size: 4, integer: true}
|
|
38
|
+
};
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* Convert from WebGPU attribute format strings to accessor {type, size, normalized, integer}
|
|
42
|
+
* @param {*} format
|
|
43
|
+
*
|
|
44
|
+
export function mapWebGPUFormatToAccessor(format) {
|
|
45
|
+
const accessorDefinition = FORMAT_TO_ACCESSOR[format];
|
|
46
|
+
assert(accessorDefinition, 'invalid attribute format');
|
|
47
|
+
return Object.freeze(accessorDefinition);
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* Convert from accessor {type, size, normalized, integer} to WebGPU attribute format strings
|
|
52
|
+
* @param {*} format
|
|
53
|
+
*
|
|
54
|
+
export function mapAccessorToWebGPUFormat(accessor) {
|
|
55
|
+
const {type = GL.FLOAT, size = 1, normalized = false, integer = false} = accessor;
|
|
56
|
+
assert(size >=1 && size <=4);
|
|
57
|
+
// `norm` suffix (uchar4norm)
|
|
58
|
+
const norm = normalized ? 'norm' : '';
|
|
59
|
+
// size 1 is ommitted in format names (float vs float2)
|
|
60
|
+
const count = size === 1 ? '' : size;
|
|
61
|
+
switch (type) {
|
|
62
|
+
case GL.UNSIGNED_BYTE:
|
|
63
|
+
switch (size) {
|
|
64
|
+
case 2:
|
|
65
|
+
case 4:
|
|
66
|
+
return `uchar${count}${norm}`;
|
|
67
|
+
}
|
|
68
|
+
case GL.BYTE:
|
|
69
|
+
switch (size) {
|
|
70
|
+
case 2:
|
|
71
|
+
case 4:
|
|
72
|
+
return `char${count}${norm}`;
|
|
73
|
+
}
|
|
74
|
+
case GL.UNSIGNED_SHORT:
|
|
75
|
+
switch (size) {
|
|
76
|
+
case 2:
|
|
77
|
+
case 4:
|
|
78
|
+
return `ushort${count}${norm}`;
|
|
79
|
+
}
|
|
80
|
+
case GL.SHORT:
|
|
81
|
+
switch (size) {
|
|
82
|
+
case 2:
|
|
83
|
+
case 4:
|
|
84
|
+
return `short${count}${norm}`;
|
|
85
|
+
}
|
|
86
|
+
case GL.HALF_FLOAT:
|
|
87
|
+
switch (size) {
|
|
88
|
+
case 2:
|
|
89
|
+
case 4:
|
|
90
|
+
return `half${count}`;
|
|
91
|
+
}
|
|
92
|
+
case GL.FLOAT:
|
|
93
|
+
return `float${count}`;
|
|
94
|
+
case GL.UNSIGNED_INT:
|
|
95
|
+
return `uint${count}`;
|
|
96
|
+
case GL.INT:
|
|
97
|
+
return `int${count}`;
|
|
98
|
+
}
|
|
99
|
+
throw new Error('illegal accessor');
|
|
100
|
+
}
|
|
101
|
+
*/
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
// luma.gl, MIT license
|
|
2
|
+
import {TextureFormat} from '@luma.gl/api';
|
|
3
|
+
|
|
4
|
+
/** Ensure a texture format is WebGPU compatible */
|
|
5
|
+
export function getWebGPUTextureFormat(format: TextureFormat): GPUTextureFormat {
|
|
6
|
+
if (format.includes('webgl')) {
|
|
7
|
+
throw new Error('webgl-only format');
|
|
8
|
+
}
|
|
9
|
+
return format as GPUTextureFormat;
|
|
10
|
+
}
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
// luma.gl, MIT license
|
|
2
|
+
// Forked from Kangz/mipmapper.js under MIT license Copyright 2020 Brandon Jones
|
|
3
|
+
// https://gist.github.com/Kangz/782d5f1ae502daf53910a13f55db2f83
|
|
4
|
+
|
|
5
|
+
// @ts-nocheck this is written against outdated WebGPU API, needs an update pass
|
|
6
|
+
|
|
7
|
+
const VS_GEN_MIPMAP = `\#version 450
|
|
8
|
+
const vec2 pos[4] = vec2[4](vec2(-1.0f, 1.0f), vec2(1.0f, 1.0f), vec2(-1.0f, -1.0f), vec2(1.0f, -1.0f));
|
|
9
|
+
layout(location = 0) out vec2 vTex;
|
|
10
|
+
void main() {
|
|
11
|
+
gl_Position = vec4(pos[gl_VertexIndex], 0.0, 1.0);
|
|
12
|
+
vTex = gl_Position / 2.0f + vec2(0.5f);
|
|
13
|
+
}`;
|
|
14
|
+
|
|
15
|
+
const FS_GEN_MIPMAP = `#version 450
|
|
16
|
+
layout(set = 0, binding = 0) uniform sampler imgSampler;
|
|
17
|
+
layout(set = 0, binding = 1) uniform texture2D img;
|
|
18
|
+
layout(location = 0) in vec2 vTex;
|
|
19
|
+
layout(location = 0) out vec4 outColor;
|
|
20
|
+
void main() {
|
|
21
|
+
outColor = texture(sampler2D(img, imgSampler), vTex);
|
|
22
|
+
}`;
|
|
23
|
+
|
|
24
|
+
/** WebGPU does not have built-in mipmap creation */
|
|
25
|
+
export class WebGPUMipmapGenerator {
|
|
26
|
+
device: GPUDevice;
|
|
27
|
+
mipmapSampler: GPUSampler;
|
|
28
|
+
mipmapPipeline: GPURenderPipeline;
|
|
29
|
+
|
|
30
|
+
constructor(device: GPUDevice, glslang) {
|
|
31
|
+
this.device = device;
|
|
32
|
+
|
|
33
|
+
this.mipmapSampler = device.createSampler({ minFilter: 'linear' });
|
|
34
|
+
|
|
35
|
+
this.mipmapPipeline = device.createRenderPipeline({
|
|
36
|
+
vertexStage: {
|
|
37
|
+
module: device.createShaderModule({
|
|
38
|
+
code: glslang.compileGLSL(VS_GEN_MIPMAP, 'vertex')
|
|
39
|
+
}),
|
|
40
|
+
entryPoint: 'main'
|
|
41
|
+
},
|
|
42
|
+
fragmentStage: {
|
|
43
|
+
module: device.createShaderModule({
|
|
44
|
+
code: glslang.compileGLSL(FS_GEN_MIPMAP, 'fragment')
|
|
45
|
+
}),
|
|
46
|
+
entryPoint: 'main'
|
|
47
|
+
},
|
|
48
|
+
primitiveTopology: 'triangle-strip',
|
|
49
|
+
colorStates: [{
|
|
50
|
+
format: 'rgba8unorm',
|
|
51
|
+
}]
|
|
52
|
+
});
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
generateMipmappedTexture(imageBitmap: ImageBitmap) {
|
|
56
|
+
let textureSize = {
|
|
57
|
+
width: imageBitmap.width,
|
|
58
|
+
height: imageBitmap.height,
|
|
59
|
+
depth: 1,
|
|
60
|
+
}
|
|
61
|
+
const mipLevelCount = Math.floor(Math.log2(Math.max(imageBitmap.width, imageBitmap.height))) + 1;
|
|
62
|
+
|
|
63
|
+
// Populate the top level of the srcTexture with the imageBitmap.
|
|
64
|
+
const texture = this.device.createTexture({
|
|
65
|
+
size: textureSize,
|
|
66
|
+
format: 'rgba8unorm',
|
|
67
|
+
usage: GPUTextureUsage.COPY_DST | GPUTextureUsage.SAMPLED | GPUTextureUsage.OUTPUT_ATTACHMENT,
|
|
68
|
+
mipLevelCount
|
|
69
|
+
});
|
|
70
|
+
this.device.queue.copyImageBitmapToTexture({ imageBitmap }, { texture: srcTexture }, textureSize);
|
|
71
|
+
|
|
72
|
+
const commandEncoder = this.device.createCommandEncoder({});
|
|
73
|
+
for (let i = 1; i < mipLevelCount; ++i) {
|
|
74
|
+
const passEncoder = commandEncoder.beginRenderPass({
|
|
75
|
+
colorAttachments: [{
|
|
76
|
+
attachment: texture.createView({
|
|
77
|
+
baseMipLevel: i,
|
|
78
|
+
mipLevelCount: 1
|
|
79
|
+
}),
|
|
80
|
+
loadValue: { r: 1.0, g: 0.0, b: 0.0, a: 0.0 },
|
|
81
|
+
}],
|
|
82
|
+
});
|
|
83
|
+
|
|
84
|
+
const bindGroup = this.device.createBindGroup({
|
|
85
|
+
layout: this.mipmapPipeline.getBindGroupLayout(0),
|
|
86
|
+
bindings: [{
|
|
87
|
+
binding: 0,
|
|
88
|
+
resource: this.mipmapSampler,
|
|
89
|
+
}, {
|
|
90
|
+
binding: 1,
|
|
91
|
+
resource: texture.createView({
|
|
92
|
+
baseMipLevel: i - 1,
|
|
93
|
+
mipLevelCount: 1
|
|
94
|
+
}),
|
|
95
|
+
}],
|
|
96
|
+
});
|
|
97
|
+
|
|
98
|
+
passEncoder.setPipeline(this.mipmapPipeline);
|
|
99
|
+
passEncoder.setBindGroup(0, bindGroup);
|
|
100
|
+
passEncoder.draw(4);
|
|
101
|
+
passEncoder.endPass();
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
this.device.queue.submit([commandEncoder.finish()]);
|
|
105
|
+
return texture;
|
|
106
|
+
}
|
|
107
|
+
}
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
// luma.gl, MIT license
|
|
2
|
+
import type {ShaderLayout, BindingLayout, Binding} from '@luma.gl/api';
|
|
3
|
+
import {Buffer, Sampler, Texture, log, cast} from '@luma.gl/api';
|
|
4
|
+
import type WebGPUBuffer from '../resources/webgpu-buffer';
|
|
5
|
+
import type WebGPUSampler from '../resources/webgpu-sampler';
|
|
6
|
+
import type WebGPUTexture from '../resources/webgpu-texture';
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Create a WebGPU "bind group layout" from an array of luma.gl bindings
|
|
10
|
+
* @note bind groups can be automatically generated by WebGPU.
|
|
11
|
+
*/
|
|
12
|
+
export function makeBindGroupLayout(device: GPUDevice, layout: GPUBindGroupLayout, bindings: Binding[]): GPUBindGroupLayout {
|
|
13
|
+
throw new Error('not implemented');
|
|
14
|
+
// return device.createBindGroupLayout({
|
|
15
|
+
// layout,
|
|
16
|
+
// entries: getBindGroupEntries(bindings)
|
|
17
|
+
// })
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* Create a WebGPU "bind group" from an array of luma.gl bindings
|
|
22
|
+
*/
|
|
23
|
+
export function getBindGroup(
|
|
24
|
+
device: GPUDevice,
|
|
25
|
+
bindGroupLayout: GPUBindGroupLayout,
|
|
26
|
+
layout: ShaderLayout,
|
|
27
|
+
bindings: Record<string, Binding>
|
|
28
|
+
): GPUBindGroup {
|
|
29
|
+
const entries = getBindGroupEntries(bindings, layout);
|
|
30
|
+
return device.createBindGroup({
|
|
31
|
+
layout: bindGroupLayout,
|
|
32
|
+
entries
|
|
33
|
+
});
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
export function getShaderLayoutBinding(layout: ShaderLayout, bindingName: string): BindingLayout {
|
|
37
|
+
const bindingLayout = layout.bindings.find(binding => binding.name === bindingName);
|
|
38
|
+
if (!bindingLayout) {
|
|
39
|
+
log.warn(`Binding ${bindingName} not set: Not found in shader layout.`)();
|
|
40
|
+
}
|
|
41
|
+
return bindingLayout;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* @param bindings
|
|
46
|
+
* @returns
|
|
47
|
+
*/
|
|
48
|
+
function getBindGroupEntries(bindings: Record<string, Binding>, layout: ShaderLayout): GPUBindGroupEntry[] {
|
|
49
|
+
const entries: GPUBindGroupEntry[] = [];
|
|
50
|
+
|
|
51
|
+
for (const [bindingName, value] of Object.entries(bindings)) {
|
|
52
|
+
const bindingLayout = getShaderLayoutBinding(layout, bindingName);
|
|
53
|
+
if (bindingLayout) {
|
|
54
|
+
entries.push(getBindGroupEntry(value, bindingLayout.location));
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
return entries;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
function getBindGroupEntry(binding: Binding, index: number): GPUBindGroupEntry {
|
|
62
|
+
if (binding instanceof Buffer) {
|
|
63
|
+
return {
|
|
64
|
+
binding: index,
|
|
65
|
+
resource: {
|
|
66
|
+
buffer: cast<WebGPUBuffer>(binding).handle
|
|
67
|
+
}
|
|
68
|
+
};
|
|
69
|
+
}
|
|
70
|
+
if (binding instanceof Sampler) {
|
|
71
|
+
return {
|
|
72
|
+
binding: index,
|
|
73
|
+
resource: cast<WebGPUSampler>(binding).handle
|
|
74
|
+
};
|
|
75
|
+
} else if (binding instanceof Texture) {
|
|
76
|
+
return {
|
|
77
|
+
binding: index,
|
|
78
|
+
resource: cast<WebGPUTexture>(binding).handle.createView()
|
|
79
|
+
};
|
|
80
|
+
}
|
|
81
|
+
throw new Error('invalid binding');
|
|
82
|
+
}
|
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
import type {ShaderLayout, BufferMapping, AttributeLayout} from '@luma.gl/api';
|
|
2
|
+
import {decodeVertexFormat} from '@luma.gl/api';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Build a WebGPU vertex buffer layout intended for use in a GPURenderPassDescriptor.
|
|
6
|
+
* Converts luma.gl attribute definitions to a WebGPU GPUVertexBufferLayout[] array
|
|
7
|
+
* @param layout
|
|
8
|
+
* @param bufferMap The buffer map is optional
|
|
9
|
+
* @returns WebGPU layout intended for a GPURenderPassDescriptor.
|
|
10
|
+
*/
|
|
11
|
+
export function getVertexBufferLayout(layout: ShaderLayout, bufferMap: BufferMapping[]): GPUVertexBufferLayout[] {
|
|
12
|
+
const vertexBufferLayouts: GPUVertexBufferLayout[] = [];
|
|
13
|
+
const usedAttributes = new Set<string>();
|
|
14
|
+
|
|
15
|
+
// First handle any buffers mentioned in `bufferMapping`
|
|
16
|
+
for (const mapping of bufferMap) {
|
|
17
|
+
// Build vertex attributes for one buffer
|
|
18
|
+
const vertexAttributes: GPUVertexAttribute[] = [];
|
|
19
|
+
|
|
20
|
+
// TODO verify that all stepModes for one buffer are the same
|
|
21
|
+
let stepMode: 'vertex' | 'instance' = 'vertex';
|
|
22
|
+
let byteStride = 0;
|
|
23
|
+
let byteOffset = mapping.byteOffset || 0;
|
|
24
|
+
|
|
25
|
+
// interleaved mapping {..., attributes: [{...}, ...]}
|
|
26
|
+
if ('attributes' in mapping) {
|
|
27
|
+
const arrayStride = mapping.byteStride;
|
|
28
|
+
for (const interleaved of mapping.attributes) {
|
|
29
|
+
const attributeLayout = findAttributeLayout(layout, interleaved.name, usedAttributes);
|
|
30
|
+
|
|
31
|
+
stepMode = attributeLayout.stepMode || 'vertex';
|
|
32
|
+
vertexAttributes.push({
|
|
33
|
+
format: attributeLayout.format,
|
|
34
|
+
offset: byteOffset + byteStride,
|
|
35
|
+
shaderLocation: attributeLayout.location
|
|
36
|
+
});
|
|
37
|
+
|
|
38
|
+
byteStride += decodeVertexFormat(attributeLayout.format).byteLength;
|
|
39
|
+
}
|
|
40
|
+
// non-interleaved mapping (just set offset and stride)
|
|
41
|
+
} else {
|
|
42
|
+
const attributeLayout = findAttributeLayout(layout, mapping.name, usedAttributes);
|
|
43
|
+
byteStride = decodeVertexFormat(attributeLayout.format).byteLength,
|
|
44
|
+
|
|
45
|
+
stepMode = attributeLayout.stepMode || 'vertex';
|
|
46
|
+
vertexAttributes.push({
|
|
47
|
+
format: attributeLayout.format,
|
|
48
|
+
offset: byteOffset,
|
|
49
|
+
shaderLocation: attributeLayout.location
|
|
50
|
+
});
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
// Store all the attribute bindings for one buffer
|
|
54
|
+
vertexBufferLayouts.push({
|
|
55
|
+
arrayStride: mapping.byteStride || byteStride,
|
|
56
|
+
stepMode: stepMode || 'vertex',
|
|
57
|
+
attributes: vertexAttributes
|
|
58
|
+
});
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
// Add any non-mapped attributes
|
|
62
|
+
for (const attribute of layout.attributes) {
|
|
63
|
+
if (!usedAttributes.has(attribute.name)) {
|
|
64
|
+
vertexBufferLayouts.push({
|
|
65
|
+
arrayStride: decodeVertexFormat(attribute.format).byteLength,
|
|
66
|
+
stepMode: attribute.stepMode || 'vertex',
|
|
67
|
+
attributes: [{
|
|
68
|
+
format: attribute.format,
|
|
69
|
+
offset: 0,
|
|
70
|
+
shaderLocation: attribute.location
|
|
71
|
+
}]
|
|
72
|
+
});
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
return vertexBufferLayouts;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
export function getBufferSlots(layout: ShaderLayout, bufferMap: BufferMapping[]): Record<string, number> {
|
|
80
|
+
const usedAttributes = new Set<string>();
|
|
81
|
+
let bufferSlot = 0;
|
|
82
|
+
const bufferSlots: Record<string, number> = {};
|
|
83
|
+
|
|
84
|
+
// First handle any buffers mentioned in `bufferMapping`
|
|
85
|
+
for (const mapping of bufferMap) {
|
|
86
|
+
// interleaved mapping {..., attributes: [{...}, ...]}
|
|
87
|
+
if ('attributes' in mapping) {
|
|
88
|
+
for (const interleaved of mapping.attributes) {
|
|
89
|
+
usedAttributes.add(interleaved.name);
|
|
90
|
+
}
|
|
91
|
+
// non-interleaved mapping (just set offset and stride)
|
|
92
|
+
} else {
|
|
93
|
+
usedAttributes.add(mapping.name);
|
|
94
|
+
}
|
|
95
|
+
bufferSlots[mapping.name] = bufferSlot++;
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
// Add any non-mapped attributes
|
|
99
|
+
for (const attribute of layout.attributes) {
|
|
100
|
+
if (!usedAttributes.has(attribute.name)) {
|
|
101
|
+
bufferSlots[attribute.name] = bufferSlot++;
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
return bufferSlots;
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
/**
|
|
109
|
+
* Looks up an attribute in the ShaderLayout.
|
|
110
|
+
* @throws if name is not in ShaderLayout
|
|
111
|
+
* @throws if name has already been referenced
|
|
112
|
+
*/
|
|
113
|
+
function findAttributeLayout(layout: ShaderLayout, name: string, attributeNames: Set<string>): AttributeLayout {
|
|
114
|
+
const attribute = layout.attributes.find(attribute => attribute.name === name);
|
|
115
|
+
if (!attribute) {
|
|
116
|
+
throw new Error(`Unknown attribute ${name}`);
|
|
117
|
+
}
|
|
118
|
+
if (attributeNames.has(name)) {
|
|
119
|
+
throw new Error(`Duplicate attribute ${name}`);
|
|
120
|
+
}
|
|
121
|
+
attributeNames.add(name);
|
|
122
|
+
return attribute;
|
|
123
|
+
}
|