Sebastien Vandenberghe 5 anni fa
parent
commit
f36d48ef3b

+ 0 - 5
src/Engines/engine.ts

@@ -595,11 +595,6 @@ export class Engine extends ThinEngine {
         }
     }
 
-    /** @hidden */
-    public _shouldOnlyUpdateCameras(): boolean {
-        return false;
-    }
-
     /**
      * Gets current aspect ratio
      * @param viewportOwner defines the camera to use to get the aspect ratio

+ 55 - 43
src/Engines/webgpuEngine.ts

@@ -1436,55 +1436,20 @@ export class WebGPUEngine extends Engine {
         this._renderEncoder = this._device.createCommandEncoder(this._renderEncoderDescriptor);
     }
 
-    private _freezeCommands: boolean = false;
-    private _frozenCommands: Nullable<GPUCommandBuffer[]> = null;
-
-    public _shouldOnlyUpdateCameras(): boolean {
-        return this._frozenCommands !== null;
-    }
-
     /**
      * End the current frame
      */
     public endFrame(): void {
         this._endRenderPass();
 
-        if (this._freezeCommands && this._frozenCommands) {
-            this._commandBuffers[0] = this._frozenCommands[0];
-            this._commandBuffers[1] = this._frozenCommands[1];
-        }
-        else {
-            this._commandBuffers[0] = this._uploadEncoder.finish();
-            this._commandBuffers[1] = this._renderEncoder.finish();
-        }
-
-        if (this._freezeCommands && !this._frozenCommands) {
-            this._frozenCommands = [ ];
-            this._frozenCommands[0] = this._commandBuffers[0];
-            this._frozenCommands[1] = this._commandBuffers[1];
-        }
+        this._commandBuffers[0] = this._uploadEncoder.finish();
+        this._commandBuffers[1] = this._renderEncoder.finish();
 
         this._device.getQueue().submit(this._commandBuffers);
 
         super.endFrame();
     }
 
-    /**
-     * Freezes the current list of commands to speed up rendering of sub sequent frames.
-     */
-    public freezeCommands(): void {
-        this._freezeCommands  = true;
-        this._frozenCommands = null;
-    }
-
-    /**
-     * Freezes the current list of commands to speed up rendering of sub sequent frames.
-     */
-    public unFreezeCommands(): void {
-        this._freezeCommands = false;
-        this._frozenCommands = null;
-    }
-
     //------------------------------------------------------------------------------
     //                              Render Pass
     //------------------------------------------------------------------------------
@@ -2221,7 +2186,7 @@ export class WebGPUEngine extends Engine {
     }
 
     private _bindVertexInputs(vertexInputs: IWebGPUPipelineContextVertexInputsCache): void {
-        const renderPass = this._currentRenderPass!;
+        const renderPass = this._bundleEncoder || this._currentRenderPass!;
 
         if (vertexInputs.indexBuffer) {
             // TODO WEBGPU. Check if cache would be worth it.
@@ -2229,20 +2194,22 @@ export class WebGPUEngine extends Engine {
         }
 
         // TODO WEBGPU. Optimize buffer reusability and types as more are now allowed.
-        this._currentRenderPass!.setVertexBuffers(vertexInputs.vertexStartSlot, vertexInputs.vertexBuffers, vertexInputs.vertexOffsets);
+        renderPass.setVertexBuffers(vertexInputs.vertexStartSlot, vertexInputs.vertexBuffers, vertexInputs.vertexOffsets);
     }
 
     private _setRenderBindGroups(bindGroups: GPUBindGroup[]): void {
         // TODO WEBGPU. Only set groups if changes happened.
-        const renderPass = this._currentRenderPass!;
+        const renderPass = this._bundleEncoder || this._currentRenderPass!;
         for (let i = 0; i < bindGroups.length; i++) {
             renderPass.setBindGroup(i, bindGroups[i]);
         }
     }
 
     private _setRenderPipeline(fillMode: number): void {
+        const renderPass = this._bundleEncoder || this._currentRenderPass!;
+
         const pipeline = this._getRenderPipeline(fillMode);
-        this._currentRenderPass!.setPipeline(pipeline);
+        renderPass.setPipeline(pipeline);
 
         const vertexInputs = this._getVertexInputsToRender();
         this._bindVertexInputs(vertexInputs);
@@ -2251,22 +2218,27 @@ export class WebGPUEngine extends Engine {
         this._setRenderBindGroups(bindGroups);
 
         if (this._alphaState.alphaBlend && this._alphaState._isBlendConstantsDirty) {
+            // TODO WebGPU. should use renderPass.
             this._currentRenderPass!.setBlendColor(this._alphaState._blendConstants as any);
         }
     }
 
     public drawElementsType(fillMode: number, indexStart: number, indexCount: number, instancesCount: number = 1): void {
+        const renderPass = this._bundleEncoder || this._currentRenderPass!;
+
         this._setRenderPipeline(fillMode);
 
-        this._currentRenderPass!.drawIndexed(indexCount, instancesCount, indexStart, 0, 0);
+        renderPass.drawIndexed(indexCount, instancesCount, indexStart, 0, 0);
     }
 
     public drawArraysType(fillMode: number, verticesStart: number, verticesCount: number, instancesCount: number = 1): void {
+        const renderPass = this._bundleEncoder || this._currentRenderPass!;
+
         this._currentIndexBuffer = null;
 
         this._setRenderPipeline(fillMode);
 
-        this._currentRenderPass!.draw(verticesCount, instancesCount, verticesStart, 0);
+        renderPass.draw(verticesCount, instancesCount, verticesStart, 0);
     }
 
     /**
@@ -2280,6 +2252,46 @@ export class WebGPUEngine extends Engine {
     }
 
     //------------------------------------------------------------------------------
+    //                              Render Bundle
+    //------------------------------------------------------------------------------
+
+    private _bundleEncoder: Nullable<GPURenderBundleEncoder>;
+
+    /**
+     * Start recording all the gpu calls into a bundle.
+     */
+    public startRecordBundle(): void {
+        // TODO. WebGPU. options should be dynamic.
+        this._bundleEncoder = this._device.createRenderBundleEncoder({
+            colorFormats: [ WebGPUConstants.GPUTextureFormat_bgra8unorm ],
+            depthStencilFormat: WebGPUConstants.GPUTextureFormat_depth24plusStencil8,
+            sampleCount: this._mainPassSampleCount,
+        });
+    }
+
+    /**
+     * Stops recording the bundle.
+     * @returns the recorded bundle
+     */
+    public stopRecordBundle(): GPURenderBundle {
+        const bundle = this._bundleEncoder!.finish();
+        this._bundleEncoder = null;
+        return bundle;
+    }
+
+    /**
+     * Execute the previously recorded bundle.
+     * @param bundles defines the bundle to replay
+     */
+    public executeBundles(bundles: GPURenderBundle[]): void {
+        if (!this._currentRenderPass) {
+            this._startMainRenderPass();
+        }
+
+        this._currentRenderPass!.executeBundles(bundles);
+    }
+
+    //------------------------------------------------------------------------------
     //                              Dispose
     //------------------------------------------------------------------------------
 

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

@@ -4,7 +4,6 @@ import { Logger } from "../../Misc/logger";
 import { SmartArray } from "../../Misc/smartArray";
 import { BRDFTextureTools } from "../../Misc/brdfTextureTools";
 import { Nullable } from "../../types";
-import { Camera } from "../../Cameras/camera";
 import { Scene } from "../../scene";
 import { Matrix, Vector4 } from "../../Maths/math.vector";
 import { VertexBuffer } from "../../Meshes/buffer";
@@ -1183,7 +1182,7 @@ export abstract class PBRBaseMaterial extends PushMaterial {
 
         var shaderName = "pbr";
 
-        var uniforms = ["world", "view", "viewProjection", "vEyePosition", "vLightsType", "vAmbientColor", "vAlbedoColor", "vReflectivityColor", "vEmissiveColor", "visibility", "vReflectionColor",
+        var uniforms = ["world", "view", "viewProjection", "vLightsType", "vAmbientColor", "vAlbedoColor", "vReflectivityColor", "vEmissiveColor", "visibility", "vReflectionColor",
             "vFogInfos", "vFogColor", "pointSize",
             "vAlbedoInfos", "vAmbientInfos", "vOpacityInfos", "vReflectionInfos", "vReflectionPosition", "vReflectionSize", "vEmissiveInfos", "vReflectivityInfos",
             "vMicroSurfaceSamplerInfos", "vBumpInfos", "vLightmapInfos",
@@ -1593,7 +1592,6 @@ export abstract class PBRBaseMaterial extends PushMaterial {
         ubo.addUniform("pointSize", 1);
         ubo.addUniform("vReflectivityColor", 4);
         ubo.addUniform("vEmissiveColor", 3);
-        ubo.addUniform("vEyePosition", 4);
         ubo.addUniform("vAmbientColor", 3);
 
         ubo.addUniform("vDebugMode", 2);
@@ -1842,13 +1840,6 @@ export abstract class PBRBaseMaterial extends PushMaterial {
                 // Colors
                 scene.ambientColor.multiplyToRef(this._ambientColor, this._globalAmbientColor);
 
-                var eyePosition = scene._forcedViewPosition ? scene._forcedViewPosition : (scene._mirroredCameraPosition ? scene._mirroredCameraPosition : (<Camera>scene.activeCamera).globalPosition);
-                var invertNormal = (scene.useRightHandedSystem === (scene._mirroredCameraPosition != null));
-                ubo.updateFloat4("vEyePosition",
-                    eyePosition.x,
-                    eyePosition.y,
-                    eyePosition.z,
-                    invertNormal ? -1 : 1);
                 ubo.updateColor3("vAmbientColor", this._globalAmbientColor);
 
                 ubo.updateFloat2("vDebugMode", this.debugLimit, this.debugFactor);

+ 1 - 0
src/Shaders/ShadersInclude/backgroundUboDeclaration.fx

@@ -30,4 +30,5 @@ uniform Scene {
 	mat4 viewProjectionR;
 #endif 
 	mat4 view;
+    vec4 viewPosition;
 };

+ 1 - 0
src/Shaders/ShadersInclude/defaultUboDeclaration.fx

@@ -45,4 +45,5 @@ uniform Scene {
 	mat4 viewProjectionR;
 #endif 
 	mat4 view;
+    vec4 viewPosition;
 };

+ 0 - 1
src/Shaders/ShadersInclude/pbrFragmentDeclaration.fx

@@ -9,7 +9,6 @@ uniform vec3 vEmissiveColor;
 
 uniform float visibility;
 
-uniform vec4 vEyePosition;
 uniform vec3 vAmbientColor;
 
 // Samplers

+ 3 - 5
src/Shaders/ShadersInclude/pbrUboDeclaration.fx

@@ -24,18 +24,17 @@ layout(std140, column_major) uniform;
 // }
 
 
-uniform Scene
-{
+uniform Scene {
     mat4 viewProjection;
 #ifdef MULTIVIEW
 	mat4 viewProjectionR;
 #endif 
     mat4 view;
+    vec4 viewPosition;
 };
 
 
-uniform Material
-{
+uniform Material {
     vec2 vAlbedoInfos;
     vec4 vAmbientInfos;
     vec2 vOpacityInfos;
@@ -64,7 +63,6 @@ uniform Material
     float pointSize;
     vec4 vReflectivityColor;
     vec3 vEmissiveColor;
-    vec4 vEyePosition;
     vec3 vAmbientColor;
 
     vec2 vDebugMode;

+ 4 - 0
src/Shaders/pbr.fragment.fx

@@ -21,6 +21,10 @@ precision highp float;
 
 // Declaration
 #include<__decl__pbrFragment>
+
+// TODO. WEBGPU. Probably create a camera ubo
+#define vEyePosition viewPosition
+
 #include<pbrFragmentExtraDeclaration>
 #include<__decl__lightFragment>[0..maxSimultaneousLights]
 #include<pbrFragmentSamplersDeclaration>

+ 41 - 7
src/scene.ts

@@ -63,6 +63,7 @@ declare type Animatable = import("./Animations/animatable").Animatable;
 declare type AnimationGroup = import("./Animations/animationGroup").AnimationGroup;
 declare type AnimationPropertiesOverride = import("./Animations/animationPropertiesOverride").AnimationPropertiesOverride;
 declare type Collider = import("./Collisions/collider").Collider;
+declare type WebGPUEngine = import("./Engines/webgpuEngine").WebGPUEngine;
 
 /**
  * Define an interface for all classes that will hold resources
@@ -1331,6 +1332,8 @@ export class Scene extends AbstractScene implements IAnimatable {
      */
     private geometriesByUniqueId: Nullable<{ [uniqueId: string]: number | undefined }> = null;
 
+    private _renderBundles: Nullable<GPURenderBundle[]> = null;
+
     /**
      * Creates a new Scene
      * @param engine defines the engine to use to render this scene
@@ -1604,6 +1607,7 @@ export class Scene extends AbstractScene implements IAnimatable {
         this._sceneUbo = new UniformBuffer(this._engine, undefined, true);
         this._sceneUbo.addUniform("viewProjection", 16);
         this._sceneUbo.addUniform("view", 16);
+        this._sceneUbo.addUniform("viewPosition", 4);
     }
 
     /**
@@ -1970,6 +1974,15 @@ export class Scene extends AbstractScene implements IAnimatable {
         } else if (this._sceneUbo.useUbo) {
             this._sceneUbo.updateMatrix("viewProjection", this._transformMatrix);
             this._sceneUbo.updateMatrix("view", this._viewMatrix);
+
+            const eyePosition = this._forcedViewPosition ? this._forcedViewPosition : (this._mirroredCameraPosition ? this._mirroredCameraPosition : (this.activeCamera!).globalPosition);
+            const invertNormal = (this.useRightHandedSystem === (this._mirroredCameraPosition != null));
+            this._sceneUbo.updateFloat4("viewPosition",
+                eyePosition.x,
+                eyePosition.y,
+                eyePosition.z,
+                invertNormal ? -1 : 1);
+
             this._sceneUbo.update();
         }
     }
@@ -3825,18 +3838,37 @@ export class Scene extends AbstractScene implements IAnimatable {
         this.onBeforeRenderObservable.notifyObservers(this);
 
         var engine = this.getEngine();
-        if (engine._shouldOnlyUpdateCameras()) {
-            if (this.activeCameras.length) {
-                for (let cameraIndex = 0; cameraIndex < this.activeCameras.length; cameraIndex++) {
-                    const camera = this.activeCameras[cameraIndex];
+        if (engine.isWebGPU) {
+            const webgpuEngine = (engine as WebGPUEngine);
+            if (this._activeMeshesFrozen) {
+                if (this.activeCameras.length) {
+                    for (let cameraIndex = 0; cameraIndex < this.activeCameras.length; cameraIndex++) {
+                        const camera = this.activeCameras[cameraIndex];
+                        this.setTransformMatrix(camera.getViewMatrix(), camera.getProjectionMatrix());
+                    }
+                }
+                else {
+                    const camera = this.activeCamera!;
                     this.setTransformMatrix(camera.getViewMatrix(), camera.getProjectionMatrix());
                 }
+
+                if (this._renderBundles) {
+                    webgpuEngine.executeBundles(this._renderBundles);
+                    return;
+                }
+
+                webgpuEngine.startRecordBundle();
+                webgpuEngine.onEndFrameObservable.addOnce(() => {
+                    this._renderBundles = [ webgpuEngine.stopRecordBundle() ];
+                    // TODO. WEBGPU. Frame lost.
+                    // webgpuEngine.executeBundles(this._renderBundles);
+                });
             }
             else {
-                const camera = this.activeCamera!;
-                this.setTransformMatrix(camera.getViewMatrix(), camera.getProjectionMatrix());
+                if (this._renderBundles) {
+                    this._renderBundles = null;
+                }
             }
-            return;
         }
 
         // Customs render targets
@@ -3967,6 +3999,8 @@ export class Scene extends AbstractScene implements IAnimatable {
      * Releases all held ressources
      */
     public dispose(): void {
+        this._renderBundles = null;
+
         this.beforeRender = null;
         this.afterRender = null;