浏览代码

Left Over Uniforms in Shared UBOs

Sebastien Vandenberghe 6 年之前
父节点
当前提交
91f266a89c

+ 210 - 0
src/Engines/IPipelineContext.ts

@@ -1,5 +1,6 @@
 import { Nullable } from '../types';
 import { Effect } from '../Materials/effect';
+import { IMatrixLike, IVector2Like, IVector3Like, IVector4Like, IColor3Like, IColor4Like } from '../Maths/math.like';
 
 /**
  * Class used to store and describe the pipeline context associated with an effect
@@ -19,4 +20,213 @@ export interface IPipelineContext {
 
     /** @hidden */
     _fillEffectInformation(effect: Effect, uniformBuffersNames: { [key: string]: number }, uniformsNames: string[], uniforms: { [key: string]: Nullable<WebGLUniformLocation> }, samplerList: string[], samplers: { [key: string]: number }, attributesNames: string[], attributes: number[]): void;
+
+    /** Releases the resources associated with the pipeline. */
+    dispose(): void;
+
+    /**
+     * Sets an interger value on a uniform variable.
+     * @param uniformName Name of the variable.
+     * @param value Value to be set.
+     */
+    setInt(uniformName: string, value: number): void;
+
+    /**
+     * Sets an int array on a uniform variable.
+     * @param uniformName Name of the variable.
+     * @param array array to be set.
+     */
+    setIntArray(uniformName: string, array: Int32Array): void;
+
+    /**
+     * Sets an int array 2 on a uniform variable. (Array is specified as single array eg. [1,2,3,4] will result in [[1,2],[3,4]] in the shader)
+     * @param uniformName Name of the variable.
+     * @param array array to be set.
+     */
+    setIntArray2(uniformName: string, array: Int32Array): void;
+
+    /**
+     * Sets an int array 3 on a uniform variable. (Array is specified as single array eg. [1,2,3,4,5,6] will result in [[1,2,3],[4,5,6]] in the shader)
+     * @param uniformName Name of the variable.
+     * @param array array to be set.
+     */
+    setIntArray3(uniformName: string, array: Int32Array): void;
+
+    /**
+     * Sets an int array 4 on a uniform variable. (Array is specified as single array eg. [1,2,3,4,5,6,7,8] will result in [[1,2,3,4],[5,6,7,8]] in the shader)
+     * @param uniformName Name of the variable.
+     * @param array array to be set.
+     */
+    setIntArray4(uniformName: string, array: Int32Array): void;
+
+    /**
+     * Sets an float array on a uniform variable.
+     * @param uniformName Name of the variable.
+     * @param array array to be set.
+     */
+    setFloatArray(uniformName: string, array: Float32Array): void;
+
+    /**
+     * Sets an float array 2 on a uniform variable. (Array is specified as single array eg. [1,2,3,4] will result in [[1,2],[3,4]] in the shader)
+     * @param uniformName Name of the variable.
+     * @param array array to be set.
+     */
+    setFloatArray2(uniformName: string, array: Float32Array): void;
+
+    /**
+     * Sets an float array 3 on a uniform variable. (Array is specified as single array eg. [1,2,3,4,5,6] will result in [[1,2,3],[4,5,6]] in the shader)
+     * @param uniformName Name of the variable.
+     * @param array array to be set.
+     */
+    setFloatArray3(uniformName: string, array: Float32Array): void;
+
+    /**
+     * Sets an float array 4 on a uniform variable. (Array is specified as single array eg. [1,2,3,4,5,6,7,8] will result in [[1,2,3,4],[5,6,7,8]] in the shader)
+     * @param uniformName Name of the variable.
+     * @param array array to be set.
+     */
+    setFloatArray4(uniformName: string, array: Float32Array): void;
+
+    /**
+     * Sets an array on a uniform variable.
+     * @param uniformName Name of the variable.
+     * @param array array to be set.
+     */
+    setArray(uniformName: string, array: number[]): void;
+
+    /**
+     * Sets an array 2 on a uniform variable. (Array is specified as single array eg. [1,2,3,4] will result in [[1,2],[3,4]] in the shader)
+     * @param uniformName Name of the variable.
+     * @param array array to be set.
+     */
+    setArray2(uniformName: string, array: number[]): void;
+
+    /**
+     * Sets an array 3 on a uniform variable. (Array is specified as single array eg. [1,2,3,4,5,6] will result in [[1,2,3],[4,5,6]] in the shader)
+     * @param uniformName Name of the variable.
+     * @param array array to be set.
+     * @returns this effect.
+     */
+    setArray3(uniformName: string, array: number[]): void;
+
+    /**
+     * Sets an array 4 on a uniform variable. (Array is specified as single array eg. [1,2,3,4,5,6,7,8] will result in [[1,2,3,4],[5,6,7,8]] in the shader)
+     * @param uniformName Name of the variable.
+     * @param array array to be set.
+     */
+    setArray4(uniformName: string, array: number[]): void;
+
+    /**
+     * Sets matrices on a uniform variable.
+     * @param uniformName Name of the variable.
+     * @param matrices matrices to be set.
+     */
+    setMatrices(uniformName: string, matrices: Float32Array): void;
+
+    /**
+     * Sets matrix on a uniform variable.
+     * @param uniformName Name of the variable.
+     * @param matrix matrix to be set.
+     */
+    setMatrix(uniformName: string, matrix: IMatrixLike): void;
+
+    /**
+     * Sets a 3x3 matrix on a uniform variable. (Speicified as [1,2,3,4,5,6,7,8,9] will result in [1,2,3][4,5,6][7,8,9] matrix)
+     * @param uniformName Name of the variable.
+     * @param matrix matrix to be set.
+     */
+    setMatrix3x3(uniformName: string, matrix: Float32Array): void;
+
+    /**
+     * Sets a 2x2 matrix on a uniform variable. (Speicified as [1,2,3,4] will result in [1,2][3,4] matrix)
+     * @param uniformName Name of the variable.
+     * @param matrix matrix to be set.
+     */
+    setMatrix2x2(uniformName: string, matrix: Float32Array): void;
+
+    /**
+     * Sets a float on a uniform variable.
+     * @param uniformName Name of the variable.
+     * @param value value to be set.
+     * @returns this effect.
+     */
+    setFloat(uniformName: string, value: number): void;
+
+    /**
+     * Sets a boolean on a uniform variable.
+     * @param uniformName Name of the variable.
+     * @param bool value to be set.
+     */
+    setBool(uniformName: string, bool: boolean): void;
+
+    /**
+     * Sets a Vector2 on a uniform variable.
+     * @param uniformName Name of the variable.
+     * @param vector2 vector2 to be set.
+     */
+    setVector2(uniformName: string, vector2: IVector2Like): void;
+
+    /**
+     * Sets a float2 on a uniform variable.
+     * @param uniformName Name of the variable.
+     * @param x First float in float2.
+     * @param y Second float in float2.
+     */
+    setFloat2(uniformName: string, x: number, y: number): void;
+
+    /**
+     * Sets a Vector3 on a uniform variable.
+     * @param uniformName Name of the variable.
+     * @param vector3 Value to be set.
+     */
+    setVector3(uniformName: string, vector3: IVector3Like): void;
+
+    /**
+     * Sets a float3 on a uniform variable.
+     * @param uniformName Name of the variable.
+     * @param x First float in float3.
+     * @param y Second float in float3.
+     * @param z Third float in float3.
+     */
+    setFloat3(uniformName: string, x: number, y: number, z: number): void;
+
+    /**
+     * Sets a Vector4 on a uniform variable.
+     * @param uniformName Name of the variable.
+     * @param vector4 Value to be set.
+     */
+    setVector4(uniformName: string, vector4: IVector4Like): void;
+
+    /**
+     * Sets a float4 on a uniform variable.
+     * @param uniformName Name of the variable.
+     * @param x First float in float4.
+     * @param y Second float in float4.
+     * @param z Third float in float4.
+     * @param w Fourth float in float4.
+     * @returns this effect.
+     */
+    setFloat4(uniformName: string, x: number, y: number, z: number, w: number): void;
+
+    /**
+     * Sets a Color3 on a uniform variable.
+     * @param uniformName Name of the variable.
+     * @param color3 Value to be set.
+     */
+    setColor3(uniformName: string, color3: IColor3Like): void;
+
+    /**
+     * Sets a Color4 on a uniform variable.
+     * @param uniformName Name of the variable.
+     * @param color3 Value to be set.
+     * @param alpha Alpha value to be set.
+     */
+    setColor4(uniformName: string, color3: IColor3Like, alpha: number): void;
+
+    /**
+     * Sets a Color4 on a uniform variable
+     * @param uniformName defines the name of the variable
+     * @param color4 defines the value to be set
+     */
+    setDirectColor4(uniformName: string, color4: IColor4Like): void;
 }

+ 425 - 0
src/Engines/WebGL/webGLPipelineContext.ts

@@ -2,9 +2,13 @@ import { IPipelineContext } from '../IPipelineContext';
 import { Engine } from '../engine';
 import { Nullable } from '../../types';
 import { Effect } from '../../Materials/effect';
+import { IMatrixLike, IVector2Like, IVector3Like, IVector4Like, IColor3Like, IColor4Like } from '../../Maths/math.like';
 
 /** @hidden */
 export class WebGLPipelineContext implements IPipelineContext {
+    private _valueCache: { [key: string]: any } = {};
+    private _uniforms: { [key: string]: Nullable<WebGLUniformLocation> };
+
     public engine: Engine;
     public program: Nullable<WebGLProgram>;
     public context?: WebGLRenderingContext;
@@ -47,6 +51,7 @@ export class WebGLPipelineContext implements IPipelineContext {
         effectAvailableUniforms.forEach((uniform, index) => {
             uniforms[uniformsNames[index]] = uniform;
         });
+        this._uniforms = uniforms;
 
         let index: number;
         for (index = 0; index < samplerList.length; index++) {
@@ -63,4 +68,424 @@ export class WebGLPipelineContext implements IPipelineContext {
 
         attributes.push(...engine.getAttributes(this, attributesNames));
     }
+
+    /**
+     * Release all associated resources.
+     **/
+    public dispose() {
+        this._uniforms = { };
+    }
+
+    /** @hidden */
+    public _cacheMatrix(uniformName: string, matrix: IMatrixLike): boolean {
+        var cache = this._valueCache[uniformName];
+        var flag = matrix.updateFlag;
+        if (cache !== undefined && cache === flag) {
+            return false;
+        }
+
+        this._valueCache[uniformName] = flag;
+
+        return true;
+    }
+
+    /** @hidden */
+    public _cacheFloat2(uniformName: string, x: number, y: number): boolean {
+        var cache = this._valueCache[uniformName];
+        if (!cache) {
+            cache = [x, y];
+            this._valueCache[uniformName] = cache;
+            return true;
+        }
+
+        var changed = false;
+        if (cache[0] !== x) {
+            cache[0] = x;
+            changed = true;
+        }
+        if (cache[1] !== y) {
+            cache[1] = y;
+            changed = true;
+        }
+
+        return changed;
+    }
+
+    /** @hidden */
+    public _cacheFloat3(uniformName: string, x: number, y: number, z: number): boolean {
+        var cache = this._valueCache[uniformName];
+        if (!cache) {
+            cache = [x, y, z];
+            this._valueCache[uniformName] = cache;
+            return true;
+        }
+
+        var changed = false;
+        if (cache[0] !== x) {
+            cache[0] = x;
+            changed = true;
+        }
+        if (cache[1] !== y) {
+            cache[1] = y;
+            changed = true;
+        }
+        if (cache[2] !== z) {
+            cache[2] = z;
+            changed = true;
+        }
+
+        return changed;
+    }
+
+    /** @hidden */
+    public _cacheFloat4(uniformName: string, x: number, y: number, z: number, w: number): boolean {
+        var cache = this._valueCache[uniformName];
+        if (!cache) {
+            cache = [x, y, z, w];
+            this._valueCache[uniformName] = cache;
+            return true;
+        }
+
+        var changed = false;
+        if (cache[0] !== x) {
+            cache[0] = x;
+            changed = true;
+        }
+        if (cache[1] !== y) {
+            cache[1] = y;
+            changed = true;
+        }
+        if (cache[2] !== z) {
+            cache[2] = z;
+            changed = true;
+        }
+        if (cache[3] !== w) {
+            cache[3] = w;
+            changed = true;
+        }
+
+        return changed;
+    }
+
+    /**
+     * Sets an interger value on a uniform variable.
+     * @param uniformName Name of the variable.
+     * @param value Value to be set.
+     */
+    public setInt(uniformName: string, value: number): void {
+        var cache = this._valueCache[uniformName];
+        if (cache !== undefined && cache === value) {
+            return;
+        }
+
+        this._valueCache[uniformName] = value;
+
+        this.engine.setInt(this._uniforms[uniformName], value);
+    }
+
+    /**
+     * Sets an int array on a uniform variable.
+     * @param uniformName Name of the variable.
+     * @param array array to be set.
+     */
+    public setIntArray(uniformName: string, array: Int32Array): void {
+        this._valueCache[uniformName] = null;
+        this.engine.setIntArray(this._uniforms[uniformName], array);
+    }
+
+    /**
+     * Sets an int array 2 on a uniform variable. (Array is specified as single array eg. [1,2,3,4] will result in [[1,2],[3,4]] in the shader)
+     * @param uniformName Name of the variable.
+     * @param array array to be set.
+     */
+    public setIntArray2(uniformName: string, array: Int32Array): void {
+        this._valueCache[uniformName] = null;
+        this.engine.setIntArray2(this._uniforms[uniformName], array);
+    }
+
+    /**
+     * Sets an int array 3 on a uniform variable. (Array is specified as single array eg. [1,2,3,4,5,6] will result in [[1,2,3],[4,5,6]] in the shader)
+     * @param uniformName Name of the variable.
+     * @param array array to be set.
+     */
+    public setIntArray3(uniformName: string, array: Int32Array): void {
+        this._valueCache[uniformName] = null;
+        this.engine.setIntArray3(this._uniforms[uniformName], array);
+    }
+
+    /**
+     * Sets an int array 4 on a uniform variable. (Array is specified as single array eg. [1,2,3,4,5,6,7,8] will result in [[1,2,3,4],[5,6,7,8]] in the shader)
+     * @param uniformName Name of the variable.
+     * @param array array to be set.
+     */
+    public setIntArray4(uniformName: string, array: Int32Array): void {
+        this._valueCache[uniformName] = null;
+        this.engine.setIntArray4(this._uniforms[uniformName], array);
+    }
+
+    /**
+     * Sets an float array on a uniform variable.
+     * @param uniformName Name of the variable.
+     * @param array array to be set.
+     */
+    public setFloatArray(uniformName: string, array: Float32Array): void {
+        this._valueCache[uniformName] = null;
+        this.engine.setFloatArray(this._uniforms[uniformName], array);
+    }
+
+    /**
+     * Sets an float array 2 on a uniform variable. (Array is specified as single array eg. [1,2,3,4] will result in [[1,2],[3,4]] in the shader)
+     * @param uniformName Name of the variable.
+     * @param array array to be set.
+     */
+    public setFloatArray2(uniformName: string, array: Float32Array): void {
+        this._valueCache[uniformName] = null;
+        this.engine.setFloatArray2(this._uniforms[uniformName], array);
+    }
+
+    /**
+     * Sets an float array 3 on a uniform variable. (Array is specified as single array eg. [1,2,3,4,5,6] will result in [[1,2,3],[4,5,6]] in the shader)
+     * @param uniformName Name of the variable.
+     * @param array array to be set.
+     */
+    public setFloatArray3(uniformName: string, array: Float32Array): void {
+        this._valueCache[uniformName] = null;
+        this.engine.setFloatArray3(this._uniforms[uniformName], array);
+    }
+
+    /**
+     * Sets an float array 4 on a uniform variable. (Array is specified as single array eg. [1,2,3,4,5,6,7,8] will result in [[1,2,3,4],[5,6,7,8]] in the shader)
+     * @param uniformName Name of the variable.
+     * @param array array to be set.
+     */
+    public setFloatArray4(uniformName: string, array: Float32Array): void {
+        this._valueCache[uniformName] = null;
+        this.engine.setFloatArray4(this._uniforms[uniformName], array);
+    }
+
+    /**
+     * Sets an array on a uniform variable.
+     * @param uniformName Name of the variable.
+     * @param array array to be set.
+     */
+    public setArray(uniformName: string, array: number[]): void {
+        this._valueCache[uniformName] = null;
+        this.engine.setArray(this._uniforms[uniformName], array);
+    }
+
+    /**
+     * Sets an array 2 on a uniform variable. (Array is specified as single array eg. [1,2,3,4] will result in [[1,2],[3,4]] in the shader)
+     * @param uniformName Name of the variable.
+     * @param array array to be set.
+     */
+    public setArray2(uniformName: string, array: number[]): void {
+        this._valueCache[uniformName] = null;
+        this.engine.setArray2(this._uniforms[uniformName], array);
+    }
+
+    /**
+     * Sets an array 3 on a uniform variable. (Array is specified as single array eg. [1,2,3,4,5,6] will result in [[1,2,3],[4,5,6]] in the shader)
+     * @param uniformName Name of the variable.
+     * @param array array to be set.
+     * @returns this effect.
+     */
+    public setArray3(uniformName: string, array: number[]): void {
+        this._valueCache[uniformName] = null;
+        this.engine.setArray3(this._uniforms[uniformName], array);
+    }
+
+    /**
+     * Sets an array 4 on a uniform variable. (Array is specified as single array eg. [1,2,3,4,5,6,7,8] will result in [[1,2,3,4],[5,6,7,8]] in the shader)
+     * @param uniformName Name of the variable.
+     * @param array array to be set.
+     */
+    public setArray4(uniformName: string, array: number[]): void {
+        this._valueCache[uniformName] = null;
+        this.engine.setArray4(this._uniforms[uniformName], array);
+    }
+
+    /**
+     * Sets matrices on a uniform variable.
+     * @param uniformName Name of the variable.
+     * @param matrices matrices to be set.
+     */
+    public setMatrices(uniformName: string, matrices: Float32Array): void {
+        if (!matrices) {
+            return;
+        }
+
+        this._valueCache[uniformName] = null;
+        this.engine.setMatrices(this._uniforms[uniformName], matrices);
+    }
+
+    /**
+     * Sets matrix on a uniform variable.
+     * @param uniformName Name of the variable.
+     * @param matrix matrix to be set.
+     */
+    public setMatrix(uniformName: string, matrix: IMatrixLike): void {
+        if (this._cacheMatrix(uniformName, matrix)) {
+            this.engine.setMatrices(this._uniforms[uniformName], matrix.toArray() as Float32Array);
+        }
+    }
+
+    /**
+     * Sets a 3x3 matrix on a uniform variable. (Speicified as [1,2,3,4,5,6,7,8,9] will result in [1,2,3][4,5,6][7,8,9] matrix)
+     * @param uniformName Name of the variable.
+     * @param matrix matrix to be set.
+     */
+    public setMatrix3x3(uniformName: string, matrix: Float32Array): void {
+        this._valueCache[uniformName] = null;
+        this.engine.setMatrix3x3(this._uniforms[uniformName], matrix);
+    }
+
+    /**
+     * Sets a 2x2 matrix on a uniform variable. (Speicified as [1,2,3,4] will result in [1,2][3,4] matrix)
+     * @param uniformName Name of the variable.
+     * @param matrix matrix to be set.
+     */
+    public setMatrix2x2(uniformName: string, matrix: Float32Array): void {
+        this._valueCache[uniformName] = null;
+        this.engine.setMatrix2x2(this._uniforms[uniformName], matrix);
+    }
+
+    /**
+     * Sets a float on a uniform variable.
+     * @param uniformName Name of the variable.
+     * @param value value to be set.
+     * @returns this effect.
+     */
+    public setFloat(uniformName: string, value: number): void {
+        var cache = this._valueCache[uniformName];
+        if (cache !== undefined && cache === value) {
+            return;
+        }
+
+        this._valueCache[uniformName] = value;
+
+        this.engine.setFloat(this._uniforms[uniformName], value);
+    }
+
+    /**
+     * Sets a boolean on a uniform variable.
+     * @param uniformName Name of the variable.
+     * @param bool value to be set.
+     */
+    public setBool(uniformName: string, bool: boolean): void {
+        var cache = this._valueCache[uniformName];
+        if (cache !== undefined && cache === bool) {
+            return;
+        }
+
+        this._valueCache[uniformName] = bool;
+
+        this.engine.setBool(this._uniforms[uniformName], bool ? 1 : 0);
+    }
+
+    /**
+     * Sets a Vector2 on a uniform variable.
+     * @param uniformName Name of the variable.
+     * @param vector2 vector2 to be set.
+     */
+    public setVector2(uniformName: string, vector2: IVector2Like): void {
+        if (this._cacheFloat2(uniformName, vector2.x, vector2.y)) {
+            this.engine.setFloat2(this._uniforms[uniformName], vector2.x, vector2.y);
+        }
+    }
+
+    /**
+     * Sets a float2 on a uniform variable.
+     * @param uniformName Name of the variable.
+     * @param x First float in float2.
+     * @param y Second float in float2.
+     */
+    public setFloat2(uniformName: string, x: number, y: number): void {
+        if (this._cacheFloat2(uniformName, x, y)) {
+            this.engine.setFloat2(this._uniforms[uniformName], x, y);
+        }
+    }
+
+    /**
+     * Sets a Vector3 on a uniform variable.
+     * @param uniformName Name of the variable.
+     * @param vector3 Value to be set.
+     */
+    public setVector3(uniformName: string, vector3: IVector3Like): void {
+        if (this._cacheFloat3(uniformName, vector3.x, vector3.y, vector3.z)) {
+            this.engine.setFloat3(this._uniforms[uniformName], vector3.x, vector3.y, vector3.z);
+        }
+    }
+
+    /**
+     * Sets a float3 on a uniform variable.
+     * @param uniformName Name of the variable.
+     * @param x First float in float3.
+     * @param y Second float in float3.
+     * @param z Third float in float3.
+     */
+    public setFloat3(uniformName: string, x: number, y: number, z: number): void {
+        if (this._cacheFloat3(uniformName, x, y, z)) {
+            this.engine.setFloat3(this._uniforms[uniformName], x, y, z);
+        }
+    }
+
+    /**
+     * Sets a Vector4 on a uniform variable.
+     * @param uniformName Name of the variable.
+     * @param vector4 Value to be set.
+     */
+    public setVector4(uniformName: string, vector4: IVector4Like): void {
+        if (this._cacheFloat4(uniformName, vector4.x, vector4.y, vector4.z, vector4.w)) {
+            this.engine.setFloat4(this._uniforms[uniformName], vector4.x, vector4.y, vector4.z, vector4.w);
+        }
+    }
+
+    /**
+     * Sets a float4 on a uniform variable.
+     * @param uniformName Name of the variable.
+     * @param x First float in float4.
+     * @param y Second float in float4.
+     * @param z Third float in float4.
+     * @param w Fourth float in float4.
+     * @returns this effect.
+     */
+    public setFloat4(uniformName: string, x: number, y: number, z: number, w: number): void {
+        if (this._cacheFloat4(uniformName, x, y, z, w)) {
+            this.engine.setFloat4(this._uniforms[uniformName], x, y, z, w);
+        }
+    }
+
+    /**
+     * Sets a Color3 on a uniform variable.
+     * @param uniformName Name of the variable.
+     * @param color3 Value to be set.
+     */
+    public setColor3(uniformName: string, color3: IColor3Like): void {
+        if (this._cacheFloat3(uniformName, color3.r, color3.g, color3.b)) {
+            this.engine.setFloat3(this._uniforms[uniformName], color3.r, color3.g, color3.b);
+        }
+    }
+
+    /**
+     * Sets a Color4 on a uniform variable.
+     * @param uniformName Name of the variable.
+     * @param color3 Value to be set.
+     * @param alpha Alpha value to be set.
+     */
+    public setColor4(uniformName: string, color3: IColor3Like, alpha: number): void {
+        if (this._cacheFloat4(uniformName, color3.r, color3.g, color3.b, alpha)) {
+            this.engine.setFloat4(this._uniforms[uniformName], color3.r, color3.g, color3.b, alpha);
+        }
+    }
+
+    /**
+     * Sets a Color4 on a uniform variable
+     * @param uniformName defines the name of the variable
+     * @param color4 defines the value to be set
+     */
+    public setDirectColor4(uniformName: string, color4: IColor4Like): void {
+        if (this._cacheFloat4(uniformName, color4.r, color4.g, color4.b, color4.a)) {
+            this.engine.setDirectColor4(this._uniforms[uniformName], color4);
+        }
+    }
 }

+ 356 - 6
src/Engines/WebGPU/webgpuPipelineContext.ts

@@ -4,6 +4,19 @@ import { WebGPUEngine } from '../webgpuEngine';
 import { InternalTexture } from '../../Materials/Textures/internalTexture';
 import { Effect } from '../../Materials/effect';
 import { WebGPUShaderProcessingContext } from './webgpuShaderProcessingContext';
+import { UniformBuffer } from "../../Materials/uniformBuffer";
+import { IMatrixLike, IVector2Like, IVector3Like, IVector4Like, IColor3Like, IColor4Like } from '../../Maths/math.like';
+import { _IDoNeedToBeInTheBuild } from '../../Particles';
+
+const _uniformSizes: { [type: string]: number } = {
+    "float": 1,
+    "vec2": 2,
+    "vec3": 3,
+    "vec4": 4,
+    "mat2": 4,
+    "mat3": 9,
+    "mat4": 16
+};
 
 /** @hidden */
 export interface IWebGPUPipelineContextSamplerCache {
@@ -37,6 +50,9 @@ export class WebGPUPipelineContext implements IPipelineContext {
     public orderedAttributes: string[];
     public orderedUBOsAndSamplers: { name: string, isSampler: boolean }[][];
 
+    public leftOverUniforms: { name: string, type: string }[];
+    public leftOverUniformsByName: { [name: string]: string };
+
     public sources: {
         vertex: string
         fragment: string,
@@ -53,6 +69,11 @@ export class WebGPUPipelineContext implements IPipelineContext {
 
     public renderPipeline: GPURenderPipeline;
 
+    /**
+     * Stores the uniform buffer
+     */
+    public uniformBuffer: Nullable<UniformBuffer>;
+
     // Default implementation.
     public onCompiled?: () => void;
 
@@ -68,12 +89,17 @@ export class WebGPUPipelineContext implements IPipelineContext {
         return false;
     }
 
-    constructor(shaderProcessingContext: WebGPUShaderProcessingContext) {
-        this.availableAttributes = shaderProcessingContext.availableAttributes;
-        this.availableUBOs = shaderProcessingContext.availableUBOs;
-        this.availableSamplers = shaderProcessingContext.availableSamplers;
-        this.orderedAttributes = shaderProcessingContext.orderedAttributes;
-        this.orderedUBOsAndSamplers = shaderProcessingContext.orderedUBOsAndSamplers;
+    constructor(shaderProcessingContext: WebGPUShaderProcessingContext, engine: WebGPUEngine) {
+        if (shaderProcessingContext) {
+            this.availableAttributes = shaderProcessingContext.availableAttributes;
+            this.availableUBOs = shaderProcessingContext.availableUBOs;
+            this.availableSamplers = shaderProcessingContext.availableSamplers;
+            this.orderedAttributes = shaderProcessingContext.orderedAttributes;
+            this.orderedUBOsAndSamplers = shaderProcessingContext.orderedUBOsAndSamplers;
+
+            this.leftOverUniforms = shaderProcessingContext.leftOverUniforms;
+            this.leftOverUniformsByName = {};
+        }
     }
 
     public _handlesSpectorRebuildCallback(onCompiled: (program: any) => void): void {
@@ -111,5 +137,329 @@ export class WebGPUPipelineContext implements IPipelineContext {
         }
 
         attributes.push(...engine.getAttributes(this, attributesNames));
+
+        // Build the uniform layout for the left over uniforms.
+        this.buildUniformLayout();
+    }
+
+    /**
+     * Build the uniform buffer used in the material.
+     */
+    public buildUniformLayout(): void {
+        if (!this.leftOverUniforms.length) {
+            return;
+        }
+
+        this.uniformBuffer = new UniformBuffer(this.engine);
+
+        for (let leftOverUniform of this.leftOverUniforms) {
+            const size = _uniformSizes[leftOverUniform.type];
+            this.uniformBuffer.addUniform(leftOverUniform.name, size);
+            // TODO WEBGPU. Replace with info from uniform buffer class
+            this.leftOverUniformsByName[leftOverUniform.name] = leftOverUniform.type;
+        }
+
+        this.uniformBuffer.create();
+    }
+
+    /**
+     * Release all associated resources.
+     **/
+    public dispose() {
+        if (this.uniformBuffer) {
+            this.uniformBuffer.dispose();
+        }
+        // TODO WEBGPU. Dispose all resources.
+    }
+
+    /**
+     * Sets an interger value on a uniform variable.
+     * @param uniformName Name of the variable.
+     * @param value Value to be set.
+     */
+    public setInt(uniformName: string, value: number): void {
+        throw "setInt not Supported in LeftOver UBO.";
+    }
+
+    /**
+     * Sets an int array on a uniform variable.
+     * @param uniformName Name of the variable.
+     * @param array array to be set.
+     */
+    public setIntArray(uniformName: string, array: Int32Array): void {
+        throw "setIntArray not Supported in LeftOver UBO.";
+    }
+
+    /**
+     * Sets an int array 2 on a uniform variable. (Array is specified as single array eg. [1,2,3,4] will result in [[1,2],[3,4]] in the shader)
+     * @param uniformName Name of the variable.
+     * @param array array to be set.
+     */
+    public setIntArray2(uniformName: string, array: Int32Array): void {
+        throw "setIntArray2 not Supported in LeftOver UBO.";
+    }
+
+    /**
+     * Sets an int array 3 on a uniform variable. (Array is specified as single array eg. [1,2,3,4,5,6] will result in [[1,2,3],[4,5,6]] in the shader)
+     * @param uniformName Name of the variable.
+     * @param array array to be set.
+     */
+    public setIntArray3(uniformName: string, array: Int32Array): void {
+        throw "setIntArray3 not Supported in LeftOver UBO.";
+    }
+
+    /**
+     * Sets an int array 4 on a uniform variable. (Array is specified as single array eg. [1,2,3,4,5,6,7,8] will result in [[1,2,3,4],[5,6,7,8]] in the shader)
+     * @param uniformName Name of the variable.
+     * @param array array to be set.
+     */
+    public setIntArray4(uniformName: string, array: Int32Array): void {
+        throw "setIntArray4 not Supported in LeftOver UBO.";
+    }
+
+    /**
+     * Sets an float array on a uniform variable.
+     * @param uniformName Name of the variable.
+     * @param array array to be set.
+     */
+    public setFloatArray(uniformName: string, array: Float32Array): void {
+        // TODO WEBGPU. MorphTarget.
+        throw "setFloatArray not Supported in LeftOver UBO.";
+    }
+
+    /**
+     * Sets an float array 2 on a uniform variable. (Array is specified as single array eg. [1,2,3,4] will result in [[1,2],[3,4]] in the shader)
+     * @param uniformName Name of the variable.
+     * @param array array to be set.
+     */
+    public setFloatArray2(uniformName: string, array: Float32Array): void {
+        throw "setFloatArray2 not Supported in LeftOver UBO.";
+    }
+
+    /**
+     * Sets an float array 3 on a uniform variable. (Array is specified as single array eg. [1,2,3,4,5,6] will result in [[1,2,3],[4,5,6]] in the shader)
+     * @param uniformName Name of the variable.
+     * @param array array to be set.
+     */
+    public setFloatArray3(uniformName: string, array: Float32Array): void {
+        throw "setFloatArray3 not Supported in LeftOver UBO.";
+    }
+
+    /**
+     * Sets an float array 4 on a uniform variable. (Array is specified as single array eg. [1,2,3,4,5,6,7,8] will result in [[1,2,3,4],[5,6,7,8]] in the shader)
+     * @param uniformName Name of the variable.
+     * @param array array to be set.
+     */
+    public setFloatArray4(uniformName: string, array: Float32Array): void {
+        throw "setFloatArray4 not Supported in LeftOver UBO.";
+    }
+
+    /**
+     * Sets an array on a uniform variable.
+     * @param uniformName Name of the variable.
+     * @param array array to be set.
+     */
+    public setArray(uniformName: string, array: number[]): void {
+        // TODO WEBGPU.
+        throw "setArray not Supported in LeftOver UBO.";
+    }
+
+    /**
+     * Sets an array 2 on a uniform variable. (Array is specified as single array eg. [1,2,3,4] will result in [[1,2],[3,4]] in the shader)
+     * @param uniformName Name of the variable.
+     * @param array array to be set.
+     */
+    public setArray2(uniformName: string, array: number[]): void {
+        // TODO WEBGPU.
+        throw "setArray2 not Supported in LeftOver UBO.";
+    }
+
+    /**
+     * Sets an array 3 on a uniform variable. (Array is specified as single array eg. [1,2,3,4,5,6] will result in [[1,2,3],[4,5,6]] in the shader)
+     * @param uniformName Name of the variable.
+     * @param array array to be set.
+     * @returns this effect.
+     */
+    public setArray3(uniformName: string, array: number[]): void {
+        // TODO WEBGPU.
+        throw "setArray3 not Supported in LeftOver UBO.";
+    }
+
+    /**
+     * Sets an array 4 on a uniform variable. (Array is specified as single array eg. [1,2,3,4,5,6,7,8] will result in [[1,2,3,4],[5,6,7,8]] in the shader)
+     * @param uniformName Name of the variable.
+     * @param array array to be set.
+     */
+    public setArray4(uniformName: string, array: number[]): void {
+        // TODO WEBGPU.
+        throw "setArray4 not Supported in LeftOver UBO.";
+    }
+
+    /**
+     * Sets matrices on a uniform variable.
+     * @param uniformName Name of the variable.
+     * @param matrices matrices to be set.
+     */
+    public setMatrices(uniformName: string, matrices: Float32Array): void {
+        // TODO WEBGPU.
+        throw "setMatrices not Supported in LeftOver UBO.";
+    }
+
+    /**
+     * Sets matrix on a uniform variable.
+     * @param uniformName Name of the variable.
+     * @param matrix matrix to be set.
+     */
+    public setMatrix(uniformName: string, matrix: IMatrixLike): void {
+        if (!this.uniformBuffer || !this.leftOverUniformsByName[uniformName]) {
+            return;
+        }
+        this.uniformBuffer.updateMatrix(uniformName, matrix);
+    }
+
+    /**
+     * Sets a 3x3 matrix on a uniform variable. (Speicified as [1,2,3,4,5,6,7,8,9] will result in [1,2,3][4,5,6][7,8,9] matrix)
+     * @param uniformName Name of the variable.
+     * @param matrix matrix to be set.
+     */
+    public setMatrix3x3(uniformName: string, matrix: Float32Array): void {
+        if (!this.uniformBuffer || !this.leftOverUniformsByName[uniformName]) {
+            return;
+        }
+        this.uniformBuffer.updateMatrix3x3(uniformName, matrix);
+    }
+
+    /**
+     * Sets a 2x2 matrix on a uniform variable. (Speicified as [1,2,3,4] will result in [1,2][3,4] matrix)
+     * @param uniformName Name of the variable.
+     * @param matrix matrix to be set.
+     */
+    public setMatrix2x2(uniformName: string, matrix: Float32Array): void {
+        if (!this.uniformBuffer || !this.leftOverUniformsByName[uniformName]) {
+            return;
+        }
+        this.uniformBuffer.updateMatrix2x2(uniformName, matrix);
+    }
+
+    /**
+     * Sets a float on a uniform variable.
+     * @param uniformName Name of the variable.
+     * @param value value to be set.
+     * @returns this effect.
+     */
+    public setFloat(uniformName: string, value: number): void {
+        if (!this.uniformBuffer || !this.leftOverUniformsByName[uniformName]) {
+            return;
+        }
+        this.uniformBuffer.updateFloat(uniformName, value);
+    }
+
+    /**
+     * Sets a boolean on a uniform variable.
+     * @param uniformName Name of the variable.
+     * @param bool value to be set.
+     */
+    public setBool(uniformName: string, bool: boolean): void {
+        // this.engine.setBool(this._uniforms[uniformName], bool ? 1 : 0);
+        // TODO WEBGPU.
+        throw "setBool not Supported in LeftOver UBO.";
+    }
+
+    /**
+     * Sets a Vector2 on a uniform variable.
+     * @param uniformName Name of the variable.
+     * @param vector2 vector2 to be set.
+     */
+    public setVector2(uniformName: string, vector2: IVector2Like): void {
+        this.setFloat2(uniformName, vector2.x, vector2.y);
+    }
+
+    /**
+     * Sets a float2 on a uniform variable.
+     * @param uniformName Name of the variable.
+     * @param x First float in float2.
+     * @param y Second float in float2.
+     */
+    public setFloat2(uniformName: string, x: number, y: number): void {
+        if (!this.uniformBuffer || !this.leftOverUniformsByName[uniformName]) {
+            return;
+        }
+        this.uniformBuffer.updateFloat2(uniformName, x, y);
+    }
+
+    /**
+     * Sets a Vector3 on a uniform variable.
+     * @param uniformName Name of the variable.
+     * @param vector3 Value to be set.
+     */
+    public setVector3(uniformName: string, vector3: IVector3Like): void {
+        this.setFloat3(uniformName, vector3.x, vector3.y, vector3.z);
+    }
+
+    /**
+     * Sets a float3 on a uniform variable.
+     * @param uniformName Name of the variable.
+     * @param x First float in float3.
+     * @param y Second float in float3.
+     * @param z Third float in float3.
+     */
+    public setFloat3(uniformName: string, x: number, y: number, z: number): void {
+        if (!this.uniformBuffer || !this.leftOverUniformsByName[uniformName]) {
+            return;
+        }
+        this.uniformBuffer.updateFloat3(uniformName, x, y, z);
+    }
+
+    /**
+     * Sets a Vector4 on a uniform variable.
+     * @param uniformName Name of the variable.
+     * @param vector4 Value to be set.
+     */
+    public setVector4(uniformName: string, vector4: IVector4Like): void {
+        this.setFloat4(uniformName, vector4.x, vector4.y, vector4.z, vector4.w);
+    }
+
+    /**
+     * Sets a float4 on a uniform variable.
+     * @param uniformName Name of the variable.
+     * @param x First float in float4.
+     * @param y Second float in float4.
+     * @param z Third float in float4.
+     * @param w Fourth float in float4.
+     * @returns this effect.
+     */
+    public setFloat4(uniformName: string, x: number, y: number, z: number, w: number): void {
+        if (!this.uniformBuffer || !this.leftOverUniformsByName[uniformName]) {
+            return;
+        }
+        this.uniformBuffer.updateFloat4(uniformName, x, y, z, w);
+    }
+
+    /**
+     * Sets a Color3 on a uniform variable.
+     * @param uniformName Name of the variable.
+     * @param color3 Value to be set.
+     */
+    public setColor3(uniformName: string, color3: IColor3Like): void {
+        this.setFloat3(uniformName, color3.b, color3.g, color3.b);
+    }
+
+    /**
+     * Sets a Color4 on a uniform variable.
+     * @param uniformName Name of the variable.
+     * @param color3 Value to be set.
+     * @param alpha Alpha value to be set.
+     */
+    public setColor4(uniformName: string, color3: IColor3Like, alpha: number): void {
+        this.setFloat4(uniformName, color3.b, color3.g, color3.b, alpha);
+    }
+
+    /**
+     * Sets a Color4 on a uniform variable
+     * @param uniformName defines the name of the variable
+     * @param color4 defines the value to be set
+     */
+    public setDirectColor4(uniformName: string, color4: IColor4Like): void {
+        this.setFloat4(uniformName, color4.b, color4.g, color4.b, color4.a);
     }
 }

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

@@ -18,6 +18,8 @@ export class WebGPUShaderProcessingContext implements ShaderProcessingContext {
     public availableUBOs: { [key: string]: { setIndex: number, bindingIndex: number} };
     public availableSamplers: { [key: string]: { setIndex: number, bindingIndex: number} };
 
+    public leftOverUniforms: { name: string, type: string }[];
+
     public orderedAttributes: string[];
     public orderedUBOsAndSamplers: { name: string, isSampler: boolean }[][];
 
@@ -34,6 +36,8 @@ export class WebGPUShaderProcessingContext implements ShaderProcessingContext {
 
         this.orderedAttributes = [];
         this.orderedUBOsAndSamplers = [];
+
+        this.leftOverUniforms = [];
     }
 
     public getNextFreeUBOBinding() {

+ 30 - 2
src/Engines/WebGPU/webgpuShaderProcessors.ts

@@ -14,6 +14,7 @@ const _knownSamplers: { [key: string]: { setIndex: number, bindingIndex: number}
     // "reflectionSampler": { setIndex: 0, bindingIndex: 3 },
 };
 
+// TODO WEBGPU. sampler3D
 const _samplerFunctionByWebGLSamplerType: { [key: string]: string } = {
     "textureCube": "samplerCube",
     "texture2D": "sampler2D",
@@ -104,7 +105,11 @@ export class WebGPUShaderProcessor implements IShaderProcessor {
                 webgpuProcessingContext.orderedUBOsAndSamplers[setIndex][textureBindingIndex] = { isSampler: true, name };
             }
             else {
-                // TODO WEBGPU. Manage none UBOs uniforms.
+                webgpuProcessingContext.leftOverUniforms.push({
+                    name,
+                    type: uniformType
+                });
+                uniform = "";
             }
         }
         return uniform;
@@ -160,7 +165,7 @@ export class WebGPUShaderProcessor implements IShaderProcessor {
     //     return closingBracketLine;
     // }
 
-    public postProcessor(code: string, defines: string[], isFragment: boolean) {
+    public postProcessor(code: string, defines: string[], isFragment: boolean, processingContext: Nullable<ShaderProcessingContext>) {
         const hasDrawBuffersExtension = code.search(/#extension.+GL_EXT_draw_buffers.+require/) !== -1;
 
         // Remove extensions
@@ -193,6 +198,29 @@ export class WebGPUShaderProcessor implements IShaderProcessor {
             code += "gl_Position.y *= -1.; }";
         }
 
+        // Builds the leftover UBOs.
+        const webgpuProcessingContext = processingContext! as WebGPUShaderProcessingContext;
+        if (webgpuProcessingContext.leftOverUniforms.length) {
+            const name = "LeftOver";
+            let availableUBO = webgpuProcessingContext.availableUBOs[name];
+            if (!availableUBO) {
+                availableUBO = webgpuProcessingContext.getNextFreeUBOBinding();
+                webgpuProcessingContext.availableUBOs[name] = availableUBO;
+                if (!webgpuProcessingContext.orderedUBOsAndSamplers[availableUBO.setIndex]) {
+                    webgpuProcessingContext.orderedUBOsAndSamplers[availableUBO.setIndex] = [];
+                }
+                webgpuProcessingContext.orderedUBOsAndSamplers[availableUBO.setIndex][availableUBO.bindingIndex] = { isSampler: false, name };
+            }
+
+            let ubo = `layout(set = ${availableUBO.setIndex}, binding = ${availableUBO.bindingIndex}) uniform ${name} {\n    `;
+            for (let leftOverUniform of webgpuProcessingContext.leftOverUniforms) {
+                ubo += `    ${leftOverUniform.type} ${leftOverUniform.name};\n`;
+            }
+            ubo += "};\n\n";
+
+            code = ubo + code;
+        }
+
         return code;
     }
 }

+ 85 - 3
src/Engines/webgpuEngine.ts

@@ -121,6 +121,8 @@ export class WebGPUEngine extends Engine {
         availableSamplers: { [key: string]: { setIndex: number, bindingIndex: number} },
         orderedAttributes: string[],
         orderedUBOsAndSamplers: { name: string, isSampler: boolean }[][],
+        leftOverUniforms: { name: string, type: string }[],
+        leftOverUniformsByName: { [name: string]: string },
         sources: {
             vertex: string
             fragment: string,
@@ -790,7 +792,7 @@ export class WebGPUEngine extends Engine {
     }
 
     public createPipelineContext(shaderProcessingContext: Nullable<ShaderProcessingContext>): IPipelineContext {
-        var pipelineContext = new WebGPUPipelineContext(shaderProcessingContext! as WebGPUShaderProcessingContext);
+        var pipelineContext = new WebGPUPipelineContext(shaderProcessingContext! as WebGPUShaderProcessingContext, this);
         pipelineContext.engine = this;
         return pipelineContext;
     }
@@ -803,6 +805,7 @@ export class WebGPUEngine extends Engine {
         key: string) {
         const webGpuContext = pipelineContext as WebGPUPipelineContext;
 
+        // TODO WEBGPU. Check if caches could be reuse from piepline ???
         const shader = this._compiledShaders[key];
         if (shader) {
             webGpuContext.stages = shader.stages;
@@ -811,6 +814,8 @@ export class WebGPUEngine extends Engine {
             webGpuContext.availableSamplers = shader.availableSamplers;
             webGpuContext.orderedAttributes = shader.orderedAttributes;
             webGpuContext.orderedUBOsAndSamplers = shader.orderedUBOsAndSamplers;
+            webGpuContext.leftOverUniforms = shader.leftOverUniforms;
+            webGpuContext.leftOverUniformsByName = shader.leftOverUniformsByName;
             webGpuContext.sources = shader.sources;
         }
         else {
@@ -828,6 +833,8 @@ export class WebGPUEngine extends Engine {
                 availableSamplers: webGpuContext.availableSamplers,
                 orderedAttributes: webGpuContext.orderedAttributes,
                 orderedUBOsAndSamplers: webGpuContext.orderedUBOsAndSamplers,
+                leftOverUniforms: webGpuContext.leftOverUniforms,
+                leftOverUniformsByName: webGpuContext.leftOverUniformsByName,
                 sources: {
                     fragment: fragmentSourceCode,
                     vertex: vertexSourceCode
@@ -1569,6 +1576,68 @@ export class WebGPUEngine extends Engine {
         return WebGPUConstants.GPUColorWriteBits_NONE;
     }
 
+    /**
+     * Sets the current alpha mode
+     * @param mode defines the mode to use (one of the Engine.ALPHA_XXX)
+     * @param noDepthWriteChange defines if depth writing state should remains unchanged (false by default)
+     * @see http://doc.babylonjs.com/resources/transparency_and_how_meshes_are_rendered
+     */
+    public setAlphaMode(mode: number, noDepthWriteChange: boolean = false): void {
+        if (this._alphaMode === mode) {
+            return;
+        }
+
+        switch (mode) {
+            case Engine.ALPHA_DISABLE:
+                this._alphaState.alphaBlend = false;
+                break;
+            case Engine.ALPHA_PREMULTIPLIED:
+                //this._alphaState.setAlphaBlendFunctionParameters(this._gl.ONE, this._gl.ONE_MINUS_SRC_ALPHA, this._gl.ONE, this._gl.ONE);
+                this._alphaState.alphaBlend = true;
+                break;
+            case Engine.ALPHA_PREMULTIPLIED_PORTERDUFF:
+                //this._alphaState.setAlphaBlendFunctionParameters(this._gl.ONE, this._gl.ONE_MINUS_SRC_ALPHA, this._gl.ONE, this._gl.ONE_MINUS_SRC_ALPHA);
+                this._alphaState.alphaBlend = true;
+                break;
+            case Engine.ALPHA_COMBINE:
+                //this._alphaState.setAlphaBlendFunctionParameters(this._gl.SRC_ALPHA, this._gl.ONE_MINUS_SRC_ALPHA, this._gl.ONE, this._gl.ONE);
+                this._alphaState.alphaBlend = true;
+                break;
+            case Engine.ALPHA_ONEONE:
+                //this._alphaState.setAlphaBlendFunctionParameters(this._gl.ONE, this._gl.ONE, this._gl.ZERO, this._gl.ONE);
+                this._alphaState.alphaBlend = true;
+                break;
+            case Engine.ALPHA_ADD:
+                //this._alphaState.setAlphaBlendFunctionParameters(this._gl.SRC_ALPHA, this._gl.ONE, this._gl.ZERO, this._gl.ONE);
+                this._alphaState.alphaBlend = true;
+                break;
+            case Engine.ALPHA_SUBTRACT:
+                //this._alphaState.setAlphaBlendFunctionParameters(this._gl.ZERO, this._gl.ONE_MINUS_SRC_COLOR, this._gl.ONE, this._gl.ONE);
+                this._alphaState.alphaBlend = true;
+                break;
+            case Engine.ALPHA_MULTIPLY:
+                //this._alphaState.setAlphaBlendFunctionParameters(this._gl.DST_COLOR, this._gl.ZERO, this._gl.ONE, this._gl.ONE);
+                this._alphaState.alphaBlend = true;
+                break;
+            case Engine.ALPHA_MAXIMIZED:
+                //this._alphaState.setAlphaBlendFunctionParameters(this._gl.SRC_ALPHA, this._gl.ONE_MINUS_SRC_COLOR, this._gl.ONE, this._gl.ONE);
+                this._alphaState.alphaBlend = true;
+                break;
+            case Engine.ALPHA_INTERPOLATE:
+                //this._alphaState.setAlphaBlendFunctionParameters(this._gl.CONSTANT_COLOR, this._gl.ONE_MINUS_CONSTANT_COLOR, this._gl.CONSTANT_ALPHA, this._gl.ONE_MINUS_CONSTANT_ALPHA);
+                this._alphaState.alphaBlend = true;
+                break;
+            case Engine.ALPHA_SCREENMODE:
+                //this._alphaState.setAlphaBlendFunctionParameters(this._gl.ONE, this._gl.ONE_MINUS_SRC_COLOR, this._gl.ONE, this._gl.ONE_MINUS_SRC_ALPHA);
+                this._alphaState.alphaBlend = true;
+                break;
+        }
+        if (!noDepthWriteChange) {
+            this.setDepthWrite(mode === Engine.ALPHA_DISABLE);
+        }
+        this._alphaMode = mode;
+    }
+
     private _getColorStateDescriptors(): GPUColorStateDescriptor[] {
         // TODO WEBGPU. Color State according to the cached blend state.
         // And the current render pass attaschment setup.
@@ -1846,14 +1915,21 @@ export class WebGPUEngine extends Engine {
         return vertexInputs;
     }
 
-    // TODO WEBGPU. find a better solution than hardcoded groups.
     private _getBindGroupsToRender(): GPUBindGroup[] {
         const webgpuPipelineContext = this._currentEffect!._pipelineContext as WebGPUPipelineContext;
         let bindGroups = webgpuPipelineContext.bindGroups;
         if (bindGroups) {
+            if (webgpuPipelineContext.uniformBuffer) {
+                webgpuPipelineContext.uniformBuffer.update();
+            }
             return bindGroups;
         }
 
+        if (webgpuPipelineContext.uniformBuffer) {
+            this.bindUniformBufferBase(webgpuPipelineContext.uniformBuffer.getBuffer()!, 0, "LeftOver");
+            webgpuPipelineContext.uniformBuffer.update();
+        }
+
         bindGroups = [];
         webgpuPipelineContext.bindGroups = bindGroups;
 
@@ -1884,6 +1960,9 @@ export class WebGPUEngine extends Engine {
                             resource: bindingInfo.texture._webGPUSampler!,
                         });
                     }
+                    else {
+                        Logger.Error("Sampler has not been bound: " + bindingDefinition.name);
+                    }
                 }
                 else {
                     const dataBuffer = this._uniformsBuffers[bindingDefinition.name];
@@ -1898,6 +1977,9 @@ export class WebGPUEngine extends Engine {
                             },
                         });
                     }
+                    else {
+                        Logger.Error("UBO has not been bound: " + bindingDefinition.name);
+                    }
                 }
             }
 
@@ -2030,9 +2112,9 @@ export class WebGPUEngine extends Engine {
 
     public _unpackFlipY(value: boolean) { }
 
+    // TODO WEBGPU. All of this should go once engine split with baseEngine.
     public bindUniformBlock(pipelineContext: IPipelineContext, blockName: string, index: number): void {
     }
-
     public getUniforms(pipelineContext: IPipelineContext, uniformsNames: string[]): Nullable<WebGLUniformLocation>[] {
         return [];
     }

+ 1 - 12
src/Materials/PBR/pbrBaseMaterial.ts

@@ -1608,11 +1608,6 @@ export abstract class PBRBaseMaterial extends PushMaterial {
         ubo.addUniform("vSphericalYZ", 3);
         ubo.addUniform("vSphericalZX", 3);
 
-        if (this.getScene().getEngine().isWebGPU) {
-            ubo.addUniform("exposureLinear", 1);
-            ubo.addUniform("contrast", 1);
-        }
-
         ubo.create();
     }
 
@@ -1931,13 +1926,7 @@ export abstract class PBRBaseMaterial extends PushMaterial {
             }
 
             // image processing
-            if (scene.getEngine().isWebGPU) {
-                ubo.updateFloat("exposureLinear", this._imageProcessingConfiguration.exposure);
-                ubo.updateFloat("contrast", this._imageProcessingConfiguration.contrast);
-            }
-            else {
-                this._imageProcessingConfiguration!.bind(this._activeEffect);
-            }
+            this._imageProcessingConfiguration!.bind(this._activeEffect);
 
             // Log. depth
             MaterialHelper.BindLogDepth(defines, this._activeEffect, scene);

+ 35 - 202
src/Materials/effect.ts

@@ -277,9 +277,8 @@ export class Effect implements IDisposable {
     public _vertexSourceCode: string = "";
     /** @hidden */
     public _fragmentSourceCode: string = "";
-    private _valueCache: { [key: string]: any } = {};
-    private static _baseCache: { [key: number]: DataBuffer } = {};
 
+    private static _baseCache: { [key: number]: DataBuffer } = {};
     private _processingContext: Nullable<ShaderProcessingContext>;
 
     /**
@@ -712,7 +711,6 @@ export class Effect implements IDisposable {
         let attributesNames = this._attributesNames;
         let defines = this.defines;
         let fallbacks = this._fallbacks;
-        this._valueCache = {};
 
         var previousPipelineContext = this._pipelineContext;
 
@@ -885,97 +883,6 @@ export class Effect implements IDisposable {
         this._engine.setTextureFromPostProcessOutput(this._samplers[channel], postProcess);
     }
 
-    /** @hidden */
-    public _cacheMatrix(uniformName: string, matrix: IMatrixLike): boolean {
-        var cache = this._valueCache[uniformName];
-        var flag = matrix.updateFlag;
-        if (cache !== undefined && cache === flag) {
-            return false;
-        }
-
-        this._valueCache[uniformName] = flag;
-
-        return true;
-    }
-
-    /** @hidden */
-    public _cacheFloat2(uniformName: string, x: number, y: number): boolean {
-        var cache = this._valueCache[uniformName];
-        if (!cache) {
-            cache = [x, y];
-            this._valueCache[uniformName] = cache;
-            return true;
-        }
-
-        var changed = false;
-        if (cache[0] !== x) {
-            cache[0] = x;
-            changed = true;
-        }
-        if (cache[1] !== y) {
-            cache[1] = y;
-            changed = true;
-        }
-
-        return changed;
-    }
-
-    /** @hidden */
-    public _cacheFloat3(uniformName: string, x: number, y: number, z: number): boolean {
-        var cache = this._valueCache[uniformName];
-        if (!cache) {
-            cache = [x, y, z];
-            this._valueCache[uniformName] = cache;
-            return true;
-        }
-
-        var changed = false;
-        if (cache[0] !== x) {
-            cache[0] = x;
-            changed = true;
-        }
-        if (cache[1] !== y) {
-            cache[1] = y;
-            changed = true;
-        }
-        if (cache[2] !== z) {
-            cache[2] = z;
-            changed = true;
-        }
-
-        return changed;
-    }
-
-    /** @hidden */
-    public _cacheFloat4(uniformName: string, x: number, y: number, z: number, w: number): boolean {
-        var cache = this._valueCache[uniformName];
-        if (!cache) {
-            cache = [x, y, z, w];
-            this._valueCache[uniformName] = cache;
-            return true;
-        }
-
-        var changed = false;
-        if (cache[0] !== x) {
-            cache[0] = x;
-            changed = true;
-        }
-        if (cache[1] !== y) {
-            cache[1] = y;
-            changed = true;
-        }
-        if (cache[2] !== z) {
-            cache[2] = z;
-            changed = true;
-        }
-        if (cache[3] !== w) {
-            cache[3] = w;
-            changed = true;
-        }
-
-        return changed;
-    }
-
     /**
      * Binds a buffer to a uniform.
      * @param buffer Buffer to bind.
@@ -1006,15 +913,7 @@ export class Effect implements IDisposable {
      * @returns this effect.
      */
     public setInt(uniformName: string, value: number): Effect {
-        var cache = this._valueCache[uniformName];
-        if (cache !== undefined && cache === value) {
-            return this;
-        }
-
-        this._valueCache[uniformName] = value;
-
-        this._engine.setInt(this._uniforms[uniformName], value);
-
+        this._pipelineContext!.setInt(uniformName, value);
         return this;
     }
 
@@ -1025,9 +924,7 @@ export class Effect implements IDisposable {
      * @returns this effect.
      */
     public setIntArray(uniformName: string, array: Int32Array): Effect {
-        this._valueCache[uniformName] = null;
-        this._engine.setIntArray(this._uniforms[uniformName], array);
-
+        this._pipelineContext!.setIntArray(uniformName, array);
         return this;
     }
 
@@ -1038,9 +935,7 @@ export class Effect implements IDisposable {
      * @returns this effect.
      */
     public setIntArray2(uniformName: string, array: Int32Array): Effect {
-        this._valueCache[uniformName] = null;
-        this._engine.setIntArray2(this._uniforms[uniformName], array);
-
+        this._pipelineContext!.setIntArray2(uniformName, array);
         return this;
     }
 
@@ -1051,9 +946,7 @@ export class Effect implements IDisposable {
      * @returns this effect.
      */
     public setIntArray3(uniformName: string, array: Int32Array): Effect {
-        this._valueCache[uniformName] = null;
-        this._engine.setIntArray3(this._uniforms[uniformName], array);
-
+        this._pipelineContext!.setIntArray3(uniformName, array);
         return this;
     }
 
@@ -1064,9 +957,7 @@ export class Effect implements IDisposable {
      * @returns this effect.
      */
     public setIntArray4(uniformName: string, array: Int32Array): Effect {
-        this._valueCache[uniformName] = null;
-        this._engine.setIntArray4(this._uniforms[uniformName], array);
-
+        this._pipelineContext!.setIntArray4(uniformName, array);
         return this;
     }
 
@@ -1077,9 +968,7 @@ export class Effect implements IDisposable {
      * @returns this effect.
      */
     public setFloatArray(uniformName: string, array: Float32Array): Effect {
-        this._valueCache[uniformName] = null;
-        this._engine.setFloatArray(this._uniforms[uniformName], array);
-
+        this._pipelineContext!.setFloatArray(uniformName, array);
         return this;
     }
 
@@ -1090,9 +979,7 @@ export class Effect implements IDisposable {
      * @returns this effect.
      */
     public setFloatArray2(uniformName: string, array: Float32Array): Effect {
-        this._valueCache[uniformName] = null;
-        this._engine.setFloatArray2(this._uniforms[uniformName], array);
-
+        this._pipelineContext!.setFloatArray2(uniformName, array);
         return this;
     }
 
@@ -1103,9 +990,7 @@ export class Effect implements IDisposable {
      * @returns this effect.
      */
     public setFloatArray3(uniformName: string, array: Float32Array): Effect {
-        this._valueCache[uniformName] = null;
-        this._engine.setFloatArray3(this._uniforms[uniformName], array);
-
+        this._pipelineContext!.setFloatArray3(uniformName, array);
         return this;
     }
 
@@ -1116,9 +1001,7 @@ export class Effect implements IDisposable {
      * @returns this effect.
      */
     public setFloatArray4(uniformName: string, array: Float32Array): Effect {
-        this._valueCache[uniformName] = null;
-        this._engine.setFloatArray4(this._uniforms[uniformName], array);
-
+        this._pipelineContext!.setFloatArray4(uniformName, array);
         return this;
     }
 
@@ -1129,9 +1012,7 @@ export class Effect implements IDisposable {
      * @returns this effect.
      */
     public setArray(uniformName: string, array: number[]): Effect {
-        this._valueCache[uniformName] = null;
-        this._engine.setArray(this._uniforms[uniformName], array);
-
+        this._pipelineContext!.setArray(uniformName, array);
         return this;
     }
 
@@ -1142,9 +1023,7 @@ export class Effect implements IDisposable {
      * @returns this effect.
      */
     public setArray2(uniformName: string, array: number[]): Effect {
-        this._valueCache[uniformName] = null;
-        this._engine.setArray2(this._uniforms[uniformName], array);
-
+        this._pipelineContext!.setArray2(uniformName, array);
         return this;
     }
 
@@ -1155,9 +1034,7 @@ export class Effect implements IDisposable {
      * @returns this effect.
      */
     public setArray3(uniformName: string, array: number[]): Effect {
-        this._valueCache[uniformName] = null;
-        this._engine.setArray3(this._uniforms[uniformName], array);
-
+        this._pipelineContext!.setArray3(uniformName, array);
         return this;
     }
 
@@ -1168,9 +1045,7 @@ export class Effect implements IDisposable {
      * @returns this effect.
      */
     public setArray4(uniformName: string, array: number[]): Effect {
-        this._valueCache[uniformName] = null;
-        this._engine.setArray4(this._uniforms[uniformName], array);
-
+        this._pipelineContext!.setArray4(uniformName, array);
         return this;
     }
 
@@ -1181,13 +1056,7 @@ export class Effect implements IDisposable {
      * @returns this effect.
      */
     public setMatrices(uniformName: string, matrices: Float32Array): Effect {
-        if (!matrices) {
-            return this;
-        }
-
-        this._valueCache[uniformName] = null;
-        this._engine.setMatrices(this._uniforms[uniformName], matrices);
-
+        this._pipelineContext!.setMatrices(uniformName, matrices);
         return this;
     }
 
@@ -1198,9 +1067,7 @@ export class Effect implements IDisposable {
      * @returns this effect.
      */
     public setMatrix(uniformName: string, matrix: IMatrixLike): Effect {
-        if (this._cacheMatrix(uniformName, matrix)) {
-            this._engine.setMatrices(this._uniforms[uniformName], matrix.toArray() as Float32Array);
-        }
+        this._pipelineContext!.setMatrix(uniformName, matrix);
         return this;
     }
 
@@ -1211,9 +1078,7 @@ export class Effect implements IDisposable {
      * @returns this effect.
      */
     public setMatrix3x3(uniformName: string, matrix: Float32Array): Effect {
-        this._valueCache[uniformName] = null;
-        this._engine.setMatrix3x3(this._uniforms[uniformName], matrix);
-
+        this._pipelineContext!.setMatrix3x3(uniformName, matrix);
         return this;
     }
 
@@ -1224,9 +1089,7 @@ export class Effect implements IDisposable {
      * @returns this effect.
      */
     public setMatrix2x2(uniformName: string, matrix: Float32Array): Effect {
-        this._valueCache[uniformName] = null;
-        this._engine.setMatrix2x2(this._uniforms[uniformName], matrix);
-
+        this._pipelineContext!.setMatrix2x2(uniformName, matrix);
         return this;
     }
 
@@ -1237,15 +1100,7 @@ export class Effect implements IDisposable {
      * @returns this effect.
      */
     public setFloat(uniformName: string, value: number): Effect {
-        var cache = this._valueCache[uniformName];
-        if (cache !== undefined && cache === value) {
-            return this;
-        }
-
-        this._valueCache[uniformName] = value;
-
-        this._engine.setFloat(this._uniforms[uniformName], value);
-
+        this._pipelineContext!.setFloat(uniformName, value);
         return this;
     }
 
@@ -1256,15 +1111,7 @@ export class Effect implements IDisposable {
      * @returns this effect.
      */
     public setBool(uniformName: string, bool: boolean): Effect {
-        var cache = this._valueCache[uniformName];
-        if (cache !== undefined && cache === bool) {
-            return this;
-        }
-
-        this._valueCache[uniformName] = bool;
-
-        this._engine.setBool(this._uniforms[uniformName], bool ? 1 : 0);
-
+        this._pipelineContext!.setBool(uniformName, bool);
         return this;
     }
 
@@ -1275,9 +1122,7 @@ export class Effect implements IDisposable {
      * @returns this effect.
      */
     public setVector2(uniformName: string, vector2: IVector2Like): Effect {
-        if (this._cacheFloat2(uniformName, vector2.x, vector2.y)) {
-            this._engine.setFloat2(this._uniforms[uniformName], vector2.x, vector2.y);
-        }
+        this._pipelineContext!.setVector2(uniformName, vector2);
         return this;
     }
 
@@ -1289,9 +1134,7 @@ export class Effect implements IDisposable {
      * @returns this effect.
      */
     public setFloat2(uniformName: string, x: number, y: number): Effect {
-        if (this._cacheFloat2(uniformName, x, y)) {
-            this._engine.setFloat2(this._uniforms[uniformName], x, y);
-        }
+        this._pipelineContext!.setFloat2(uniformName, x, y);
         return this;
     }
 
@@ -1302,9 +1145,7 @@ export class Effect implements IDisposable {
      * @returns this effect.
      */
     public setVector3(uniformName: string, vector3: IVector3Like): Effect {
-        if (this._cacheFloat3(uniformName, vector3.x, vector3.y, vector3.z)) {
-            this._engine.setFloat3(this._uniforms[uniformName], vector3.x, vector3.y, vector3.z);
-        }
+        this._pipelineContext!.setVector3(uniformName, vector3);
         return this;
     }
 
@@ -1317,9 +1158,7 @@ export class Effect implements IDisposable {
      * @returns this effect.
      */
     public setFloat3(uniformName: string, x: number, y: number, z: number): Effect {
-        if (this._cacheFloat3(uniformName, x, y, z)) {
-            this._engine.setFloat3(this._uniforms[uniformName], x, y, z);
-        }
+        this._pipelineContext!.setFloat3(uniformName, x, y, z);
         return this;
     }
 
@@ -1330,9 +1169,7 @@ export class Effect implements IDisposable {
      * @returns this effect.
      */
     public setVector4(uniformName: string, vector4: IVector4Like): Effect {
-        if (this._cacheFloat4(uniformName, vector4.x, vector4.y, vector4.z, vector4.w)) {
-            this._engine.setFloat4(this._uniforms[uniformName], vector4.x, vector4.y, vector4.z, vector4.w);
-        }
+        this._pipelineContext!.setVector4(uniformName, vector4);
         return this;
     }
 
@@ -1346,9 +1183,7 @@ export class Effect implements IDisposable {
      * @returns this effect.
      */
     public setFloat4(uniformName: string, x: number, y: number, z: number, w: number): Effect {
-        if (this._cacheFloat4(uniformName, x, y, z, w)) {
-            this._engine.setFloat4(this._uniforms[uniformName], x, y, z, w);
-        }
+        this._pipelineContext!.setFloat4(uniformName, x, y, z, w);
         return this;
     }
 
@@ -1359,10 +1194,7 @@ export class Effect implements IDisposable {
      * @returns this effect.
      */
     public setColor3(uniformName: string, color3: IColor3Like): Effect {
-
-        if (this._cacheFloat3(uniformName, color3.r, color3.g, color3.b)) {
-            this._engine.setFloat3(this._uniforms[uniformName], color3.r, color3.g, color3.b);
-        }
+        this._pipelineContext!.setColor3(uniformName, color3);
         return this;
     }
 
@@ -1374,9 +1206,7 @@ export class Effect implements IDisposable {
      * @returns this effect.
      */
     public setColor4(uniformName: string, color3: IColor3Like, alpha: number): Effect {
-        if (this._cacheFloat4(uniformName, color3.r, color3.g, color3.b, alpha)) {
-            this._engine.setFloat4(this._uniforms[uniformName], color3.r, color3.g, color3.b, alpha);
-        }
+        this._pipelineContext!.setColor4(uniformName, color3, alpha);
         return this;
     }
 
@@ -1387,14 +1217,17 @@ export class Effect implements IDisposable {
      * @returns this effect.
      */
     public setDirectColor4(uniformName: string, color4: IColor4Like): Effect {
-        if (this._cacheFloat4(uniformName, color4.r, color4.g, color4.b, color4.a)) {
-            this._engine.setDirectColor4(this._uniforms[uniformName], color4);
-        }
+        this._pipelineContext!.setDirectColor4(uniformName, color4);
         return this;
     }
 
-    /** Release all associated resources */
+    /**
+     * Release all associated resources.
+     **/
     public dispose() {
+        if (this._pipelineContext) {
+            this._pipelineContext.dispose();
+        }
         this._engine._releaseEffect(this);
     }
 

+ 4 - 3
src/Materials/uniformBuffer.ts

@@ -6,6 +6,7 @@ import { Effect } from "./effect";
 import { BaseTexture } from "../Materials/Textures/baseTexture";
 import { DataBuffer } from '../Meshes/dataBuffer';
 import { Color3 } from '../Maths/math.color';
+import { IMatrixLike } from '../Maths/math.like';
 /**
  * Uniform buffer objects.
  *
@@ -80,7 +81,7 @@ export class UniformBuffer {
      * This is dynamic to allow compat with webgl 1 and 2.
      * You will need to pass the name of the uniform as well as the value.
      */
-    public updateMatrix: (name: string, mat: Matrix) => void;
+    public updateMatrix: (name: string, mat: IMatrixLike) => void;
 
     /**
      * Lambda to Update vec3 of float from a Vector in a uniform buffer.
@@ -534,11 +535,11 @@ export class UniformBuffer {
         this.updateUniform(name, UniformBuffer._tempBuffer, 4);
     }
 
-    private _updateMatrixForEffect(name: string, mat: Matrix) {
+    private _updateMatrixForEffect(name: string, mat: IMatrixLike) {
         this._currentEffect.setMatrix(name, mat);
     }
 
-    private _updateMatrixForUniform(name: string, mat: Matrix) {
+    private _updateMatrixForUniform(name: string, mat: IMatrixLike) {
         this.updateUniform(name, <any>mat.toArray(), 16);
     }
 

+ 1 - 5
src/Shaders/ShadersInclude/imageProcessingDeclaration.fx

@@ -1,6 +1,4 @@
-#ifndef WEBGPU
-
-#ifdef EXPOSURE
+#ifdef EXPOSURE
 	uniform float exposureLinear;
 #endif
 
@@ -27,6 +25,4 @@
 		uniform sampler2D txColorTransform;
 	#endif
 	uniform vec4 colorTransformSettings;
-#endif
-
 #endif

+ 0 - 6
src/Shaders/ShadersInclude/pbrUboDeclaration.fx

@@ -118,12 +118,6 @@ uniform Material
     vec3 vSphericalXY;
     vec3 vSphericalYZ;
     vec3 vSphericalZX;
-
-    // Image Processing TODO WEBGPU Hack
-    #ifdef WEBGPU
-	float exposureLinear;
-	float contrast;
-    #endif
 };
 
 uniform Mesh