mirror of
https://github.com/galacean/engine.git
synced 2026-06-14 04:57:42 +08:00
refactor(shader): remove raw GLSL shader path
All built-in shaders (including ParticleFeedback) now consume ShaderLab via the precompiled instructions path. The legacy raw GLSL string overload is unreachable production code, so drop it for a single canonical path through ShaderPass. - ShaderPass: keep only the (name, vertexInstructions, fragmentInstructions, platformTarget, tags?) constructor; drop _vertexSource / _fragmentSource fields and _compilePlatformSource - Shader.create: drop the (name, vertexSource, fragmentSource) overload - ShaderFactory: drop compilePlatformSource and parseCustomMacros (no remaining callers); registerInclude / unRegisterInclude / parseIncludes / convertTo300 stay (still used by ShaderLab includes) - Tests: rewrite Shader.test custom-shader cases via SubShader / ShaderPass instructions overload; drop the GSP-vs-GLSL benchmark case
This commit is contained in:
@@ -53,15 +53,6 @@ export class Shader implements IReferable {
|
||||
*/
|
||||
static create(shaderSource: string, platformTarget?: ShaderLanguage): Shader;
|
||||
|
||||
/**
|
||||
* Create a shader.
|
||||
* @param name - Name of the shader
|
||||
* @param vertexSource - Vertex source code
|
||||
* @param fragmentSource - Fragment source code
|
||||
* @returns Shader
|
||||
*/
|
||||
static create(name: string, vertexSource: string, fragmentSource: string): Shader;
|
||||
|
||||
/**
|
||||
* Create a shader.
|
||||
* @param name - Name of the shader
|
||||
@@ -80,17 +71,16 @@ export class Shader implements IReferable {
|
||||
|
||||
static create(
|
||||
nameOrShaderSource: string,
|
||||
vertexSourceOrShaderPassesOrSubShadersOrPlatformTarget?: ShaderLanguage | SubShader[] | ShaderPass[] | string,
|
||||
fragmentSource?: string
|
||||
shaderPassesOrSubShadersOrPlatformTarget?: ShaderLanguage | SubShader[] | ShaderPass[]
|
||||
): Shader {
|
||||
let shader: Shader;
|
||||
const shaderMap = Shader._shaderMap;
|
||||
|
||||
if (vertexSourceOrShaderPassesOrSubShadersOrPlatformTarget == undefined) {
|
||||
vertexSourceOrShaderPassesOrSubShadersOrPlatformTarget = ShaderLanguage.GLSLES100;
|
||||
if (shaderPassesOrSubShadersOrPlatformTarget == undefined) {
|
||||
shaderPassesOrSubShadersOrPlatformTarget = ShaderLanguage.GLSLES100;
|
||||
}
|
||||
|
||||
if (typeof vertexSourceOrShaderPassesOrSubShadersOrPlatformTarget === "number") {
|
||||
if (typeof shaderPassesOrSubShadersOrPlatformTarget === "number") {
|
||||
const shaderCompiler = Shader._shaderCompiler;
|
||||
if (!shaderCompiler) {
|
||||
throw "ShaderCompiler has not been set up yet.";
|
||||
@@ -112,7 +102,7 @@ export class Shader implements IReferable {
|
||||
passSource.contents,
|
||||
passSource.vertexEntry,
|
||||
passSource.fragmentEntry,
|
||||
vertexSourceOrShaderPassesOrSubShadersOrPlatformTarget
|
||||
shaderPassesOrSubShadersOrPlatformTarget
|
||||
);
|
||||
|
||||
if (!shaderPassSource) {
|
||||
@@ -123,7 +113,7 @@ export class Shader implements IReferable {
|
||||
passSource.name,
|
||||
shaderPassSource.vertexShaderInstructions,
|
||||
shaderPassSource.fragmentShaderInstructions,
|
||||
vertexSourceOrShaderPassesOrSubShadersOrPlatformTarget as ShaderLanguage,
|
||||
shaderPassesOrSubShadersOrPlatformTarget as ShaderLanguage,
|
||||
passSource.tags
|
||||
);
|
||||
|
||||
@@ -148,24 +138,16 @@ export class Shader implements IReferable {
|
||||
console.error(`Shader named "${nameOrShaderSource}" already exists.`);
|
||||
return;
|
||||
}
|
||||
if (typeof vertexSourceOrShaderPassesOrSubShadersOrPlatformTarget === "string") {
|
||||
const shaderPass = new ShaderPass(vertexSourceOrShaderPassesOrSubShadersOrPlatformTarget, fragmentSource);
|
||||
shader = new Shader(nameOrShaderSource, [new SubShader("Default", [shaderPass])]);
|
||||
} else {
|
||||
if (vertexSourceOrShaderPassesOrSubShadersOrPlatformTarget.length > 0) {
|
||||
if (vertexSourceOrShaderPassesOrSubShadersOrPlatformTarget[0].constructor === ShaderPass) {
|
||||
shader = new Shader(nameOrShaderSource, [
|
||||
new SubShader("Default", <ShaderPass[]>vertexSourceOrShaderPassesOrSubShadersOrPlatformTarget)
|
||||
]);
|
||||
} else {
|
||||
shader = new Shader(
|
||||
nameOrShaderSource,
|
||||
<SubShader[]>vertexSourceOrShaderPassesOrSubShadersOrPlatformTarget.slice()
|
||||
);
|
||||
}
|
||||
if (shaderPassesOrSubShadersOrPlatformTarget.length > 0) {
|
||||
if (shaderPassesOrSubShadersOrPlatformTarget[0].constructor === ShaderPass) {
|
||||
shader = new Shader(nameOrShaderSource, [
|
||||
new SubShader("Default", <ShaderPass[]>shaderPassesOrSubShadersOrPlatformTarget)
|
||||
]);
|
||||
} else {
|
||||
throw "SubShader or ShaderPass count must large than 0.";
|
||||
shader = new Shader(nameOrShaderSource, <SubShader[]>shaderPassesOrSubShadersOrPlatformTarget.slice());
|
||||
}
|
||||
} else {
|
||||
throw "SubShader or ShaderPass count must large than 0.";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -45,15 +45,13 @@ export class ShaderPass extends ShaderPart {
|
||||
[RenderStateElementKey.RenderQueueType]: ShaderProperty.getByName("renderQueueType")
|
||||
};
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
_platformTarget: ShaderLanguage | undefined;
|
||||
/** @internal */
|
||||
_platformTarget: ShaderLanguage;
|
||||
|
||||
/** @internal - Flat instruction array for vertex shader. */
|
||||
_vertexShaderInstructions?: ShaderInstruction[];
|
||||
_vertexShaderInstructions: ShaderInstruction[];
|
||||
/** @internal */
|
||||
_fragmentShaderInstructions?: ShaderInstruction[];
|
||||
_fragmentShaderInstructions: ShaderInstruction[];
|
||||
|
||||
/** @internal */
|
||||
_shaderPassId: number = 0;
|
||||
@@ -72,34 +70,9 @@ export class ShaderPass extends ShaderPart {
|
||||
/** @internal Transform feedback output varyings (WebGL2 only). */
|
||||
_feedbackVaryings?: string[];
|
||||
|
||||
private _vertexSource?: string;
|
||||
private _fragmentSource?: string;
|
||||
|
||||
private static _shaderMacroList: ShaderMacro[] = [];
|
||||
private static _macroMap: Map<string, string> = new Map();
|
||||
|
||||
/**
|
||||
* Create a shader pass.
|
||||
* @param name - Shader pass name
|
||||
* @param vertexSource - Vertex shader source
|
||||
* @param fragmentSource - Fragment shader source
|
||||
* @param tags - Tags
|
||||
*/
|
||||
constructor(
|
||||
name: string,
|
||||
vertexSource: string,
|
||||
fragmentSource: string,
|
||||
tags?: Record<string, number | string | boolean>
|
||||
);
|
||||
|
||||
/**
|
||||
* Create a shader pass.
|
||||
* @param vertexSource - Vertex shader source
|
||||
* @param fragmentSource - Fragment shader source
|
||||
* @param tags - Tags
|
||||
*/
|
||||
constructor(vertexSource: string, fragmentSource: string, tags?: Record<string, number | string | boolean>);
|
||||
|
||||
/**
|
||||
* Create a shader pass from precompiled instructions.
|
||||
* @param name - Shader pass name
|
||||
@@ -114,47 +87,18 @@ export class ShaderPass extends ShaderPart {
|
||||
fragmentShaderInstructions: ShaderInstruction[],
|
||||
platformTarget: ShaderLanguage,
|
||||
tags?: Record<string, number | string | boolean>
|
||||
);
|
||||
|
||||
constructor(
|
||||
nameOrVertexSource: string,
|
||||
vertexSourceOrFragmentSourceOrInstructions: string | ShaderInstruction[],
|
||||
fragmentSourceOrTags?: string | ShaderInstruction[] | Record<string, number | string | boolean>,
|
||||
tagsOrPlatformTarget?: Record<string, number | string | boolean> | ShaderLanguage,
|
||||
tags?: Record<string, number | string | boolean>
|
||||
) {
|
||||
super();
|
||||
this._shaderPassId = ShaderPass._shaderPassCounter++;
|
||||
|
||||
if (Array.isArray(vertexSourceOrFragmentSourceOrInstructions)) {
|
||||
// Instructions overload: (name, vertexInst, fragInst, platformTarget, tags?)
|
||||
this._name = nameOrVertexSource;
|
||||
this._vertexShaderInstructions = vertexSourceOrFragmentSourceOrInstructions;
|
||||
this._fragmentShaderInstructions = fragmentSourceOrTags as ShaderInstruction[];
|
||||
this._platformTarget = tagsOrPlatformTarget as ShaderLanguage;
|
||||
tags = { pipelineStage: PipelineStage.Forward, ...tags };
|
||||
} else if (typeof fragmentSourceOrTags === "string") {
|
||||
// Named overload: (name, vertexSource, fragmentSource, tags?)
|
||||
this._name = nameOrVertexSource;
|
||||
this._vertexSource = vertexSourceOrFragmentSourceOrInstructions;
|
||||
this._fragmentSource = fragmentSourceOrTags;
|
||||
tags = {
|
||||
pipelineStage: PipelineStage.Forward,
|
||||
...(tagsOrPlatformTarget as Record<string, number | string | boolean>)
|
||||
};
|
||||
} else {
|
||||
// Unnamed overload: (vertexSource, fragmentSource, tags?)
|
||||
this._name = "Default";
|
||||
this._vertexSource = nameOrVertexSource;
|
||||
this._fragmentSource = vertexSourceOrFragmentSourceOrInstructions as string;
|
||||
tags = {
|
||||
pipelineStage: PipelineStage.Forward,
|
||||
...(fragmentSourceOrTags as Record<string, number | string | boolean>)
|
||||
};
|
||||
}
|
||||
this._name = name;
|
||||
this._vertexShaderInstructions = vertexShaderInstructions;
|
||||
this._fragmentShaderInstructions = fragmentShaderInstructions;
|
||||
this._platformTarget = platformTarget;
|
||||
|
||||
for (const key in tags) {
|
||||
this.setTag(key, tags[key]);
|
||||
const mergedTags = { pipelineStage: PipelineStage.Forward, ...tags };
|
||||
for (const key in mergedTags) {
|
||||
this.setTag(key, mergedTags[key]);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -189,21 +133,10 @@ export class ShaderPass extends ShaderPart {
|
||||
}
|
||||
|
||||
private _getCanonicalShaderProgram(engine: Engine, macroCollection: ShaderMacroCollection): ShaderProgram {
|
||||
const { vertexSource, fragmentSource } =
|
||||
this._platformTarget != undefined
|
||||
? this._compileShaderSource(engine, macroCollection)
|
||||
: this._compilePlatformSource(engine, macroCollection);
|
||||
|
||||
const { vertexSource, fragmentSource } = this._compileShaderSource(engine, macroCollection);
|
||||
return new ShaderProgram(engine, vertexSource, fragmentSource, this._feedbackVaryings);
|
||||
}
|
||||
|
||||
private _compilePlatformSource(
|
||||
engine: Engine,
|
||||
macroCollection: ShaderMacroCollection
|
||||
): { vertexSource: string; fragmentSource: string } {
|
||||
return ShaderFactory.compilePlatformSource(engine, macroCollection, this._vertexSource, this._fragmentSource);
|
||||
}
|
||||
|
||||
private _compileShaderSource(
|
||||
engine: Engine,
|
||||
macroCollection: ShaderMacroCollection
|
||||
|
||||
@@ -1,8 +1,4 @@
|
||||
import { GLCapabilityType } from "../base/Constant";
|
||||
import { Logger } from "../base/Logger";
|
||||
import { Engine } from "../Engine";
|
||||
import { ShaderMacro } from "../shader/ShaderMacro";
|
||||
import { ShaderMacroCollection } from "../shader/ShaderMacroCollection";
|
||||
import { ShaderLib } from "./ShaderLib";
|
||||
|
||||
export class ShaderFactory {
|
||||
@@ -18,65 +14,6 @@ export class ShaderFactory {
|
||||
|
||||
private static readonly _has300OutInFragReg = /\bout\s+(?:\w+\s+)?(?:vec4)\s+(?:\w+)\s*;/; // [layout(location = 0)] out [highp] vec4 [color];
|
||||
|
||||
static parseCustomMacros(macros: ShaderMacro[]) {
|
||||
return macros.map((m) => `#define ${m.value ? m.name + ` ` + m.value : m.name}\n`).join("");
|
||||
}
|
||||
|
||||
/**
|
||||
* @internal
|
||||
* Compile vertex and fragment source with standard macros, includes, and version header.
|
||||
* @param engine - Engine instance
|
||||
* @param macroCollection - Current macro collection
|
||||
* @param vertexSource - Raw vertex shader source (may contain #include)
|
||||
* @param fragmentSource - Raw fragment shader source
|
||||
* @returns Compiled { vertexSource, fragmentSource } ready for ShaderProgram
|
||||
*/
|
||||
static compilePlatformSource(
|
||||
engine: Engine,
|
||||
macroCollection: ShaderMacroCollection,
|
||||
vertexSource: string,
|
||||
fragmentSource: string
|
||||
): { vertexSource: string; fragmentSource: string } {
|
||||
const isWebGL2 = engine._hardwareRenderer.isWebGL2;
|
||||
const shaderMacroList = new Array<ShaderMacro>();
|
||||
ShaderMacro._getMacrosElements(macroCollection, shaderMacroList);
|
||||
shaderMacroList.push(ShaderMacro.getByName(isWebGL2 ? "GRAPHICS_API_WEBGL2" : "GRAPHICS_API_WEBGL1"));
|
||||
if (engine._hardwareRenderer.canIUse(GLCapabilityType.shaderTextureLod)) {
|
||||
shaderMacroList.push(ShaderMacro.getByName("HAS_TEX_LOD"));
|
||||
}
|
||||
if (engine._hardwareRenderer.canIUse(GLCapabilityType.standardDerivatives)) {
|
||||
shaderMacroList.push(ShaderMacro.getByName("HAS_DERIVATIVES"));
|
||||
}
|
||||
|
||||
let noIncludeVertex = ShaderFactory.parseIncludes(vertexSource);
|
||||
let noIncludeFrag = ShaderFactory.parseIncludes(fragmentSource);
|
||||
|
||||
const macroStr = ShaderFactory.parseCustomMacros(shaderMacroList);
|
||||
noIncludeVertex = macroStr + noIncludeVertex;
|
||||
noIncludeFrag = macroStr + noIncludeFrag;
|
||||
|
||||
if (isWebGL2) {
|
||||
noIncludeVertex = ShaderFactory.convertTo300(noIncludeVertex);
|
||||
noIncludeFrag = ShaderFactory.convertTo300(noIncludeFrag, true);
|
||||
}
|
||||
|
||||
const versionStr = isWebGL2 ? "#version 300 es" : "#version 100";
|
||||
const precisionStr = `
|
||||
#ifdef GL_FRAGMENT_PRECISION_HIGH
|
||||
precision highp float;
|
||||
precision highp int;
|
||||
#else
|
||||
precision mediump float;
|
||||
precision mediump int;
|
||||
#endif
|
||||
`;
|
||||
|
||||
return {
|
||||
vertexSource: `${versionStr}\nprecision highp float;\n${noIncludeVertex}`,
|
||||
fragmentSource: `${versionStr}\n${isWebGL2 ? "" : ShaderFactory._shaderExtension}${precisionStr}${noIncludeFrag}`
|
||||
};
|
||||
}
|
||||
|
||||
static registerInclude(includeName: string, includeSource: string) {
|
||||
if (ShaderLib[includeName]) {
|
||||
throw `The "${includeName}" shader include already exist`;
|
||||
|
||||
@@ -19,18 +19,22 @@ import { ShaderCompiler } from "@galacean/engine-shader-compiler";
|
||||
import { vi, describe, expect, it } from "vitest";
|
||||
|
||||
const shaderCompiler = new ShaderCompiler();
|
||||
// @ts-ignore
|
||||
Shader._shaderCompiler = shaderCompiler;
|
||||
|
||||
const makePass = (name = "Default") =>
|
||||
new ShaderPass(name, [], [], ShaderLanguage.GLSLES100);
|
||||
|
||||
describe("Shader", () => {
|
||||
describe("Custom Shader", () => {
|
||||
it("Shader", () => {
|
||||
// Create shader
|
||||
let customShader = Shader.create("customByStringCreate", customVS, customFS);
|
||||
customShader = Shader.create("customByPassCreate", [new ShaderPass(customVS, customFS)]);
|
||||
customShader = Shader.create("custom", [new SubShader("Default", [new ShaderPass(customVS, customFS)])]);
|
||||
// Create shader via ShaderPass[] / SubShader[] overloads
|
||||
Shader.create("customByPassCreate", [makePass()]);
|
||||
const customShader = Shader.create("custom", [new SubShader("Default", [makePass()])]);
|
||||
|
||||
// Create same name shader
|
||||
const errorSpy = vi.spyOn(console, "error");
|
||||
Shader.create("custom", [new SubShader("Default", [new ShaderPass(customVS, customFS)])]);
|
||||
Shader.create("custom", [new SubShader("Default", [makePass()])]);
|
||||
expect(errorSpy).toHaveBeenCalledWith('Shader named "custom" already exists.');
|
||||
vi.resetAllMocks();
|
||||
|
||||
@@ -342,23 +346,6 @@ describe("Shader", () => {
|
||||
});
|
||||
});
|
||||
|
||||
const customVS = `
|
||||
attribute vec3 POSITION;
|
||||
uniform mat4 renderer_MVPMat;
|
||||
|
||||
void main() {
|
||||
gl_Position = renderer_MVPMat * vec4(POSITION, 1.0);
|
||||
}
|
||||
`;
|
||||
|
||||
const customFS = `
|
||||
uniform vec4 material_BaseColor;
|
||||
|
||||
void main() {
|
||||
gl_FragColor = material_BaseColor;
|
||||
}
|
||||
`;
|
||||
|
||||
const testShaderCompilerCode = `
|
||||
Shader "Test-Default" {
|
||||
SubShader "Default" {
|
||||
|
||||
@@ -357,120 +357,4 @@ describe("Precompile Benchmark", async () => {
|
||||
});
|
||||
});
|
||||
|
||||
// ═══════════════════════════════════════════════════════════
|
||||
// 6. Variant switch breakdown: CPU / GPU / Total
|
||||
//
|
||||
// CPU measured via _compileShaderSource / compilePlatformSource
|
||||
// Total measured via _getCanonicalShaderProgram (CPU + GPU)
|
||||
// GPU = Total - CPU
|
||||
//
|
||||
// GSP CPU: buildMacroList + evaluateShaderInstructions + convertTo300 + assemble
|
||||
// GLSL CPU: buildMacroList + parseIncludes + parseCustomMacros + convertTo300 + assemble
|
||||
// GPU: new ShaderProgram(engine, vs, fs) — WebGL compile + link
|
||||
// ═══════════════════════════════════════════════════════════
|
||||
describe("6. Variant switch: CPU / GPU / Total (PBR)", () => {
|
||||
it("precompiled (GSP) vs raw GLSL path", () => {
|
||||
// @ts-ignore
|
||||
Shader._shaderCompiler = shaderCompiler;
|
||||
const precompiled = shaderCompiler._precompile(PBRSource, ShaderLanguage.GLSLES100);
|
||||
const forwardPassData = precompiled.subShaders[0].passes.find((p) => !p.isUsePass)!;
|
||||
|
||||
// GSP ShaderPass (with instructions)
|
||||
const gspShaderPass = new ShaderPass(
|
||||
forwardPassData.name,
|
||||
forwardPassData.vertexShaderInstructions!,
|
||||
forwardPassData.fragmentShaderInstructions!,
|
||||
ShaderLanguage.GLSLES100,
|
||||
forwardPassData.tags
|
||||
);
|
||||
|
||||
// GLSL ShaderPass (raw source, no instructions → compilePlatformSource path)
|
||||
const parsed = shaderCompiler._parseShaderSource(PBRSource);
|
||||
const livePassSource = parsed.subShaders[0].passes.find((p) => !p.isUsePass)!;
|
||||
const liveProg = shaderCompiler._parseShaderPass(
|
||||
livePassSource.contents,
|
||||
livePassSource.vertexEntry,
|
||||
livePassSource.fragmentEntry,
|
||||
ShaderLanguage.GLSLES100
|
||||
)!;
|
||||
// Use original CodeGen GLSL (with all #ifdef branches preserved)
|
||||
const glslShaderPass = new ShaderPass(
|
||||
livePassSource.name,
|
||||
liveProg.vertex,
|
||||
liveProg.fragment,
|
||||
livePassSource.tags
|
||||
);
|
||||
|
||||
Logger.disable();
|
||||
|
||||
const scenarios: Array<{ label: string; macros: ShaderMacroCollection }> = [
|
||||
{ label: "empty", macros: new ShaderMacroCollection() },
|
||||
{ label: "base (11)", macros: buildMacroCollection(baseMacros) },
|
||||
{ label: "full (18)", macros: buildMacroCollection([...baseMacros, ...materialVariantMacros]) }
|
||||
];
|
||||
|
||||
console.log("\n=== Variant Switch Breakdown (PBR Forward Pass) ===");
|
||||
console.log(
|
||||
"| Scenario | GSP CPU (ms) | GLSL CPU (ms) | GSP GPU (ms) | GLSL GPU (ms) | GSP Total (ms) | GLSL Total (ms) | GSP Size | GLSL Size |"
|
||||
);
|
||||
console.log(
|
||||
"|----------|-------------|--------------|-------------|--------------|---------------|----------------|----------|------------|"
|
||||
);
|
||||
|
||||
// Split-timing bench: measure CPU and GPU within the same iteration
|
||||
function benchSplit(
|
||||
shaderPass: ShaderPass,
|
||||
macroCollection: ShaderMacroCollection,
|
||||
compileMethod: string,
|
||||
runs: number,
|
||||
warmup: number
|
||||
): { cpu: number; gpu: number; total: number; vsLen: number; fsLen: number } {
|
||||
// Warmup
|
||||
for (let i = 0; i < warmup; i++) {
|
||||
// @ts-ignore
|
||||
shaderPass._getCanonicalShaderProgram(engine, macroCollection);
|
||||
}
|
||||
|
||||
const cpuTimes: number[] = [];
|
||||
const gpuTimes: number[] = [];
|
||||
let vsLen = 0;
|
||||
let fsLen = 0;
|
||||
|
||||
for (let i = 0; i < runs; i++) {
|
||||
// CPU: compile source
|
||||
const t0 = performance.now();
|
||||
// @ts-ignore
|
||||
const { vertexSource, fragmentSource } = shaderPass[compileMethod](engine, macroCollection);
|
||||
const t1 = performance.now();
|
||||
vsLen = vertexSource.length;
|
||||
fsLen = fragmentSource.length;
|
||||
|
||||
// GPU: create ShaderProgram
|
||||
// @ts-ignore
|
||||
new ShaderProgram(engine, vertexSource, fragmentSource);
|
||||
const t2 = performance.now();
|
||||
|
||||
cpuTimes.push(t1 - t0);
|
||||
gpuTimes.push(t2 - t1);
|
||||
}
|
||||
|
||||
cpuTimes.sort((a, b) => a - b);
|
||||
gpuTimes.sort((a, b) => a - b);
|
||||
const cpuAvg = cpuTimes.reduce((s, t) => s + t, 0) / cpuTimes.length;
|
||||
const gpuAvg = gpuTimes.reduce((s, t) => s + t, 0) / gpuTimes.length;
|
||||
return { cpu: cpuAvg, gpu: gpuAvg, total: cpuAvg + gpuAvg, vsLen, fsLen };
|
||||
}
|
||||
|
||||
for (const { label, macros } of scenarios) {
|
||||
const gsp = benchSplit(gspShaderPass, macros, "_compileShaderSource", 10, 3);
|
||||
const glsl = benchSplit(glslShaderPass, macros, "_compilePlatformSource", 10, 3);
|
||||
|
||||
console.log(
|
||||
`| ${label.padEnd(8)} | ${gsp.cpu.toFixed(3).padStart(11)} | ${glsl.cpu.toFixed(3).padStart(12)} | ${gsp.gpu.toFixed(2).padStart(11)} | ${glsl.gpu.toFixed(2).padStart(12)} | ${gsp.total.toFixed(2).padStart(13)} | ${glsl.total.toFixed(2).padStart(14)} | ${(gsp.vsLen + gsp.fsLen).toString().padStart(9)} | ${(glsl.vsLen + glsl.fsLen).toString().padStart(10)} |`
|
||||
);
|
||||
}
|
||||
|
||||
Logger.enable();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user