@deck.gl/aggregation-layers 9.4.0-alpha.1 → 9.4.0-beta.1

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.
Files changed (210) hide show
  1. package/dist/common/aggregator/gpu-aggregator/webgl-aggregation-transform.d.ts.map +1 -1
  2. package/dist/common/aggregator/gpu-aggregator/webgl-aggregation-transform.js +1 -3
  3. package/dist/common/aggregator/gpu-aggregator/webgl-aggregation-transform.js.map +1 -1
  4. package/dist/common/aggregator/gpu-aggregator/webgl-bin-sorter.js +0 -1
  5. package/dist/common/aggregator/gpu-aggregator/webgl-bin-sorter.js.map +1 -1
  6. package/dist/dist.dev.js +642 -38
  7. package/dist/grid-layer/grid-cell-layer.d.ts.map +1 -1
  8. package/dist/grid-layer/grid-cell-layer.js +3 -2
  9. package/dist/grid-layer/grid-cell-layer.js.map +1 -1
  10. package/dist/grid-layer/grid-cell-layer.wgsl.d.ts +3 -0
  11. package/dist/grid-layer/grid-cell-layer.wgsl.d.ts.map +1 -0
  12. package/dist/grid-layer/grid-cell-layer.wgsl.js +114 -0
  13. package/dist/grid-layer/grid-cell-layer.wgsl.js.map +1 -0
  14. package/dist/grid-layer/grid-layer-uniforms.d.ts +1 -0
  15. package/dist/grid-layer/grid-layer-uniforms.d.ts.map +1 -1
  16. package/dist/grid-layer/grid-layer-uniforms.js +14 -0
  17. package/dist/grid-layer/grid-layer-uniforms.js.map +1 -1
  18. package/dist/heatmap-layer/heatmap-layer-uniforms.d.ts +2 -0
  19. package/dist/heatmap-layer/heatmap-layer-uniforms.d.ts.map +1 -1
  20. package/dist/heatmap-layer/heatmap-layer-uniforms.js +19 -0
  21. package/dist/heatmap-layer/heatmap-layer-uniforms.js.map +1 -1
  22. package/dist/heatmap-layer/heatmap-layer.d.ts.map +1 -1
  23. package/dist/heatmap-layer/heatmap-layer.js +59 -12
  24. package/dist/heatmap-layer/heatmap-layer.js.map +1 -1
  25. package/dist/heatmap-layer/max.wgsl.d.ts +3 -0
  26. package/dist/heatmap-layer/max.wgsl.d.ts.map +1 -0
  27. package/dist/heatmap-layer/max.wgsl.js +48 -0
  28. package/dist/heatmap-layer/max.wgsl.js.map +1 -0
  29. package/dist/heatmap-layer/triangle-layer-uniforms.d.ts +1 -0
  30. package/dist/heatmap-layer/triangle-layer-uniforms.d.ts.map +1 -1
  31. package/dist/heatmap-layer/triangle-layer-uniforms.js +16 -0
  32. package/dist/heatmap-layer/triangle-layer-uniforms.js.map +1 -1
  33. package/dist/heatmap-layer/triangle-layer.d.ts.map +1 -1
  34. package/dist/heatmap-layer/triangle-layer.js +3 -2
  35. package/dist/heatmap-layer/triangle-layer.js.map +1 -1
  36. package/dist/heatmap-layer/triangle-layer.wgsl.d.ts +3 -0
  37. package/dist/heatmap-layer/triangle-layer.wgsl.d.ts.map +1 -0
  38. package/dist/heatmap-layer/triangle-layer.wgsl.js +65 -0
  39. package/dist/heatmap-layer/triangle-layer.wgsl.js.map +1 -0
  40. package/dist/heatmap-layer/weights.wgsl.d.ts +3 -0
  41. package/dist/heatmap-layer/weights.wgsl.d.ts.map +1 -0
  42. package/dist/heatmap-layer/weights.wgsl.js +64 -0
  43. package/dist/heatmap-layer/weights.wgsl.js.map +1 -0
  44. package/dist/hexagon-layer/hexagon-cell-layer.d.ts.map +1 -1
  45. package/dist/hexagon-layer/hexagon-cell-layer.js +2 -2
  46. package/dist/hexagon-layer/hexagon-cell-layer.js.map +1 -1
  47. package/dist/hexagon-layer/hexagon-cell-layer.wgsl.d.ts +3 -0
  48. package/dist/hexagon-layer/hexagon-cell-layer.wgsl.d.ts.map +1 -0
  49. package/dist/hexagon-layer/hexagon-cell-layer.wgsl.js +120 -0
  50. package/dist/hexagon-layer/hexagon-cell-layer.wgsl.js.map +1 -0
  51. package/dist/hexagon-layer/hexagon-layer-uniforms.d.ts +1 -0
  52. package/dist/hexagon-layer/hexagon-layer-uniforms.d.ts.map +1 -1
  53. package/dist/hexagon-layer/hexagon-layer-uniforms.js +13 -0
  54. package/dist/hexagon-layer/hexagon-layer-uniforms.js.map +1 -1
  55. package/dist/index.cjs +13268 -1488
  56. package/dist/index.cjs.map +3 -4
  57. package/dist/screen-grid-layer/screen-grid-cell-layer.d.ts +1 -6
  58. package/dist/screen-grid-layer/screen-grid-cell-layer.d.ts.map +1 -1
  59. package/dist/screen-grid-layer/screen-grid-cell-layer.js +3 -2
  60. package/dist/screen-grid-layer/screen-grid-cell-layer.js.map +1 -1
  61. package/dist/screen-grid-layer/screen-grid-cell-layer.wgsl.d.ts +3 -0
  62. package/dist/screen-grid-layer/screen-grid-cell-layer.wgsl.d.ts.map +1 -0
  63. package/dist/screen-grid-layer/screen-grid-cell-layer.wgsl.js +76 -0
  64. package/dist/screen-grid-layer/screen-grid-cell-layer.wgsl.js.map +1 -0
  65. package/dist/screen-grid-layer/screen-grid-layer-uniforms.d.ts +1 -0
  66. package/dist/screen-grid-layer/screen-grid-layer-uniforms.d.ts.map +1 -1
  67. package/dist/screen-grid-layer/screen-grid-layer-uniforms.js +12 -0
  68. package/dist/screen-grid-layer/screen-grid-layer-uniforms.js.map +1 -1
  69. package/dist.min.js +545 -35
  70. package/dist.webgl-only/common/aggregation-layer.js +68 -0
  71. package/dist.webgl-only/common/aggregation-layer.js.map +1 -0
  72. package/dist.webgl-only/common/aggregator/aggregator.js +5 -0
  73. package/dist.webgl-only/common/aggregator/aggregator.js.map +1 -0
  74. package/dist.webgl-only/common/aggregator/cpu-aggregator/aggregate.js +69 -0
  75. package/dist.webgl-only/common/aggregator/cpu-aggregator/aggregate.js.map +1 -0
  76. package/dist.webgl-only/common/aggregator/cpu-aggregator/cpu-aggregator.js +141 -0
  77. package/dist.webgl-only/common/aggregator/cpu-aggregator/cpu-aggregator.js.map +1 -0
  78. package/dist.webgl-only/common/aggregator/cpu-aggregator/sort-bins.js +44 -0
  79. package/dist.webgl-only/common/aggregator/cpu-aggregator/sort-bins.js.map +1 -0
  80. package/dist.webgl-only/common/aggregator/cpu-aggregator/vertex-accessor.js +56 -0
  81. package/dist.webgl-only/common/aggregator/cpu-aggregator/vertex-accessor.js.map +1 -0
  82. package/dist.webgl-only/common/aggregator/gpu-aggregator/aggregation-transform-uniforms.js +22 -0
  83. package/dist.webgl-only/common/aggregator/gpu-aggregator/aggregation-transform-uniforms.js.map +1 -0
  84. package/dist.webgl-only/common/aggregator/gpu-aggregator/bin-sorter-uniforms.js +18 -0
  85. package/dist.webgl-only/common/aggregator/gpu-aggregator/bin-sorter-uniforms.js.map +1 -0
  86. package/dist.webgl-only/common/aggregator/gpu-aggregator/utils.js +24 -0
  87. package/dist.webgl-only/common/aggregator/gpu-aggregator/utils.js.map +1 -0
  88. package/dist.webgl-only/common/aggregator/gpu-aggregator/webgl-aggregation-transform.js +222 -0
  89. package/dist.webgl-only/common/aggregator/gpu-aggregator/webgl-aggregation-transform.js.map +1 -0
  90. package/dist.webgl-only/common/aggregator/gpu-aggregator/webgl-aggregator.js +203 -0
  91. package/dist.webgl-only/common/aggregator/gpu-aggregator/webgl-aggregator.js.map +1 -0
  92. package/dist.webgl-only/common/aggregator/gpu-aggregator/webgl-bin-sorter.js +225 -0
  93. package/dist.webgl-only/common/aggregator/gpu-aggregator/webgl-bin-sorter.js.map +1 -0
  94. package/dist.webgl-only/common/aggregator/index.js +6 -0
  95. package/dist.webgl-only/common/aggregator/index.js.map +1 -0
  96. package/dist.webgl-only/common/types.js +5 -0
  97. package/dist.webgl-only/common/types.js.map +1 -0
  98. package/dist.webgl-only/common/utils/bounds-utils.js +21 -0
  99. package/dist.webgl-only/common/utils/bounds-utils.js.map +1 -0
  100. package/dist.webgl-only/common/utils/color-utils.js +65 -0
  101. package/dist.webgl-only/common/utils/color-utils.js.map +1 -0
  102. package/dist.webgl-only/common/utils/prop-utils.js +13 -0
  103. package/dist.webgl-only/common/utils/prop-utils.js.map +1 -0
  104. package/dist.webgl-only/common/utils/scale-utils.js +181 -0
  105. package/dist.webgl-only/common/utils/scale-utils.js.map +1 -0
  106. package/dist.webgl-only/contour-layer/bin-options-uniforms.js +18 -0
  107. package/dist.webgl-only/contour-layer/bin-options-uniforms.js.map +1 -0
  108. package/dist.webgl-only/contour-layer/contour-layer.js +282 -0
  109. package/dist.webgl-only/contour-layer/contour-layer.js.map +1 -0
  110. package/dist.webgl-only/contour-layer/contour-utils.js +60 -0
  111. package/dist.webgl-only/contour-layer/contour-utils.js.map +1 -0
  112. package/dist.webgl-only/contour-layer/marching-squares-codes.js +341 -0
  113. package/dist.webgl-only/contour-layer/marching-squares-codes.js.map +1 -0
  114. package/dist.webgl-only/contour-layer/marching-squares.js +151 -0
  115. package/dist.webgl-only/contour-layer/marching-squares.js.map +1 -0
  116. package/dist.webgl-only/contour-layer/value-reader.js +47 -0
  117. package/dist.webgl-only/contour-layer/value-reader.js.map +1 -0
  118. package/dist.webgl-only/grid-layer/bin-options-uniforms.js +18 -0
  119. package/dist.webgl-only/grid-layer/bin-options-uniforms.js.map +1 -0
  120. package/dist.webgl-only/grid-layer/grid-cell-layer-vertex.glsl.js +51 -0
  121. package/dist.webgl-only/grid-layer/grid-cell-layer-vertex.glsl.js.map +1 -0
  122. package/dist.webgl-only/grid-layer/grid-cell-layer.js +95 -0
  123. package/dist.webgl-only/grid-layer/grid-cell-layer.js.map +1 -0
  124. package/dist.webgl-only/grid-layer/grid-cell-layer.wgsl.js +5 -0
  125. package/dist.webgl-only/grid-layer/grid-cell-layer.wgsl.js.map +1 -0
  126. package/dist.webgl-only/grid-layer/grid-layer-uniforms.js +26 -0
  127. package/dist.webgl-only/grid-layer/grid-layer-uniforms.js.map +1 -0
  128. package/dist.webgl-only/grid-layer/grid-layer.js +362 -0
  129. package/dist.webgl-only/grid-layer/grid-layer.js.map +1 -0
  130. package/dist.webgl-only/heatmap-layer/aggregation-layer.js +140 -0
  131. package/dist.webgl-only/heatmap-layer/aggregation-layer.js.map +1 -0
  132. package/dist.webgl-only/heatmap-layer/heatmap-layer-uniforms.js +36 -0
  133. package/dist.webgl-only/heatmap-layer/heatmap-layer-uniforms.js.map +1 -0
  134. package/dist.webgl-only/heatmap-layer/heatmap-layer-utils.js +67 -0
  135. package/dist.webgl-only/heatmap-layer/heatmap-layer-utils.js.map +1 -0
  136. package/dist.webgl-only/heatmap-layer/heatmap-layer.js +513 -0
  137. package/dist.webgl-only/heatmap-layer/heatmap-layer.js.map +1 -0
  138. package/dist.webgl-only/heatmap-layer/max-fs.glsl.js +13 -0
  139. package/dist.webgl-only/heatmap-layer/max-fs.glsl.js.map +1 -0
  140. package/dist.webgl-only/heatmap-layer/max-vs.glsl.js +18 -0
  141. package/dist.webgl-only/heatmap-layer/max-vs.glsl.js.map +1 -0
  142. package/dist.webgl-only/heatmap-layer/max.wgsl.js +5 -0
  143. package/dist.webgl-only/heatmap-layer/max.wgsl.js.map +1 -0
  144. package/dist.webgl-only/heatmap-layer/triangle-layer-fragment.glsl.js +34 -0
  145. package/dist.webgl-only/heatmap-layer/triangle-layer-fragment.glsl.js.map +1 -0
  146. package/dist.webgl-only/heatmap-layer/triangle-layer-uniforms.js +25 -0
  147. package/dist.webgl-only/heatmap-layer/triangle-layer-uniforms.js.map +1 -0
  148. package/dist.webgl-only/heatmap-layer/triangle-layer-vertex.glsl.js +28 -0
  149. package/dist.webgl-only/heatmap-layer/triangle-layer-vertex.glsl.js.map +1 -0
  150. package/dist.webgl-only/heatmap-layer/triangle-layer.js +49 -0
  151. package/dist.webgl-only/heatmap-layer/triangle-layer.js.map +1 -0
  152. package/dist.webgl-only/heatmap-layer/triangle-layer.wgsl.js +5 -0
  153. package/dist.webgl-only/heatmap-layer/triangle-layer.wgsl.js.map +1 -0
  154. package/dist.webgl-only/heatmap-layer/weights-fs.glsl.js +21 -0
  155. package/dist.webgl-only/heatmap-layer/weights-fs.glsl.js.map +1 -0
  156. package/dist.webgl-only/heatmap-layer/weights-vs.glsl.js +21 -0
  157. package/dist.webgl-only/heatmap-layer/weights-vs.glsl.js.map +1 -0
  158. package/dist.webgl-only/heatmap-layer/weights.wgsl.js +5 -0
  159. package/dist.webgl-only/heatmap-layer/weights.wgsl.js.map +1 -0
  160. package/dist.webgl-only/hexagon-layer/bin-options-uniforms.js +18 -0
  161. package/dist.webgl-only/hexagon-layer/bin-options-uniforms.js.map +1 -0
  162. package/dist.webgl-only/hexagon-layer/hexagon-cell-layer-vertex.glsl.js +55 -0
  163. package/dist.webgl-only/hexagon-layer/hexagon-cell-layer-vertex.glsl.js.map +1 -0
  164. package/dist.webgl-only/hexagon-layer/hexagon-cell-layer.js +90 -0
  165. package/dist.webgl-only/hexagon-layer/hexagon-cell-layer.js.map +1 -0
  166. package/dist.webgl-only/hexagon-layer/hexagon-cell-layer.wgsl.js +5 -0
  167. package/dist.webgl-only/hexagon-layer/hexagon-cell-layer.wgsl.js.map +1 -0
  168. package/dist.webgl-only/hexagon-layer/hexagon-layer-uniforms.js +24 -0
  169. package/dist.webgl-only/hexagon-layer/hexagon-layer-uniforms.js.map +1 -0
  170. package/dist.webgl-only/hexagon-layer/hexagon-layer.js +360 -0
  171. package/dist.webgl-only/hexagon-layer/hexagon-layer.js.map +1 -0
  172. package/dist.webgl-only/hexagon-layer/hexbin.js +70 -0
  173. package/dist.webgl-only/hexagon-layer/hexbin.js.map +1 -0
  174. package/dist.webgl-only/index.cjs +15625 -0
  175. package/dist.webgl-only/index.cjs.map +6 -0
  176. package/dist.webgl-only/index.js +11 -0
  177. package/dist.webgl-only/index.js.map +1 -0
  178. package/dist.webgl-only/screen-grid-layer/bin-options-uniforms.js +16 -0
  179. package/dist.webgl-only/screen-grid-layer/bin-options-uniforms.js.map +1 -0
  180. package/dist.webgl-only/screen-grid-layer/screen-grid-cell-layer.js +88 -0
  181. package/dist.webgl-only/screen-grid-layer/screen-grid-cell-layer.js.map +1 -0
  182. package/dist.webgl-only/screen-grid-layer/screen-grid-cell-layer.wgsl.js +5 -0
  183. package/dist.webgl-only/screen-grid-layer/screen-grid-cell-layer.wgsl.js.map +1 -0
  184. package/dist.webgl-only/screen-grid-layer/screen-grid-layer-fragment.glsl.js +16 -0
  185. package/dist.webgl-only/screen-grid-layer/screen-grid-layer-fragment.glsl.js.map +1 -0
  186. package/dist.webgl-only/screen-grid-layer/screen-grid-layer-uniforms.js +22 -0
  187. package/dist.webgl-only/screen-grid-layer/screen-grid-layer-uniforms.js.map +1 -0
  188. package/dist.webgl-only/screen-grid-layer/screen-grid-layer-vertex.glsl.js +31 -0
  189. package/dist.webgl-only/screen-grid-layer/screen-grid-layer-vertex.glsl.js.map +1 -0
  190. package/dist.webgl-only/screen-grid-layer/screen-grid-layer.js +194 -0
  191. package/dist.webgl-only/screen-grid-layer/screen-grid-layer.js.map +1 -0
  192. package/package.json +14 -5
  193. package/src/common/aggregator/gpu-aggregator/webgl-aggregation-transform.ts +1 -3
  194. package/src/common/aggregator/gpu-aggregator/webgl-bin-sorter.ts +0 -1
  195. package/src/grid-layer/grid-cell-layer.ts +3 -2
  196. package/src/grid-layer/grid-cell-layer.wgsl.ts +114 -0
  197. package/src/grid-layer/grid-layer-uniforms.ts +15 -0
  198. package/src/heatmap-layer/heatmap-layer-uniforms.ts +20 -0
  199. package/src/heatmap-layer/heatmap-layer.ts +67 -13
  200. package/src/heatmap-layer/max.wgsl.ts +48 -0
  201. package/src/heatmap-layer/triangle-layer-uniforms.ts +17 -0
  202. package/src/heatmap-layer/triangle-layer.ts +3 -2
  203. package/src/heatmap-layer/triangle-layer.wgsl.ts +65 -0
  204. package/src/heatmap-layer/weights.wgsl.ts +64 -0
  205. package/src/hexagon-layer/hexagon-cell-layer.ts +2 -3
  206. package/src/hexagon-layer/hexagon-cell-layer.wgsl.ts +120 -0
  207. package/src/hexagon-layer/hexagon-layer-uniforms.ts +14 -0
  208. package/src/screen-grid-layer/screen-grid-cell-layer.ts +4 -4
  209. package/src/screen-grid-layer/screen-grid-cell-layer.wgsl.ts +76 -0
  210. package/src/screen-grid-layer/screen-grid-layer-uniforms.ts +13 -0
@@ -0,0 +1,222 @@
1
+ // deck.gl
2
+ // SPDX-License-Identifier: MIT
3
+ // Copyright (c) vis.gl contributors
4
+ import { BufferTransform } from '@luma.gl/engine';
5
+ import { createRenderTarget } from "./utils.js";
6
+ import { TEXTURE_WIDTH } from "./webgl-bin-sorter.js";
7
+ import { aggregatorTransformUniforms } from "./aggregation-transform-uniforms.js";
8
+ const MAX_FLOAT32 = 3e38;
9
+ export class WebGLAggregationTransform {
10
+ constructor(device, props) {
11
+ /** Packed from bin ids */
12
+ this.binBuffer = null;
13
+ /** Packed values from each channel of each bin
14
+ * Stride is number of channels * 4 bytes (float32)
15
+ */
16
+ this.valueBuffer = null;
17
+ /** Aggregated [min, max] for each channel */
18
+ this._domains = null;
19
+ this.device = device;
20
+ this.channelCount = props.channelCount;
21
+ this.transform = createTransform(device, props);
22
+ this.domainFBO = createRenderTarget(device, 2, 1);
23
+ }
24
+ destroy() {
25
+ this.transform.destroy();
26
+ this.binBuffer?.destroy();
27
+ this.valueBuffer?.destroy();
28
+ this.domainFBO.colorAttachments[0].texture.destroy();
29
+ this.domainFBO.destroy();
30
+ }
31
+ get domains() {
32
+ if (!this._domains) {
33
+ // Domain model has run, but result has not been read to CPU
34
+ const buffer = this.device.readPixelsToArrayWebGL(this.domainFBO).buffer;
35
+ const domain = new Float32Array(buffer);
36
+ this._domains = [
37
+ [-domain[4], domain[0]],
38
+ [-domain[5], domain[1]],
39
+ [-domain[6], domain[2]]
40
+ ].slice(0, this.channelCount);
41
+ }
42
+ return this._domains;
43
+ }
44
+ setDimensions(binCount, binIdRange) {
45
+ const { model, transformFeedback } = this.transform;
46
+ model.setVertexCount(binCount);
47
+ const aggregatorTransformProps = {
48
+ binIdRange: [
49
+ binIdRange[0][0],
50
+ binIdRange[0][1],
51
+ binIdRange[1]?.[0] || 0,
52
+ binIdRange[1]?.[1] || 0
53
+ ]
54
+ };
55
+ model.shaderInputs.setProps({ aggregatorTransform: aggregatorTransformProps });
56
+ // Only destroy existing buffer if it is not large enough
57
+ const binBufferByteLength = binCount * binIdRange.length * 4;
58
+ if (!this.binBuffer || this.binBuffer.byteLength < binBufferByteLength) {
59
+ this.binBuffer?.destroy();
60
+ this.binBuffer = this.device.createBuffer({ byteLength: binBufferByteLength });
61
+ transformFeedback.setBuffer('binIds', this.binBuffer);
62
+ }
63
+ const valueBufferByteLength = binCount * this.channelCount * 4;
64
+ if (!this.valueBuffer || this.valueBuffer.byteLength < valueBufferByteLength) {
65
+ this.valueBuffer?.destroy();
66
+ this.valueBuffer = this.device.createBuffer({ byteLength: valueBufferByteLength });
67
+ transformFeedback.setBuffer('values', this.valueBuffer);
68
+ }
69
+ }
70
+ update(bins, operations) {
71
+ if (!bins) {
72
+ return;
73
+ }
74
+ const transform = this.transform;
75
+ const target = this.domainFBO;
76
+ const isCount = [0, 1, 2].map(i => (operations[i] === 'COUNT' ? 1 : 0));
77
+ const isMean = [0, 1, 2].map(i => (operations[i] === 'MEAN' ? 1 : 0));
78
+ const aggregatorTransformProps = {
79
+ isCount: isCount,
80
+ isMean: isMean,
81
+ bins
82
+ };
83
+ transform.model.shaderInputs.setProps({ aggregatorTransform: aggregatorTransformProps });
84
+ transform.run({
85
+ id: 'gpu-aggregation-domain',
86
+ framebuffer: target,
87
+ discard: false,
88
+ parameters: {
89
+ viewport: [0, 0, 2, 1]
90
+ },
91
+ clearColor: [-MAX_FLOAT32, -MAX_FLOAT32, -MAX_FLOAT32, 0],
92
+ clearDepth: false,
93
+ clearStencil: false
94
+ });
95
+ // Clear the last read results. This will be lazy-populated if used.
96
+ this._domains = null;
97
+ }
98
+ }
99
+ function createTransform(device, props) {
100
+ const vs = /* glsl */ `\
101
+ #version 300 es
102
+ #define SHADER_NAME gpu-aggregation-domain-vertex
103
+
104
+ uniform sampler2D bins;
105
+
106
+ #if NUM_DIMS == 1
107
+ out float binIds;
108
+ #else
109
+ out vec2 binIds;
110
+ #endif
111
+
112
+ #if NUM_CHANNELS == 1
113
+ flat out float values;
114
+ #elif NUM_CHANNELS == 2
115
+ flat out vec2 values;
116
+ #else
117
+ flat out vec3 values;
118
+ #endif
119
+
120
+ const float NAN = intBitsToFloat(-1);
121
+
122
+ void main() {
123
+ int row = gl_VertexID / SAMPLER_WIDTH;
124
+ int col = gl_VertexID - row * SAMPLER_WIDTH;
125
+ vec4 weights = texelFetch(bins, ivec2(col, row), 0);
126
+ vec3 value3 = mix(
127
+ mix(weights.rgb, vec3(weights.a), aggregatorTransform.isCount),
128
+ weights.rgb / max(weights.a, 1.0),
129
+ aggregatorTransform.isMean
130
+ );
131
+ if (weights.a == 0.0) {
132
+ value3 = vec3(NAN);
133
+ }
134
+
135
+ #if NUM_DIMS == 1
136
+ binIds = float(gl_VertexID + aggregatorTransform.binIdRange.x);
137
+ #else
138
+ int y = gl_VertexID / (aggregatorTransform.binIdRange.y - aggregatorTransform.binIdRange.x);
139
+ int x = gl_VertexID - y * (aggregatorTransform.binIdRange.y - aggregatorTransform.binIdRange.x);
140
+ binIds.y = float(y + aggregatorTransform.binIdRange.z);
141
+ binIds.x = float(x + aggregatorTransform.binIdRange.x);
142
+ #endif
143
+
144
+ #if NUM_CHANNELS == 3
145
+ values = value3;
146
+ #elif NUM_CHANNELS == 2
147
+ values = value3.xy;
148
+ #else
149
+ values = value3.x;
150
+ #endif
151
+
152
+ gl_Position = vec4(0., 0., 0., 1.);
153
+ // This model renders into a 2x1 texture to obtain min and max simultaneously.
154
+ // See comments in fragment shader
155
+ gl_PointSize = 2.0;
156
+ }
157
+ `;
158
+ const fs = /* glsl */ `\
159
+ #version 300 es
160
+ #define SHADER_NAME gpu-aggregation-domain-fragment
161
+
162
+ precision highp float;
163
+
164
+ #if NUM_CHANNELS == 1
165
+ flat in float values;
166
+ #elif NUM_CHANNELS == 2
167
+ flat in vec2 values;
168
+ #else
169
+ flat in vec3 values;
170
+ #endif
171
+
172
+ out vec4 fragColor;
173
+
174
+ void main() {
175
+ vec3 value3;
176
+ #if NUM_CHANNELS == 3
177
+ value3 = values;
178
+ #elif NUM_CHANNELS == 2
179
+ value3.xy = values;
180
+ #else
181
+ value3.x = values;
182
+ #endif
183
+ if (isnan(value3.x)) discard;
184
+ // This shader renders into a 2x1 texture with blending=max
185
+ // The left pixel yields the max value of each channel
186
+ // The right pixel yields the min value of each channel
187
+ if (gl_FragCoord.x < 1.0) {
188
+ fragColor = vec4(value3, 1.0);
189
+ } else {
190
+ fragColor = vec4(-value3, 1.0);
191
+ }
192
+ }
193
+ `;
194
+ // Enable intBitsToFloat on Firefox + Nvidia driver: https://github.com/visgl/deck.gl/pull/10069
195
+ if (device.type === 'webgl') {
196
+ // @ts-expect-error WebGLDevice method
197
+ device.getExtension('GL_ARB_shader_bit_encoding');
198
+ }
199
+ return new BufferTransform(device, {
200
+ vs,
201
+ fs,
202
+ topology: 'point-list',
203
+ modules: [aggregatorTransformUniforms],
204
+ parameters: {
205
+ blend: true,
206
+ blendColorSrcFactor: 'one',
207
+ blendColorDstFactor: 'one',
208
+ blendColorOperation: 'max',
209
+ blendAlphaSrcFactor: 'one',
210
+ blendAlphaDstFactor: 'one',
211
+ blendAlphaOperation: 'max'
212
+ },
213
+ defines: {
214
+ NUM_DIMS: props.dimensions,
215
+ NUM_CHANNELS: props.channelCount,
216
+ SAMPLER_WIDTH: TEXTURE_WIDTH
217
+ },
218
+ varyings: ['binIds', 'values'],
219
+ disableWarnings: true
220
+ });
221
+ }
222
+ //# sourceMappingURL=webgl-aggregation-transform.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"webgl-aggregation-transform.js","sourceRoot":"","sources":["../../../../src/common/aggregator/gpu-aggregator/webgl-aggregation-transform.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,203 @@
1
+ // deck.gl
2
+ // SPDX-License-Identifier: MIT
3
+ // Copyright (c) vis.gl contributors
4
+ import { WebGLBinSorter } from "./webgl-bin-sorter.js";
5
+ import { WebGLAggregationTransform } from "./webgl-aggregation-transform.js";
6
+ import { _deepEqual as deepEqual, log } from '@deck.gl/core';
7
+ /** An Aggregator implementation that calculates aggregation on the GPU */
8
+ export class WebGLAggregator {
9
+ /** Checks if the current device supports GPU aggregation */
10
+ static isSupported(device) {
11
+ return (device.features.has('float32-renderable-webgl') &&
12
+ device.features.has('texture-blend-float-webgl'));
13
+ }
14
+ constructor(device, props) {
15
+ this.binCount = 0;
16
+ /** Cached outputs */
17
+ this.binIds = null;
18
+ this.results = [];
19
+ this.device = device;
20
+ this.dimensions = props.dimensions;
21
+ this.channelCount = props.channelCount;
22
+ this.props = {
23
+ ...props,
24
+ pointCount: 0,
25
+ binIdRange: [[0, 0]],
26
+ operations: [],
27
+ attributes: {},
28
+ binOptions: {}
29
+ };
30
+ this.needsUpdate = new Array(this.channelCount).fill(true);
31
+ this.binSorter = new WebGLBinSorter(device, props);
32
+ this.aggregationTransform = new WebGLAggregationTransform(device, props);
33
+ this.setProps(props);
34
+ }
35
+ getBins() {
36
+ const buffer = this.aggregationTransform.binBuffer;
37
+ if (!buffer) {
38
+ return null;
39
+ }
40
+ if (this.binIds?.buffer !== buffer) {
41
+ // deck.gl Attribute.setBinaryValue uses shallow comparison to determine if attribute value has changed
42
+ // For performance, only create a new binary attribute descriptor when Buffer changes
43
+ this.binIds = { buffer, type: 'float32', size: this.dimensions };
44
+ }
45
+ return this.binIds;
46
+ }
47
+ /** Returns an accessor to the output for a given channel. */
48
+ getResult(channel) {
49
+ const buffer = this.aggregationTransform.valueBuffer;
50
+ if (!buffer || channel >= this.channelCount) {
51
+ return null;
52
+ }
53
+ if (this.results[channel]?.buffer !== buffer) {
54
+ this.results[channel] = {
55
+ buffer,
56
+ type: 'float32',
57
+ size: 1,
58
+ stride: this.channelCount * 4,
59
+ offset: channel * 4
60
+ };
61
+ }
62
+ return this.results[channel];
63
+ }
64
+ /** Returns the [min, max] of aggregated values for a given channel. */
65
+ getResultDomain(channel) {
66
+ return this.aggregationTransform.domains[channel];
67
+ }
68
+ /** Returns the information for a given bin. */
69
+ getBin(index) {
70
+ if (index < 0 || index >= this.binCount) {
71
+ return null;
72
+ }
73
+ const { binIdRange } = this.props;
74
+ let id;
75
+ if (this.dimensions === 1) {
76
+ id = [index + binIdRange[0][0]];
77
+ }
78
+ else {
79
+ const [[x0, x1], [y0]] = binIdRange;
80
+ const width = x1 - x0;
81
+ id = [(index % width) + x0, Math.floor(index / width) + y0];
82
+ }
83
+ const pixel = this.binSorter.getBinValues(index);
84
+ if (!pixel) {
85
+ return null;
86
+ }
87
+ const count = pixel[3];
88
+ const value = [];
89
+ for (let channel = 0; channel < this.channelCount; channel++) {
90
+ const operation = this.props.operations[channel];
91
+ if (operation === 'COUNT') {
92
+ value[channel] = count;
93
+ }
94
+ else if (count === 0) {
95
+ value[channel] = NaN;
96
+ }
97
+ else {
98
+ value[channel] = operation === 'MEAN' ? pixel[channel] / count : pixel[channel];
99
+ }
100
+ }
101
+ return { id, value, count };
102
+ }
103
+ /** Release GPU resources */
104
+ destroy() {
105
+ this.binSorter.destroy();
106
+ this.aggregationTransform.destroy();
107
+ }
108
+ /** Update aggregation props. Normalize prop values and set change flags. */
109
+ // eslint-disable-next-line complexity, max-statements
110
+ setProps(props) {
111
+ const oldProps = this.props;
112
+ // Update local settings. These will set the flag this._needsUpdate
113
+ if ('binIdRange' in props && !deepEqual(props.binIdRange, oldProps.binIdRange, 2)) {
114
+ const binIdRange = props.binIdRange;
115
+ log.assert(binIdRange.length === this.dimensions);
116
+ if (this.dimensions === 1) {
117
+ const [[x0, x1]] = binIdRange;
118
+ this.binCount = x1 - x0;
119
+ }
120
+ else {
121
+ const [[x0, x1], [y0, y1]] = binIdRange;
122
+ this.binCount = (x1 - x0) * (y1 - y0);
123
+ }
124
+ this.binSorter.setDimensions(this.binCount, binIdRange);
125
+ this.aggregationTransform.setDimensions(this.binCount, binIdRange);
126
+ this.setNeedsUpdate();
127
+ }
128
+ if (props.operations) {
129
+ for (let channel = 0; channel < this.channelCount; channel++) {
130
+ if (props.operations[channel] !== oldProps.operations[channel]) {
131
+ this.setNeedsUpdate(channel);
132
+ }
133
+ }
134
+ }
135
+ if (props.pointCount !== undefined && props.pointCount !== oldProps.pointCount) {
136
+ this.binSorter.setModelProps({ vertexCount: props.pointCount });
137
+ this.setNeedsUpdate();
138
+ }
139
+ if (props.binOptions) {
140
+ if (!deepEqual(props.binOptions, oldProps.binOptions, 2)) {
141
+ this.setNeedsUpdate();
142
+ }
143
+ this.binSorter.model.shaderInputs.setProps({ binOptions: props.binOptions });
144
+ }
145
+ if (props.attributes) {
146
+ const attributeBuffers = {};
147
+ const constantAttributes = {};
148
+ for (const attribute of Object.values(props.attributes)) {
149
+ for (const [attributeName, value] of Object.entries(attribute.getValue())) {
150
+ if (ArrayBuffer.isView(value)) {
151
+ constantAttributes[attributeName] = value;
152
+ }
153
+ else if (value) {
154
+ attributeBuffers[attributeName] = value;
155
+ }
156
+ }
157
+ }
158
+ this.binSorter.setModelProps({ attributes: attributeBuffers, constantAttributes });
159
+ }
160
+ if (props.shaderModuleProps) {
161
+ this.binSorter.setModelProps({ shaderModuleProps: props.shaderModuleProps });
162
+ }
163
+ Object.assign(this.props, props);
164
+ }
165
+ /** Flags a channel to need update.
166
+ * This is called internally by setProps() if certain props change
167
+ * Users of this class still need to manually set the dirty flag sometimes, because even if no props changed
168
+ * the underlying buffers could have been updated and require rerunning the aggregation
169
+ * @param {number} channel - mark the given channel as dirty. If not provided, all channels will be updated.
170
+ */
171
+ setNeedsUpdate(channel) {
172
+ if (channel === undefined) {
173
+ this.needsUpdate.fill(true);
174
+ }
175
+ else {
176
+ this.needsUpdate[channel] = true;
177
+ }
178
+ }
179
+ update() { }
180
+ /** Run aggregation */
181
+ preDraw() {
182
+ if (!this.needsUpdate.some(Boolean)) {
183
+ return;
184
+ }
185
+ const { operations } = this.props;
186
+ const operationsToUpdate = this.needsUpdate.map((needsUpdate, i) => needsUpdate ? operations[i] : null);
187
+ // Render data to bins
188
+ this.binSorter.update(operationsToUpdate);
189
+ // Read to buffer and calculate domain
190
+ this.aggregationTransform.update(this.binSorter.texture, operations);
191
+ for (let i = 0; i < this.channelCount; i++) {
192
+ if (this.needsUpdate[i]) {
193
+ this.needsUpdate[i] = false;
194
+ this.props.onUpdate?.({ channel: i });
195
+ }
196
+ }
197
+ // Uncomment to debug
198
+ // console.log('binsFBO', new Float32Array(this.device.readPixelsToArrayWebGL(this.binSorter.texture!).buffer));
199
+ // console.log('binsBuffer', new Float32Array(this.aggregationTransform.binBuffer?.readSyncWebGL().buffer!));
200
+ // console.log('resultBuffer', new Float32Array(this.aggregationTransform.valueBuffer?.readSyncWebGL().buffer!));
201
+ }
202
+ }
203
+ //# sourceMappingURL=webgl-aggregator.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"webgl-aggregator.js","sourceRoot":"","sources":["../../../../src/common/aggregator/gpu-aggregator/webgl-aggregator.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,225 @@
1
+ // deck.gl
2
+ // SPDX-License-Identifier: MIT
3
+ // Copyright (c) vis.gl contributors
4
+ import { Model } from '@luma.gl/engine';
5
+ import { createRenderTarget } from "./utils.js";
6
+ import { binSorterUniforms } from "./bin-sorter-uniforms.js";
7
+ const COLOR_CHANNELS = [0x1, 0x2, 0x4, 0x8]; // GPU color mask RED, GREEN, BLUE, ALPHA
8
+ const MAX_FLOAT32 = 3e38;
9
+ const EMPTY_MASKS = { SUM: 0, MEAN: 0, MIN: 0, MAX: 0, COUNT: 0 };
10
+ export const TEXTURE_WIDTH = 1024;
11
+ /**
12
+ * This class manages the resources for performing the first step of aggregation
13
+ * Sort a list of data points into a number of bins
14
+ */
15
+ export class WebGLBinSorter {
16
+ constructor(device, props) {
17
+ /**
18
+ * A packed texture in which each pixel represents a bin.
19
+ * The index of the pixel in the memory layout is the bin index.
20
+ * Alpha value is the count of data points that fall into this bin
21
+ * R,G,B values are the aggregated values of each channel:
22
+ * - Sum of all data points if operation is 'SUM', or 'MEAN'
23
+ * - Min of all data points if operation is 'MIN'
24
+ * - Max of all data points if operation is 'MAX'
25
+ */
26
+ this.binsFBO = null;
27
+ this.device = device;
28
+ this.model = createModel(device, props);
29
+ }
30
+ get texture() {
31
+ return this.binsFBO ? this.binsFBO.colorAttachments[0].texture : null;
32
+ }
33
+ destroy() {
34
+ this.model.destroy();
35
+ this.binsFBO?.colorAttachments[0].texture.destroy();
36
+ this.binsFBO?.destroy();
37
+ }
38
+ getBinValues(index) {
39
+ if (!this.binsFBO) {
40
+ return null;
41
+ }
42
+ const x = index % TEXTURE_WIDTH;
43
+ const y = Math.floor(index / TEXTURE_WIDTH);
44
+ const buffer = this.device.readPixelsToArrayWebGL(this.binsFBO, {
45
+ sourceX: x,
46
+ sourceY: y,
47
+ sourceWidth: 1,
48
+ sourceHeight: 1
49
+ }).buffer;
50
+ return new Float32Array(buffer);
51
+ }
52
+ setDimensions(binCount, binIdRange) {
53
+ const width = TEXTURE_WIDTH;
54
+ const height = Math.ceil(binCount / width);
55
+ // Only destroy existing texture if it is not large enough
56
+ if (!this.binsFBO) {
57
+ this.binsFBO = createRenderTarget(this.device, width, height);
58
+ }
59
+ else if (this.binsFBO.height < height) {
60
+ this.binsFBO.resize({ width, height });
61
+ }
62
+ const binSorterProps = {
63
+ binIdRange: [
64
+ binIdRange[0][0],
65
+ binIdRange[0][1],
66
+ binIdRange[1]?.[0] || 0,
67
+ binIdRange[1]?.[1] || 0
68
+ ],
69
+ targetSize: [this.binsFBO.width, this.binsFBO.height]
70
+ };
71
+ this.model.shaderInputs.setProps({ binSorter: binSorterProps });
72
+ }
73
+ setModelProps(props) {
74
+ const model = this.model;
75
+ if (props.attributes) {
76
+ model.setAttributes(props.attributes);
77
+ }
78
+ if (props.constantAttributes) {
79
+ model.setConstantAttributes(props.constantAttributes);
80
+ }
81
+ if (props.vertexCount !== undefined) {
82
+ model.setVertexCount(props.vertexCount);
83
+ }
84
+ if (props.shaderModuleProps) {
85
+ model.shaderInputs.setProps(props.shaderModuleProps);
86
+ }
87
+ }
88
+ /** Update aggregation */
89
+ update(
90
+ /** The aggregation operation for each channel. Use null to skip update. */
91
+ operations) {
92
+ if (!this.binsFBO) {
93
+ return;
94
+ }
95
+ const masks = getMaskByOperation(operations);
96
+ this._updateBins('SUM', masks.SUM + masks.MEAN);
97
+ this._updateBins('MIN', masks.MIN);
98
+ this._updateBins('MAX', masks.MAX);
99
+ }
100
+ /** Recalculate aggregation on the given channels using the given operation */
101
+ _updateBins(operation,
102
+ /** GPU bit mask of one or more channels that should be updated */
103
+ colorMask) {
104
+ if (colorMask === 0) {
105
+ return;
106
+ }
107
+ colorMask |= COLOR_CHANNELS[3]; // Also renders to the alpha channel (point count)
108
+ const model = this.model;
109
+ const target = this.binsFBO;
110
+ const initialValue = operation === 'MAX' ? -MAX_FLOAT32 : operation === 'MIN' ? MAX_FLOAT32 : 0;
111
+ const renderPass = this.device.beginRenderPass({
112
+ id: `gpu-aggregation-${operation}`,
113
+ framebuffer: target,
114
+ parameters: {
115
+ viewport: [0, 0, target.width, target.height],
116
+ colorMask
117
+ },
118
+ clearColor: [initialValue, initialValue, initialValue, 0],
119
+ clearDepth: false,
120
+ clearStencil: false
121
+ });
122
+ model.setParameters({
123
+ blend: true,
124
+ blendColorSrcFactor: 'one',
125
+ blendColorDstFactor: 'one',
126
+ blendAlphaSrcFactor: 'one',
127
+ blendAlphaDstFactor: 'one',
128
+ blendColorOperation: operation === 'MAX' ? 'max' : operation === 'MIN' ? 'min' : 'add',
129
+ blendAlphaOperation: 'add'
130
+ });
131
+ model.draw(renderPass);
132
+ renderPass.end();
133
+ }
134
+ }
135
+ /** Convert a [channel -> operation] map to a [operation -> GPU color mask] map */
136
+ function getMaskByOperation(operations) {
137
+ const result = { ...EMPTY_MASKS };
138
+ for (let channel = 0; channel < operations.length; channel++) {
139
+ const op = operations[channel];
140
+ if (op) {
141
+ result[op] += COLOR_CHANNELS[channel];
142
+ }
143
+ }
144
+ return result;
145
+ }
146
+ function createModel(device, props) {
147
+ let userVs = props.vs;
148
+ if (props.dimensions === 2) {
149
+ // If user provides 2d bin IDs, convert them to 1d indices for data packing
150
+ userVs += /* glsl */ `
151
+ void getBin(out int binId) {
152
+ ivec2 binId2;
153
+ getBin(binId2);
154
+ if (binId2.x < binSorter.binIdRange.x || binId2.x >= binSorter.binIdRange.y) {
155
+ binId = -1;
156
+ } else {
157
+ binId = (binId2.y - binSorter.binIdRange.z) * (binSorter.binIdRange.y - binSorter.binIdRange.x) + binId2.x;
158
+ }
159
+ }
160
+ `;
161
+ }
162
+ const vs = `\
163
+ #version 300 es
164
+ #define SHADER_NAME gpu-aggregation-sort-bins-vertex
165
+
166
+ ${userVs}
167
+
168
+ out vec3 v_Value;
169
+
170
+ void main() {
171
+ int binIndex;
172
+ getBin(binIndex);
173
+ binIndex = binIndex - binSorter.binIdRange.x;
174
+ if (binIndex < 0) {
175
+ gl_Position = vec4(0.);
176
+ return;
177
+ }
178
+ int row = binIndex / binSorter.targetSize.x;
179
+ int col = binIndex - row * binSorter.targetSize.x;
180
+ vec2 position = (vec2(col, row) + 0.5) / vec2(binSorter.targetSize) * 2.0 - 1.0;
181
+ gl_Position = vec4(position, 0.0, 1.0);
182
+ gl_PointSize = 1.0;
183
+
184
+ #if NUM_CHANNELS == 3
185
+ getValue(v_Value);
186
+ #elif NUM_CHANNELS == 2
187
+ getValue(v_Value.xy);
188
+ #else
189
+ getValue(v_Value.x);
190
+ #endif
191
+ }
192
+ `;
193
+ const fs = /* glsl */ `\
194
+ #version 300 es
195
+ #define SHADER_NAME gpu-aggregation-sort-bins-fragment
196
+
197
+ precision highp float;
198
+
199
+ in vec3 v_Value;
200
+ out vec4 fragColor;
201
+
202
+ void main() {
203
+ fragColor.xyz = v_Value;
204
+
205
+ #ifdef MODULE_GEOMETRY
206
+ geometry.uv = vec2(0.);
207
+ DECKGL_FILTER_COLOR(fragColor, geometry);
208
+ #endif
209
+
210
+ fragColor.w = 1.0;
211
+ }
212
+ `;
213
+ const model = new Model(device, {
214
+ bufferLayout: props.bufferLayout,
215
+ modules: [...(props.modules || []), binSorterUniforms],
216
+ defines: { ...props.defines, NON_INSTANCED_MODEL: 1, NUM_CHANNELS: props.channelCount },
217
+ isInstanced: false,
218
+ vs,
219
+ fs,
220
+ topology: 'point-list',
221
+ disableWarnings: true
222
+ });
223
+ return model;
224
+ }
225
+ //# sourceMappingURL=webgl-bin-sorter.js.map