Bläddra i källkod

Added push/pop debug markers

Popov72 4 år sedan
förälder
incheckning
917058fefb

+ 3 - 1
localDevWebGPU/index.html

@@ -146,7 +146,9 @@
                                     "depth24unorm-stencil8",
                                     "depth32float-stencil8"
                                 ]
-                            }
+                            },
+                            enableGPUDebugMarkers: true,
+                            antialiasing: true,
                         });
                         engine.initAsync(glslangOptions).then(() => onLoad(engine));
                     }

+ 1 - 1
src/Engines/WebGPU/webgpuTextureHelper.ts

@@ -216,7 +216,7 @@ export class WebGPUTextureHelper {
             commandEncoder = this._device.createCommandEncoder({});
         }
 
-        commandEncoder!.pushDebugGroup("start create mipmaps");
+        commandEncoder!.pushDebugGroup("create mipmaps");
 
         for (let i = 1; i < mipLevelCount; ++i) {
             const passEncoder = commandEncoder!.beginRenderPass({

+ 18 - 0
src/Engines/thinEngine.ts

@@ -782,6 +782,24 @@ export class ThinEngine {
     }
 
     /**
+     * @hidden
+     */
+    public _debugPushGroup(groupName: string, targetObject?: number): void {
+    }
+
+    /**
+     * @hidden
+     */
+    public _debugPopGroup(targetObject?: number): void {
+    }
+
+    /**
+     * @hidden
+     */
+    public _debugInsertMarker(text: string, targetObject?: number): void {
+    }
+
+    /**
      * Shared initialization across engines types.
      * @param canvas The canvas associated with this instance of the engine.
      * @param doNotHandleTouchAction Defines that engine should ignore modifying touch action attribute and style

+ 88 - 10
src/Engines/webgpuEngine.ts

@@ -127,6 +127,11 @@ export interface WebGPUEngineOptions extends GPURequestAdapterOptions {
      * Defines wether the stencil buffer should be enabled.
      */
     stencil?: boolean;
+
+    /**
+     * Defines wether we should generate debug markers in the gpu command lists (can be seen with PIX for eg)
+     */
+    enableGPUDebugMarkers?: boolean;
 }
 
 /**
@@ -194,6 +199,7 @@ export class WebGPUEngine extends Engine {
     private _mainRenderPass: Nullable<GPURenderPassEncoder> = null;
     private _currentRenderTargetColorAttachmentViewDescriptor: GPUTextureViewDescriptor;
     private _currentRenderTargetDepthAttachmentViewDescriptor: GPUTextureViewDescriptor;
+    private _pendingDebugCommands: Array<[string, Nullable<string>]> = [];
 
     // DrawCall Life Cycle
     // Effect is on the parent class
@@ -244,6 +250,7 @@ export class WebGPUEngine extends Engine {
         options.swapChainFormat = options.swapChainFormat || WebGPUConstants.TextureFormat.BGRA8Unorm;
         options.antialiasing = false; //options.antialiasing === undefined ? true : options.antialiasing;
         options.stencil = options.stencil ?? true;
+        options.enableGPUDebugMarkers = options.enableGPUDebugMarkers ?? false;
 
         Logger.Log(`Babylon.js v${Engine.Version} - WebGPU engine`);
         if (!navigator.gpu) {
@@ -2362,6 +2369,8 @@ export class WebGPUEngine extends Engine {
         this._counters.numPipelineDescriptorCreation = 0;
         this._counters.numBindGroupsCreation = 0;
 
+        this._pendingDebugCommands.length = 0;
+
         super.endFrame();
 
         if (dbgVerboseLogsForFirstFrames) {
@@ -2389,7 +2398,7 @@ export class WebGPUEngine extends Engine {
         const colorTextureView = gpuTexture.createView(this._currentRenderTargetColorAttachmentViewDescriptor);
         const depthTextureView = gpuDepthStencilTexture?.createView(this._currentRenderTargetDepthAttachmentViewDescriptor);
 
-        this._renderTargetEncoder.pushDebugGroup("start render target rendering");
+        this._debugPushGroup("render target pass", 1);
 
         const renderPassDescriptor = {
             colorAttachments: [{
@@ -2415,6 +2424,8 @@ export class WebGPUEngine extends Engine {
 
         this._currentRenderPass = renderPass;
 
+        this._debugFlushPendingCommands();
+
         this._resetCurrentViewport(1);
     }
 
@@ -2426,13 +2437,14 @@ export class WebGPUEngine extends Engine {
                     console.log("frame #" + (this as any)._count + " - render target end pass - internalTexture.uniqueId=", this._currentRenderTarget?.uniqueId);
                 }
             }
-            this._renderTargetEncoder.popDebugGroup();
+            this._debugPopGroup(1);
             this._resetCurrentViewport(1);
         }
     }
 
     private _getCurrentRenderPass(): GPURenderPassEncoder {
         if (this._currentRenderTarget && !this._currentRenderPass) {
+            // delayed creation of the render target pass, but we now need to create it as we are requested the render pass
             this._startRenderTargetRenderPass(this._currentRenderTarget, null, false, false);
         } else if (!this._currentRenderPass) {
             this._startMainRenderPass();
@@ -2462,7 +2474,7 @@ export class WebGPUEngine extends Engine {
             }
         }
 
-        this._renderEncoder.pushDebugGroup("start main rendering");
+        this._debugPushGroup("main pass", 0);
 
         this._currentRenderPass = this._renderEncoder.beginRenderPass({
             colorAttachments: this._mainColorAttachments,
@@ -2471,6 +2483,8 @@ export class WebGPUEngine extends Engine {
 
         this._mainRenderPass = this._currentRenderPass;
 
+        this._debugFlushPendingCommands();
+
         this._resetCurrentViewport(0);
     }
 
@@ -2482,7 +2496,7 @@ export class WebGPUEngine extends Engine {
                     console.log("frame #" + (this as any)._count + " - main end pass");
                 }
             }
-            this._renderEncoder.popDebugGroup();
+            this._debugPopGroup(0);
             this._resetCurrentViewport(0);
             if (this._mainRenderPass === this._currentRenderPass) {
                 this._currentRenderPass = null;
@@ -2564,6 +2578,10 @@ export class WebGPUEngine extends Engine {
         // TODO WEBGPU remove the assert debugging code
         assert(this._currentRenderTarget === null || (this._currentRenderTarget !== null && texture === this._currentRenderTarget), "unBindFramebuffer - the texture we wan't to unbind is not the same than the currentRenderTarget! texture=" + texture + ", this._currentRenderTarget=" + this._currentRenderTarget);
 
+        if (onBeforeUnbind) {
+            onBeforeUnbind();
+        }
+
         if (this._currentRenderPass && this._currentRenderPass !== this._mainRenderPass) {
             this._endRenderTargetRenderPass();
         }
@@ -2574,18 +2592,14 @@ export class WebGPUEngine extends Engine {
             this._generateMipmaps(texture);
         }
 
-        if (onBeforeUnbind) {
-            onBeforeUnbind();
-        }
-
         this._currentRenderPass = this._mainRenderPass;
         this._setDepthTextureFormat(this._getMainDepthTextureFormat());
         this._setColorFormat(this._options.swapChainFormat!);
     }
 
     public flushFramebuffer(): void {
-        this._commandBuffers[0] = this._uploadEncoder.finish();
-        this._commandBuffers[1] = this._renderTargetEncoder.finish();
+        this._commandBuffers[0] = this._renderTargetEncoder.finish();
+        this._commandBuffers[1] = this._uploadEncoder.finish();
         this._commandBuffers[2] = this._renderEncoder.finish();
 
         this._device.defaultQueue.submit(this._commandBuffers);
@@ -3627,6 +3641,70 @@ export class WebGPUEngine extends Engine {
         return this._canvas;
     }
 
+    public _debugPushGroup(groupName: string, targetObject?: number): void {
+        if (!this._options.enableGPUDebugMarkers) {
+            return;
+        }
+
+        if (targetObject === 0 || targetObject === 1) {
+            const encoder = targetObject === 0 ? this._renderEncoder : this._renderTargetEncoder;
+            encoder.pushDebugGroup(groupName);
+        } else if (this._currentRenderPass) {
+            this._currentRenderPass.pushDebugGroup(groupName);
+        } else {
+            this._pendingDebugCommands.push(["push", groupName]);
+        }
+    }
+
+    public _debugPopGroup(targetObject?: number): void {
+        if (!this._options.enableGPUDebugMarkers) {
+            return;
+        }
+
+        if (targetObject === 0 || targetObject === 1) {
+            const encoder = targetObject === 0 ? this._renderEncoder : this._renderTargetEncoder;
+            encoder.popDebugGroup();
+        } else if (this._currentRenderPass) {
+            this._currentRenderPass.popDebugGroup();
+        } else {
+            this._pendingDebugCommands.push(["pop", null]);
+        }
+    }
+
+    public _debugInsertMarker(text: string, targetObject?: number): void {
+        if (!this._options.enableGPUDebugMarkers) {
+            return;
+        }
+
+        if (targetObject === 0 || targetObject === 1) {
+            const encoder = targetObject === 0 ? this._renderEncoder : this._renderTargetEncoder;
+            encoder.insertDebugMarker(text);
+        } else if (this._currentRenderPass) {
+            this._currentRenderPass.insertDebugMarker(text);
+        } else {
+            this._pendingDebugCommands.push(["insert", text]);
+        }
+    }
+
+    private _debugFlushPendingCommands(): void {
+        for (let i = 0; i < this._pendingDebugCommands.length; ++i) {
+            const [name, param] = this._pendingDebugCommands[i];
+
+            switch (name) {
+                case "push":
+                    this._debugPushGroup(param!);
+                    break;
+                case "pop":
+                    this._debugPopGroup();
+                    break;
+                case "insert":
+                    this._debugInsertMarker(param!);
+                    break;
+            }
+        }
+        this._pendingDebugCommands.length = 0;
+    }
+
     //------------------------------------------------------------------------------
     //                              Errors
     //------------------------------------------------------------------------------

+ 2 - 0
src/Lights/Shadows/cascadedShadowGenerator.ts

@@ -795,6 +795,7 @@ export class CascadedShadowGenerator extends ShadowGenerator {
 
         let engine = this._scene.getEngine();
 
+        this._shadowMap.onBeforeBindObservable.clear();
         this._shadowMap.onBeforeRenderObservable.clear();
 
         this._shadowMap.onBeforeRenderObservable.add((layer: number) => {
@@ -806,6 +807,7 @@ export class CascadedShadowGenerator extends ShadowGenerator {
         });
 
         this._shadowMap.onBeforeBindObservable.add(() => {
+            engine._debugPushGroup(`cascaded shadow map generation for ${this._nameForCustomEffect}`, 1);
             if (this._breaksAreDirty) {
                 this._splitFrustum();
             }

+ 6 - 0
src/Lights/Shadows/shadowGenerator.ts

@@ -902,6 +902,10 @@ export class ShadowGenerator implements IShadowGenerator {
 
         let engine = this._scene.getEngine();
 
+        this._shadowMap.onBeforeBindObservable.add(() => {
+            engine._debugPushGroup(`shadow map generation for ${this._nameForCustomEffect}`, 1);
+        });
+
         // Record Face Index before render.
         this._shadowMap.onBeforeRenderObservable.add((faceIndex: number) => {
             this._currentFaceIndex = faceIndex;
@@ -920,6 +924,7 @@ export class ShadowGenerator implements IShadowGenerator {
                 engine.setColorWrite(true);
             }
             if (!this.useBlurExponentialShadowMap && !this.useBlurCloseExponentialShadowMap) {
+                engine._debugPopGroup(1);
                 return;
             }
             let shadowMap = this.getShadowMapForRendering();
@@ -928,6 +933,7 @@ export class ShadowGenerator implements IShadowGenerator {
                 const texture = shadowMap.getInternalTexture()!;
                 this._scene.postProcessManager.directRender(this._blurPostProcesses, texture, true);
                 engine.unBindFramebuffer(texture, true);
+                engine._debugPopGroup(1);
             }
         });
 

+ 4 - 0
src/Materials/Textures/Procedurals/proceduralTexture.ts

@@ -575,6 +575,8 @@ export class ProceduralTexture extends Texture {
             return;
         }
 
+        engine._debugPushGroup(`procedural texture generation for ${this.name}`, 1);
+
         if (this.isCube) {
             for (var face = 0; face < 6; face++) {
                 engine.bindFramebuffer(this._texture, face, undefined, undefined, true);
@@ -615,6 +617,8 @@ export class ProceduralTexture extends Texture {
         // Unbind
         engine.unBindFramebuffer(this._texture, this.isCube);
 
+        engine._debugPopGroup(1);
+
         if (this.onGenerated) {
             this.onGenerated();
         }

+ 10 - 0
src/Materials/Textures/mirrorTexture.ts

@@ -156,6 +156,16 @@ export class MirrorTexture extends RenderTargetTexture {
             this._updateGammaSpace;
         });
 
+        const engine = this.getScene()!.getEngine();
+
+        this.onBeforeBindObservable.add(() => {
+            engine._debugPushGroup(`mirror generation for ${name}`, 1);
+        });
+
+        this.onAfterUnbindObservable.add(() => {
+            engine._debugPopGroup(1);
+        });
+
         this.onBeforeRenderObservable.add(() => {
             Matrix.ReflectionToRef(this.mirrorPlane, this._mirrorMatrix);
             this._savedViewMatrix = scene.getViewMatrix();

+ 7 - 12
src/Materials/Textures/renderTargetTexture.ts

@@ -849,6 +849,8 @@ export class RenderTargetTexture extends Texture {
             return;
         }
 
+        engine._debugPushGroup(`render to face #${faceIndex} layer #${layer}`, 1);
+
         // Bind
         if (this._postProcessManager) {
             this._postProcessManager._prepareFrame(this._texture, this._postProcesses);
@@ -935,19 +937,12 @@ export class RenderTargetTexture extends Texture {
         }
 
         // Unbind
-        if (!this.isCube || faceIndex === 5) {
-            if (this.isCube) {
-
-                if (faceIndex === 5) {
-                    engine.generateMipMapsForCubemap(this._texture);
-                }
-            }
-
-            this.unbindFrameBuffer(engine, faceIndex);
-
-        } else {
-            this.onAfterRenderObservable.notifyObservers(faceIndex);
+        if (this.isCube && faceIndex === 5) {
+            engine.generateMipMapsForCubemap(this._texture);
         }
+
+        this.unbindFrameBuffer(engine, faceIndex);
+        engine._debugPopGroup(1);
     }
 
     /**

+ 4 - 1
src/Misc/minMaxReducer.ts

@@ -195,9 +195,12 @@ export class MinMaxReducer {
         }
 
         this._onAfterUnbindObserver = this._sourceTexture.onAfterUnbindObservable.add(() => {
+            const engine = this._camera.getScene().getEngine();
+            engine._debugPushGroup(`min max reduction`, 1);
             this._reductionSteps![0].activate(this._camera);
             this._postProcessManager.directRender(this._reductionSteps!, this._reductionSteps![0].inputTexture, this._forceFullscreenViewport);
-            this._camera.getScene().getEngine().unBindFramebuffer(this._reductionSteps![0].inputTexture, false);
+            engine.unBindFramebuffer(this._reductionSteps![0].inputTexture, false);
+            engine._debugPopGroup(1);
         });
 
         this._activated = true;

+ 2 - 0
src/PostProcesses/postProcess.ts

@@ -591,6 +591,8 @@ export class PostProcess {
             this._engine.bindFramebuffer(target, 0, undefined, undefined, this.forceFullscreenViewport);
         }
 
+        this._engine._debugInsertMarker(`post process ${this.name} input`);
+
         this.onActivateObservable.notifyObservers(camera);
 
         // Clear

+ 2 - 0
src/PostProcesses/postProcessManager.ts

@@ -116,6 +116,7 @@ export class PostProcessManager {
                 } else if (!doNotBindFrambuffer) {
                     engine.restoreDefaultFramebuffer();
                 }
+                engine._debugInsertMarker(`post process ${postProcesses[index].name} output`);
             }
 
             var pp = postProcesses[index];
@@ -175,6 +176,7 @@ export class PostProcessManager {
                     engine.restoreDefaultFramebuffer();
                     pp._outputTexture = null;
                 }
+                engine._debugInsertMarker(`post process ${postProcesses[index].name} output`);
             }
 
             if (doNotPresent) {

+ 5 - 0
src/Probes/reflectionProbe.ts

@@ -142,9 +142,14 @@ export class ReflectionProbe {
             scene._forcedViewPosition = this.position;
         });
 
+        this._renderTargetTexture.onBeforeBindObservable.add(() => {
+            scene.getEngine()._debugPushGroup(`reflection probe generation for ${name}`, 1);
+        });
+
         this._renderTargetTexture.onAfterUnbindObservable.add(() => {
             scene._forcedViewPosition = null;
             scene.updateTransformMatrix(true);
+            scene.getEngine()._debugPopGroup(1);
         });
     }
 

+ 8 - 0
src/Rendering/depthRenderer.ts

@@ -92,6 +92,14 @@ export class DepthRenderer {
             engine.clear(this._clearColor, true, true, true);
         });
 
+        this._depthMap.onBeforeBindObservable.add(() => {
+            engine._debugPushGroup("depth renderer", 1);
+        });
+
+        this._depthMap.onAfterUnbindObservable.add(() => {
+            engine._debugPopGroup(1);
+        });
+
         // Custom render function
         var renderSubMesh = (subMesh: SubMesh): void => {
             var renderingMesh = subMesh.getRenderingMesh();