@babylonjs/core 7.3.2 → 7.3.3

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 (68) hide show
  1. package/Compute/computeEffect.js +4 -4
  2. package/Compute/computeEffect.js.map +1 -1
  3. package/Engines/IPipelineContext.d.ts +3 -0
  4. package/Engines/IPipelineContext.js.map +1 -1
  5. package/Engines/Native/nativePipelineContext.d.ts +2 -0
  6. package/Engines/Native/nativePipelineContext.js +3 -0
  7. package/Engines/Native/nativePipelineContext.js.map +1 -1
  8. package/Engines/Processors/iShaderProcessor.d.ts +3 -2
  9. package/Engines/Processors/iShaderProcessor.js.map +1 -1
  10. package/Engines/Processors/shaderProcessor.d.ts +15 -23
  11. package/Engines/Processors/shaderProcessor.js +332 -320
  12. package/Engines/Processors/shaderProcessor.js.map +1 -1
  13. package/Engines/WebGL/webGLPipelineContext.d.ts +2 -0
  14. package/Engines/WebGL/webGLPipelineContext.js +3 -0
  15. package/Engines/WebGL/webGLPipelineContext.js.map +1 -1
  16. package/Engines/WebGL/webGLShaderProcessors.d.ts +3 -2
  17. package/Engines/WebGL/webGLShaderProcessors.js +2 -2
  18. package/Engines/WebGL/webGLShaderProcessors.js.map +1 -1
  19. package/Engines/WebGPU/Extensions/engine.computeShader.js +1 -1
  20. package/Engines/WebGPU/Extensions/engine.computeShader.js.map +1 -1
  21. package/Engines/WebGPU/webgpuPipelineContext.d.ts +2 -0
  22. package/Engines/WebGPU/webgpuPipelineContext.js +3 -0
  23. package/Engines/WebGPU/webgpuPipelineContext.js.map +1 -1
  24. package/Engines/WebGPU/webgpuShaderProcessorsGLSL.d.ts +3 -2
  25. package/Engines/WebGPU/webgpuShaderProcessorsGLSL.js +2 -4
  26. package/Engines/WebGPU/webgpuShaderProcessorsGLSL.js.map +1 -1
  27. package/Engines/abstractEngine.d.ts +10 -5
  28. package/Engines/abstractEngine.functions.d.ts +38 -0
  29. package/Engines/abstractEngine.functions.js +75 -0
  30. package/Engines/abstractEngine.functions.js.map +1 -0
  31. package/Engines/abstractEngine.js +22 -14
  32. package/Engines/abstractEngine.js.map +1 -1
  33. package/Engines/constants.d.ts +2 -0
  34. package/Engines/constants.js +2 -0
  35. package/Engines/constants.js.map +1 -1
  36. package/Engines/thinEngine.d.ts +11 -6
  37. package/Engines/thinEngine.functions.d.ts +96 -0
  38. package/Engines/thinEngine.functions.js +249 -0
  39. package/Engines/thinEngine.functions.js.map +1 -0
  40. package/Engines/thinEngine.js +50 -129
  41. package/Engines/thinEngine.js.map +1 -1
  42. package/Engines/webgpuEngine.js +5 -1
  43. package/Engines/webgpuEngine.js.map +1 -1
  44. package/Materials/Node/Blocks/Dual/textureBlock.js +3 -3
  45. package/Materials/Node/Blocks/Dual/textureBlock.js.map +1 -1
  46. package/Materials/Textures/Procedurals/proceduralTexture.d.ts +9 -1
  47. package/Materials/Textures/Procedurals/proceduralTexture.js +16 -0
  48. package/Materials/Textures/Procedurals/proceduralTexture.js.map +1 -1
  49. package/Materials/effect.d.ts +11 -6
  50. package/Materials/effect.functions.d.ts +86 -0
  51. package/Materials/effect.functions.js +185 -0
  52. package/Materials/effect.functions.js.map +1 -0
  53. package/Materials/effect.js +94 -153
  54. package/Materials/effect.js.map +1 -1
  55. package/Materials/effect.webgl.functions.d.ts +13 -0
  56. package/Materials/effect.webgl.functions.js +83 -0
  57. package/Materials/effect.webgl.functions.js.map +1 -0
  58. package/Materials/materialPluginManager.js +2 -2
  59. package/Materials/materialPluginManager.js.map +1 -1
  60. package/Meshes/Compression/dracoCompression.js.map +1 -1
  61. package/Meshes/Compression/dracoCompressionWorker.d.ts +1 -1
  62. package/Meshes/Compression/dracoCompressionWorker.js +21 -10
  63. package/Meshes/Compression/dracoCompressionWorker.js.map +1 -1
  64. package/Meshes/Node/nodeGeometryBlock.js +1 -0
  65. package/Meshes/Node/nodeGeometryBlock.js.map +1 -1
  66. package/Misc/fileTools.js +4 -3
  67. package/Misc/fileTools.js.map +1 -1
  68. package/package.json +1 -1
@@ -1,10 +1,9 @@
1
1
  import { Observable } from "../Misc/observable.js";
2
2
 
3
- import { GetDOMTextContent, IsWindowObjectExist } from "../Misc/domManagement.js";
4
3
  import { Logger } from "../Misc/logger.js";
5
- import { ShaderProcessor } from "../Engines/Processors/shaderProcessor.js";
6
4
  import { ShaderStore as EngineShaderStore } from "../Engines/shaderStore.js";
7
5
  import { ShaderLanguage } from "./shaderLanguage.js";
6
+ import { _processShaderCode, getCachedPipeline, createAndPreparePipelineContext, resetCachedPipeline } from "./effect.functions.js";
8
7
  /**
9
8
  * Effect containing vertex and fragment shader that can be executed on an object.
10
9
  */
@@ -123,6 +122,8 @@ export class Effect {
123
122
  this._processFinalCode = null;
124
123
  this.name = baseName;
125
124
  this._key = key;
125
+ const pipelineName = this._key.replace(/\r/g, "").replace(/\n/g, "|");
126
+ let cachedPipeline = undefined;
126
127
  if (attributesNamesOrOptions.attributes) {
127
128
  const options = attributesNamesOrOptions;
128
129
  this._engine = uniformsNamesOrEngine;
@@ -145,6 +146,7 @@ export class Effect {
145
146
  }
146
147
  this._processFinalCode = options.processFinalCode ?? null;
147
148
  this._processCodeAfterIncludes = options.processCodeAfterIncludes ?? undefined;
149
+ cachedPipeline = options.existingPipelineContext;
148
150
  }
149
151
  else {
150
152
  this._engine = engine;
@@ -159,42 +161,29 @@ export class Effect {
159
161
  this._indexParameters = indexParameters;
160
162
  this._fallbacks = fallbacks;
161
163
  }
164
+ // Use the cache if we can. For now, WebGL2 only.
165
+ if (this._engine.shaderPlatformName === "WEBGL2") {
166
+ cachedPipeline = getCachedPipeline(pipelineName, this._engine._gl) ?? cachedPipeline;
167
+ }
162
168
  this._attributeLocationByName = {};
163
169
  this.uniqueId = Effect._UniqueIdSeed++;
164
- this._processShaderCode();
165
- }
166
- /** @internal */
167
- _processShaderCode(shaderProcessor = null, keepExistingPipelineContext = false) {
168
- let vertexSource;
169
- let fragmentSource;
170
- const baseName = this.name;
171
- const hostDocument = IsWindowObjectExist() ? this._engine.getHostDocument() : null;
172
- if (typeof baseName === "string") {
173
- vertexSource = baseName;
174
- }
175
- else if (baseName.vertexSource) {
176
- vertexSource = "source:" + baseName.vertexSource;
177
- }
178
- else if (baseName.vertexElement) {
179
- vertexSource = hostDocument?.getElementById(baseName.vertexElement) || baseName.vertexElement;
180
- }
181
- else {
182
- vertexSource = baseName.vertex || baseName;
183
- }
184
- if (typeof baseName === "string") {
185
- fragmentSource = baseName;
186
- }
187
- else if (baseName.fragmentSource) {
188
- fragmentSource = "source:" + baseName.fragmentSource;
189
- }
190
- else if (baseName.fragmentElement) {
191
- fragmentSource = hostDocument?.getElementById(baseName.fragmentElement) || baseName.fragmentElement;
170
+ if (!cachedPipeline) {
171
+ this._processShaderCode();
192
172
  }
193
173
  else {
194
- fragmentSource = baseName.fragment || baseName;
174
+ this._pipelineContext = cachedPipeline;
175
+ this._pipelineContext.setEngine(this._engine);
176
+ this._onRenderingStateCompiled(this._pipelineContext);
177
+ // rebuildRebind for spector
178
+ if (this._pipelineContext.program) {
179
+ this._pipelineContext.program.__SPECTOR_rebuildProgram = this._rebuildProgram.bind(this);
180
+ }
195
181
  }
182
+ }
183
+ /** @internal */
184
+ _processShaderCode(shaderProcessor = null, keepExistingPipelineContext = false) {
196
185
  this._processingContext = this._engine._getShaderProcessingContext(this._shaderLanguage);
197
- let processorOptions = {
186
+ const processorOptions = {
198
187
  defines: this.defines.split("\n"),
199
188
  indexParameters: this._indexParameters,
200
189
  isFragment: false,
@@ -210,52 +199,11 @@ export class Effect {
210
199
  useReverseDepthBuffer: this._engine.useReverseDepthBuffer,
211
200
  processCodeAfterIncludes: this._processCodeAfterIncludes,
212
201
  };
213
- const shaderCodes = [undefined, undefined];
214
- const shadersLoaded = () => {
215
- if (shaderCodes[0] && shaderCodes[1]) {
216
- processorOptions.isFragment = true;
217
- const [migratedVertexCode, fragmentCode] = shaderCodes;
218
- ShaderProcessor.Process(fragmentCode, processorOptions, (migratedFragmentCode, codeBeforeMigration) => {
219
- this._fragmentSourceCodeBeforeMigration = codeBeforeMigration;
220
- if (this._processFinalCode) {
221
- migratedFragmentCode = this._processFinalCode("fragment", migratedFragmentCode);
222
- }
223
- const finalShaders = ShaderProcessor.Finalize(migratedVertexCode, migratedFragmentCode, processorOptions);
224
- processorOptions = null;
225
- this._useFinalCode(finalShaders.vertexCode, finalShaders.fragmentCode, baseName, keepExistingPipelineContext);
226
- }, this._engine);
227
- }
228
- };
229
- this._loadShader(vertexSource, "Vertex", "", (vertexCode) => {
230
- ShaderProcessor.Initialize(processorOptions);
231
- ShaderProcessor.Process(vertexCode, processorOptions, (migratedVertexCode, codeBeforeMigration) => {
232
- this._rawVertexSourceCode = vertexCode;
233
- this._vertexSourceCodeBeforeMigration = codeBeforeMigration;
234
- if (this._processFinalCode) {
235
- migratedVertexCode = this._processFinalCode("vertex", migratedVertexCode);
236
- }
237
- shaderCodes[0] = migratedVertexCode;
238
- shadersLoaded();
239
- }, this._engine);
240
- });
241
- this._loadShader(fragmentSource, "Fragment", "Pixel", (fragmentCode) => {
242
- this._rawFragmentSourceCode = fragmentCode;
243
- shaderCodes[1] = fragmentCode;
244
- shadersLoaded();
245
- });
246
- }
247
- _useFinalCode(migratedVertexCode, migratedFragmentCode, baseName, keepExistingPipelineContext = false) {
248
- if (baseName) {
249
- const vertex = baseName.vertexElement || baseName.vertex || baseName.spectorName || baseName;
250
- const fragment = baseName.fragmentElement || baseName.fragment || baseName.spectorName || baseName;
251
- this._vertexSourceCode = (this._shaderLanguage === ShaderLanguage.WGSL ? "//" : "") + "#define SHADER_NAME vertex:" + vertex + "\n" + migratedVertexCode;
252
- this._fragmentSourceCode = (this._shaderLanguage === ShaderLanguage.WGSL ? "//" : "") + "#define SHADER_NAME fragment:" + fragment + "\n" + migratedFragmentCode;
253
- }
254
- else {
202
+ _processShaderCode(processorOptions, this.name, this._processFinalCode, (migratedVertexCode, migratedFragmentCode) => {
255
203
  this._vertexSourceCode = migratedVertexCode;
256
204
  this._fragmentSourceCode = migratedFragmentCode;
257
- }
258
- this._prepareEffect(keepExistingPipelineContext);
205
+ this._prepareEffect(keepExistingPipelineContext);
206
+ }, this._shaderLanguage, this._engine, this);
259
207
  }
260
208
  /**
261
209
  * Unique key for this effect
@@ -421,46 +369,6 @@ export class Effect {
421
369
  this._checkIsReady(previousPipelineContext);
422
370
  }, 16);
423
371
  }
424
- _loadShader(shader, key, optionalKey, callback) {
425
- if (typeof HTMLElement !== "undefined") {
426
- // DOM element ?
427
- if (shader instanceof HTMLElement) {
428
- const shaderCode = GetDOMTextContent(shader);
429
- callback(shaderCode);
430
- return;
431
- }
432
- }
433
- // Direct source ?
434
- if (shader.substr(0, 7) === "source:") {
435
- callback(shader.substr(7));
436
- return;
437
- }
438
- // Base64 encoded ?
439
- if (shader.substr(0, 7) === "base64:") {
440
- const shaderBinary = window.atob(shader.substr(7));
441
- callback(shaderBinary);
442
- return;
443
- }
444
- const shaderStore = EngineShaderStore.GetShadersStore(this._shaderLanguage);
445
- // Is in local store ?
446
- if (shaderStore[shader + key + "Shader"]) {
447
- callback(shaderStore[shader + key + "Shader"]);
448
- return;
449
- }
450
- if (optionalKey && shaderStore[shader + optionalKey + "Shader"]) {
451
- callback(shaderStore[shader + optionalKey + "Shader"]);
452
- return;
453
- }
454
- let shaderUrl;
455
- if (shader[0] === "." || shader[0] === "/" || shader.indexOf("http") > -1) {
456
- shaderUrl = shader;
457
- }
458
- else {
459
- shaderUrl = EngineShaderStore.GetShadersRepository(this._shaderLanguage) + shader;
460
- }
461
- // Vertex shader
462
- this._engine._loadFile(shaderUrl + "." + key.toLowerCase() + ".fx", callback);
463
- }
464
372
  /**
465
373
  * Gets the vertex shader source code of this effect
466
374
  * This is the final source code that will be compiled, after all the processing has been done (pre-processing applied, code injection/replacement, etc)
@@ -507,6 +415,26 @@ export class Effect {
507
415
  get rawFragmentSourceCode() {
508
416
  return this._rawFragmentSourceCode;
509
417
  }
418
+ getPipelineGenerationOptions() {
419
+ return {
420
+ platformName: this._engine.shaderPlatformName,
421
+ shaderLanguage: this._shaderLanguage,
422
+ shaderNameOrContent: this.name,
423
+ key: this._key,
424
+ defines: this.defines.split("\n"),
425
+ addGlobalDefines: false,
426
+ extendedProcessingOptions: {
427
+ indexParameters: this._indexParameters,
428
+ isNDCHalfZRange: this._engine.isNDCHalfZRange,
429
+ useReverseDepthBuffer: this._engine.useReverseDepthBuffer,
430
+ supportsUniformBuffers: this._engine.supportsUniformBuffers,
431
+ },
432
+ extendedCreatePipelineOptions: {
433
+ transformFeedbackVaryings: this._transformFeedbackVaryings,
434
+ createAsRaw: !!(this._vertexSourceCodeOverride && this._fragmentSourceCodeOverride),
435
+ },
436
+ };
437
+ }
510
438
  /**
511
439
  * Recompiles the webGL program
512
440
  * @param vertexSourceCode The source code for the vertex shader.
@@ -536,52 +464,65 @@ export class Effect {
536
464
  this._fallbacks = null;
537
465
  this._prepareEffect();
538
466
  }
467
+ _onRenderingStateCompiled(pipelineContext) {
468
+ this._pipelineContext = pipelineContext;
469
+ this._pipelineContext.setEngine(this._engine);
470
+ this._attributes = [];
471
+ this._pipelineContext._fillEffectInformation(this, this._uniformBuffersNames, this._uniformsNames, this._uniforms, this._samplerList, this._samplers, this._attributesNames, this._attributes);
472
+ // Caches attribute locations.
473
+ if (this._attributesNames) {
474
+ for (let i = 0; i < this._attributesNames.length; i++) {
475
+ const name = this._attributesNames[i];
476
+ this._attributeLocationByName[name] = this._attributes[i];
477
+ }
478
+ }
479
+ this._engine.bindSamplers(this);
480
+ this._compilationError = "";
481
+ this._isReady = true;
482
+ if (this.onCompiled) {
483
+ this.onCompiled(this);
484
+ }
485
+ this.onCompileObservable.notifyObservers(this);
486
+ this.onCompileObservable.clear();
487
+ // Unbind mesh reference in fallbacks
488
+ if (this._fallbacks) {
489
+ this._fallbacks.unBindMesh();
490
+ }
491
+ }
539
492
  /**
540
493
  * Prepares the effect
541
494
  * @internal
542
495
  */
543
496
  _prepareEffect(keepExistingPipelineContext = false) {
544
- const attributesNames = this._attributesNames;
545
- const defines = this.defines;
546
497
  const previousPipelineContext = this._pipelineContext;
547
498
  this._isReady = false;
548
499
  try {
500
+ const overrides = !!(this._vertexSourceCodeOverride && this._fragmentSourceCodeOverride);
501
+ const defines = overrides ? null : this.defines;
502
+ const vertex = overrides ? this._vertexSourceCodeOverride : this._vertexSourceCode;
503
+ const fragment = overrides ? this._fragmentSourceCodeOverride : this._fragmentSourceCode;
549
504
  const engine = this._engine;
550
- this._pipelineContext = (keepExistingPipelineContext ? previousPipelineContext : undefined) ?? engine.createPipelineContext(this._processingContext);
551
- this._pipelineContext._name = this._key.replace(/\r/g, "").replace(/\n/g, "|");
552
- const rebuildRebind = (vertexSourceCode, fragmentSourceCode, onCompiled, onError) => this._rebuildProgram(vertexSourceCode, fragmentSourceCode, onCompiled, onError);
553
- if (this._vertexSourceCodeOverride && this._fragmentSourceCodeOverride) {
554
- engine._preparePipelineContext(this._pipelineContext, this._vertexSourceCodeOverride, this._fragmentSourceCodeOverride, true, this._rawVertexSourceCode, this._rawFragmentSourceCode, rebuildRebind, null, this._transformFeedbackVaryings, this._key);
555
- }
556
- else {
557
- engine._preparePipelineContext(this._pipelineContext, this._vertexSourceCode, this._fragmentSourceCode, false, this._rawVertexSourceCode, this._rawFragmentSourceCode, rebuildRebind, defines, this._transformFeedbackVaryings, this._key);
558
- }
559
- engine._executeWhenRenderingStateIsCompiled(this._pipelineContext, () => {
560
- this._attributes = [];
561
- this._pipelineContext._fillEffectInformation(this, this._uniformBuffersNames, this._uniformsNames, this._uniforms, this._samplerList, this._samplers, attributesNames, this._attributes);
562
- // Caches attribute locations.
563
- if (attributesNames) {
564
- for (let i = 0; i < attributesNames.length; i++) {
565
- const name = attributesNames[i];
566
- this._attributeLocationByName[name] = this._attributes[i];
505
+ this._pipelineContext = createAndPreparePipelineContext({
506
+ existingPipelineContext: keepExistingPipelineContext ? previousPipelineContext : null,
507
+ vertex,
508
+ fragment,
509
+ context: engine.shaderPlatformName === "WEBGL2" ? engine._gl : undefined,
510
+ rebuildRebind: (vertexSourceCode, fragmentSourceCode, onCompiled, onError) => this._rebuildProgram(vertexSourceCode, fragmentSourceCode, onCompiled, onError),
511
+ defines,
512
+ transformFeedbackVaryings: this._transformFeedbackVaryings,
513
+ name: this._key.replace(/\r/g, "").replace(/\n/g, "|"),
514
+ createAsRaw: overrides,
515
+ parallelShaderCompile: engine._caps.parallelShaderCompile,
516
+ shaderProcessingContext: this._processingContext,
517
+ onRenderingStateCompiled: (pipelineContext) => {
518
+ if (previousPipelineContext && !keepExistingPipelineContext) {
519
+ this._engine._deletePipelineContext(previousPipelineContext);
567
520
  }
568
- }
569
- engine.bindSamplers(this);
570
- this._compilationError = "";
571
- this._isReady = true;
572
- if (this.onCompiled) {
573
- this.onCompiled(this);
574
- }
575
- this.onCompileObservable.notifyObservers(this);
576
- this.onCompileObservable.clear();
577
- // Unbind mesh reference in fallbacks
578
- if (this._fallbacks) {
579
- this._fallbacks.unBindMesh();
580
- }
581
- if (previousPipelineContext && !keepExistingPipelineContext) {
582
- this.getEngine()._deletePipelineContext(previousPipelineContext);
583
- }
584
- });
521
+ if (pipelineContext) {
522
+ this._onRenderingStateCompiled(pipelineContext);
523
+ }
524
+ },
525
+ }, this._engine.createPipelineContext.bind(this._engine), this._engine._preparePipelineContext.bind(this._engine));
585
526
  if (this._pipelineContext.isAsync) {
586
527
  this._checkIsReady(previousPipelineContext);
587
528
  }
@@ -1201,7 +1142,7 @@ export class Effect {
1201
1142
  **/
1202
1143
  dispose() {
1203
1144
  if (this._pipelineContext) {
1204
- this._pipelineContext.dispose();
1145
+ resetCachedPipeline(this._pipelineContext);
1205
1146
  }
1206
1147
  this._engine._releaseEffect(this);
1207
1148
  this._isDisposed = true;