浏览代码

Merge pull request #9498 from Popov72/mrt-clear

Add a clearAttachments method to the engine to be webgpu compatible
sebavan 4 年之前
父节点
当前提交
70514310c9
共有 3 个文件被更改,包括 70 次插入20 次删除
  1. 30 0
      src/Engines/Extensions/engine.multiRender.ts
  2. 34 11
      src/Engines/webgpuEngine.ts
  3. 6 9
      src/Rendering/prePassRenderer.ts

+ 30 - 0
src/Engines/Extensions/engine.multiRender.ts

@@ -1,5 +1,6 @@
 import { InternalTexture, InternalTextureSource } from '../../Materials/Textures/internalTexture';
 import { IMultiRenderTargetOptions } from '../../Materials/Textures/multiRenderTarget';
+import { IColor4Like } from "../../Maths/math.like";
 import { Logger } from '../../Misc/logger';
 import { Nullable } from '../../types';
 import { Constants } from '../constants';
@@ -51,6 +52,16 @@ declare module "../../Engines/thinEngine" {
          * Restores the webgl state to only draw on the main color attachment
          */
         restoreSingleAttachment() : void;
+
+        /**
+         * Clears a list of attachments
+         * @param attachments list of the attachments
+         * @param colorMain clear color for the main attachment (the first one)
+         * @param colorOthers clear color for the other attachments
+         * @param clearDepth true to clear the depth buffer. Used only for the first attachment
+         * @param clearStencil true to clear the stencil buffer. Used only for the first attachment
+         */
+        clearAttachments(attachments: number[], colorMain: Nullable<IColor4Like>, colorOthers: Nullable<IColor4Like>, clearDepth: boolean, clearStencil: boolean): void;
     }
 }
 
@@ -82,6 +93,25 @@ ThinEngine.prototype.bindAttachments = function(attachments: number[]): void {
     gl.drawBuffers(attachments);
 };
 
+ThinEngine.prototype.clearAttachments = function(attachments: number[], colorMain: Nullable<IColor4Like>, colorOthers: Nullable<IColor4Like>, clearDepth: boolean, clearStencil: boolean): void {
+    if (attachments.length === 0) {
+        return;
+    }
+
+    const gl = this._gl;
+
+    gl.drawBuffers([attachments[0]]);
+    this.clear(colorMain, colorMain !== null, clearDepth, clearStencil);
+
+    const saveVal = attachments[0];
+    attachments[0] = gl.NONE;
+
+    gl.drawBuffers(attachments);
+    this.clear(colorOthers, colorOthers !== null, false, false);
+
+    attachments[0] = saveVal;
+};
+
 ThinEngine.prototype.unBindMultiColorAttachmentFramebuffer = function(textures: InternalTexture[], disableGenerateMipMaps: boolean = false, onBeforeUnbind?: () => void): void {
     this._currentRenderTarget = null;
 

+ 34 - 11
src/Engines/webgpuEngine.ts

@@ -813,12 +813,31 @@ export class WebGPUEngine extends Engine {
             if (this._currentRenderPass) {
                 this._endRenderTargetRenderPass();
             }
-            this._startRenderTargetRenderPass(this._currentRenderTarget!, backBuffer ? color : null, depth, stencil);
+            this._startRenderTargetRenderPass(this._currentRenderTarget!, backBuffer ? color : null, backBuffer ? color : null, depth, stencil);
         } else {
             this._startMainRenderPass(true, backBuffer ? color : null, depth, stencil);
         }
     }
 
+    /**
+     * Clears a list of attachments
+     * @param attachments list of the attachments
+     * @param colorMain clear color for the main attachment (the first one)
+     * @param colorOthers clear color for the other attachments
+     * @param clearDepth true to clear the depth buffer. Used only for the first attachment
+     * @param clearStencil true to clear the stencil buffer. Used only for the first attachment
+     */
+    public clearAttachments(attachments: number[], colorMain: Nullable<IColor4Like>, colorOthers: Nullable<IColor4Like>, clearDepth: boolean, clearStencil: boolean): void {
+        if (attachments.length === 0 || !this._currentRenderTarget) {
+            return;
+        }
+
+        if (this._currentRenderPass) {
+            this._endRenderTargetRenderPass();
+        }
+        this._startRenderTargetRenderPass(this._currentRenderTarget!, colorMain, colorOthers, clearDepth, clearStencil);
+    }
+
     //------------------------------------------------------------------------------
     //                              Vertex/Index Buffers
     //------------------------------------------------------------------------------
@@ -2671,7 +2690,7 @@ export class WebGPUEngine extends Engine {
 
         // restart the render pass
         if (currentPassType === 1) {
-            this._startRenderTargetRenderPass(this._currentRenderTarget!, null, false, false);
+            this._startRenderTargetRenderPass(this._currentRenderTarget!, null, null, false, false);
         } else if (currentPassType === 2) {
             this._startMainRenderPass(false);
         }
@@ -2681,7 +2700,7 @@ export class WebGPUEngine extends Engine {
     //                              Render Pass
     //------------------------------------------------------------------------------
 
-    private _startRenderTargetRenderPass(internalTexture: InternalTexture, clearColor: Nullable<IColor4Like>, clearDepth: boolean, clearStencil: boolean) {
+    private _startRenderTargetRenderPass(internalTexture: InternalTexture, clearColorMain: Nullable<IColor4Like>, clearColorOtherAttachments: Nullable<IColor4Like>, clearDepth: boolean, clearStencil: boolean) {
         const gpuWrapper = internalTexture._hardwareTexture as WebGPUHardwareTexture;
         const gpuTexture = gpuWrapper.underlyingResource!;
 
@@ -2703,14 +2722,19 @@ export class WebGPUEngine extends Engine {
                 const gpuMRTWrapper = mrtTexture?._hardwareTexture as Nullable<WebGPUHardwareTexture>;
                 const gpuMRTTexture = gpuMRTWrapper?.underlyingResource;
                 if (gpuMRTWrapper && gpuMRTTexture) {
+                    const viewDescriptor = {
+                        ...this._rttRenderPassWrapper.colorAttachmentViewDescriptor,
+                        format: gpuMRTWrapper.format,
+                    };
                     const gpuMSAATexture = gpuMRTWrapper.msaaTexture;
-                    const colorTextureView = gpuMRTTexture.createView(this._rttRenderPassWrapper.colorAttachmentViewDescriptor!);
-                    const colorMSAATextureView = gpuMSAATexture?.createView(this._rttRenderPassWrapper.colorAttachmentViewDescriptor!);
+                    const colorTextureView = gpuMRTTexture.createView(viewDescriptor);
+                    const colorMSAATextureView = gpuMSAATexture?.createView(viewDescriptor);
+                    const clearColor = i === 0 ? (clearColorMain ? clearColorMain : WebGPUConstants.LoadOp.Load) : (clearColorOtherAttachments ? clearColorOtherAttachments : WebGPUConstants.LoadOp.Load);
 
                     colorAttachments.push({
                         attachment: colorMSAATextureView ? colorMSAATextureView : colorTextureView,
                         resolveTarget: gpuMSAATexture ? colorTextureView : undefined,
-                        loadValue: clearColor !== null ? clearColor : WebGPUConstants.LoadOp.Load,
+                        loadValue: clearColor,
                         storeOp: WebGPUConstants.StoreOp.Store,
                     });
                 }
@@ -2725,7 +2749,7 @@ export class WebGPUEngine extends Engine {
             colorAttachments.push({
                 attachment: colorMSAATextureView ? colorMSAATextureView : colorTextureView,
                 resolveTarget: gpuMSAATexture ? colorTextureView : undefined,
-                loadValue: clearColor !== null ? clearColor : WebGPUConstants.LoadOp.Load,
+                loadValue: clearColorMain !== null ? clearColorMain : WebGPUConstants.LoadOp.Load,
                 storeOp: WebGPUConstants.StoreOp.Store,
             });
         }
@@ -2779,7 +2803,7 @@ export class WebGPUEngine extends Engine {
     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);
+            this._startRenderTargetRenderPass(this._currentRenderTarget, null, null, false, false);
         } else if (!this._currentRenderPass) {
             this._startMainRenderPass(false);
         }
@@ -3556,15 +3580,14 @@ export class WebGPUEngine extends Engine {
                 if (index > 0) {
                     const mrtTexture = textureArray[index - 1];
                     const gpuMRTWrapper = mrtTexture?._hardwareTexture as Nullable<WebGPUHardwareTexture>;
-                    const gpuMRTTexture = gpuMRTWrapper?.underlyingResource as Nullable<WebGPUHardwareTexture>;
                     descriptors.push({
-                        format: gpuMRTTexture?.format ?? this._colorFormat,
+                        format: gpuMRTWrapper?.format ?? this._colorFormat,
                         alphaBlend,
                         colorBlend,
                         writeMask,
                     });
                 } else {
-                    // TODO WEBGPU what to do when this._mrtAttachments[i] === 0? The corresponding texture should be bound as an "empty" texture
+                    descriptors.push(undefined as any); // TODO WEBGPU what to do when this._mrtAttachments[i] === 0? The corresponding texture should be bound as an "empty" texture
                 }
             }
         } else {

+ 6 - 9
src/Rendering/prePassRenderer.ts

@@ -87,7 +87,6 @@ export class PrePassRenderer {
 
     private _multiRenderAttachments: number[];
     private _defaultAttachments: number[];
-    private _clearAttachments: number[];
 
     private _postProcesses: PostProcess[] = [];
 
@@ -197,7 +196,6 @@ export class PrePassRenderer {
         }
 
         this._multiRenderAttachments = this._engine.buildTextureLayout(multiRenderLayout);
-        this._clearAttachments = this._engine.buildTextureLayout(clearLayout);
         this._defaultAttachments = this._engine.buildTextureLayout(defaultLayout);
     }
 
@@ -313,15 +311,14 @@ export class PrePassRenderer {
         if (this._enabled) {
             this._bindFrameBuffer();
 
-            // Regular clear color with the scene clear color of the 1st attachment
-            this._engine.clear(this._scene.clearColor,
-                this._scene.autoClear || this._scene.forceWireframe || this._scene.forcePointsCloud,
+            this._engine.clearAttachments(
+                this._multiRenderAttachments,
+                this._scene.autoClear || this._scene.forceWireframe || this._scene.forcePointsCloud ? this._scene.clearColor : null,
+                this._clearColor,
                 this._scene.autoClearDepthAndStencil,
-                this._scene.autoClearDepthAndStencil);
+                this._scene.autoClearDepthAndStencil,
+            );
 
-            // Clearing other attachment with 0 on all other attachments
-            this._engine.bindAttachments(this._clearAttachments);
-            this._engine.clear(this._clearColor, true, false, false);
             this._engine.bindAttachments(this._defaultAttachments);
         }
     }