@luma.gl/webgl 9.3.0-alpha.4 → 9.3.0-alpha.8

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/adapter/converters/device-parameters.d.ts +1 -1
  2. package/dist/adapter/converters/device-parameters.d.ts.map +1 -1
  3. package/dist/adapter/converters/device-parameters.js +4 -1
  4. package/dist/adapter/converters/device-parameters.js.map +1 -1
  5. package/dist/adapter/converters/sampler-parameters.d.ts +1 -1
  6. package/dist/adapter/converters/sampler-parameters.d.ts.map +1 -1
  7. package/dist/adapter/converters/sampler-parameters.js +1 -1
  8. package/dist/adapter/converters/sampler-parameters.js.map +1 -1
  9. package/dist/adapter/converters/shader-formats.d.ts +1 -64
  10. package/dist/adapter/converters/shader-formats.d.ts.map +1 -1
  11. package/dist/adapter/converters/shader-formats.js +1 -64
  12. package/dist/adapter/converters/shader-formats.js.map +1 -1
  13. package/dist/adapter/converters/webgl-shadertypes.d.ts +1 -3
  14. package/dist/adapter/converters/webgl-shadertypes.d.ts.map +1 -1
  15. package/dist/adapter/converters/webgl-shadertypes.js +1 -6
  16. package/dist/adapter/converters/webgl-shadertypes.js.map +1 -1
  17. package/dist/adapter/converters/webgl-texture-table.d.ts +8 -4
  18. package/dist/adapter/converters/webgl-texture-table.d.ts.map +1 -1
  19. package/dist/adapter/converters/webgl-texture-table.js +122 -58
  20. package/dist/adapter/converters/webgl-texture-table.js.map +1 -1
  21. package/dist/adapter/converters/webgl-vertex-formats.d.ts +1 -1
  22. package/dist/adapter/converters/webgl-vertex-formats.d.ts.map +1 -1
  23. package/dist/adapter/converters/webgl-vertex-formats.js +1 -1
  24. package/dist/adapter/converters/webgl-vertex-formats.js.map +1 -1
  25. package/dist/adapter/device-helpers/webgl-device-features.d.ts +1 -1
  26. package/dist/adapter/device-helpers/webgl-device-features.d.ts.map +1 -1
  27. package/dist/adapter/device-helpers/webgl-device-features.js +1 -2
  28. package/dist/adapter/device-helpers/webgl-device-features.js.map +1 -1
  29. package/dist/adapter/device-helpers/webgl-device-info.d.ts +1 -1
  30. package/dist/adapter/device-helpers/webgl-device-info.d.ts.map +1 -1
  31. package/dist/adapter/device-helpers/webgl-device-info.js +6 -1
  32. package/dist/adapter/device-helpers/webgl-device-info.js.map +1 -1
  33. package/dist/adapter/device-helpers/webgl-device-limits.d.ts +1 -1
  34. package/dist/adapter/device-helpers/webgl-device-limits.d.ts.map +1 -1
  35. package/dist/adapter/device-helpers/webgl-device-limits.js +1 -1
  36. package/dist/adapter/device-helpers/webgl-device-limits.js.map +1 -1
  37. package/dist/adapter/helpers/format-utils.d.ts +1 -1
  38. package/dist/adapter/helpers/format-utils.d.ts.map +1 -1
  39. package/dist/adapter/helpers/format-utils.js +1 -1
  40. package/dist/adapter/helpers/format-utils.js.map +1 -1
  41. package/dist/adapter/helpers/get-shader-layout-from-glsl.js +30 -19
  42. package/dist/adapter/helpers/get-shader-layout-from-glsl.js.map +1 -1
  43. package/dist/adapter/helpers/set-uniform.d.ts +1 -1
  44. package/dist/adapter/helpers/set-uniform.d.ts.map +1 -1
  45. package/dist/adapter/helpers/set-uniform.js +1 -1
  46. package/dist/adapter/helpers/set-uniform.js.map +1 -1
  47. package/dist/adapter/helpers/webgl-texture-utils.d.ts +1 -1
  48. package/dist/adapter/helpers/webgl-texture-utils.d.ts.map +1 -1
  49. package/dist/adapter/helpers/webgl-texture-utils.js +4 -4
  50. package/dist/adapter/helpers/webgl-texture-utils.js.map +1 -1
  51. package/dist/adapter/helpers/webgl-topology-utils.d.ts +1 -1
  52. package/dist/adapter/helpers/webgl-topology-utils.d.ts.map +1 -1
  53. package/dist/adapter/helpers/webgl-topology-utils.js +1 -1
  54. package/dist/adapter/helpers/webgl-topology-utils.js.map +1 -1
  55. package/dist/adapter/resources/webgl-buffer.d.ts +1 -1
  56. package/dist/adapter/resources/webgl-buffer.d.ts.map +1 -1
  57. package/dist/adapter/resources/webgl-buffer.js +20 -5
  58. package/dist/adapter/resources/webgl-buffer.js.map +1 -1
  59. package/dist/adapter/resources/webgl-command-buffer.d.ts +3 -3
  60. package/dist/adapter/resources/webgl-command-buffer.d.ts.map +1 -1
  61. package/dist/adapter/resources/webgl-command-buffer.js +22 -36
  62. package/dist/adapter/resources/webgl-command-buffer.js.map +1 -1
  63. package/dist/adapter/resources/webgl-command-encoder.d.ts +6 -5
  64. package/dist/adapter/resources/webgl-command-encoder.d.ts.map +1 -1
  65. package/dist/adapter/resources/webgl-command-encoder.js +23 -8
  66. package/dist/adapter/resources/webgl-command-encoder.js.map +1 -1
  67. package/dist/adapter/resources/webgl-framebuffer.d.ts +3 -1
  68. package/dist/adapter/resources/webgl-framebuffer.d.ts.map +1 -1
  69. package/dist/adapter/resources/webgl-framebuffer.js +10 -1
  70. package/dist/adapter/resources/webgl-framebuffer.js.map +1 -1
  71. package/dist/adapter/resources/webgl-query-set.d.ts +37 -31
  72. package/dist/adapter/resources/webgl-query-set.d.ts.map +1 -1
  73. package/dist/adapter/resources/webgl-query-set.js +247 -96
  74. package/dist/adapter/resources/webgl-query-set.js.map +1 -1
  75. package/dist/adapter/resources/webgl-render-pass.d.ts +1 -1
  76. package/dist/adapter/resources/webgl-render-pass.d.ts.map +1 -1
  77. package/dist/adapter/resources/webgl-render-pass.js +25 -11
  78. package/dist/adapter/resources/webgl-render-pass.js.map +1 -1
  79. package/dist/adapter/resources/webgl-render-pipeline.d.ts +17 -21
  80. package/dist/adapter/resources/webgl-render-pipeline.d.ts.map +1 -1
  81. package/dist/adapter/resources/webgl-render-pipeline.js +69 -167
  82. package/dist/adapter/resources/webgl-render-pipeline.js.map +1 -1
  83. package/dist/adapter/resources/webgl-sampler.d.ts +1 -1
  84. package/dist/adapter/resources/webgl-sampler.d.ts.map +1 -1
  85. package/dist/adapter/resources/webgl-sampler.js +1 -1
  86. package/dist/adapter/resources/webgl-sampler.js.map +1 -1
  87. package/dist/adapter/resources/webgl-shader.d.ts +1 -1
  88. package/dist/adapter/resources/webgl-shader.d.ts.map +1 -1
  89. package/dist/adapter/resources/webgl-shader.js +15 -8
  90. package/dist/adapter/resources/webgl-shader.js.map +1 -1
  91. package/dist/adapter/resources/webgl-shared-render-pipeline.d.ts +24 -0
  92. package/dist/adapter/resources/webgl-shared-render-pipeline.d.ts.map +1 -0
  93. package/dist/adapter/resources/webgl-shared-render-pipeline.js +155 -0
  94. package/dist/adapter/resources/webgl-shared-render-pipeline.js.map +1 -0
  95. package/dist/adapter/resources/webgl-texture.d.ts +27 -6
  96. package/dist/adapter/resources/webgl-texture.d.ts.map +1 -1
  97. package/dist/adapter/resources/webgl-texture.js +199 -101
  98. package/dist/adapter/resources/webgl-texture.js.map +1 -1
  99. package/dist/adapter/resources/webgl-transform-feedback.js +1 -1
  100. package/dist/adapter/resources/webgl-transform-feedback.js.map +1 -1
  101. package/dist/adapter/resources/webgl-vertex-array.d.ts +2 -2
  102. package/dist/adapter/resources/webgl-vertex-array.d.ts.map +1 -1
  103. package/dist/adapter/resources/webgl-vertex-array.js +1 -1
  104. package/dist/adapter/resources/webgl-vertex-array.js.map +1 -1
  105. package/dist/adapter/webgl-device.d.ts +6 -3
  106. package/dist/adapter/webgl-device.d.ts.map +1 -1
  107. package/dist/adapter/webgl-device.js +36 -4
  108. package/dist/adapter/webgl-device.js.map +1 -1
  109. package/dist/adapter/webgl-presentation-context.d.ts +21 -0
  110. package/dist/adapter/webgl-presentation-context.d.ts.map +1 -0
  111. package/dist/adapter/webgl-presentation-context.js +64 -0
  112. package/dist/adapter/webgl-presentation-context.js.map +1 -0
  113. package/dist/constants/index.d.ts +3 -0
  114. package/dist/constants/index.d.ts.map +1 -0
  115. package/dist/constants/index.js +5 -0
  116. package/dist/constants/index.js.map +1 -0
  117. package/dist/constants/webgl-constants.d.ts +822 -0
  118. package/dist/constants/webgl-constants.d.ts.map +1 -0
  119. package/dist/constants/webgl-constants.js +928 -0
  120. package/dist/constants/webgl-constants.js.map +1 -0
  121. package/dist/constants/webgl-types.d.ts +480 -0
  122. package/dist/constants/webgl-types.d.ts.map +1 -0
  123. package/dist/constants/webgl-types.js +6 -0
  124. package/dist/constants/webgl-types.js.map +1 -0
  125. package/dist/context/debug/webgl-developer-tools.js +1 -1
  126. package/dist/context/debug/webgl-developer-tools.js.map +1 -1
  127. package/dist/context/helpers/webgl-context-data.d.ts +1 -1
  128. package/dist/context/helpers/webgl-context-data.d.ts.map +1 -1
  129. package/dist/context/helpers/webgl-extensions.d.ts +1 -1
  130. package/dist/context/helpers/webgl-extensions.d.ts.map +1 -1
  131. package/dist/context/parameters/unified-parameter-api.d.ts +1 -1
  132. package/dist/context/parameters/unified-parameter-api.d.ts.map +1 -1
  133. package/dist/context/parameters/webgl-parameter-tables.d.ts +1 -1
  134. package/dist/context/parameters/webgl-parameter-tables.d.ts.map +1 -1
  135. package/dist/context/parameters/webgl-parameter-tables.js +1 -1
  136. package/dist/context/parameters/webgl-parameter-tables.js.map +1 -1
  137. package/dist/context/polyfills/polyfill-webgl1-extensions.js +1 -1
  138. package/dist/context/polyfills/polyfill-webgl1-extensions.js.map +1 -1
  139. package/dist/dist.dev.js +1473 -824
  140. package/dist/dist.min.js +2 -2
  141. package/dist/index.cjs +3 -5491
  142. package/dist/index.cjs.map +4 -4
  143. package/dist/index.d.ts +2 -0
  144. package/dist/index.d.ts.map +1 -1
  145. package/dist/index.js +1 -0
  146. package/dist/index.js.map +1 -1
  147. package/dist/webgl-constants.d.ts +2 -0
  148. package/dist/webgl-constants.d.ts.map +1 -0
  149. package/dist/webgl-constants.js +5 -0
  150. package/dist/webgl-constants.js.map +1 -0
  151. package/dist/webgl-types.d.ts +2 -0
  152. package/dist/webgl-types.d.ts.map +1 -0
  153. package/dist/{types.js → webgl-types.js} +1 -1
  154. package/dist/webgl-types.js.map +1 -0
  155. package/package.json +18 -4
  156. package/src/adapter/converters/device-parameters.ts +6 -2
  157. package/src/adapter/converters/sampler-parameters.ts +1 -1
  158. package/src/adapter/converters/shader-formats.ts +1 -66
  159. package/src/adapter/converters/webgl-shadertypes.ts +1 -9
  160. package/src/adapter/converters/webgl-texture-table.ts +160 -68
  161. package/src/adapter/converters/webgl-vertex-formats.ts +1 -1
  162. package/src/adapter/device-helpers/webgl-device-features.ts +2 -3
  163. package/src/adapter/device-helpers/webgl-device-info.ts +7 -1
  164. package/src/adapter/device-helpers/webgl-device-limits.ts +1 -1
  165. package/src/adapter/helpers/format-utils.ts +1 -1
  166. package/src/adapter/helpers/get-shader-layout-from-glsl.ts +38 -20
  167. package/src/adapter/helpers/set-uniform.ts +1 -1
  168. package/src/adapter/helpers/webgl-texture-utils.ts +4 -4
  169. package/src/adapter/helpers/webgl-topology-utils.ts +1 -1
  170. package/src/adapter/resources/webgl-buffer.ts +17 -5
  171. package/src/adapter/resources/webgl-command-buffer.ts +28 -28
  172. package/src/adapter/resources/webgl-command-encoder.ts +28 -11
  173. package/src/adapter/resources/webgl-framebuffer.ts +12 -1
  174. package/src/adapter/resources/webgl-query-set.ts +295 -101
  175. package/src/adapter/resources/webgl-render-pass.ts +26 -13
  176. package/src/adapter/resources/webgl-render-pipeline.ts +101 -196
  177. package/src/adapter/resources/webgl-sampler.ts +1 -1
  178. package/src/adapter/resources/webgl-shader.ts +15 -8
  179. package/src/adapter/resources/webgl-shared-render-pipeline.ts +211 -0
  180. package/src/adapter/resources/webgl-texture.ts +324 -122
  181. package/src/adapter/resources/webgl-transform-feedback.ts +1 -1
  182. package/src/adapter/resources/webgl-vertex-array.ts +1 -1
  183. package/src/adapter/webgl-device.ts +50 -6
  184. package/src/adapter/webgl-presentation-context.ts +93 -0
  185. package/src/constants/index.d.ts.map +1 -0
  186. package/src/constants/index.js.map +1 -0
  187. package/src/constants/index.ts +31 -0
  188. package/src/constants/webgl-constants.d.ts.map +1 -0
  189. package/src/constants/webgl-constants.js.map +1 -0
  190. package/src/constants/webgl-constants.ts +1051 -0
  191. package/src/constants/webgl-types.d.ts.map +1 -0
  192. package/src/constants/webgl-types.js.map +1 -0
  193. package/src/constants/webgl-types.ts +813 -0
  194. package/src/context/debug/webgl-developer-tools.ts +1 -1
  195. package/src/context/helpers/webgl-context-data.ts +1 -1
  196. package/src/context/helpers/webgl-extensions.ts +1 -1
  197. package/src/context/parameters/unified-parameter-api.ts +1 -1
  198. package/src/context/parameters/webgl-parameter-tables.ts +1 -1
  199. package/src/context/polyfills/polyfill-webgl1-extensions.ts +1 -1
  200. package/src/index.ts +26 -0
  201. package/src/webgl-constants.d.ts.map +1 -0
  202. package/src/webgl-constants.js.map +1 -0
  203. package/src/webgl-constants.ts +5 -0
  204. package/src/webgl-types.d.ts.map +1 -0
  205. package/src/webgl-types.js.map +1 -0
  206. package/src/webgl-types.ts +29 -0
  207. package/dist/types.d.ts +0 -11
  208. package/dist/types.d.ts.map +0 -1
  209. package/dist/types.js.map +0 -1
  210. package/src/types.ts +0 -14
@@ -8,15 +8,15 @@ import type {
8
8
  PrimitiveTopology,
9
9
  ShaderLayout,
10
10
  UniformValue,
11
- Binding,
11
+ Bindings,
12
+ BindingsByGroup,
12
13
  RenderPass,
13
14
  VertexArray
14
15
  } from '@luma.gl/core';
15
- import {RenderPipeline, log} from '@luma.gl/core';
16
+ import {RenderPipeline, flattenBindingsByGroup, log, normalizeBindingsByGroup} from '@luma.gl/core';
16
17
  // import {getAttributeInfosFromLayouts} from '@luma.gl/core';
17
- import {GL} from '@luma.gl/constants';
18
+ import {GL} from '@luma.gl/webgl/constants';
18
19
 
19
- import {getShaderLayoutFromGLSL} from '../helpers/get-shader-layout-from-glsl';
20
20
  import {withDeviceAndGLParameters} from '../converters/device-parameters';
21
21
  import {setUniform} from '../helpers/set-uniform';
22
22
  // import {copyUniform, checkUniformValues} from '../../classes/uniforms';
@@ -30,8 +30,7 @@ import {WEBGLTextureView} from './webgl-texture-view';
30
30
  import {WEBGLRenderPass} from './webgl-render-pass';
31
31
  import {WEBGLTransformFeedback} from './webgl-transform-feedback';
32
32
  import {getGLDrawMode} from '../helpers/webgl-topology-utils';
33
-
34
- const LOG_PROGRAM_PERF_PRIORITY = 4;
33
+ import {WEBGLSharedRenderPipeline} from './webgl-shared-render-pipeline';
35
34
 
36
35
  /** Creates a new render pipeline */
37
36
  export class WEBGLRenderPipeline extends RenderPipeline {
@@ -46,10 +45,10 @@ export class WEBGLRenderPipeline extends RenderPipeline {
46
45
  /** The layout extracted from shader by WebGL introspection APIs */
47
46
  introspectedLayout: ShaderLayout;
48
47
 
49
- /** Uniforms set on this model */
48
+ /** Compatibility path for direct pipeline.setBindings() usage */
49
+ bindings: Bindings = {};
50
+ /** Compatibility path for direct pipeline.uniforms usage */
50
51
  uniforms: Record<string, UniformValue> = {};
51
- /** Bindings set on this model */
52
- bindings: Record<string, Binding> = {};
53
52
  /** WebGL varyings */
54
53
  varyings: string[] | null = null;
55
54
 
@@ -63,64 +62,47 @@ export class WEBGLRenderPipeline extends RenderPipeline {
63
62
  constructor(device: WebGLDevice, props: RenderPipelineProps) {
64
63
  super(device, props);
65
64
  this.device = device;
66
- this.handle = this.props.handle || this.device.gl.createProgram();
65
+ const webglSharedRenderPipeline =
66
+ (this.sharedRenderPipeline as WEBGLSharedRenderPipeline | null) ||
67
+ (this.device._createSharedRenderPipelineWebGL(props) as WEBGLSharedRenderPipeline);
68
+
69
+ this.sharedRenderPipeline = webglSharedRenderPipeline;
70
+ this.handle = webglSharedRenderPipeline.handle;
71
+ this.vs = webglSharedRenderPipeline.vs;
72
+ this.fs = webglSharedRenderPipeline.fs;
73
+ this.linkStatus = webglSharedRenderPipeline.linkStatus;
74
+ this.introspectedLayout = webglSharedRenderPipeline.introspectedLayout;
67
75
  this.device._setWebGLDebugMetadata(this.handle, this, {spector: {id: this.props.id}});
68
76
 
69
- // Create shaders if needed
70
- this.vs = props.vs as WEBGLShader;
71
- this.fs = props.fs as WEBGLShader;
72
- // assert(this.vs.stage === 'vertex');
73
- // assert(this.fs.stage === 'fragment');
74
-
75
- // Setup varyings if supplied
76
- // @ts-expect-error WebGL only
77
- const {varyings, bufferMode = GL.SEPARATE_ATTRIBS} = props;
78
- if (varyings && varyings.length > 0) {
79
- this.varyings = varyings;
80
- this.device.gl.transformFeedbackVaryings(this.handle, varyings, bufferMode);
81
- }
82
-
83
- this._linkShaders();
84
- log.time(3, `RenderPipeline ${this.id} - shaderLayout introspection`)();
85
- this.introspectedLayout = getShaderLayoutFromGLSL(this.device.gl, this.handle);
86
- log.timeEnd(3, `RenderPipeline ${this.id} - shaderLayout introspection`)();
87
-
88
- // Merge provided layout with introspected layout
77
+ // WebGL only honors shaderLayout overrides for attributes that already exist in the
78
+ // linked program, and only the `type` / `stepMode` fields participate in the merge.
79
+ // Bindings and unknown attributes are ignored. If WebGL cache keys ever depend on
80
+ // `shaderLayout`, they need to match these merge semantics rather than the raw prop.
89
81
  this.shaderLayout = props.shaderLayout
90
82
  ? mergeShaderLayout(this.introspectedLayout, props.shaderLayout)
91
83
  : this.introspectedLayout;
92
84
  }
93
85
 
94
86
  override destroy(): void {
95
- if (this.handle) {
96
- // log.error(`Deleting program ${this.id}`)();
97
- this.device.gl.useProgram(null);
98
- this.device.gl.deleteProgram(this.handle);
99
- this.destroyed = true;
100
- // @ts-expect-error
101
- this.handle.destroyed = true;
102
- // @ts-ignore
103
- this.handle = null;
87
+ if (this.destroyed) {
88
+ return;
89
+ }
90
+ if (this.sharedRenderPipeline && !this.props._sharedRenderPipeline) {
91
+ this.sharedRenderPipeline.destroy();
104
92
  }
93
+ this.destroyResource();
105
94
  }
106
95
 
107
96
  /**
108
- * Bindings include: textures, samplers and uniform buffers
109
- * @todo needed for portable model
97
+ * Compatibility shim for code paths that still set bindings on the pipeline.
98
+ * Shared-model draws pass bindings per draw and do not rely on this state.
110
99
  */
111
- setBindings(bindings: Record<string, Binding>, options?: {disableWarnings?: boolean}): void {
112
- // if (log.priority >= 2) {
113
- // checkUniformValues(uniforms, this.id, this._uniformSetters);
114
- // }
115
-
116
- for (const [name, value] of Object.entries(bindings)) {
117
- // Accept both `xyz` and `xyzUniforms` as valid names for `xyzUniforms` uniform block
118
- // This convention allows shaders to name uniform blocks as `uniform appUniforms {} app;`
119
- // and reference them as `app` from both GLSL and JS.
120
- // TODO - this is rather hacky - we could also remap the name directly in the shader layout.
121
- const binding =
122
- this.shaderLayout.bindings.find(binding_ => binding_.name === name) ||
123
- this.shaderLayout.bindings.find(binding_ => binding_.name === `${name}Uniforms`);
100
+ setBindings(bindings: Bindings | BindingsByGroup, options?: {disableWarnings?: boolean}): void {
101
+ const flatBindings = flattenBindingsByGroup(
102
+ normalizeBindingsByGroup(this.shaderLayout, bindings)
103
+ );
104
+ for (const [name, value] of Object.entries(flatBindings)) {
105
+ const binding = getShaderLayoutBindingByName(this.shaderLayout, name);
124
106
 
125
107
  if (!binding) {
126
108
  const validBindings = this.shaderLayout.bindings
@@ -132,7 +114,7 @@ export class WEBGLRenderPipeline extends RenderPipeline {
132
114
  value
133
115
  )();
134
116
  }
135
- continue; // eslint-disable-line no-continue
117
+ continue;
136
118
  }
137
119
  if (!value) {
138
120
  log.warn(`Unsetting binding "${name}" in render pipeline "${this.id}"`)();
@@ -184,7 +166,16 @@ export class WEBGLRenderPipeline extends RenderPipeline {
184
166
  firstInstance?: number;
185
167
  baseVertex?: number;
186
168
  transformFeedback?: WEBGLTransformFeedback;
169
+ bindings?: Bindings;
170
+ bindGroups?: BindingsByGroup;
171
+ _bindGroupCacheKeys?: Partial<Record<number, object>>;
172
+ uniforms?: Record<string, UniformValue>;
187
173
  }): boolean {
174
+ this._syncLinkStatus();
175
+ const drawBindings = options.bindGroups
176
+ ? flattenBindingsByGroup(options.bindGroups)
177
+ : options.bindings || this.bindings;
178
+
188
179
  const {
189
180
  renderPass,
190
181
  parameters = this.props.parameters,
@@ -198,7 +189,8 @@ export class WEBGLRenderPipeline extends RenderPipeline {
198
189
  // firstIndex,
199
190
  // firstInstance,
200
191
  // baseVertex,
201
- transformFeedback
192
+ transformFeedback,
193
+ uniforms = this.uniforms
202
194
  } = options;
203
195
 
204
196
  const glDrawMode = getGLDrawMode(topology);
@@ -216,7 +208,7 @@ export class WEBGLRenderPipeline extends RenderPipeline {
216
208
  // Note: async textures set as uniforms might still be loading.
217
209
  // Now that all uniforms have been updated, check if any texture
218
210
  // in the uniforms is not yet initialized, then we don't draw
219
- if (!this._areTexturesRenderable()) {
211
+ if (!this._areTexturesRenderable(drawBindings)) {
220
212
  log.info(2, `RenderPipeline:${this.id}.draw() aborted - textures not yet loaded`)();
221
213
  // Note: false means that the app needs to redraw the pipeline again.
222
214
  return false;
@@ -239,8 +231,8 @@ export class WEBGLRenderPipeline extends RenderPipeline {
239
231
  }
240
232
 
241
233
  // We have to apply bindings before every draw call since other draw calls will overwrite
242
- this._applyBindings();
243
- this._applyUniforms();
234
+ this._applyBindings(drawBindings, {disableWarnings: this.props.disableWarnings});
235
+ this._applyUniforms(uniforms);
244
236
 
245
237
  const webglRenderPass = renderPass as WEBGLRenderPass;
246
238
 
@@ -278,138 +270,16 @@ export class WEBGLRenderPipeline extends RenderPipeline {
278
270
  return true;
279
271
  }
280
272
 
281
- // PRIVATE METHODS
282
-
283
- // setAttributes(attributes: Record<string, Buffer>): void {}
284
- // setBindings(bindings: Record<string, Binding>): void {}
285
-
286
- protected async _linkShaders() {
287
- const {gl} = this.device;
288
- gl.attachShader(this.handle, this.vs.handle);
289
- gl.attachShader(this.handle, this.fs.handle);
290
- log.time(LOG_PROGRAM_PERF_PRIORITY, `linkProgram for ${this.id}`)();
291
- gl.linkProgram(this.handle);
292
- log.timeEnd(LOG_PROGRAM_PERF_PRIORITY, `linkProgram for ${this.id}`)();
293
-
294
- // TODO Avoid checking program linking error in production
295
- if (log.level === 0) {
296
- // return;
297
- }
298
-
299
- if (!this.device.features.has('compilation-status-async-webgl')) {
300
- const status = this._getLinkStatus();
301
- this._reportLinkStatus(status);
302
- return;
303
- }
304
-
305
- // async case
306
- log.once(1, 'RenderPipeline linking is asynchronous')();
307
- await this._waitForLinkComplete();
308
- log.info(2, `RenderPipeline ${this.id} - async linking complete: ${this.linkStatus}`)();
309
- const status = this._getLinkStatus();
310
- this._reportLinkStatus(status);
311
- }
312
-
313
- /** Report link status. First, check for shader compilation failures if linking fails */
314
- async _reportLinkStatus(status: 'success' | 'link-error' | 'validation-error'): Promise<void> {
315
- switch (status) {
316
- case 'success':
317
- return;
318
-
319
- default:
320
- const errorType = status === 'link-error' ? 'Link error' : 'Validation error';
321
- // First check for shader compilation failures if linking fails
322
- switch (this.vs.compilationStatus) {
323
- case 'error':
324
- this.vs.debugShader();
325
- throw new Error(`${this} ${errorType} during compilation of ${this.vs}`);
326
- case 'pending':
327
- await this.vs.asyncCompilationStatus;
328
- this.vs.debugShader();
329
- break;
330
- case 'success':
331
- break;
332
- }
333
-
334
- switch (this.fs?.compilationStatus) {
335
- case 'error':
336
- this.fs.debugShader();
337
- throw new Error(`${this} ${errorType} during compilation of ${this.fs}`);
338
- case 'pending':
339
- await this.fs.asyncCompilationStatus;
340
- this.fs.debugShader();
341
- break;
342
- case 'success':
343
- break;
344
- }
345
-
346
- const linkErrorLog = this.device.gl.getProgramInfoLog(this.handle);
347
- this.device.reportError(
348
- new Error(`${errorType} during ${status}: ${linkErrorLog}`),
349
- this
350
- )();
351
- this.device.debug();
352
- }
353
- }
354
-
355
- /**
356
- * Get the shader compilation status
357
- * TODO - Load log even when no error reported, to catch warnings?
358
- * https://gamedev.stackexchange.com/questions/30429/how-to-detect-glsl-warnings
359
- */
360
- _getLinkStatus(): 'success' | 'link-error' | 'validation-error' {
361
- const {gl} = this.device;
362
- const linked = gl.getProgramParameter(this.handle, GL.LINK_STATUS);
363
- if (!linked) {
364
- this.linkStatus = 'error';
365
- return 'link-error';
366
- }
367
-
368
- gl.validateProgram(this.handle);
369
- const validated = gl.getProgramParameter(this.handle, GL.VALIDATE_STATUS);
370
- if (!validated) {
371
- this.linkStatus = 'error';
372
- return 'validation-error';
373
- }
374
-
375
- this.linkStatus = 'success';
376
- return 'success';
377
- }
378
-
379
- /** Use KHR_parallel_shader_compile extension if available */
380
- async _waitForLinkComplete(): Promise<void> {
381
- const waitMs = async (ms: number) => await new Promise(resolve => setTimeout(resolve, ms));
382
- const DELAY_MS = 10; // Shader compilation is typically quite fast (with some exceptions)
383
-
384
- // If status polling is not available, we can't wait for completion. Just wait a little to minimize blocking
385
- if (!this.device.features.has('compilation-status-async-webgl')) {
386
- await waitMs(DELAY_MS);
387
- return;
388
- }
389
-
390
- const {gl} = this.device;
391
- for (;;) {
392
- const complete = gl.getProgramParameter(this.handle, GL.COMPLETION_STATUS_KHR);
393
- if (complete) {
394
- return;
395
- }
396
- await waitMs(DELAY_MS);
397
- }
398
- }
399
-
400
273
  /**
401
274
  * Checks if all texture-values uniforms are renderable (i.e. loaded)
402
275
  * Update a texture if needed (e.g. from video)
403
276
  * Note: This is currently done before every draw call
404
277
  */
405
- _areTexturesRenderable() {
278
+ _areTexturesRenderable(bindings: Bindings) {
406
279
  let texturesRenderable = true;
407
280
 
408
281
  for (const bindingInfo of this.shaderLayout.bindings) {
409
- if (
410
- !this.bindings[bindingInfo.name] &&
411
- !this.bindings[bindingInfo.name.replace(/Uniforms$/, '')]
412
- ) {
282
+ if (!getBindingValueForLayoutBinding(bindings, bindingInfo.name)) {
413
283
  log.warn(`Binding ${bindingInfo.name} not found in ${this.id}`)();
414
284
  texturesRenderable = false;
415
285
  }
@@ -426,7 +296,9 @@ export class WEBGLRenderPipeline extends RenderPipeline {
426
296
  }
427
297
 
428
298
  /** Apply any bindings (before each draw call) */
429
- _applyBindings() {
299
+ _applyBindings(bindings: Bindings, _options?: {disableWarnings?: boolean}) {
300
+ this._syncLinkStatus();
301
+
430
302
  // If we are using async linking, we need to wait until linking completes
431
303
  if (this.linkStatus !== 'success') {
432
304
  return;
@@ -438,9 +310,7 @@ export class WEBGLRenderPipeline extends RenderPipeline {
438
310
  let textureUnit = 0;
439
311
  let uniformBufferIndex = 0;
440
312
  for (const binding of this.shaderLayout.bindings) {
441
- // Accept both `xyz` and `xyzUniforms` as valid names for `xyzUniforms` uniform block
442
- const value =
443
- this.bindings[binding.name] || this.bindings[binding.name.replace(/Uniforms$/, '')];
313
+ const value = getBindingValueForLayoutBinding(bindings, binding.name);
444
314
  if (!value) {
445
315
  throw new Error(`No value for binding ${binding.name} in ${this.id}`);
446
316
  }
@@ -456,15 +326,13 @@ export class WEBGLRenderPipeline extends RenderPipeline {
456
326
  if (value instanceof WEBGLBuffer) {
457
327
  gl.bindBufferBase(GL.UNIFORM_BUFFER, uniformBufferIndex, value.handle);
458
328
  } else {
329
+ const bufferBinding = value as {buffer: WEBGLBuffer; offset?: number; size?: number};
459
330
  gl.bindBufferRange(
460
331
  GL.UNIFORM_BUFFER,
461
332
  uniformBufferIndex,
462
- // @ts-expect-error
463
- value.buffer.handle,
464
- // @ts-expect-error
465
- value.offset || 0,
466
- // @ts-expect-error
467
- value.size || value.buffer.byteLength - value.offset
333
+ bufferBinding.buffer.handle,
334
+ bufferBinding.offset || 0,
335
+ bufferBinding.size || bufferBinding.buffer.byteLength - (bufferBinding.offset || 0)
468
336
  );
469
337
  }
470
338
  uniformBufferIndex += 1;
@@ -518,15 +386,19 @@ export class WEBGLRenderPipeline extends RenderPipeline {
518
386
  * Due to program sharing, uniforms need to be reset before every draw call
519
387
  * (though caching will avoid redundant WebGL calls)
520
388
  */
521
- _applyUniforms() {
389
+ _applyUniforms(uniforms: Record<string, UniformValue>) {
522
390
  for (const uniformLayout of this.shaderLayout.uniforms || []) {
523
391
  const {name, location, type, textureUnit} = uniformLayout;
524
- const value = this.uniforms[name] ?? textureUnit;
392
+ const value = uniforms[name] ?? textureUnit;
525
393
  if (value !== undefined) {
526
394
  setUniform(this.device.gl, location, type, value);
527
395
  }
528
396
  }
529
397
  }
398
+
399
+ private _syncLinkStatus(): void {
400
+ this.linkStatus = (this.sharedRenderPipeline as WEBGLSharedRenderPipeline).linkStatus;
401
+ }
530
402
  }
531
403
 
532
404
  /**
@@ -539,7 +411,8 @@ function mergeShaderLayout(baseLayout: ShaderLayout, overrideLayout: ShaderLayou
539
411
  // Deep clone the base layout
540
412
  const mergedLayout: ShaderLayout = {
541
413
  ...baseLayout,
542
- attributes: baseLayout.attributes.map(attribute => ({...attribute}))
414
+ attributes: baseLayout.attributes.map(attribute => ({...attribute})),
415
+ bindings: baseLayout.bindings.map(binding => ({...binding}))
543
416
  };
544
417
  // Merge the attributes
545
418
  for (const attribute of overrideLayout?.attributes || []) {
@@ -551,5 +424,37 @@ function mergeShaderLayout(baseLayout: ShaderLayout, overrideLayout: ShaderLayou
551
424
  baseAttribute.stepMode = attribute.stepMode || baseAttribute.stepMode;
552
425
  }
553
426
  }
427
+
428
+ for (const binding of overrideLayout?.bindings || []) {
429
+ const baseBinding = getShaderLayoutBindingByName(mergedLayout, binding.name);
430
+ if (!baseBinding) {
431
+ log.warn(`shader layout binding ${binding.name} not present in shader`);
432
+ continue;
433
+ }
434
+ Object.assign(baseBinding, binding);
435
+ }
554
436
  return mergedLayout;
555
437
  }
438
+
439
+ function getShaderLayoutBindingByName(
440
+ shaderLayout: ShaderLayout,
441
+ bindingName: string
442
+ ): ShaderLayout['bindings'][number] | undefined {
443
+ return shaderLayout.bindings.find(
444
+ binding =>
445
+ binding.name === bindingName ||
446
+ binding.name === `${bindingName}Uniforms` ||
447
+ `${binding.name}Uniforms` === bindingName
448
+ );
449
+ }
450
+
451
+ function getBindingValueForLayoutBinding(
452
+ bindings: Bindings,
453
+ bindingName: string
454
+ ): Bindings[string] | undefined {
455
+ return (
456
+ bindings[bindingName] ||
457
+ bindings[`${bindingName}Uniforms`] ||
458
+ bindings[bindingName.replace(/Uniforms$/, '')]
459
+ );
460
+ }
@@ -3,7 +3,7 @@
3
3
  // Copyright (c) vis.gl contributors
4
4
 
5
5
  import {Sampler, SamplerProps} from '@luma.gl/core';
6
- import {GL, GLSamplerParameters} from '@luma.gl/constants';
6
+ import {GL, GLSamplerParameters} from '@luma.gl/webgl/constants';
7
7
  import {convertSamplerParametersToWebGL} from '../converters/sampler-parameters';
8
8
  import type {WebGLDevice} from '../webgl-device';
9
9
 
@@ -3,7 +3,7 @@
3
3
  // Copyright (c) vis.gl contributors
4
4
 
5
5
  import {Shader, ShaderProps, CompilerMessage, log} from '@luma.gl/core';
6
- import {GL} from '@luma.gl/constants';
6
+ import {GL} from '@luma.gl/webgl/constants';
7
7
  import {parseShaderCompilerLog} from '../helpers/parse-shader-compiler-log';
8
8
  import {WebGLDevice} from '../webgl-device';
9
9
 
@@ -31,7 +31,13 @@ export class WEBGLShader extends Shader {
31
31
  // default framebuffer handle is null, so we can't set spector metadata...
32
32
  device._setWebGLDebugMetadata(this.handle, this, {spector: this.props});
33
33
 
34
- this._compile(this.source);
34
+ const compilationStatus = this._compile(this.source);
35
+ if (compilationStatus && typeof compilationStatus.catch === 'function') {
36
+ compilationStatus.catch(() => {
37
+ // Ensure any async compile status errors are consumed.
38
+ this.compilationStatus = 'error';
39
+ });
40
+ }
35
41
  }
36
42
 
37
43
  override destroy(): void {
@@ -71,7 +77,7 @@ export class WEBGLShader extends Shader {
71
77
  // PRIVATE METHODS
72
78
 
73
79
  /** Compile a shader and get compilation status */
74
- protected async _compile(source: string): Promise<void> {
80
+ protected _compile(source: string): void | Promise<void> {
75
81
  source = source.startsWith('#version ') ? source : `#version 300 es\n${source}`;
76
82
 
77
83
  const {gl} = this.device;
@@ -97,12 +103,13 @@ export class WEBGLShader extends Shader {
97
103
 
98
104
  // async case
99
105
  log.once(1, 'Shader compilation is asynchronous')();
100
- await this._waitForCompilationComplete();
101
- log.info(2, `Shader ${this.id} - async compilation complete: ${this.compilationStatus}`)();
102
- this._getCompilationStatus();
106
+ return this._waitForCompilationComplete().then(() => {
107
+ log.info(2, `Shader ${this.id} - async compilation complete: ${this.compilationStatus}`)();
108
+ this._getCompilationStatus();
103
109
 
104
- // The `Shader` base class will determine if debug window should be opened based on this.compilationStatus
105
- this.debugShader();
110
+ // The `Shader` base class will determine if debug window should be opened based on this.compilationStatus
111
+ this.debugShader();
112
+ });
106
113
  }
107
114
 
108
115
  /** Use KHR_parallel_shader_compile extension if available */