@babylonjs/core
Version:
Getting started? Play directly with the Babylon.js API using our [playground](https://playground.babylonjs.com/). It also contains a lot of samples to learn how to use it.
193 lines • 8.3 kB
JavaScript
import { GetDOMTextContent, IsWindowObjectExist } from "../Misc/domManagement.js";
import { getStateObject } from "../Engines/thinEngine.functions.js";
import { ShaderStore } from "../Engines/shaderStore.js";
import { Logger } from "../Misc/logger.js";
import { Finalize, Initialize, Process } from "../Engines/Processors/shaderProcessor.js";
import { _loadFile } from "../Engines/abstractEngine.functions.js";
/**
* Get a cached pipeline context
* @param name the pipeline name
* @param context the context to be used when creating the pipeline
* @returns the cached pipeline context if it exists
* @internal
*/
export function getCachedPipeline(name, context) {
const stateObject = getStateObject(context);
return stateObject.cachedPipelines[name];
}
/**
* @internal
*/
export function resetCachedPipeline(pipeline) {
const name = pipeline._name;
const context = pipeline.context;
if (name && context) {
const stateObject = getStateObject(context);
const cachedPipeline = stateObject.cachedPipelines[name];
cachedPipeline?.dispose();
delete stateObject.cachedPipelines[name];
}
}
/** @internal */
export function _processShaderCode(processorOptions, baseName, processFinalCode, onFinalCodeReady, shaderLanguage, engine, effectContext) {
let vertexSource;
let fragmentSource;
// const baseName = this.name;
const hostDocument = IsWindowObjectExist() ? engine?.getHostDocument() : null;
if (typeof baseName === "string") {
vertexSource = baseName;
}
else if (baseName.vertexSource) {
vertexSource = "source:" + baseName.vertexSource;
}
else if (baseName.vertexElement) {
vertexSource = hostDocument?.getElementById(baseName.vertexElement) || baseName.vertexElement;
}
else {
vertexSource = baseName.vertex || baseName;
}
if (typeof baseName === "string") {
fragmentSource = baseName;
}
else if (baseName.fragmentSource) {
fragmentSource = "source:" + baseName.fragmentSource;
}
else if (baseName.fragmentElement) {
fragmentSource = hostDocument?.getElementById(baseName.fragmentElement) || baseName.fragmentElement;
}
else {
fragmentSource = baseName.fragment || baseName;
}
const shaderCodes = [undefined, undefined];
const shadersLoaded = () => {
if (shaderCodes[0] && shaderCodes[1]) {
processorOptions.isFragment = true;
const [migratedVertexCode, fragmentCode] = shaderCodes;
Process(fragmentCode, processorOptions, (migratedFragmentCode, codeBeforeMigration) => {
if (effectContext) {
effectContext._fragmentSourceCodeBeforeMigration = codeBeforeMigration;
}
if (processFinalCode) {
migratedFragmentCode = processFinalCode("fragment", migratedFragmentCode);
}
const finalShaders = Finalize(migratedVertexCode, migratedFragmentCode, processorOptions);
processorOptions = null;
const finalCode = _useFinalCode(finalShaders.vertexCode, finalShaders.fragmentCode, baseName, shaderLanguage);
onFinalCodeReady?.(finalCode.vertexSourceCode, finalCode.fragmentSourceCode);
}, engine);
}
};
_loadShader(vertexSource, "Vertex", "", (vertexCode) => {
Initialize(processorOptions);
Process(vertexCode, processorOptions, (migratedVertexCode, codeBeforeMigration) => {
if (effectContext) {
effectContext._rawVertexSourceCode = vertexCode;
effectContext._vertexSourceCodeBeforeMigration = codeBeforeMigration;
}
if (processFinalCode) {
migratedVertexCode = processFinalCode("vertex", migratedVertexCode);
}
shaderCodes[0] = migratedVertexCode;
shadersLoaded();
}, engine);
}, shaderLanguage);
_loadShader(fragmentSource, "Fragment", "Pixel", (fragmentCode) => {
if (effectContext) {
effectContext._rawFragmentSourceCode = fragmentCode;
}
shaderCodes[1] = fragmentCode;
shadersLoaded();
}, shaderLanguage);
}
function _loadShader(shader, key, optionalKey, callback, shaderLanguage, _loadFileInjection) {
if (typeof HTMLElement !== "undefined") {
// DOM element ?
if (shader instanceof HTMLElement) {
const shaderCode = GetDOMTextContent(shader);
callback(shaderCode);
return;
}
}
// Direct source ?
if (shader.substring(0, 7) === "source:") {
callback(shader.substring(7));
return;
}
// Base64 encoded ?
if (shader.substring(0, 7) === "base64:") {
const shaderBinary = window.atob(shader.substring(7));
callback(shaderBinary);
return;
}
const shaderStore = ShaderStore.GetShadersStore(shaderLanguage);
// Is in local store ?
if (shaderStore[shader + key + "Shader"]) {
callback(shaderStore[shader + key + "Shader"]);
return;
}
if (optionalKey && shaderStore[shader + optionalKey + "Shader"]) {
callback(shaderStore[shader + optionalKey + "Shader"]);
return;
}
let shaderUrl;
if (shader[0] === "." || shader[0] === "/" || shader.indexOf("http") > -1) {
shaderUrl = shader;
}
else {
shaderUrl = ShaderStore.GetShadersRepository(shaderLanguage) + shader;
}
_loadFileInjection = _loadFileInjection || _loadFile;
if (!_loadFileInjection) {
// we got to this point and loadFile was not injected - throw an error
throw new Error("loadFileInjection is not defined");
}
// Vertex shader
_loadFileInjection(shaderUrl + "." + key.toLowerCase() + ".fx", callback);
}
function _useFinalCode(migratedVertexCode, migratedFragmentCode, baseName, shaderLanguage) {
if (baseName) {
const vertex = baseName.vertexElement || baseName.vertex || baseName.spectorName || baseName;
const fragment = baseName.fragmentElement || baseName.fragment || baseName.spectorName || baseName;
return {
vertexSourceCode: (shaderLanguage === 1 /* ShaderLanguage.WGSL */ ? "//" : "") + "#define SHADER_NAME vertex:" + vertex + "\n" + migratedVertexCode,
fragmentSourceCode: (shaderLanguage === 1 /* ShaderLanguage.WGSL */ ? "//" : "") + "#define SHADER_NAME fragment:" + fragment + "\n" + migratedFragmentCode,
};
}
else {
return {
vertexSourceCode: migratedVertexCode,
fragmentSourceCode: migratedFragmentCode,
};
}
}
/**
* Creates and prepares a pipeline context
* @internal
*/
export const createAndPreparePipelineContext = (options, createPipelineContext, _preparePipelineContext, _executeWhenRenderingStateIsCompiled) => {
try {
const stateObject = options.context ? getStateObject(options.context) : null;
if (stateObject) {
// will not remove the reference to parallelShaderPrecompile, but will prevent it from being used in the next shader compilation
stateObject.disableParallelShaderCompile = options.disableParallelCompilation;
}
const pipelineContext = options.existingPipelineContext || createPipelineContext(options.shaderProcessingContext);
pipelineContext._name = options.name;
if (options.name && stateObject) {
stateObject.cachedPipelines[options.name] = pipelineContext;
}
// Flagged as async as we may need to delay load some processing tools
// This does not break anything as the execution is waiting for _executeWhenRenderingStateIsCompiled
_preparePipelineContext(pipelineContext, options.vertex, options.fragment, !!options.createAsRaw, "", "", options.rebuildRebind, options.defines, options.transformFeedbackVaryings, "", () => {
_executeWhenRenderingStateIsCompiled(pipelineContext, () => {
options.onRenderingStateCompiled?.(pipelineContext);
});
});
return pipelineContext;
}
catch (e) {
Logger.Error("Error compiling effect");
throw e;
}
};
//# sourceMappingURL=effect.functions.js.map