Selaa lähdekoodia

Add separate depth/culling and stencil state managers for webgpu

Popov72 4 vuotta sitten
vanhempi
commit
38c2cc7bb3

+ 127 - 0
src/Engines/WebGPU/webgpuDepthCullingState.ts

@@ -0,0 +1,127 @@
+import { Nullable } from "../../types";
+import { WebGPUCacheRenderPipeline } from "./webgpuCacheRenderPipeline";
+import { DepthCullingState } from "../../States/depthCullingState";
+
+/**
+ * @hidden
+ **/
+export class WebGPUDepthCullingState extends DepthCullingState {
+
+    private _cache: WebGPUCacheRenderPipeline;
+
+    /**
+     * Initializes the state.
+     */
+    public constructor(cache: WebGPUCacheRenderPipeline) {
+        super(false);
+        this._cache = cache;
+        this.reset();
+    }
+
+    public get zOffset(): number {
+        return this._zOffset;
+    }
+
+    public set zOffset(value: number) {
+        if (this._zOffset === value) {
+            return;
+        }
+
+        this._zOffset = value;
+        this._isZOffsetDirty = true;
+        this._cache.setDepthBiasSlopeScale(value);
+    }
+
+    public get cullFace(): Nullable<number> {
+        return this._cullFace;
+    }
+
+    public set cullFace(value: Nullable<number>) {
+        if (this._cullFace === value) {
+            return;
+        }
+
+        this._cullFace = value;
+        this._isCullFaceDirty = true;
+        this._cache.setCullFace(value ?? 1);
+    }
+
+    public get cull(): Nullable<boolean> {
+        return this._cull;
+    }
+
+    public set cull(value: Nullable<boolean>) {
+        if (this._cull === value) {
+            return;
+        }
+
+        this._cull = value;
+        this._isCullDirty = true;
+        this._cache.setCullEnabled(!!value);
+    }
+
+    public get depthFunc(): Nullable<number> {
+        return this._depthFunc;
+    }
+
+    public set depthFunc(value: Nullable<number>) {
+        if (this._depthFunc === value) {
+            return;
+        }
+
+        this._depthFunc = value;
+        this._isDepthFuncDirty = true;
+        this._cache.setDepthCompare(value);
+    }
+
+    public get depthMask(): boolean {
+        return this._depthMask;
+    }
+
+    public set depthMask(value: boolean) {
+        if (this._depthMask === value) {
+            return;
+        }
+
+        this._depthMask = value;
+        this._isDepthMaskDirty = true;
+        this._cache.setDepthWriteEnabled(value);
+    }
+
+    public get depthTest(): boolean {
+        return this._depthTest;
+    }
+
+    public set depthTest(value: boolean) {
+        if (this._depthTest === value) {
+            return;
+        }
+
+        this._depthTest = value;
+        this._isDepthTestDirty = true;
+        this._cache.setDepthTestEnabled(value);
+    }
+
+    public get frontFace(): Nullable<number> {
+        return this._frontFace;
+    }
+
+    public set frontFace(value: Nullable<number>) {
+        if (this._frontFace === value) {
+            return;
+        }
+
+        this._frontFace = value;
+        this._isFrontFaceDirty = true;
+        this._cache.setFrontFace(value ?? 2);
+    }
+
+    public reset() {
+        super.reset();
+        this._cache.resetDepthCullingState();
+    }
+
+    public apply(gl: WebGLRenderingContext) {
+        // nothing to do
+    }
+}

+ 136 - 0
src/Engines/WebGPU/webgpuStencilState.ts

@@ -0,0 +1,136 @@
+import { WebGPUCacheRenderPipeline } from "./webgpuCacheRenderPipeline";
+import { StencilState } from "../../States/stencilState";
+
+/**
+ * @hidden
+ **/
+export class WebGPUStencilState extends StencilState {
+
+    private _cache: WebGPUCacheRenderPipeline;
+
+    public constructor(cache: WebGPUCacheRenderPipeline) {
+        super(false);
+        this._cache = cache;
+        this.reset();
+    }
+
+    public get stencilFunc(): number {
+        return this._stencilFunc;
+    }
+
+    public set stencilFunc(value: number) {
+        if (this._stencilFunc === value) {
+            return;
+        }
+
+        this._stencilFunc = value;
+        this._isStencilFuncDirty = true;
+        this._cache.setStencilCompare(value);
+    }
+
+    public get stencilFuncRef(): number {
+        return this._stencilFuncRef;
+    }
+
+    public set stencilFuncRef(value: number) {
+        if (this._stencilFuncRef === value) {
+            return;
+        }
+
+        this._stencilFuncRef = value;
+        this._isStencilFuncDirty = true;
+    }
+
+    public get stencilFuncMask(): number {
+        return this._stencilFuncMask;
+    }
+
+    public set stencilFuncMask(value: number) {
+        if (this._stencilFuncMask === value) {
+            return;
+        }
+
+        this._stencilFuncMask = value;
+        this._isStencilFuncDirty = true;
+        this._cache.setStencilReadMask(value);
+    }
+
+    public get stencilOpStencilFail(): number {
+        return this._stencilOpStencilFail;
+    }
+
+    public set stencilOpStencilFail(value: number) {
+        if (this._stencilOpStencilFail === value) {
+            return;
+        }
+
+        this._stencilOpStencilFail = value;
+        this._isStencilOpDirty = true;
+        this._cache.setStencilFailOp(value);
+    }
+
+    public get stencilOpDepthFail(): number {
+        return this._stencilOpDepthFail;
+    }
+
+    public set stencilOpDepthFail(value: number) {
+        if (this._stencilOpDepthFail === value) {
+            return;
+        }
+
+        this._stencilOpDepthFail = value;
+        this._isStencilOpDirty = true;
+        this._cache.setStencilDepthFailOp(value);
+    }
+
+    public get stencilOpStencilDepthPass(): number {
+        return this._stencilOpStencilDepthPass;
+    }
+
+    public set stencilOpStencilDepthPass(value: number) {
+        if (this._stencilOpStencilDepthPass === value) {
+            return;
+        }
+
+        this._stencilOpStencilDepthPass = value;
+        this._isStencilOpDirty = true;
+        this._cache.setStencilPassOp(value);
+    }
+
+    public get stencilMask(): number {
+        return this._stencilMask;
+    }
+
+    public set stencilMask(value: number) {
+        if (this._stencilMask === value) {
+            return;
+        }
+
+        this._stencilMask = value;
+        this._isStencilMaskDirty = true;
+        this._cache.setStencilWriteMask(value);
+    }
+
+    public get stencilTest(): boolean {
+        return this._stencilTest;
+    }
+
+    public set stencilTest(value: boolean) {
+        if (this._stencilTest === value) {
+            return;
+        }
+
+        this._stencilTest = value;
+        this._isStencilTestDirty = true;
+        this._cache.setStencilEnabled(value);
+    }
+
+    public reset() {
+        super.reset();
+        this._cache.resetStencilState();
+    }
+
+    public apply(gl: WebGLRenderingContext) {
+        // nothing to do
+    }
+}

+ 4 - 4
src/Engines/engine.ts

@@ -952,28 +952,28 @@ export class Engine extends ThinEngine {
      * Sets the current depth function to GREATER
      */
     public setDepthFunctionToGreater(): void {
-        this._depthCullingState.depthFunc = this._gl.GREATER;
+        this._depthCullingState.depthFunc = Constants.GREATER;
     }
 
     /**
      * Sets the current depth function to GEQUAL
      */
     public setDepthFunctionToGreaterOrEqual(): void {
-        this._depthCullingState.depthFunc = this._gl.GEQUAL;
+        this._depthCullingState.depthFunc = Constants.GEQUAL;
     }
 
     /**
      * Sets the current depth function to LESS
      */
     public setDepthFunctionToLess(): void {
-        this._depthCullingState.depthFunc = this._gl.LESS;
+        this._depthCullingState.depthFunc = Constants.LESS;
     }
 
     /**
      * Sets the current depth function to LEQUAL
      */
     public setDepthFunctionToLessOrEqual(): void {
-        this._depthCullingState.depthFunc = this._gl.LEQUAL;
+        this._depthCullingState.depthFunc = Constants.LEQUAL;
     }
 
     private _cachedStencilBuffer: boolean;

+ 10 - 126
src/Engines/webgpuEngine.ts

@@ -36,6 +36,9 @@ import { IMultiRenderTargetOptions } from '../Materials/Textures/multiRenderTarg
 import { WebGPUCacheSampler } from "./WebGPU/webgpuCacheSampler";
 import { WebGPUShaderManager } from "./WebGPU/webgpuShaderManager";
 import { WebGPUCacheRenderPipeline } from "./WebGPU/webgpuCacheRenderPipeline";
+import { WebGPUCacheRenderPipelineTree } from "./WebGPU/webgpuCacheRenderPipelineTree";
+import { WebGPUStencilState } from "./WebGPU/webgpuStencilState";
+import { WebGPUDepthCullingState } from "./WebGPU/webgpuDepthCullingState";
 
 import "../Shaders/clearQuad.vertex";
 import "../Shaders/clearQuad.fragment";
@@ -368,10 +371,6 @@ export class WebGPUEngine extends Engine {
         this._mainPassSampleCount = options.antialiasing ? this._defaultSampleCount : 1;
         this._isStencilEnable = options.stencil;
 
-        this._depthCullingState.depthTest = true;
-        this._depthCullingState.depthFunc = Constants.LEQUAL;
-        this._depthCullingState.depthMask = true;
-
         this._sharedInit(canvas, !!options.doNotHandleTouchAction, options.audioEngine);
 
         // TODO. WEBGPU. Use real way to do it.
@@ -442,10 +441,14 @@ export class WebGPUEngine extends Engine {
 
                 this._emptyVertexBuffer = new VertexBuffer(this, [0], "", false, false, 1, false, 0, 1);
 
-                this._cacheRenderPipeline = new WebGPUCacheRenderPipeline(this._device, this._emptyVertexBuffer);
+                this._cacheRenderPipeline = new WebGPUCacheRenderPipelineTree(this._device, this._emptyVertexBuffer);
+
+                this._depthCullingState = new WebGPUDepthCullingState(this._cacheRenderPipeline);
+                this._stencilState = new WebGPUStencilState(this._cacheRenderPipeline);
 
-                this._cacheRenderPipeline.setDepthCompare(this._depthCullingState.depthFunc);
-                //this._cacheRenderPipeline.disabled = true;
+                this._depthCullingState.depthTest = true;
+                this._depthCullingState.depthFunc = Constants.LEQUAL;
+                this._depthCullingState.depthMask = true;
 
                 this._textureHelper.setCommandEncoder(this._uploadEncoder);
 
@@ -710,12 +713,9 @@ export class WebGPUEngine extends Engine {
             this._currentProgram = null;
 
             this._stencilState.reset();
-            this._cacheRenderPipeline.resetStencilState();
 
             this._depthCullingState.reset();
             this._depthCullingState.depthFunc = Constants.LEQUAL;
-            this._cacheRenderPipeline.resetDepthCullingState();
-            this._cacheRenderPipeline.setDepthCompare(Constants.LEQUAL);
 
             this._alphaState.reset();
             this._alphaMode = Constants.ALPHA_ADD;
@@ -3210,12 +3210,6 @@ export class WebGPUEngine extends Engine {
     //                              Render
     //------------------------------------------------------------------------------
 
-    public setZOffset(value: number): void {
-        if (value !== this._depthCullingState.zOffset) {
-            this._depthCullingState.zOffset = value;
-        }
-    }
-
     private _setColorFormat(wrapper: WebGPURenderPassWrapper): void {
         const format = wrapper.colorAttachmentGPUTextures[0].format;
         this._cacheRenderPipeline.setColorFormat(format);
@@ -3233,66 +3227,6 @@ export class WebGPUEngine extends Engine {
         this._depthTextureFormat = wrapper.depthTextureFormat;
     }
 
-    public setDepthBuffer(enable: boolean): void {
-        if (this._depthCullingState.depthTest !== enable) {
-            this._depthCullingState.depthTest = enable;
-        }
-    }
-
-    public setDepthWrite(enable: boolean): void {
-        if (this._depthCullingState.depthMask !== enable) {
-            this._depthCullingState.depthMask = enable;
-        }
-    }
-
-    public setStencilBuffer(enable: boolean): void {
-        if (this._stencilState.stencilTest !== enable) {
-            this._stencilState.stencilTest = enable;
-        }
-    }
-
-    public setStencilMask(mask: number): void {
-        if (this._stencilState.stencilMask !== mask) {
-            this._stencilState.stencilMask = mask;
-        }
-    }
-
-    public setStencilFunction(stencilFunc: number) {
-        if (this._stencilState.stencilFunc !== stencilFunc) {
-            this._stencilState.stencilFunc = stencilFunc;
-        }
-    }
-
-    public setStencilFunctionReference(reference: number) {
-        if (this._stencilState.stencilFuncRef !== reference) {
-            this._stencilState.stencilFuncRef = reference;
-        }
-    }
-
-    public setStencilFunctionMask(mask: number) {
-        if (this._stencilState.stencilFuncMask !== mask) {
-            this._stencilState.stencilFuncMask = mask;
-        }
-    }
-
-    public setStencilOperationFail(operation: number): void {
-        if (this._stencilState.stencilOpStencilFail !== operation) {
-            this._stencilState.stencilOpStencilFail = operation;
-        }
-    }
-
-    public setStencilOperationDepthFail(operation: number): void {
-        if (this._stencilState.stencilOpDepthFail !== operation) {
-            this._stencilState.stencilOpDepthFail = operation;
-        }
-    }
-
-    public setStencilOperationPass(operation: number): void {
-        if (this._stencilState.stencilOpStencilDepthPass !== operation) {
-            this._stencilState.stencilOpStencilDepthPass = operation;
-        }
-    }
-
     public setDitheringState(value: boolean): void {
         // Does not exist in WebGPU
     }
@@ -3301,36 +3235,6 @@ export class WebGPUEngine extends Engine {
         // Does not exist in WebGPU
     }
 
-    public setDepthFunction(depthFunc: number) {
-        if (this._depthCullingState.depthFunc !== depthFunc) {
-            this._depthCullingState.depthFunc = depthFunc;
-        }
-    }
-
-    public setDepthFunctionToGreater(): void {
-        if (this._depthCullingState.depthFunc !== Constants.GREATER) {
-            this._depthCullingState.depthFunc = Constants.GREATER;
-        }
-    }
-
-    public setDepthFunctionToGreaterOrEqual(): void {
-        if (this._depthCullingState.depthFunc !== Constants.GEQUAL) {
-            this._depthCullingState.depthFunc = Constants.GEQUAL;
-        }
-    }
-
-    public setDepthFunctionToLess(): void {
-        if (this._depthCullingState.depthFunc !== Constants.LESS) {
-            this._depthCullingState.depthFunc = Constants.LESS;
-        }
-    }
-
-    public setDepthFunctionToLessOrEqual(): void {
-        if (this._depthCullingState.depthFunc !== Constants.LEQUAL) {
-            this._depthCullingState.depthFunc = Constants.LEQUAL;
-        }
-    }
-
     /**
      * Set various states to the context
      * @param culling defines backface culling state
@@ -3596,26 +3500,6 @@ export class WebGPUEngine extends Engine {
     private _setRenderPipeline(fillMode: number): void {
         const renderPass = this._bundleEncoder || this._getCurrentRenderPass();
 
-        this._cacheRenderPipeline.setDepthCullingState(
-            !!this._depthCullingState.cull,
-            this._depthCullingState.frontFace ?? 2,
-            this._depthCullingState.cullFace ?? 1,
-            this._depthCullingState.zOffset,
-            this._depthCullingState.depthTest,
-            this._depthCullingState.depthMask,
-            this._depthCullingState.depthFunc
-        );
-
-        this._cacheRenderPipeline.setStencilState(
-            this._stencilState.stencilTest,
-            this._stencilState.stencilFunc,
-            this._stencilState.stencilOpDepthFail,
-            this._stencilState.stencilOpStencilDepthPass,
-            this._stencilState.stencilOpStencilFail,
-            this._stencilState.stencilFuncMask,
-            this._stencilState.stencilMask
-        );
-
         const pipeline = this._cacheRenderPipeline.getRenderPipeline(fillMode, this._currentEffect!, this._currentRenderTarget ? this._currentRenderTarget.samples : this._mainPassSampleCount);
         renderPass.setPipeline(pipeline);
 

+ 19 - 17
src/States/depthCullingState.ts

@@ -4,27 +4,29 @@ import { Nullable } from "../types";
  * @hidden
  **/
 export class DepthCullingState {
-    private _isDepthTestDirty = false;
-    private _isDepthMaskDirty = false;
-    private _isDepthFuncDirty = false;
-    private _isCullFaceDirty = false;
-    private _isCullDirty = false;
-    private _isZOffsetDirty = false;
-    private _isFrontFaceDirty = false;
-
-    private _depthTest: boolean;
-    private _depthMask: boolean;
-    private _depthFunc: Nullable<number>;
-    private _cull: Nullable<boolean>;
-    private _cullFace: Nullable<number>;
-    private _zOffset: number;
-    private _frontFace: Nullable<number>;
+    protected _isDepthTestDirty = false;
+    protected _isDepthMaskDirty = false;
+    protected _isDepthFuncDirty = false;
+    protected _isCullFaceDirty = false;
+    protected _isCullDirty = false;
+    protected _isZOffsetDirty = false;
+    protected _isFrontFaceDirty = false;
+
+    protected _depthTest: boolean;
+    protected _depthMask: boolean;
+    protected _depthFunc: Nullable<number>;
+    protected _cull: Nullable<boolean>;
+    protected _cullFace: Nullable<number>;
+    protected _zOffset: number;
+    protected _frontFace: Nullable<number>;
 
     /**
      * Initializes the state.
      */
-    public constructor() {
-        this.reset();
+    public constructor(reset = true) {
+        if (reset) {
+            this.reset();
+        }
     }
 
     public get isDirty(): boolean {

+ 16 - 14
src/States/stencilState.ts

@@ -10,22 +10,22 @@ export class StencilState {
     /** Passed to stencilOperation to specify that stencil value must be replaced */
     public static readonly REPLACE = Constants.REPLACE;
 
-    private _isStencilTestDirty = false;
-    private _isStencilMaskDirty = false;
-    private _isStencilFuncDirty = false;
-    private _isStencilOpDirty = false;
+    protected _isStencilTestDirty = false;
+    protected _isStencilMaskDirty = false;
+    protected _isStencilFuncDirty = false;
+    protected _isStencilOpDirty = false;
 
-    private _stencilTest: boolean;
+    protected _stencilTest: boolean;
 
-    private _stencilMask: number;
+    protected _stencilMask: number;
 
-    private _stencilFunc: number;
-    private _stencilFuncRef: number;
-    private _stencilFuncMask: number;
+    protected _stencilFunc: number;
+    protected _stencilFuncRef: number;
+    protected _stencilFuncMask: number;
 
-    private _stencilOpStencilFail: number;
-    private _stencilOpDepthFail: number;
-    private _stencilOpStencilDepthPass: number;
+    protected _stencilOpStencilFail: number;
+    protected _stencilOpDepthFail: number;
+    protected _stencilOpStencilDepthPass: number;
 
     public get isDirty(): boolean {
         return this._isStencilTestDirty || this._isStencilMaskDirty || this._isStencilFuncDirty || this._isStencilOpDirty;
@@ -135,8 +135,10 @@ export class StencilState {
         this._isStencilTestDirty = true;
     }
 
-    public constructor() {
-        this.reset();
+    public constructor(reset = true) {
+        if (reset) {
+            this.reset();
+        }
     }
 
     public reset() {