UNPKG

xgpu

Version:

XGPU is an extendable library for WebGPU that provides a higher-level, easy-to-use interface for building rendering engines or processing numeric data. It handles automatic data binding, buffer alignment, variable declarations in shaders, and more. XGPU i

196 lines (179 loc) 6.35 kB
// Copyright (c) 2023 Thomas Le Coz. All rights reserved. // This code is governed by an MIT license that can be found in the LICENSE file. import { ShaderNode } from "./ShaderNode"; export class ShaderStage { inputs = []; outputs = []; export = []; require = []; pipelineConstants = {}; constants; main; shaderType; constructor(shaderType) { this.shaderType = shaderType; this.constants = new ShaderNode(); this.main = new ShaderNode("", true); } debugLogs = []; debugRenders = []; /* public extractDebugInfo(shaderCode: string): string { const { code, debugLogs, debugRenders } = ShaderStage.extractDebugInfo(shaderCode); this.debugLogs = debugLogs; this.debugRenders = debugRenders; return code; } public static extractDebugInfo(code: string): { code: string, debugLogs: any[], debugRenders: any[] } { const result: any = {}; result.debugLogs = []; result.debugRenders = []; const cut = (s: string) => { let id; for (let i = s.length - 1; i > -1; i--) { if (s[i] === ",") { id = i; break; } } return { label: s.slice(0, id), val: s.slice(id + 1) } } const extractDebug = (line: string) => { let s: string = line.split("XGPU.debug(")[1].split(");")[0]; //const { label, val } = cut(s); //console.log("A = ", label); //console.log("B = ", val); result.debugLogs.push(cut(s)); } const extractDebugRender = (line: string) => { //XGPU.renderDebug("testC : ",output.position,vec4(0.0,0.0,1.0,1.0)); let s: string = line.split("XGPU.renderDebug(")[1].split(");")[0]; let t = s.split(",vec4") let color = "vec4" + t[1]; s = t[0]; //const { label, val } = cut(s); //console.log("A = ", label); //console.log("B = ", val); //console.log("C = ", color); result.debugRenders.push({ ...cut(s), color }) } const lines: string[] = code.split("\n"); const newLines: string[] = []; for (let i = 0; i < lines.length; i++) { if (lines[i].includes("XGPU.debug")) { extractDebug(lines[i]) } else if (lines[i].includes("XGPU.renderDebug")) { extractDebugRender(lines[i]); } else { newLines.push(lines[i]); } } result.code = newLines.join("\n"); return result; }*/ unwrapVariableInMainFunction(shaderVariables) { const variables = shaderVariables.split("\n"); let s; let objs = []; for (let i = 0; i < variables.length; i++) { variables[i] = s = variables[i].split("\t").join("").trim().slice(4); if (!s.length) continue; let t = s.split(" = "); let varName = t[0].split(":")[0]; let otherName = t[1].slice(0, t[1].length - 1); objs.push({ varName, otherName }); } const searchAndReplace = (shaderCode, wordToReplace, replacement) => { const regex = new RegExp(`(?<=[^\\w.])\\b${wordToReplace}\\b`, 'g'); return shaderCode.replace(regex, replacement); }; let shader = this.main.value + ""; for (let i = 0; i < objs.length; i++) { shader = searchAndReplace(shader, objs[i].varName, objs[i].otherName); } return shader; } unwrapVariableInWGSL(shaderVariables, wgsl) { const variables = shaderVariables.split("\n"); let s; let objs = []; for (let i = 0; i < variables.length; i++) { variables[i] = s = variables[i].split("\t").join("").trim().slice(4); if (!s.length) continue; let t = s.split(" = "); let varName = t[0].split(":")[0]; let otherName = t[1].slice(0, t[1].length - 1); objs.push({ varName, otherName }); } const searchAndReplace = (shaderCode, wordToReplace, replacement) => { const regex = new RegExp(`(?<=[^\\w.])\\b${wordToReplace}\\b`, 'g'); return shaderCode.replace(regex, replacement); }; for (let i = 0; i < objs.length; i++) { wgsl = searchAndReplace(wgsl, objs[i].varName, objs[i].otherName); } return wgsl; } addOutputVariable(name, shaderType) { this.outputs.push({ name, type: shaderType.type }); } addInputVariable(name, shaderTypeOrBuiltIn) { this.outputs.push({ name, type: shaderTypeOrBuiltIn.type, builtin: shaderTypeOrBuiltIn.builtin }); } formatWGSLCode(code) { const res = code.split("\n"); let count = 0; let tabs = []; for (let i = 0; i < 16; i++) { if (i == 0) tabs[i] = ""; else tabs[i] = tabs[i - 1] + "\t"; } const res2 = []; var s; var empty = true; for (let i = 0; i < res.length; i++) { s = res[i].trim(); if (s.includes("}")) count--; if (s != "" || !empty) { empty = s == ""; res2.push(tabs[count] + s); } if (res[i].includes("{")) count++; } return res2.join("\n"); } get shaderInfos() { return this._shaderInfos; } _shaderInfos; build(shaderPipeline, input) { //must be overrided; if (!shaderPipeline || !input) { } ; if (this._shaderInfos) return this._shaderInfos; this._shaderInfos = { code: "", output: null }; return this._shaderInfos; } }