Bladeren bron

Attribute Auto Processing

Sebastien Vandenberghe 6 jaren geleden
bovenliggende
commit
74306cc508

+ 4 - 1
src/Engines/Processors/iShaderProcessor.ts

@@ -1,6 +1,9 @@
+import { Nullable } from "../../types";
+import { ShaderProcessingContext } from "./shaderProcessingOptions";
+
 /** @hidden */
 export interface IShaderProcessor {
-    attributeProcessor?: (attribute: string) => string;
+    attributeProcessor?: (attribute: string, processingContext: Nullable<ShaderProcessingContext>) => string;
     varyingProcessor?: (varying: string, isFragment: boolean) => string;
     uniformProcessor?: (uniform: string, isFragment: boolean) => string;
     uniformBufferProcessor?: (uniformBuffer: string, isFragment: boolean) => string;

+ 1 - 1
src/Engines/Processors/shaderCodeNode.ts

@@ -19,7 +19,7 @@ export class ShaderCodeNode {
             let processor = options.processor;
             if (processor) {
                 if (processor.attributeProcessor && StringTools.StartsWith(this.line, "attribute")) {
-                    value = processor.attributeProcessor(this.line);
+                    value = processor.attributeProcessor(this.line, options.processingContext);
                 } else if (processor.varyingProcessor && StringTools.StartsWith(this.line, "varying")) {
                     value = processor.varyingProcessor(this.line, options.isFragment);
                 } else if ((processor.uniformProcessor || processor.uniformBufferProcessor) && StringTools.StartsWith(this.line, "uniform")) {

+ 4 - 0
src/Engines/Processors/shaderProcessingOptions.ts

@@ -2,6 +2,9 @@ import { IShaderProcessor } from './iShaderProcessor';
 import { Nullable } from '../../types';
 
 /** @hidden */
+export interface ShaderProcessingContext { }
+
+/** @hidden */
 export interface ProcessingOptions {
     defines: string[];
     indexParameters: any;
@@ -14,4 +17,5 @@ export interface ProcessingOptions {
     version: string;
     platformName: string;
     lookForClosingBracketForUniformBuffer?: boolean;
+    processingContext: Nullable<ShaderProcessingContext>;
 }

+ 5 - 0
src/Engines/WebGPU/webgpuPipelineContext.ts

@@ -3,6 +3,7 @@ import { Nullable } from '../../types';
 import { WebGPUEngine } from '../webgpuEngine';
 import { InternalTexture } from '../../Materials/Textures/internalTexture';
 import { Effect } from '../../Materials/effect';
+import { WebGPUShaderProcessingContext } from './webgpuShaderProcessingContext';
 
 /** @hidden */
 export interface IWebGPUPipelineContextSamplerCache {
@@ -60,6 +61,10 @@ export class WebGPUPipelineContext implements IPipelineContext {
         return false;
     }
 
+    constructor(shaderProcessingContext: WebGPUShaderProcessingContext) {
+        this.availableAttributes = shaderProcessingContext.availableAttributes;
+    }
+
     public _handlesSpectorRebuildCallback(onCompiled: (program: any) => void): void {
         // Nothing to do yet for spector.
     }

+ 15 - 0
src/Engines/WebGPU/webgpuShaderProcessingContext.ts

@@ -0,0 +1,15 @@
+import { ShaderProcessingContext } from "../processors/shaderProcessingOptions";
+
+/**
+ * @hidden
+ */
+export class WebGPUShaderProcessingContext implements ShaderProcessingContext {
+    public attributeNextLocation: number;
+
+    public availableAttributes: { [key: string]: number };
+
+    constructor() {
+        this.attributeNextLocation = 0;
+        this.availableAttributes = { };
+    }
+}

+ 17 - 15
src/Engines/WebGPU/webgpuShaderProcessors.ts

@@ -1,8 +1,10 @@
+import { Nullable } from '../../types';
 import { IShaderProcessor } from '../Processors/iShaderProcessor';
+import { ShaderProcessingContext } from "../processors/shaderProcessingOptions";
+import { WebGPUShaderProcessingContext } from './webgpuShaderProcessingContext';
 
 /** @hidden */
 export class WebGPUShaderProcessor implements IShaderProcessor {
-    // attributeProcessor?: (attribute: string) => string;
     // varyingProcessor?: (varying: string, isFragment: boolean) => string;
     // uniformProcessor?: (uniform: string, isFragment: boolean) => string;
     // uniformBufferProcessor?: (uniformBuffer: string, isFragment: boolean) => string;
@@ -11,21 +13,21 @@ export class WebGPUShaderProcessor implements IShaderProcessor {
     // preProcessor?: (code: string, defines: string[], isFragment: boolean) => string;
     // postProcessor?: (code: string, defines: string[], isFragment: boolean) => string;
 
-    public attributeProcessor(attribute: string) {
-        return attribute.replace("attribute", "in");
-        // const inOut = isFragment ? "in" : "out";
-        // const attribRegex = new RegExp(/\s+attribute\s+(\w+)\s+/gm);
+    public attributeProcessor(attribute: string, processingContext: Nullable<ShaderProcessingContext>) {
+        const webgpuProcessingContext = processingContext! as WebGPUShaderProcessingContext;
 
-        // let location = 0;
-        // let match = attribRegex.exec(code);
-        // while (match != null) {
-        //     if (match[1]) {
-        //         code = code.replace(match[0], ` layout(location = ${location}) ${inOut} ${match[1]} `);
-        //         location++;
-        //     }
-        //     match = attribRegex.exec(code);
-        // }
-        // return code;
+        // return attribute.replace("attribute", "in");
+        const attribRegex = new RegExp(/\s*attribute\s+(\S+)\s+(\S+)\s*;/gm);
+
+        const match = attribRegex.exec(attribute);
+        const location = webgpuProcessingContext.attributeNextLocation++;
+        if (match != null) {
+            const name = match[2];
+
+            webgpuProcessingContext.availableAttributes[name] = location;
+            attribute = attribute.replace(match[0], `layout(location = ${location}) in ${match[1]} ${name};`);
+        }
+        return attribute;
     }
 
     public varyingProcessor(varying: string, isFragment: boolean) {

+ 8 - 1
src/Engines/engine.ts

@@ -26,6 +26,7 @@ import { IPipelineContext } from './IPipelineContext';
 import { DataBuffer } from '../Meshes/dataBuffer';
 import { WebGLDataBuffer } from '../Meshes/WebGL/webGLDataBuffer';
 import { IShaderProcessor } from './Processors/iShaderProcessor';
+import { ShaderProcessingContext } from "./Processors/shaderProcessingOptions";
 import { WebGL2ShaderProcessor } from './WebGL/webGL2ShaderProcessors';
 import { PerfCounter } from '../Misc/perfCounter';
 import { IFileRequest } from '../Misc/fileRequest';
@@ -1315,6 +1316,11 @@ export class Engine {
         return null;
     }
 
+    /** @hidden */
+    public _getShaderProcessingContext(): Nullable<ShaderProcessingContext> {
+        return null;
+    }
+
     // WebVR
 
     /**
@@ -3325,9 +3331,10 @@ export class Engine {
 
     /**
      * Creates a new pipeline context
+     * @param shaderProcessingContext defines the shader processing context used during the processing if available
      * @returns the new pipeline
      */
-    public createPipelineContext(): IPipelineContext {
+    public createPipelineContext(shaderProcessingContext: Nullable<ShaderProcessingContext>): IPipelineContext {
         var pipelineContext = new WebGLPipelineContext();
         pipelineContext.engine = this;
 

+ 9 - 22
src/Engines/webgpuEngine.ts

@@ -20,6 +20,8 @@ import { IInternalTextureLoader } from "../Materials/Textures/internalTextureLoa
 import { BaseTexture } from "../Materials/Textures/baseTexture";
 import { IShaderProcessor } from "./Processors/iShaderProcessor";
 import { WebGPUShaderProcessor } from "./WebGPU/webgpuShaderProcessors";
+import { ShaderProcessingContext } from "./Processors/shaderProcessingOptions";
+import { WebGPUShaderProcessingContext } from "./WebGPU/webgpuShaderProcessingContext";
 
 /**
  * Options to create the WebGPU engine
@@ -345,6 +347,11 @@ export class WebGPUEngine extends Engine {
         return new WebGPUShaderProcessor();
     }
 
+    /** @hidden */
+    public _getShaderProcessingContext(): Nullable<ShaderProcessingContext> {
+        return new WebGPUShaderProcessingContext();
+    }
+
     //------------------------------------------------------------------------------
     //                          Static Pipeline WebGPU States
     //------------------------------------------------------------------------------
@@ -773,8 +780,8 @@ export class WebGPUEngine extends Engine {
         throw "Not available on WebGPU";
     }
 
-    public createPipelineContext(): IPipelineContext {
-        var pipelineContext = new WebGPUPipelineContext();
+    public createPipelineContext(shaderProcessingContext: Nullable<ShaderProcessingContext>): IPipelineContext {
+        var pipelineContext = new WebGPUPipelineContext(shaderProcessingContext! as WebGPUShaderProcessingContext);
         pipelineContext.engine = this;
         return pipelineContext;
     }
@@ -802,7 +809,6 @@ export class WebGPUEngine extends Engine {
                 webGpuContext.stages = this._compilePipelineStageDescriptor(vertexSourceCode, fragmentSourceCode, defines);
             }
 
-            this._findAttributes(webGpuContext, vertexSourceCode);
             this._findUBOs(webGpuContext, fragmentSourceCode);
 
             this._compiledShaders[key] = {
@@ -817,25 +823,6 @@ export class WebGPUEngine extends Engine {
         }
     }
 
-    private _findAttributes(pipelineContext: WebGPUPipelineContext, vertexSourceCode: string): void {
-        // TODO.
-        // Hard coded for WebGPU until an introspection lib is available.
-
-        const results: { [key: string]: number } = { };
-
-        const vertexShaderCode = vertexSourceCode;
-        const attributesRegex = /layout\(location\s*=\s*([0-9]*)\)\s*in\s*\S*\s*(\S*);/gm;
-        let matches: RegExpExecArray | null;
-        while (matches = attributesRegex.exec(vertexShaderCode)) {
-            const location = matches[1];
-            const name = matches[2];
-
-            results[name] = +location;
-        }
-
-        pipelineContext.availableAttributes = results;
-    }
-
     private _findUBOs(pipelineContext: WebGPUPipelineContext, fragmentSourceCode: string): void {
         // TODO.
         // Hard coded for WebGPU until an introspection lib is available.

+ 9 - 4
src/Materials/effect.ts

@@ -7,7 +7,7 @@ import { IDisposable } from '../scene';
 import { IPipelineContext } from '../Engines/IPipelineContext';
 import { DataBuffer } from '../Meshes/dataBuffer';
 import { ShaderProcessor } from '../Engines/Processors/shaderProcessor';
-import { ProcessingOptions } from '../Engines/Processors/shaderProcessingOptions';
+import { ProcessingOptions, ShaderProcessingContext } from '../Engines/Processors/shaderProcessingOptions';
 import { IMatrixLike, IVector2Like, IVector3Like, IVector4Like, IColor3Like, IColor4Like } from '../Maths/math.like';
 
 declare type Engine = import("../Engines/engine").Engine;
@@ -280,6 +280,8 @@ export class Effect implements IDisposable {
     private _valueCache: { [key: string]: any } = {};
     private static _baseCache: { [key: number]: DataBuffer } = {};
 
+    private _processingContext: Nullable<ShaderProcessingContext>;
+
     /**
      * Instantiates an effect.
      * An effect can be used to create/manage/execute vertex and fragment shaders.
@@ -374,7 +376,9 @@ export class Effect implements IDisposable {
             fragmentSource = baseName.fragment || baseName;
         }
 
-        let processorOptions: ProcessingOptions = {
+        this._processingContext = engine!._getShaderProcessingContext();
+
+        const processorOptions: ProcessingOptions = {
             defines: this.defines.split("\n"),
             indexParameters: this._indexParameters,
             isFragment: false,
@@ -384,7 +388,8 @@ export class Effect implements IDisposable {
             shadersRepository: Effect.ShadersRepository,
             includesShadersStore: Effect.IncludesShadersStore,
             version: (this._engine.webGLVersion * 100).toString(),
-            platformName: this._engine.shaderPlatformName
+            platformName: this._engine.shaderPlatformName,
+            processingContext: this._processingContext
         };
 
         this._loadVertexShader(vertexSource, (vertexCode) => {
@@ -714,7 +719,7 @@ export class Effect implements IDisposable {
         try {
             let engine = this._engine;
 
-            this._pipelineContext = engine.createPipelineContext();
+            this._pipelineContext = engine.createPipelineContext(this._processingContext);
 
             let rebuildRebind = this._rebuildProgram.bind(this);
             if (this._vertexSourceCodeOverride && this._fragmentSourceCodeOverride) {

+ 11 - 50
src/Shaders/pbr.vertex.fx

@@ -5,73 +5,34 @@
 #define CUSTOM_VERTEX_BEGIN
 
 // Attributes
-#ifdef WEBGPU
-    layout(location = 0) in vec3 position;
-#else
-    attribute vec3 position;
-#endif
+attribute vec3 position;
+// #endif
 
 #ifdef NORMAL
-    #ifdef WEBGPU
-        layout(location = 1) in vec3 normal;
-    #else
-        attribute vec3 normal;
-    #endif
+    attribute vec3 normal;
 #endif
 
 #ifdef TANGENT
-    #ifdef WEBGPU
-        layout(location = 2) in vec4 tangent;
-    #else
-        attribute vec4 tangent;
-    #endif
+    attribute vec4 tangent;
 #endif
 
 #ifdef UV1
-    #ifdef WEBGPU
-        layout(location = 3) in vec2 uv;
-    #else
-        attribute vec2 uv;
-    #endif
+    attribute vec2 uv;
 #endif
 
 #ifdef UV2
-    #ifdef WEBGPU
-        layout(location = 4) in vec2 uv2;
-    #else
-        attribute vec2 uv2;
-    #endif
+    attribute vec2 uv2;
 #endif
 
 #ifdef VERTEXCOLOR
-    #ifdef WEBGPU
-        layout(location = 5) in vec4 color;
-    #else
-        attribute vec4 color;
-    #endif
+    attribute vec4 color;
 #endif
 
 #ifdef INSTANCES
-    #ifdef WEBGPU
-        layout(location = 6) in vec4 world0;
-    #else
-        attribute vec4 world0;
-    #endif
-    #ifdef WEBGPU
-        layout(location = 7) in vec4 world1;
-    #else
-        attribute vec4 world1;
-    #endif
-    #ifdef WEBGPU
-        layout(location = 8) in vec4 world2;
-    #else
-        attribute vec4 world2;
-    #endif
-    #ifdef WEBGPU
-        layout(location = 9) in vec4 world3;
-    #else
-        attribute vec4 world3;
-    #endif
+    attribute vec4 world0;
+    attribute vec4 world1;
+    attribute vec4 world2;
+    attribute vec4 world3;
 #endif
 
 #include<helperFunctions>