@luma.gl/engine 9.0.0-alpha.9 → 9.0.0-beta.10
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/LICENSE +3 -1
- package/dist/animation/key-frames.d.ts +1 -1
- package/dist/animation/key-frames.d.ts.map +1 -1
- package/dist/animation/key-frames.js +51 -72
- package/dist/animation/timeline.d.ts +8 -8
- package/dist/animation/timeline.d.ts.map +1 -1
- package/dist/animation/timeline.js +95 -131
- package/dist/animation-loop/animation-loop-template.d.ts +23 -0
- package/dist/animation-loop/animation-loop-template.d.ts.map +1 -0
- package/dist/animation-loop/animation-loop-template.js +21 -0
- package/dist/{lib → animation-loop}/animation-loop.d.ts +31 -23
- package/dist/animation-loop/animation-loop.d.ts.map +1 -0
- package/dist/animation-loop/animation-loop.js +442 -0
- package/dist/{lib → animation-loop}/animation-props.d.ts +4 -5
- package/dist/animation-loop/animation-props.d.ts.map +1 -0
- package/dist/animation-loop/animation-props.js +1 -0
- package/dist/animation-loop/make-animation-loop.d.ts +6 -0
- package/dist/animation-loop/make-animation-loop.d.ts.map +1 -0
- package/dist/animation-loop/make-animation-loop.js +32 -0
- package/dist/computation.d.ts +95 -0
- package/dist/computation.d.ts.map +1 -0
- package/dist/computation.js +248 -0
- package/dist/debug/copy-texture-to-image.d.ts +26 -0
- package/dist/debug/copy-texture-to-image.d.ts.map +1 -0
- package/dist/debug/copy-texture-to-image.js +43 -0
- package/dist/debug/debug-framebuffer.d.ts +11 -0
- package/dist/debug/debug-framebuffer.d.ts.map +1 -0
- package/dist/debug/debug-framebuffer.js +46 -0
- package/dist/debug/debug-shader-layout.d.ts +9 -0
- package/dist/debug/debug-shader-layout.d.ts.map +1 -0
- package/dist/debug/debug-shader-layout.js +27 -0
- package/dist/debug/pixel-data-utils.d.ts +24 -0
- package/dist/debug/pixel-data-utils.d.ts.map +1 -0
- package/dist/debug/pixel-data-utils.js +39 -0
- package/dist/dist.dev.js +9592 -0
- package/dist/dist.min.js +102 -0
- package/dist/geometries/cone-geometry.d.ts +2 -2
- package/dist/geometries/cone-geometry.d.ts.map +1 -1
- package/dist/geometries/cone-geometry.js +13 -18
- package/dist/geometries/cube-geometry.d.ts +2 -2
- package/dist/geometries/cube-geometry.d.ts.map +1 -1
- package/dist/geometries/cube-geometry.js +192 -57
- package/dist/geometries/cylinder-geometry.d.ts +2 -2
- package/dist/geometries/cylinder-geometry.d.ts.map +1 -1
- package/dist/geometries/cylinder-geometry.js +11 -15
- package/dist/geometries/ico-sphere-geometry.d.ts +2 -2
- package/dist/geometries/ico-sphere-geometry.d.ts.map +1 -1
- package/dist/geometries/ico-sphere-geometry.js +143 -171
- package/dist/geometries/plane-geometry.d.ts +2 -2
- package/dist/geometries/plane-geometry.d.ts.map +1 -1
- package/dist/geometries/plane-geometry.js +95 -122
- package/dist/geometries/sphere-geometry.d.ts +2 -2
- package/dist/geometries/sphere-geometry.d.ts.map +1 -1
- package/dist/geometries/sphere-geometry.js +78 -101
- package/dist/geometries/truncated-cone-geometry.d.ts +2 -4
- package/dist/geometries/truncated-cone-geometry.d.ts.map +1 -1
- package/dist/geometries/truncated-cone-geometry.js +100 -134
- package/dist/geometry/geometry-table.d.ts +2 -2
- package/dist/geometry/geometry-table.d.ts.map +1 -1
- package/dist/geometry/geometry-table.js +3 -1
- package/dist/geometry/geometry-utils.d.ts.map +1 -1
- package/dist/geometry/geometry-utils.js +35 -41
- package/dist/geometry/geometry.d.ts +43 -43
- package/dist/geometry/geometry.d.ts.map +1 -1
- package/dist/geometry/geometry.js +82 -139
- package/dist/geometry/gpu-geometry.d.ts +37 -0
- package/dist/geometry/gpu-geometry.d.ts.map +1 -0
- package/dist/geometry/gpu-geometry.js +90 -0
- package/dist/geometry/gpu-table.d.ts +1 -0
- package/dist/geometry/gpu-table.d.ts.map +1 -0
- package/dist/geometry/gpu-table.js +42 -0
- package/dist/index.cjs +3444 -0
- package/dist/index.cjs.map +7 -0
- package/dist/index.d.ts +43 -24
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +29 -15
- package/dist/lib/clip-space.d.ts +8 -0
- package/dist/lib/clip-space.d.ts.map +1 -1
- package/dist/lib/clip-space.js +43 -2
- package/dist/lib/pipeline-factory.d.ts +17 -51
- package/dist/lib/pipeline-factory.d.ts.map +1 -1
- package/dist/lib/pipeline-factory.js +84 -209
- package/dist/lib/shader-factory.d.ts +17 -0
- package/dist/lib/shader-factory.d.ts.map +1 -0
- package/dist/lib/shader-factory.js +46 -0
- package/dist/model/model.d.ts +219 -0
- package/dist/model/model.d.ts.map +1 -0
- package/dist/model/model.js +659 -0
- package/dist/scenegraph/group-node.d.ts +21 -0
- package/dist/scenegraph/group-node.d.ts.map +1 -0
- package/dist/scenegraph/group-node.js +84 -0
- package/dist/scenegraph/model-node.d.ts +18 -0
- package/dist/scenegraph/model-node.d.ts.map +1 -0
- package/dist/scenegraph/model-node.js +35 -0
- package/dist/scenegraph/scenegraph-node.d.ts +56 -0
- package/dist/scenegraph/scenegraph-node.d.ts.map +1 -0
- package/dist/scenegraph/scenegraph-node.js +153 -0
- package/dist/shader-inputs.d.ts +63 -0
- package/dist/shader-inputs.d.ts.map +1 -0
- package/dist/shader-inputs.js +107 -0
- package/dist/transform/buffer-transform.d.ts +35 -0
- package/dist/transform/buffer-transform.d.ts.map +1 -0
- package/dist/transform/buffer-transform.js +70 -0
- package/dist/transform/texture-transform.d.ts +57 -0
- package/dist/transform/texture-transform.d.ts.map +1 -0
- package/dist/transform/texture-transform.js +117 -0
- package/dist.min.js +25 -0
- package/package.json +24 -14
- package/src/animation/timeline.ts +35 -34
- package/src/animation-loop/animation-loop-template.ts +25 -0
- package/src/{lib → animation-loop}/animation-loop.ts +114 -93
- package/src/{lib → animation-loop}/animation-props.ts +2 -2
- package/src/animation-loop/make-animation-loop.ts +53 -0
- package/src/computation.ts +346 -0
- package/src/debug/copy-texture-to-image.ts +70 -0
- package/src/debug/debug-framebuffer.ts +70 -0
- package/src/debug/debug-shader-layout.ts +38 -0
- package/src/debug/pixel-data-utils.ts +54 -0
- package/src/geometries/cone-geometry.ts +1 -1
- package/src/geometries/cube-geometry.ts +62 -56
- package/src/geometries/cylinder-geometry.ts +2 -2
- package/src/geometries/ico-sphere-geometry.ts +6 -5
- package/src/geometries/plane-geometry.ts +5 -4
- package/src/geometries/sphere-geometry.ts +4 -3
- package/src/geometries/truncated-cone-geometry.ts +6 -14
- package/src/geometry/geometry-table.ts +10 -7
- package/src/geometry/geometry-utils.ts +19 -3
- package/src/geometry/geometry.ts +68 -110
- package/src/geometry/gpu-geometry.ts +132 -0
- package/src/geometry/gpu-table.ts +41 -0
- package/src/index.ts +37 -10
- package/src/lib/clip-space.ts +32 -34
- package/src/lib/pipeline-factory.ts +83 -193
- package/src/lib/shader-factory.ts +57 -0
- package/src/model/model.ts +835 -0
- package/src/scenegraph/group-node.ts +107 -0
- package/src/scenegraph/model-node.ts +50 -0
- package/src/scenegraph/scenegraph-node.ts +204 -0
- package/src/shader-inputs.ts +157 -0
- package/src/transform/buffer-transform.ts +102 -0
- package/src/transform/texture-transform.ts +168 -0
- package/dist/animation/key-frames.js.map +0 -1
- package/dist/animation/timeline.js.map +0 -1
- package/dist/bundle.d.ts +0 -2
- package/dist/bundle.d.ts.map +0 -1
- package/dist/bundle.js +0 -5
- package/dist/bundle.js.map +0 -1
- package/dist/geometries/cone-geometry.js.map +0 -1
- package/dist/geometries/cube-geometry.js.map +0 -1
- package/dist/geometries/cylinder-geometry.js.map +0 -1
- package/dist/geometries/ico-sphere-geometry.js.map +0 -1
- package/dist/geometries/plane-geometry.js.map +0 -1
- package/dist/geometries/sphere-geometry.js.map +0 -1
- package/dist/geometries/truncated-cone-geometry.js.map +0 -1
- package/dist/geometry/geometry-table.js.map +0 -1
- package/dist/geometry/geometry-utils.js.map +0 -1
- package/dist/geometry/geometry.js.map +0 -1
- package/dist/geometry/primitive-utils.d.ts +0 -1
- package/dist/geometry/primitive-utils.d.ts.map +0 -1
- package/dist/geometry/primitive-utils.js +0 -2
- package/dist/geometry/primitive-utils.js.map +0 -1
- package/dist/index.js.map +0 -1
- package/dist/lib/animation-loop.d.ts.map +0 -1
- package/dist/lib/animation-loop.js +0 -480
- package/dist/lib/animation-loop.js.map +0 -1
- package/dist/lib/animation-props.d.ts.map +0 -1
- package/dist/lib/animation-props.js +0 -2
- package/dist/lib/animation-props.js.map +0 -1
- package/dist/lib/clip-space.js.map +0 -1
- package/dist/lib/model-utils.d.ts +0 -5
- package/dist/lib/model-utils.d.ts.map +0 -1
- package/dist/lib/model-utils.js +0 -45
- package/dist/lib/model-utils.js.map +0 -1
- package/dist/lib/model.d.ts +0 -41
- package/dist/lib/model.d.ts.map +0 -1
- package/dist/lib/model.js +0 -182
- package/dist/lib/model.js.map +0 -1
- package/dist/lib/pipeline-factory.js.map +0 -1
- package/dist/lib/render-loop.d.ts +0 -14
- package/dist/lib/render-loop.d.ts.map +0 -1
- package/dist/lib/render-loop.js +0 -49
- package/dist/lib/render-loop.js.map +0 -1
- package/src/bundle.ts +0 -4
- package/src/geometry/primitive-utils.ts +0 -30
- package/src/lib/model-utils.ts +0 -124
- package/src/lib/model.ts +0 -183
- package/src/lib/render-loop.ts +0 -58
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
import type {PrimitiveTopology, BufferLayout} from '@luma.gl/core';
|
|
2
|
+
import {Device, Buffer, uid, assert, getVertexFormatFromAttribute} from '@luma.gl/core';
|
|
3
|
+
import type {Geometry} from '../geometry/geometry';
|
|
4
|
+
|
|
5
|
+
export type GPUGeometryProps = {
|
|
6
|
+
id?: string;
|
|
7
|
+
/** Determines how vertices are read from the 'vertex' attributes */
|
|
8
|
+
topology:
|
|
9
|
+
| 'point-list'
|
|
10
|
+
| 'line-list'
|
|
11
|
+
| 'line-strip'
|
|
12
|
+
| 'line-loop-webgl'
|
|
13
|
+
| 'triangle-list'
|
|
14
|
+
| 'triangle-strip'
|
|
15
|
+
| 'triangle-fan-webgl';
|
|
16
|
+
/** Auto calculated from attributes if not provided */
|
|
17
|
+
vertexCount: number;
|
|
18
|
+
bufferLayout: BufferLayout[];
|
|
19
|
+
indices?: Buffer | null;
|
|
20
|
+
attributes: Record<string, Buffer>;
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
export class GPUGeometry {
|
|
24
|
+
readonly id: string;
|
|
25
|
+
userData: Record<string, unknown> = {};
|
|
26
|
+
|
|
27
|
+
/** Determines how vertices are read from the 'vertex' attributes */
|
|
28
|
+
readonly topology?: PrimitiveTopology;
|
|
29
|
+
readonly bufferLayout: BufferLayout[] = [];
|
|
30
|
+
|
|
31
|
+
readonly vertexCount: number;
|
|
32
|
+
readonly indices?: Buffer | null;
|
|
33
|
+
readonly attributes: Record<string, Buffer>;
|
|
34
|
+
|
|
35
|
+
constructor(props: GPUGeometryProps) {
|
|
36
|
+
this.id = props.id || uid('geometry');
|
|
37
|
+
this.topology = props.topology;
|
|
38
|
+
this.indices = props.indices || null;
|
|
39
|
+
this.attributes = props.attributes;
|
|
40
|
+
|
|
41
|
+
this.vertexCount = props.vertexCount;
|
|
42
|
+
|
|
43
|
+
this.bufferLayout = props.bufferLayout || [];
|
|
44
|
+
|
|
45
|
+
if (this.indices) {
|
|
46
|
+
assert(this.indices.usage === Buffer.INDEX);
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
destroy(): void {
|
|
51
|
+
this.indices?.destroy();
|
|
52
|
+
for (const attribute of Object.values(this.attributes)) {
|
|
53
|
+
attribute.destroy();
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
getVertexCount(): number {
|
|
58
|
+
return this.vertexCount;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
getAttributes(): Record<string, Buffer> {
|
|
62
|
+
return this.attributes;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
getIndexes(): Buffer | null {
|
|
66
|
+
return this.indices;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
_calculateVertexCount(positions: Buffer): number {
|
|
70
|
+
// Assume that positions is a fully packed float32x3 buffer
|
|
71
|
+
const vertexCount = positions.byteLength / 12;
|
|
72
|
+
return vertexCount;
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
export function makeGPUGeometry(device: Device, geometry: Geometry | GPUGeometry): GPUGeometry {
|
|
77
|
+
if (geometry instanceof GPUGeometry) {
|
|
78
|
+
return geometry;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
const indices = getIndexBufferFromGeometry(device, geometry);
|
|
82
|
+
const {attributes, bufferLayout} = getAttributeBuffersFromGeometry(device, geometry);
|
|
83
|
+
return new GPUGeometry({
|
|
84
|
+
topology: geometry.topology || 'triangle-list',
|
|
85
|
+
bufferLayout,
|
|
86
|
+
vertexCount: geometry.vertexCount,
|
|
87
|
+
indices,
|
|
88
|
+
attributes
|
|
89
|
+
});
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
export function getIndexBufferFromGeometry(device: Device, geometry: Geometry): Buffer | undefined {
|
|
93
|
+
if (!geometry.indices) {
|
|
94
|
+
return undefined;
|
|
95
|
+
}
|
|
96
|
+
const data = geometry.indices.value;
|
|
97
|
+
return device.createBuffer({usage: Buffer.INDEX, data});
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
export function getAttributeBuffersFromGeometry(
|
|
101
|
+
device: Device,
|
|
102
|
+
geometry: Geometry
|
|
103
|
+
): {attributes: Record<string, Buffer>; bufferLayout: BufferLayout[]; vertexCount: number} {
|
|
104
|
+
const bufferLayout: BufferLayout[] = [];
|
|
105
|
+
|
|
106
|
+
const attributes: Record<string, Buffer> = {};
|
|
107
|
+
for (const [attributeName, attribute] of Object.entries(geometry.attributes)) {
|
|
108
|
+
let name: string = attributeName;
|
|
109
|
+
// TODO Map some GLTF attribute names (is this still needed?)
|
|
110
|
+
switch (attributeName) {
|
|
111
|
+
case 'POSITION':
|
|
112
|
+
name = 'positions';
|
|
113
|
+
break;
|
|
114
|
+
case 'NORMAL':
|
|
115
|
+
name = 'normals';
|
|
116
|
+
break;
|
|
117
|
+
case 'TEXCOORD_0':
|
|
118
|
+
name = 'texCoords';
|
|
119
|
+
break;
|
|
120
|
+
case 'COLOR_0':
|
|
121
|
+
name = 'colors';
|
|
122
|
+
break;
|
|
123
|
+
}
|
|
124
|
+
attributes[name] = device.createBuffer({data: attribute.value, id: `${attributeName}-buffer`});
|
|
125
|
+
const {value, size, normalized} = attribute;
|
|
126
|
+
bufferLayout.push({name, format: getVertexFormatFromAttribute(value, size, normalized)});
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
const vertexCount = geometry._calculateVertexCount(geometry.attributes, geometry.indices);
|
|
130
|
+
|
|
131
|
+
return {attributes, bufferLayout, vertexCount};
|
|
132
|
+
}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
/*
|
|
2
|
+
export function getAttributeLayoutsFromGeometry(geometry: Geometry) {
|
|
3
|
+
const layouts: Record<string, {}> = {};
|
|
4
|
+
let indices = geometry.indices;
|
|
5
|
+
|
|
6
|
+
for (const [name, attribute] of Object.entries(geometry.attributes)) {
|
|
7
|
+
const remappedName = mapAttributeName(name);
|
|
8
|
+
|
|
9
|
+
if (attribute.constant) {
|
|
10
|
+
throw new Error('constant attributes not supported');
|
|
11
|
+
} else {
|
|
12
|
+
const typedArray = attribute.value;
|
|
13
|
+
// Create accessor by copying the attribute and removing `value``
|
|
14
|
+
const accessor = {...attribute};
|
|
15
|
+
delete accessor.value;
|
|
16
|
+
buffers[remappedName] = [device.createBuffer(typedArray), accessor];
|
|
17
|
+
|
|
18
|
+
inferAttributeAccessor(name, accessor);
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export class Table {
|
|
24
|
+
length: number;
|
|
25
|
+
// columns: Record<string, TypedArray> = {};
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
export class GPUTable {
|
|
29
|
+
length: number;
|
|
30
|
+
columns: Record<string, Buffer> = {};
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
export function convertTableToGPUTable(table: Table) {
|
|
34
|
+
// for (const ) {}
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
export function renameTableColumns(table: Table, map: (name: string) => string) {
|
|
38
|
+
const newColumns = table.columns.reduce()
|
|
39
|
+
table.clone();
|
|
40
|
+
}
|
|
41
|
+
*/
|
package/src/index.ts
CHANGED
|
@@ -1,22 +1,44 @@
|
|
|
1
1
|
// luma.gl Engine API
|
|
2
|
-
export type {AnimationProps} from './lib/animation-props';
|
|
3
|
-
export type {AnimationLoopProps} from './lib/animation-loop';
|
|
4
|
-
export {AnimationLoop} from './lib/animation-loop';
|
|
5
|
-
export {RenderLoop} from './lib/render-loop';
|
|
6
|
-
export type {ModelProps} from './lib/model';
|
|
7
|
-
export {default as Model} from './lib/model';
|
|
8
|
-
|
|
9
|
-
export {PipelineFactory} from './lib/pipeline-factory';
|
|
10
2
|
|
|
11
3
|
// Animation
|
|
12
4
|
export {Timeline} from './animation/timeline';
|
|
13
5
|
export {KeyFrames} from './animation/key-frames';
|
|
6
|
+
export type {AnimationProps} from './animation-loop/animation-props';
|
|
7
|
+
|
|
8
|
+
export {AnimationLoopTemplate} from './animation-loop/animation-loop-template';
|
|
9
|
+
|
|
10
|
+
export type {AnimationLoopProps} from './animation-loop/animation-loop';
|
|
11
|
+
export {AnimationLoop} from './animation-loop/animation-loop';
|
|
12
|
+
|
|
13
|
+
export type {MakeAnimationLoopProps} from './animation-loop/make-animation-loop';
|
|
14
|
+
export {makeAnimationLoop} from './animation-loop/make-animation-loop';
|
|
15
|
+
|
|
16
|
+
export type {ModelProps} from './model/model';
|
|
17
|
+
export {Model} from './model/model';
|
|
18
|
+
|
|
19
|
+
// Transforms
|
|
20
|
+
export type {BufferTransformProps} from './transform/buffer-transform';
|
|
21
|
+
export {BufferTransform} from './transform/buffer-transform';
|
|
22
|
+
export type {TextureTransformProps} from './transform/texture-transform';
|
|
23
|
+
export {TextureTransform} from './transform/texture-transform';
|
|
24
|
+
|
|
25
|
+
export {PipelineFactory} from './lib/pipeline-factory';
|
|
26
|
+
export {ShaderFactory} from './lib/shader-factory';
|
|
14
27
|
|
|
15
28
|
// Utils
|
|
16
|
-
|
|
29
|
+
export {ClipSpace} from './lib/clip-space';
|
|
30
|
+
|
|
31
|
+
// Scenegraph Core nodes
|
|
32
|
+
export {ScenegraphNode} from './scenegraph/scenegraph-node';
|
|
33
|
+
export {GroupNode} from './scenegraph/group-node';
|
|
34
|
+
export type {ModelNodeProps} from './scenegraph/model-node';
|
|
35
|
+
export {ModelNode} from './scenegraph/model-node';
|
|
17
36
|
|
|
18
37
|
// Geometries
|
|
19
|
-
export {
|
|
38
|
+
export type {GeometryProps, GeometryAttribute} from './geometry/geometry';
|
|
39
|
+
export {Geometry} from './geometry/geometry';
|
|
40
|
+
export type {GPUGeometryProps} from './geometry/gpu-geometry';
|
|
41
|
+
export {GPUGeometry} from './geometry/gpu-geometry';
|
|
20
42
|
|
|
21
43
|
// Primitives
|
|
22
44
|
export type {ConeGeometryProps} from './geometries/cone-geometry';
|
|
@@ -34,3 +56,8 @@ export {SphereGeometry} from './geometries/sphere-geometry';
|
|
|
34
56
|
export type {TruncatedConeGeometryProps} from './geometries/truncated-cone-geometry';
|
|
35
57
|
export {TruncatedConeGeometry} from './geometries/truncated-cone-geometry';
|
|
36
58
|
|
|
59
|
+
// EXPERIMENTAL
|
|
60
|
+
export type {ShaderModuleInputs} from './shader-inputs';
|
|
61
|
+
export {ShaderInputs as _ShaderInputs} from './shader-inputs';
|
|
62
|
+
export type {ComputationProps} from './computation';
|
|
63
|
+
export {Computation} from './computation';
|
package/src/lib/clip-space.ts
CHANGED
|
@@ -1,18 +1,17 @@
|
|
|
1
|
-
|
|
2
1
|
// ClipSpace
|
|
3
|
-
|
|
4
|
-
import
|
|
5
|
-
import
|
|
6
|
-
import Geometry from '../geometry/geometry';
|
|
2
|
+
import {Device, glsl} from '@luma.gl/core';
|
|
3
|
+
import {Model, ModelProps} from '../model/model';
|
|
4
|
+
import {Geometry} from '../geometry/geometry';
|
|
7
5
|
|
|
8
|
-
const CLIPSPACE_VERTEX_SHADER = `\
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
6
|
+
const CLIPSPACE_VERTEX_SHADER = glsl`\
|
|
7
|
+
#version 300 es
|
|
8
|
+
in vec2 aClipSpacePosition;
|
|
9
|
+
in vec2 aTexCoord;
|
|
10
|
+
in vec2 aCoordinate;
|
|
12
11
|
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
12
|
+
out vec2 position;
|
|
13
|
+
out vec2 coordinate;
|
|
14
|
+
out vec2 uv;
|
|
16
15
|
|
|
17
16
|
void main(void) {
|
|
18
17
|
gl_Position = vec4(aClipSpacePosition, 0., 1.);
|
|
@@ -22,30 +21,29 @@ void main(void) {
|
|
|
22
21
|
}
|
|
23
22
|
`;
|
|
24
23
|
|
|
25
|
-
/* eslint-disable indent, no-multi-spaces
|
|
24
|
+
/* eslint-disable indent, no-multi-spaces */
|
|
26
25
|
const POSITIONS = [-1, -1, 1, -1, -1, 1, 1, 1];
|
|
27
26
|
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
}
|
|
45
|
-
|
|
27
|
+
/**
|
|
28
|
+
* A flat geometry that covers the "visible area" that the GPU renders.
|
|
29
|
+
*/
|
|
30
|
+
export class ClipSpace extends Model {
|
|
31
|
+
constructor(device: Device, opts: Omit<ModelProps, 'vs' | 'vertexCount' | 'geometry'>) {
|
|
32
|
+
const TEX_COORDS = POSITIONS.map(coord => (coord === -1 ? 0 : coord));
|
|
33
|
+
|
|
34
|
+
super(device, {
|
|
35
|
+
...opts,
|
|
36
|
+
vs: CLIPSPACE_VERTEX_SHADER,
|
|
37
|
+
vertexCount: 4,
|
|
38
|
+
geometry: new Geometry({
|
|
39
|
+
topology: 'triangle-strip',
|
|
40
|
+
vertexCount: 4,
|
|
41
|
+
attributes: {
|
|
42
|
+
aClipSpacePosition: {size: 2, value: new Float32Array(POSITIONS)},
|
|
43
|
+
aTexCoord: {size: 2, value: new Float32Array(TEX_COORDS)},
|
|
44
|
+
aCoordinate: {size: 2, value: new Float32Array(TEX_COORDS)}
|
|
45
|
+
}
|
|
46
46
|
})
|
|
47
|
-
);
|
|
48
|
-
this.setVertexCount(4);
|
|
47
|
+
});
|
|
49
48
|
}
|
|
50
49
|
}
|
|
51
|
-
*/
|
|
@@ -1,234 +1,124 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
modules?: ShaderModule[];
|
|
14
|
-
defines?: Record<string, string | number | boolean>;
|
|
15
|
-
inject?: Record<string, string>;
|
|
16
|
-
transpileToGLSL100?: boolean;
|
|
17
|
-
|
|
18
|
-
varyings?: string[];
|
|
19
|
-
bufferMode?: number,
|
|
20
|
-
};
|
|
21
|
-
|
|
22
|
-
export type GetComputePipelineOptions = {
|
|
23
|
-
cs: string;
|
|
24
|
-
parameters?: RenderPipelineParameters;
|
|
25
|
-
|
|
26
|
-
modules?: ShaderModule[];
|
|
27
|
-
defines?: Record<string, string>;
|
|
28
|
-
inject?: Record<string, string>;
|
|
29
|
-
transpileToGLSL100?: boolean;
|
|
30
|
-
|
|
31
|
-
varyings?: string[];
|
|
32
|
-
bufferMode?: number;
|
|
33
|
-
};
|
|
34
|
-
|
|
35
|
-
const DEFAULT_RENDER_PIPELINE_OPTIONS: Required<GetRenderPipelineOptions> = {
|
|
36
|
-
vs: '',
|
|
37
|
-
fs: '',
|
|
38
|
-
modules: [],
|
|
39
|
-
defines: {},
|
|
40
|
-
inject: {},
|
|
41
|
-
transpileToGLSL100: false,
|
|
42
|
-
layout: null,
|
|
43
|
-
|
|
44
|
-
varyings: [],
|
|
45
|
-
bufferMode: 0x8c8d, // // varyings/bufferMode for xform feedback, 0x8c8d: SEPARATE_ATTRIBS
|
|
46
|
-
topology: 'triangle-list',
|
|
47
|
-
parameters: {}
|
|
48
|
-
};
|
|
49
|
-
|
|
50
|
-
type GetUniformsFunc = (props?: Record<string, any>) => Record<string, any>;
|
|
51
|
-
|
|
52
|
-
/** Efficiently create shared pipelines with varying parameters */
|
|
1
|
+
// luma.gl
|
|
2
|
+
// SPDX-License-Identifier: MIT
|
|
3
|
+
// Copyright (c) vis.gl contributors
|
|
4
|
+
|
|
5
|
+
import type {RenderPipelineProps, ComputePipelineProps} from '@luma.gl/core';
|
|
6
|
+
import {Device, RenderPipeline, ComputePipeline} from '@luma.gl/core';
|
|
7
|
+
|
|
8
|
+
export type PipelineFactoryProps = RenderPipelineProps;
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Efficiently creates / caches pipelines
|
|
12
|
+
*/
|
|
53
13
|
export class PipelineFactory {
|
|
14
|
+
static defaultProps: Required<PipelineFactoryProps> = {...RenderPipeline.defaultProps};
|
|
15
|
+
|
|
54
16
|
readonly device: Device;
|
|
55
17
|
|
|
56
|
-
stateHash: number = 0; // Used to change hashing if hooks are modified
|
|
57
18
|
private _hashCounter: number = 0;
|
|
58
19
|
private readonly _hashes: Record<string, number> = {};
|
|
59
|
-
private readonly
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
private readonly
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
20
|
+
private readonly _renderPipelineCache: Record<
|
|
21
|
+
string,
|
|
22
|
+
{pipeline: RenderPipeline; useCount: number}
|
|
23
|
+
> = {};
|
|
24
|
+
private readonly _computePipelineCache: Record<
|
|
25
|
+
string,
|
|
26
|
+
{pipeline: ComputePipeline; useCount: number}
|
|
27
|
+
> = {};
|
|
28
|
+
|
|
29
|
+
/** Get the singleton default pipeline factory for the specified device */
|
|
68
30
|
static getDefaultPipelineFactory(device: Device): PipelineFactory {
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
return device.defaultPipelineFactory;
|
|
31
|
+
device._lumaData.defaultPipelineFactory =
|
|
32
|
+
device._lumaData.defaultPipelineFactory || new PipelineFactory(device);
|
|
33
|
+
return device._lumaData.defaultPipelineFactory as PipelineFactory;
|
|
73
34
|
}
|
|
74
35
|
|
|
75
36
|
constructor(device: Device) {
|
|
76
37
|
this.device = device;
|
|
77
38
|
}
|
|
78
39
|
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
}
|
|
83
|
-
this.stateHash++;
|
|
84
|
-
}
|
|
40
|
+
/** Return a RenderPipeline matching props. Reuses a similar pipeline if already created. */
|
|
41
|
+
createRenderPipeline(props: RenderPipelineProps): RenderPipeline {
|
|
42
|
+
const allProps: Required<RenderPipelineProps> = {...RenderPipeline.defaultProps, ...props};
|
|
85
43
|
|
|
86
|
-
|
|
87
|
-
const moduleName = typeof module === 'string' ? module : module.name;
|
|
88
|
-
this._defaultModules = this._defaultModules.filter((m) => m.name !== moduleName);
|
|
89
|
-
this.stateHash++;
|
|
90
|
-
}
|
|
44
|
+
const hash = this._hashRenderPipeline(allProps);
|
|
91
45
|
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
46
|
+
if (!this._renderPipelineCache[hash]) {
|
|
47
|
+
const pipeline = this.device.createRenderPipeline({
|
|
48
|
+
...allProps,
|
|
49
|
+
id: allProps.id ? `${allProps.id}-cached` : undefined
|
|
50
|
+
});
|
|
51
|
+
pipeline.hash = hash;
|
|
52
|
+
this._renderPipelineCache[hash] = {pipeline, useCount: 0};
|
|
95
53
|
}
|
|
96
|
-
this._hookFunctions.push(hook);
|
|
97
|
-
this.stateHash++;
|
|
98
|
-
}
|
|
99
54
|
|
|
100
|
-
|
|
101
|
-
pipeline
|
|
102
|
-
|
|
103
|
-
} {
|
|
104
|
-
const props: Required<GetRenderPipelineOptions> = {...DEFAULT_RENDER_PIPELINE_OPTIONS, ...options};
|
|
55
|
+
this._renderPipelineCache[hash].useCount++;
|
|
56
|
+
return this._renderPipelineCache[hash].pipeline;
|
|
57
|
+
}
|
|
105
58
|
|
|
106
|
-
|
|
59
|
+
createComputePipeline(props: ComputePipelineProps): ComputePipeline {
|
|
60
|
+
const allProps: Required<ComputePipelineProps> = {...ComputePipeline.defaultProps, ...props};
|
|
107
61
|
|
|
108
|
-
const hash = this.
|
|
62
|
+
const hash = this._hashComputePipeline(allProps);
|
|
109
63
|
|
|
110
|
-
if (!this.
|
|
111
|
-
const
|
|
64
|
+
if (!this._computePipelineCache[hash]) {
|
|
65
|
+
const pipeline = this.device.createComputePipeline({
|
|
66
|
+
...allProps,
|
|
67
|
+
id: allProps.id ? `${allProps.id}-cached` : undefined
|
|
68
|
+
});
|
|
112
69
|
pipeline.hash = hash;
|
|
113
|
-
this.
|
|
114
|
-
this._getUniforms[hash] = getUniforms || ((x?: unknown) => ({}));
|
|
115
|
-
this._useCounts[hash] = 0;
|
|
70
|
+
this._computePipelineCache[hash] = {pipeline, useCount: 0};
|
|
116
71
|
}
|
|
117
72
|
|
|
118
|
-
this.
|
|
119
|
-
|
|
120
|
-
return {
|
|
121
|
-
pipeline: this._pipelineCache[hash],
|
|
122
|
-
getUniforms: this._getUniforms[hash]
|
|
123
|
-
};
|
|
73
|
+
this._computePipelineCache[hash].useCount++;
|
|
74
|
+
return this._computePipelineCache[hash].pipeline;
|
|
124
75
|
}
|
|
125
76
|
|
|
126
|
-
release(pipeline: RenderPipeline): void {
|
|
77
|
+
release(pipeline: RenderPipeline | ComputePipeline): void {
|
|
127
78
|
const hash = pipeline.hash;
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
delete
|
|
79
|
+
const cache =
|
|
80
|
+
pipeline instanceof ComputePipeline ? this._computePipelineCache : this._renderPipelineCache;
|
|
81
|
+
cache[hash].useCount--;
|
|
82
|
+
if (cache[hash].useCount === 0) {
|
|
83
|
+
cache[hash].pipeline.destroy();
|
|
84
|
+
delete cache[hash];
|
|
134
85
|
}
|
|
135
86
|
}
|
|
136
87
|
|
|
137
|
-
getUniforms(pipeline: RenderPipeline) {
|
|
138
|
-
return this._getUniforms[pipeline.hash] || null;
|
|
139
|
-
}
|
|
140
|
-
|
|
141
88
|
// PRIVATE
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
getUniforms: GetUniformsFunc
|
|
146
|
-
} {
|
|
147
|
-
const platformInfo = {
|
|
148
|
-
gpu: this.device.info.gpu,
|
|
149
|
-
features: this.device.features
|
|
150
|
-
};
|
|
151
|
-
|
|
152
|
-
if (!props.fs) {
|
|
153
|
-
throw new Error('fs');
|
|
154
|
-
}
|
|
155
|
-
|
|
156
|
-
const assembled = assembleShaders(platformInfo, {...props, fs: props.fs, hookFunctions: this._hookFunctions});
|
|
157
|
-
|
|
158
|
-
const pipeline = this.device.createRenderPipeline({
|
|
159
|
-
...props,
|
|
160
|
-
vs: this.device.createShader({stage: 'vertex', source: assembled.vs}),
|
|
161
|
-
fs: assembled.fs ? this.device.createShader({stage: 'fragment', source: assembled.fs}) : null,
|
|
162
|
-
});
|
|
163
|
-
|
|
164
|
-
return {pipeline, getUniforms: assembled.getUniforms};
|
|
89
|
+
private _hashComputePipeline(props: ComputePipelineProps): string {
|
|
90
|
+
const shaderHash = this._getHash(props.shader.source);
|
|
91
|
+
return `${shaderHash}`;
|
|
165
92
|
}
|
|
166
93
|
|
|
167
94
|
/** Calculate a hash based on all the inputs for a render pipeline */
|
|
168
|
-
_hashRenderPipeline(props:
|
|
169
|
-
const
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
const
|
|
174
|
-
const varyingHashes = varyings.map((v) => this._getHash(v));
|
|
175
|
-
|
|
176
|
-
const
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
injectHashes.push(this._getHash(inject[key]));
|
|
95
|
+
private _hashRenderPipeline(props: RenderPipelineProps): string {
|
|
96
|
+
const vsHash = this._getHash(props.vs.source);
|
|
97
|
+
const fsHash = props.fs ? this._getHash(props.fs.source) : 0;
|
|
98
|
+
|
|
99
|
+
// WebGL specific
|
|
100
|
+
// const {varyings = [], bufferMode = {}} = props;
|
|
101
|
+
// const varyingHashes = varyings.map((v) => this._getHash(v));
|
|
102
|
+
const varyingHash = '-'; // `${varyingHashes.join('/')}B${bufferMode}`
|
|
103
|
+
const bufferLayoutHash = this._getHash(JSON.stringify(props.bufferLayout));
|
|
104
|
+
|
|
105
|
+
switch (this.device.type) {
|
|
106
|
+
// case 'webgl':
|
|
107
|
+
// WebGL is more dynamic
|
|
108
|
+
// return `${vsHash}/${fsHash}V${varyingHash}BL${bufferLayoutHash}`;
|
|
109
|
+
default:
|
|
110
|
+
// On WebGPU we need to rebuild the pipeline if topology, parameters or bufferLayout change
|
|
111
|
+
const parameterHash = this._getHash(JSON.stringify(props.parameters));
|
|
112
|
+
// TODO - Can json.stringify() generate different strings for equivalent objects if order of params is different?
|
|
113
|
+
// create a deepHash() to deduplicate?
|
|
114
|
+
return `${vsHash}/${fsHash}V${varyingHash}T${props.topology}P${parameterHash}BL${bufferLayoutHash}`;
|
|
189
115
|
}
|
|
190
|
-
|
|
191
|
-
// TODO - hash parameters!
|
|
192
|
-
const parameterHash = JSON.stringify(parameters);
|
|
193
|
-
|
|
194
|
-
return `${vsHash}/${fsHash}D${defineHashes.join('/')}M${moduleHashes.join(
|
|
195
|
-
'/'
|
|
196
|
-
)}I${injectHashes.join('/')}V${varyingHashes.join('/')}H${this.stateHash}B${props.bufferMode}${
|
|
197
|
-
props.transpileToGLSL100 ? 'T' : ''
|
|
198
|
-
}P${parameterHash}`;
|
|
199
116
|
}
|
|
200
117
|
|
|
201
|
-
_getHash(key: string): number {
|
|
118
|
+
private _getHash(key: string): number {
|
|
202
119
|
if (this._hashes[key] === undefined) {
|
|
203
120
|
this._hashes[key] = this._hashCounter++;
|
|
204
121
|
}
|
|
205
122
|
return this._hashes[key];
|
|
206
123
|
}
|
|
207
|
-
|
|
208
|
-
// Dedupe and combine with default modules
|
|
209
|
-
_getModuleList(appModules: ShaderModule[] = []): ShaderModule[] {
|
|
210
|
-
const modules = new Array(this._defaultModules.length + appModules.length);
|
|
211
|
-
const seen: Record<string, boolean> = {};
|
|
212
|
-
let count = 0;
|
|
213
|
-
|
|
214
|
-
for (let i = 0, len = this._defaultModules.length; i < len; ++i) {
|
|
215
|
-
const module = this._defaultModules[i];
|
|
216
|
-
const name = module.name;
|
|
217
|
-
modules[count++] = module;
|
|
218
|
-
seen[name] = true;
|
|
219
|
-
}
|
|
220
|
-
|
|
221
|
-
for (let i = 0, len = appModules.length; i < len; ++i) {
|
|
222
|
-
const module = appModules[i];
|
|
223
|
-
const name = module.name;
|
|
224
|
-
if (!seen[name]) {
|
|
225
|
-
modules[count++] = module;
|
|
226
|
-
seen[name] = true;
|
|
227
|
-
}
|
|
228
|
-
}
|
|
229
|
-
|
|
230
|
-
modules.length = count;
|
|
231
|
-
|
|
232
|
-
return modules;
|
|
233
|
-
}
|
|
234
124
|
}
|