浏览代码

Buffer Management

Sebastien Vandenberghe 6 年之前
父节点
当前提交
0edfa9b8f1

+ 3 - 0
Tools/DevLoader/BabylonLoader.js

@@ -206,6 +206,9 @@ var BABYLONDEVTOOLS;
                 else if (!coreOnly || module.isCore) {
                     this.loadLibrary(moduleName, module.libraries[i], module);
                 }
+                else if (coreOnly && moduleName === "loaders") {
+                    this.loadLibrary(moduleName, module.libraries[i], module);
+                }
             }
         }
 

+ 49 - 0
src/Cameras/camera.ts

@@ -13,12 +13,14 @@ import { ICullable } from "../Culling/boundingInfo";
 import { Logger } from "../Misc/logger";
 import { _TypeStore } from '../Misc/typeStore';
 import { _DevTools } from '../Misc/devTools';
+import { UniformBuffer } from "../Materials/uniformBuffer";
 
 declare type PostProcess = import("../PostProcesses/postProcess").PostProcess;
 declare type RenderTargetTexture = import("../Materials/Textures/renderTargetTexture").RenderTargetTexture;
 declare type FreeCamera = import("./freeCamera").FreeCamera;
 declare type TargetCamera = import("./targetCamera").TargetCamera;
 declare type Ray = import("../Culling/ray").Ray;
+declare type WebVRFreeCamera = import("./VR/webVRCamera").WebVRFreeCamera;
 
 /**
  * This is the base class of all the camera used in the application.
@@ -287,6 +289,12 @@ export class Camera extends Node {
     private _stateStored: boolean;
 
     /**
+     * The current camera unifom buffer.
+     * @hidden Internal use only.
+     */
+    public _uniformBuffer: UniformBuffer;
+
+    /**
      * Instantiates a new camera object.
      * This should not be used directly but through the inherited cameras: ArcRotate, Free...
      * @see http://doc.babylonjs.com/features/cameras
@@ -305,6 +313,47 @@ export class Camera extends Node {
         }
 
         this.position = position;
+
+        // Camera Uniform Buffer.
+        this._uniformBuffer = new UniformBuffer(this.getScene().getEngine());
+        this._buildUniformLayout();
+    }
+
+    protected _buildUniformLayout(): void {
+        this._uniformBuffer.addUniform("view", 16);
+        this._uniformBuffer.addUniform("viewProjection", 16);
+        this._uniformBuffer.addUniform("vEyePosition", 3);
+        this._uniformBuffer.addUniform("logarithmicDepthConstant", 1);
+        this._uniformBuffer.create();
+    }
+
+    /**
+     * Transfer the camera values to its UBO.
+     */
+    public transferToEffect(): void {
+        const ubo = this._uniformBuffer;
+        const scene = this.getScene();
+
+        ubo.updateMatrix("view", scene.getViewMatrix());
+        ubo.updateMatrix("viewProjection", scene.getTransformMatrix());
+        //if (effect.defines["LOGARITHMICDEPTH"]) {
+        ubo.updateFloat("logarithmicDepthConstant", 2.0 / (Math.log(this.maxZ + 1.0) / Math.LN2));
+        //}
+        if (scene._forcedViewPosition) {
+            ubo.updateVector3("vEyePosition", scene._forcedViewPosition);
+            return;
+        }
+        var globalPosition = scene.activeCamera!.globalPosition;
+        if (!globalPosition) {
+            // Use WebVRFreecamera's device position as global position is not it's actual position in babylon space
+            globalPosition = (scene.activeCamera! as WebVRFreeCamera).devicePosition;
+        }
+        ubo.updateVector3("vEyePosition", scene._mirroredCameraPosition ? scene._mirroredCameraPosition : globalPosition);
+
+        ubo.update();
+        
+        // TODO WEBGPU.
+        scene.getEngine().bindUniformBufferBase(ubo.getBuffer()!, 0, "Camera");
     }
 
     /**

+ 12 - 1
src/Engines/WebGPU/webgpuConstants.ts

@@ -173,7 +173,6 @@ export class WebGPUConstants {
     public static readonly GPUTextureUsage_STORAGE = 8;
     public static readonly GPUTextureUsage_OUTPUT_ATTACHMENT = 16;
 
-    
     public static readonly GPUCompareFunction_never: GPUCompareFunction = "never";
     public static readonly GPUCompareFunction_less: GPUCompareFunction = "less";
     public static readonly GPUCompareFunction_equal: GPUCompareFunction = "equal";
@@ -189,4 +188,16 @@ export class WebGPUConstants {
     public static readonly GPUBindingType_sampledTexture: GPUBindingType = "sampled-texture";
     public static readonly GPUBindingType_storageBuffer: GPUBindingType = "storage-buffer";
     public static readonly GPUBindingType_dynamicStorageBuffer: GPUBindingType = "dynamic-storage-buffer";
+
+    public static readonly GPUInputStepMode_vertex: GPUInputStepMode = "vertex";
+    public static readonly GPUInputStepMode_instance: GPUInputStepMode = "instance";
+
+    public static readonly GPUStencilOperation_keep = "keep";
+    public static readonly GPUStencilOperation_zero = "zero";
+    public static readonly GPUStencilOperation_replace = "replace";
+    public static readonly GPUStencilOperation_invert = "invert";
+    public static readonly GPUStencilOperation_incrementClamp = "increment-clamp";
+    public static readonly GPUStencilOperation_decrementClamp = "decrement-clamp";
+    public static readonly GPUStencilOperation_incrementWrap = "increment-wrap";
+    public static readonly GPUStencilOperation_decrementWrap = "decrement-wrap";
 }

+ 33 - 0
src/Engines/WebGPU/webgpuPipelineContext.ts

@@ -0,0 +1,33 @@
+import { IPipelineContext } from '../IPipelineContext';
+import { Nullable } from '../../types';
+import { WebGPUEngine } from '../webgpuEngine';
+
+/** @hidden */
+export class WebGPUPipelineContext implements IPipelineContext {
+    public engine: WebGPUEngine;
+
+    public stages: Nullable<GPURenderPipelineStageDescriptor>;
+
+    // public vertexInputDescriptor: GPUVertexAttributeDescriptor[] = [];
+
+    public vertexShaderCode: string;
+    public fragmentShaderCode: string;
+
+    public renderPipeline: GPURenderPipeline;
+
+    public bindGroupLayouts: (GPUBindGroupLayout | undefined)[];
+
+    public onCompiled?: () => void;
+
+    public get isAsync() {
+        return false;
+    }
+
+    public get isReady(): boolean {
+        if (this.stages) {
+            return true;
+        }
+
+        return false;
+    }
+}

+ 2 - 0
src/Engines/constants.ts

@@ -59,6 +59,8 @@ export class Constants {
     // Stencil Actions Constants.
     /** Passed to stencilOperation to specify that stencil value must be kept */
     public static readonly KEEP = 0x1E00;
+    /** Passed to stencilOperation to specify that stencil value must be zero */
+    public static readonly ZERO = 0x0000;
     /** Passed to stencilOperation to specify that stencil value must be replaced */
     public static readonly REPLACE = 0x1E01;
     /** Passed to stencilOperation to specify that stencil value must be incremented */

+ 12 - 2
src/Engines/engine.ts

@@ -947,6 +947,15 @@ export class Engine {
      */
     public readonly premultipliedAlpha: boolean = true;
 
+    protected _isWebGPU: boolean = false;
+
+    /**
+     * Gets a boolean indicating if the engine runs in WebGPU or not.
+     */
+    public get isWebGPU(): boolean {
+        return this._isWebGPU;
+    }
+
     /**
      * Creates a new engine
      * @param canvasOrContext defines the canvas or WebGL context to use for rendering. If you provide a WebGL context, Babylon.js will not hook events on the canvas (like pointers, keyboards, etc...) so no event observables will be available. This is mostly used when Babylon.js is used as a plugin on a system which alreay used the WebGL context
@@ -2665,8 +2674,9 @@ export class Engine {
      * Bind a buffer to the current webGL context at a given location
      * @param buffer defines the buffer to bind
      * @param location defines the index where to bind the buffer
+     * @param name Name of the uniform variable to bind
      */
-    public bindUniformBufferBase(buffer: DataBuffer, location: number): void {
+    public bindUniformBufferBase(buffer: DataBuffer, location: number, name: string): void {
         this._gl.bindBufferBase(this._gl.UNIFORM_BUFFER, location, buffer ? buffer.underlyingResource : null);
     }
 
@@ -3248,7 +3258,7 @@ export class Engine {
      * Creates a new pipeline context
      * @returns the new pipeline
      */
-    public createPipelineContext() {
+    public createPipelineContext(): IPipelineContext {
         var pipelineContext = new WebGLPipelineContext();
         pipelineContext.engine = this;
 

+ 3 - 1
src/Engines/index.ts

@@ -4,4 +4,6 @@ export * from "./engineStore";
 export * from "./nullEngine";
 export * from "./Extensions/index";
 export * from "./IPipelineContext";
-export * from "./WebGL/webGLPipelineContext";
+export * from "./WebGL/webGLPipelineContext";
+export * from "./WebGPU/webgpuConstants";
+export * from "./webgpuEngine";

文件差异内容过多而无法显示
+ 1619 - 0
src/Engines/webgpuEngine.ts


+ 27 - 13
src/LibDeclarations/webgpu.d.ts

@@ -358,9 +358,8 @@ interface GPUFenceDescriptor {
 }
 
 interface GPUInputStateDescriptor {
-  attributes?: GPUVertexAttributeDescriptor[];
   indexFormat?: GPUIndexFormat;
-  inputs?: GPUVertexInputDescriptor[];
+  vertexBuffers?: GPUVertexInputDescriptor[];
 }
 
 interface GPULimits {
@@ -418,16 +417,19 @@ interface GPURenderPassDescriptor {
   depthStencilAttachment?: GPURenderPassDepthStencilAttachmentDescriptor;
 }
 
-interface GPURenderPipelineDescriptor extends GPUPipelineDescriptorBase {
+interface GPURenderPipelineStageDescriptor {
+  vertexStage?: GPUPipelineStageDescriptor;
+  fragmentStage?: GPUPipelineStageDescriptor;
+}
+
+interface GPURenderPipelineDescriptor extends GPUPipelineDescriptorBase, GPURenderPipelineStageDescriptor {
   colorStates?: GPUColorStateDescriptor[];
-  blendStates?: GPUBlendStateDescriptor[];
+  // blendStates?: GPUBlendStateDescriptor[];
   depthStencilState?: GPUDepthStencilStateDescriptor;
-  fragmentStage?: GPUPipelineStageDescriptor;
   vertexInput?: GPUInputStateDescriptor;
   primitiveTopology?: GPUPrimitiveTopology;
   rasterizationState?: GPURasterizationStateDescriptor;
   sampleCount?: number;
-  vertexStage?: GPUPipelineStageDescriptor;
 }
 
 interface GPUSamplerDescriptor {
@@ -445,6 +447,8 @@ interface GPUSamplerDescriptor {
 }
 
 interface GPUShaderModuleDescriptor {
+  // After Migration to Canary
+  // code: Uint32Array;
   code: ArrayBuffer | string;
   label?: string;
 }
@@ -491,15 +495,16 @@ interface GPUTextureViewDescriptor {
 
 interface GPUVertexAttributeDescriptor {
   format?: GPUVertexFormat;
-  inputSlot?: number;
+  // inputSlot?: number;
   offset?: number;
   shaderLocation?: number;
 }
 
 interface GPUVertexInputDescriptor {
-  inputSlot?: number;
-  stepMode?: GPUInputStepMode;
+  // inputSlot?: number;
   stride?: number;
+  stepMode?: GPUInputStepMode;
+  attributes?: GPUVertexAttributeDescriptor[];
 }
 
 interface GPUAdapter {
@@ -522,6 +527,12 @@ interface GPUBuffer extends GPUDebugLabel {
   mapWriteAsync(): Promise<ArrayBuffer>;
   mapReadAsync(): Promise<ArrayBuffer>;
   setSubData(offset: number, ab: ArrayBuffer): void;
+  
+  // After Migration to Canary
+  // PR #261
+  // If `byteLength` is 0, the ArrayBufferView is copied to the end.
+  // That is, `byteLength` "defaults" to `src.byteLength - srcByteOffset`.
+  // setSubData(dstByteOffset: number, src: ArrayBufferView, srcByteOffset = 0, byteLength = 0): void;
 }
 
 interface GPUCommandEncoder extends GPUDebugLabel {
@@ -609,14 +620,17 @@ interface GPUQueue extends GPUDebugLabel {
 
 interface GPURenderPassEncoder extends GPUProgrammablePassEncoder {
   setPipeline(pipeline: GPURenderPipeline): void;
+  setIndexBuffer(buffer: GPUBuffer, offset: number): void;
+  setVertexBuffers(startSlot: number, buffers: GPUBuffer[], offsets: number[]): void;
+
   draw(vertexCount: number, instanceCount: number, firstVertex: number, firstInstance: number): void;
   drawIndexed(indexCount: number, instanceCount: number, firstIndex: number, baseVertex: number, firstInstance: number): void;
-  setBlendColor(color: GPUColor): void;
-  setIndexBuffer(buffer: GPUBuffer, offset: number): void;
+
+  setViewport(x: number, y: number, width: number, height: number, minDepth: number, maxDepth: number): void;
   setScissorRect(x: number, y: number, width: number, height: number): void;
+
   setStencilReference(reference: number): void;
-  setVertexBuffers(startSlot: number, buffers: GPUBuffer[], offsets: number[]): void;
-  setViewport(x: number, y: number, width: number, height: number, minDepth: number, maxDepth: number): void;
+  setBlendColor(color: GPUColor): void;
 }
 
 interface GPURenderPipeline extends GPUDebugLabel {

+ 3 - 2
src/Materials/effect.ts

@@ -239,10 +239,11 @@ export class Effect implements IDisposable {
 
     /** @hidden */
     public _bonesComputationForcedToCPU = false;
+    /** @hidden */
+    public _uniformBuffersNames: { [key: string]: number } = {};
 
     private static _uniqueIdSeed = 0;
     private _engine: Engine;
-    private _uniformBuffersNames: { [key: string]: number } = {};
     private _uniformsNames: string[];
     private _samplerList: string[];
     private _samplers: { [key: string]: number } = {};
@@ -1092,7 +1093,7 @@ export class Effect implements IDisposable {
             return;
         }
         Effect._baseCache[bufferName] = buffer;
-        this._engine.bindUniformBufferBase(buffer, bufferName);
+        this._engine.bindUniformBufferBase(buffer, bufferName, name);
     }
 
     /**

+ 16 - 0
src/Meshes/WebGPU/webgpuDataBuffer.ts

@@ -0,0 +1,16 @@
+import { DataBuffer } from '../dataBuffer';
+import { Nullable } from '../../types';
+
+/** @hidden */
+export class WebGPUDataBuffer extends DataBuffer {
+    private _buffer: Nullable<GPUBuffer>;
+
+    public constructor(resource: GPUBuffer) {
+        super();
+        this._buffer = resource;
+    }
+
+    public get underlyingResource(): any {
+        return this._buffer;
+    }
+}

+ 38 - 0
src/Meshes/abstractMesh.ts

@@ -21,6 +21,7 @@ import { IEdgesRenderer } from "../Rendering/edgesRenderer";
 import { SolidParticle } from "../Particles/solidParticle";
 import { Constants } from "../Engines/constants";
 import { AbstractActionManager } from '../Actions/abstractActionManager';
+import { UniformBuffer } from "../Materials/uniformBuffer";
 
 declare type Ray = import("../Culling/ray").Ray;
 declare type Collider = import("../Collisions/collider").Collider;
@@ -638,6 +639,12 @@ export class AbstractMesh extends TransformNode implements IDisposable, ICullabl
      */
     public onRebuildObservable = new Observable<AbstractMesh>();
 
+    /**
+     * The current camera unifom buffer.
+     * @hidden Internal use only.
+     */
+    public _uniformBuffer: UniformBuffer;
+
     // Constructor
 
     /**
@@ -651,6 +658,37 @@ export class AbstractMesh extends TransformNode implements IDisposable, ICullabl
         this.getScene().addMesh(this);
 
         this._resyncLightSources();
+
+        // Mesh Uniform Buffer.
+        this._uniformBuffer = new UniformBuffer(this.getScene().getEngine());
+        this._buildUniformLayout();
+    }
+
+    protected _buildUniformLayout(): void {
+        this._uniformBuffer.addUniform("world", 16);
+        this._uniformBuffer.addUniform("visibility", 1);
+        // TODO. Bones
+        this._uniformBuffer.create();
+    }
+
+    /**
+     * Transfer the mesh values to its UBO.
+     */
+    public transferToEffect(world: Matrix): void {
+        const ubo = this._uniformBuffer;
+
+        // TODO. Instances.
+        // if (!defines.INSTANCES) {
+        ubo.updateMatrix("world", world);
+        // }
+        ubo.updateFloat("visibility", this._visibility);
+
+        // TODO. Bones.
+
+        ubo.update();
+
+        // TODO WEBGPU.
+        this.getScene().getEngine().bindUniformBufferBase(ubo.getBuffer()!, 0, "Mesh");
     }
 
     /**

+ 2 - 1
src/Meshes/index.ts

@@ -18,4 +18,5 @@ export * from "./meshLODLevel";
 export * from "./transformNode";
 export * from "./Builders/index";
 export * from "./dataBuffer";
-export * from "./WebGL/webGLDataBuffer";
+export * from "./WebGL/webGLDataBuffer";
+export * from "./WebGPU/webgpuDataBuffer";

+ 5 - 0
src/Meshes/mesh.ts

@@ -1609,6 +1609,11 @@ export class Mesh extends AbstractMesh implements IGetSetVerticesData {
 
         var world = effectiveMesh.getWorldMatrix();
 
+        // TODO WEBGPU. Find a better approach.
+        if (engine.isWebGPU) {
+            this.transferToEffect(world);
+        }
+
         if (this._effectiveMaterial._storeEffectOnSubMeshes) {
             this._effectiveMaterial.bindForSubMesh(world, this, subMesh);
         } else {

+ 6 - 0
src/scene.ts

@@ -3493,6 +3493,12 @@ export class Scene extends AbstractScene implements IAnimatable {
 
         // Render
         this.onBeforeDrawPhaseObservable.notifyObservers(this);
+
+        // TODO WEBGPU. Find a better approach.
+        if (engine.isWebGPU) {
+            camera.transferToEffect();
+        }
+
         this._renderingManager.render(null, null, true, true);
         this.onAfterDrawPhaseObservable.notifyObservers(this);