gpu-curtains
Version:
gpu-curtains is a 3D WebGPU rendering engine. It can be used as a standalone 3D engine, but also includes extra classes focused on mapping 3d objects to DOM elements; It allows users to synchronize values such as position, sizing, or scale between them.
139 lines (138 loc) • 4.93 kB
JavaScript
import { generateUUID } from "../../utils/utils.mjs";
import { isRenderer } from "../renderers/utils.mjs";
//#region src/core/pipelines/PipelineEntry.ts
let pipelineId = 0;
/**
* Used as a base class to create a pipeline entry.<br>
* {@link PipelineEntry} roles are:
* - Patch the given {@link core/materials/Material.Material | Material} shaders code and create the corresponding {@link GPUShaderModule}.
* - Create a {@link GPUPipelineLayout | pipeline layout} with the given {@link core/materials/Material.Material#bindGroups | bind groups}
* - Create a GPU pipeline
*/
var PipelineEntry = class {
/**
* PipelineEntry constructor
* @param parameters - {@link PipelineEntryParams | parameters} used to create this {@link PipelineEntry}
*/
constructor(parameters) {
this.type = "PipelineEntry";
this.uuid = generateUUID();
let { renderer } = parameters;
const { label, shaders, useAsync, bindGroups, cacheKey } = parameters;
renderer = isRenderer(renderer, label ? label + " " + this.type : this.type);
this.renderer = renderer;
Object.defineProperty(this, "index", { value: pipelineId++ });
this.layout = null;
this.pipeline = null;
this.status = {
compiling: false,
compiled: false,
error: null
};
this.options = {
label,
shaders,
useAsync: useAsync !== void 0 ? useAsync : true,
bindGroups,
cacheKey
};
this.bindGroups = bindGroups;
}
/**
* Set or reset this {@link PipelineEntry} {@link PipelineEntry.renderer | renderer}.
* @param renderer - New {@link Renderer} or {@link GPUCurtains} instance to use.
*/
setRenderer(renderer) {
renderer = isRenderer(renderer, this.options.label + " " + this.type);
this.renderer = renderer;
}
/**
* Get whether the {@link pipeline} is ready, i.e. successfully compiled
* @readonly
*/
get ready() {
return !this.status.compiling && this.status.compiled && !this.status.error;
}
/**
* Get whether the {@link pipeline} is ready to be compiled, i.e. we have not already tried to compile it, and it's not currently compiling neither
* @readonly
*/
get canCompile() {
return !this.status.compiling && !this.status.compiled && !this.status.error;
}
/**
* Create a {@link GPUShaderModule}
* @param parameters - Parameters used
* @param parameters.code - patched WGSL code string
* @param parameters.type - {@link MaterialShadersType | shader type}
* @returns - compiled {@link GPUShaderModule} if successful
*/
createShaderModule({ code = "", type = "vertex" }) {
const shaderModule = this.renderer.createShaderModule({
label: this.options.label + ": " + type + " shader module",
code
});
if ("getCompilationInfo" in shaderModule && !this.renderer.production) shaderModule.getCompilationInfo().then((compilationInfo) => {
for (const message of compilationInfo.messages) {
let formattedMessage = "";
if (message.lineNum) formattedMessage += `Line ${message.lineNum}:${message.linePos} - ${code.substring(message.offset, message.offset + message.length)}\n`;
formattedMessage += message.message;
switch (message.type) {
case "error":
console.error(`${this.options.label} compilation error:\n${formattedMessage}`);
break;
case "warning":
console.warn(`${this.options.label} compilation warning:\n${formattedMessage}`);
break;
case "info":
console.log(`${this.options.label} compilation information:\n${formattedMessage}`);
break;
}
}
});
return shaderModule;
}
/**
* Create the {@link PipelineEntry} shaders
*/
createShaders() {}
/**
* Create the pipeline entry {@link layout}
*/
createPipelineLayout() {
this.layout = this.renderer.createPipelineLayout({
label: this.options.label + " layout",
bindGroupLayouts: this.bindGroups.map((bindGroup) => bindGroup.bindGroupLayout)
});
}
/**
* Create the {@link PipelineEntry} descriptor.
*/
createPipelineDescriptor() {}
/**
* Flush a {@link PipelineEntry}, i.e. reset its {@link bindGroups | bind groups}, {@link layout} and descriptor and recompile the {@link pipeline}.
* Used when one of the bind group or rendering property has changed.
* @param newBindGroups - new {@link bindGroups | bind groups} in case they have changed.
* @param cacheKey - new {@link core/materials/Material.Material#cacheKey | Material cacheKey} in case it has changed.
*/
flushPipelineEntry(newBindGroups = [], cacheKey = "") {
this.options.bindGroups = newBindGroups;
this.options.cacheKey = cacheKey;
this.status.compiling = false;
this.status.compiled = false;
this.status.error = null;
this.bindGroups = newBindGroups;
this.compilePipelineEntry();
}
/**
* Set up a {@link pipeline} by creating the shaders, the {@link layout} and the descriptor
*/
compilePipelineEntry() {
this.status.compiling = true;
this.createShaders();
this.createPipelineLayout();
this.createPipelineDescriptor();
}
};
//#endregion
export { PipelineEntry };