Ver código fonte

Canvas2D TransparentSegment now use Instanced Arrays

nockawa 9 anos atrás
pai
commit
7207ebf297

+ 8 - 4
src/Canvas2d/babylon.ellipse2d.ts

@@ -57,9 +57,11 @@
                         this.instancingFillAttributes = this.loadInstancingAttributes(Shape2D.SHAPE2D_FILLPARTID, effect);
                     }
 
+                    let glBuffer = context.instancedBuffers ? context.instancedBuffers[partIndex] : pid._partBuffer;
+                    let count = context.instancedBuffers ? context.instancesCount : pid._partData.usedElementCount;
                     canvas._addDrawCallCount(1, context.renderMode);
-                    engine.updateAndBindInstancesBuffer(pid._partBuffer, null, this.instancingFillAttributes);
-                    engine.draw(true, 0, this.fillIndicesCount, pid._partData.usedElementCount);
+                    engine.updateAndBindInstancesBuffer(glBuffer, null, this.instancingFillAttributes);
+                    engine.draw(true, 0, this.fillIndicesCount, count);
                     engine.unbindInstanceAttributes();
                 } else {
                     canvas._addDrawCallCount(context.partDataEndIndex - context.partDataStartIndex, context.renderMode);
@@ -87,9 +89,11 @@
                         this.instancingBorderAttributes = this.loadInstancingAttributes(Shape2D.SHAPE2D_BORDERPARTID, effect);
                     }
 
+                    let glBuffer = context.instancedBuffers ? context.instancedBuffers[partIndex] : pid._partBuffer;
+                    let count = context.instancedBuffers ? context.instancesCount : pid._partData.usedElementCount;
                     canvas._addDrawCallCount(1, context.renderMode);
-                    engine.updateAndBindInstancesBuffer(pid._partBuffer, null, this.instancingBorderAttributes);
-                    engine.draw(true, 0, this.borderIndicesCount, pid._partData.usedElementCount);
+                    engine.updateAndBindInstancesBuffer(glBuffer, null, this.instancingBorderAttributes);
+                    engine.draw(true, 0, this.borderIndicesCount, count);
                     engine.unbindInstanceAttributes();
                 } else {
                     canvas._addDrawCallCount(context.partDataEndIndex - context.partDataStartIndex, context.renderMode);

+ 70 - 10
src/Canvas2d/babylon.group2d.ts

@@ -192,7 +192,7 @@
             }
 
             if (this._renderableData) {
-                this._renderableData.dispose();
+                this._renderableData.dispose(this.owner.engine);
                 this._renderableData = null;
             }
 
@@ -557,7 +557,12 @@
                 return true;
             }
 
+            // Free the existing TransparentSegments
+            for (let ts of rd._transparentSegments) {
+                ts.dispose(this.owner.engine);
+            }
             rd._transparentSegments.splice(0);
+
             let prevSeg = null;
 
             for (let tpiI = 0; tpiI < rd._transparentPrimitives.length; tpiI++) {
@@ -601,22 +606,69 @@
             let context = new Render2DContext(Render2DContext.RenderModeTransparent);
             let rd = this._renderableData;
 
+            let useInstanced = this.owner.supportInstancedArray;
+
             let length = rd._transparentSegments.length;
             for (let i = 0; i < length; i++) {
-                let ts = rd._transparentSegments[i];
-
+                context.instancedBuffers = null;
 
+                let ts = rd._transparentSegments[i];
                 let gii = ts.groupInsanceInfo;
                 let mrc = gii.modelRenderCache;
+                let engine = this.owner.engine;
+                let count = ts.endDataIndex - ts.startDataIndex;
+
+                // Use Instanced Array if it's supported and if there's at least 5 prims to draw.
+                // We don't want to create an Instanced Buffer for less that 5 prims
+                if (useInstanced && count >= 5) {
+
+                    if (!ts.partBuffers) {
+                        let buffers = new Array<WebGLBuffer>();
+
+                        for (let j = 0; j < gii.transparentData.length; j++) {
+                            let gitd = gii.transparentData[j];
+                            let dfa = gitd._partData;
+                            let data = dfa.pack();
+                            let stride = dfa.stride;
+                            let neededSize = count * stride * 4;
+
+                            let buffer = engine.createInstancesBuffer(neededSize); // Create + bind
+                            let segData = data.subarray(ts.startDataIndex * stride, ts.endDataIndex * stride);
+                            engine.updateArrayBuffer(segData);
+                            buffers.push(buffer);
+                        }
 
-                context.useInstancing = false;
-                context.partDataStartIndex = ts.startDataIndex;
-                context.partDataEndIndex = ts.endDataIndex;
-                context.groupInfoPartData = gii.transparentData;
+                        ts.partBuffers = buffers;
+                    } else if (gii.transparentDirty) {
+                        for (let j = 0; j < gii.transparentData.length; j++) {
+                            let gitd = gii.transparentData[j];
+                            let dfa = gitd._partData;
+                            let data = dfa.pack();
+                            let stride = dfa.stride;
+
+                            let buffer = ts.partBuffers[j];
+                            let segData = data.subarray(ts.startDataIndex * stride, ts.endDataIndex * stride);
+                            engine.bindArrayBuffer(buffer);
+                            engine.updateArrayBuffer(segData);
+                        }
+                    }
+
+                    context.useInstancing = true;
+                    context.instancesCount = count;
+                    context.instancedBuffers = ts.partBuffers;
+                    context.groupInfoPartData = gii.transparentData;
 
-                let renderFailed = !mrc.render(gii, context);
+                    let renderFailed = !mrc.render(gii, context);
+                    failedCount += renderFailed ? 1 : 0;
+                } else {
+                    context.useInstancing = false;
+                    context.partDataStartIndex = ts.startDataIndex;
+                    context.partDataEndIndex = ts.endDataIndex;
+                    context.groupInfoPartData = gii.transparentData;
 
-                failedCount += renderFailed ? 1 : 0;
+                    let renderFailed = !mrc.render(gii, context);
+                    failedCount += renderFailed ? 1 : 0;
+                }
             }
 
             return failedCount;
@@ -909,7 +961,7 @@
             this._anisotropicLevel = 1;
         }
 
-        dispose() {
+        dispose(engine: Engine) {
             if (this._cacheRenderSprite) {
                 this._cacheRenderSprite.dispose();
                 this._cacheRenderSprite = null;
@@ -937,6 +989,14 @@
                 this._cacheNodeUVsChangedObservable.clear();
                 this._cacheNodeUVsChangedObservable = null;
             }
+
+            if (this._transparentSegments) {
+                for (let ts of this._transparentSegments) {
+                    ts.dispose(engine);
+                }
+                this._transparentSegments.splice(0);
+                this._transparentSegments = null;
+            }
         }
 
         addNewTransparentPrimitiveInfo(prim: RenderablePrim2D, gii: GroupInstanceInfo): TransparentPrimitiveInfo {

+ 8 - 4
src/Canvas2d/babylon.lines2d.ts

@@ -56,9 +56,11 @@
                         this.instancingFillAttributes = this.loadInstancingAttributes(Shape2D.SHAPE2D_FILLPARTID, effect);
                     }
 
+                    let glBuffer = context.instancedBuffers ? context.instancedBuffers[partIndex] : pid._partBuffer;
+                    let count = context.instancedBuffers ? context.instancesCount : pid._partData.usedElementCount;
                     canvas._addDrawCallCount(1, context.renderMode);
-                    engine.updateAndBindInstancesBuffer(pid._partBuffer, null, this.instancingFillAttributes);
-                    engine.draw(true, 0, this.fillIndicesCount, pid._partData.usedElementCount);
+                    engine.updateAndBindInstancesBuffer(glBuffer, null, this.instancingFillAttributes);
+                    engine.draw(true, 0, this.fillIndicesCount, count);
                     engine.unbindInstanceAttributes();
                 } else {
                     canvas._addDrawCallCount(context.partDataEndIndex - context.partDataStartIndex, context.renderMode);
@@ -86,9 +88,11 @@
                         this.instancingBorderAttributes = this.loadInstancingAttributes(Shape2D.SHAPE2D_BORDERPARTID, effect);
                     }
 
+                    let glBuffer = context.instancedBuffers ? context.instancedBuffers[partIndex] : pid._partBuffer;
+                    let count = context.instancedBuffers ? context.instancesCount : pid._partData.usedElementCount;
                     canvas._addDrawCallCount(1, context.renderMode);
-                    engine.updateAndBindInstancesBuffer(pid._partBuffer, null, this.instancingBorderAttributes);
-                    engine.draw(true, 0, this.borderIndicesCount, pid._partData.usedElementCount);
+                    engine.updateAndBindInstancesBuffer(glBuffer, null, this.instancingBorderAttributes);
+                    engine.draw(true, 0, this.borderIndicesCount, count);
                     engine.unbindInstanceAttributes();
                 } else {
                     canvas._addDrawCallCount(context.partDataEndIndex - context.partDataStartIndex, context.renderMode);

+ 18 - 0
src/Canvas2d/babylon.modelRenderCache.ts

@@ -123,11 +123,29 @@
     }
 
     export class TransparentSegment {
+        constructor() {
+            this.groupInsanceInfo = null;
+            this.startZ = 0;
+            this.endZ = 0;
+            this.startDataIndex = 0;
+            this.endDataIndex = 0;
+            this.partBuffers = null;
+        }
+
+        dispose(engine: Engine) {
+            if (this.partBuffers) {
+                this.partBuffers.forEach(b => engine._releaseBuffer(b));
+                this.partBuffers.splice(0);
+                this.partBuffers = null;
+            }
+        }
+
         groupInsanceInfo: GroupInstanceInfo;
         startZ: number;
         endZ: number;
         startDataIndex: number;
         endDataIndex: number;
+        partBuffers: WebGLBuffer[];
     }
 
     export class GroupInfoPartData {

+ 11 - 0
src/Canvas2d/babylon.prim2dBase.ts

@@ -19,6 +19,7 @@
             this.useInstancing = false;
             this.groupInfoPartData = null;
             this.partDataStartIndex = this.partDataEndIndex = null;
+            this.instancedBuffers = null;
         }
         /**
          * Define which render Mode should be used to render the primitive: one of Render2DContext.RenderModeXxxx property
@@ -37,6 +38,16 @@
         useInstancing: boolean;
 
         /**
+         * If specified, must take precedence from the groupInfoPartData. partIndex is the same as groupInfoPardData
+         */
+        instancedBuffers: WebGLBuffer[];
+
+        /**
+         * To use when instancedBuffers is specified, gives the count of instances to draw
+         */
+        instancesCount: number;
+
+        /**
          * Contains the data related to the primitives instances to render
          */
         groupInfoPartData: GroupInfoPartData[];

+ 8 - 4
src/Canvas2d/babylon.rectangle2d.ts

@@ -57,9 +57,11 @@
                         this.instancingFillAttributes = this.loadInstancingAttributes(Shape2D.SHAPE2D_FILLPARTID, effect);
                     }
 
+                    let glBuffer = context.instancedBuffers ? context.instancedBuffers[partIndex] : pid._partBuffer;
+                    let count = context.instancedBuffers ? context.instancesCount : pid._partData.usedElementCount;
                     canvas._addDrawCallCount(1, context.renderMode);
-                    engine.updateAndBindInstancesBuffer(pid._partBuffer, null, this.instancingFillAttributes);
-                    engine.draw(true, 0, this.fillIndicesCount, pid._partData.usedElementCount);
+                    engine.updateAndBindInstancesBuffer(glBuffer, null, this.instancingFillAttributes);
+                    engine.draw(true, 0, this.fillIndicesCount, count);
                     engine.unbindInstanceAttributes();
                 } else {
                     canvas._addDrawCallCount(context.partDataEndIndex - context.partDataStartIndex, context.renderMode);
@@ -87,9 +89,11 @@
                         this.instancingBorderAttributes = this.loadInstancingAttributes(Shape2D.SHAPE2D_BORDERPARTID, effect);
                     }
 
+                    let glBuffer = context.instancedBuffers ? context.instancedBuffers[partIndex] : pid._partBuffer;
+                    let count = context.instancedBuffers ? context.instancesCount : pid._partData.usedElementCount;
                     canvas._addDrawCallCount(1, context.renderMode);
-                    engine.updateAndBindInstancesBuffer(pid._partBuffer, null, this.instancingBorderAttributes);
-                    engine.draw(true, 0, this.borderIndicesCount, pid._partData.usedElementCount);
+                    engine.updateAndBindInstancesBuffer(glBuffer, null, this.instancingBorderAttributes);
+                    engine.draw(true, 0, this.borderIndicesCount, count);
                     engine.unbindInstanceAttributes();
                 } else {
                     canvas._addDrawCallCount(context.partDataEndIndex - context.partDataStartIndex, context.renderMode);

+ 4 - 2
src/Canvas2d/babylon.sprite2d.ts

@@ -37,9 +37,11 @@
                 if (!this.instancingAttributes) {
                     this.instancingAttributes = this.loadInstancingAttributes(Sprite2D.SPRITE2D_MAINPARTID, effect);
                 }
+                let glBuffer = context.instancedBuffers ? context.instancedBuffers[0] : pid._partBuffer;
+                let count = context.instancedBuffers ? context.instancesCount : pid._partData.usedElementCount;
                 canvas._addDrawCallCount(1, context.renderMode);
-                engine.updateAndBindInstancesBuffer(pid._partBuffer, null, this.instancingAttributes);
-                engine.draw(true, 0, 6, pid._partData.usedElementCount);
+                engine.updateAndBindInstancesBuffer(glBuffer, null, this.instancingAttributes);
+                engine.draw(true, 0, 6, count);
                 engine.unbindInstanceAttributes();
             } else {
                 canvas._addDrawCallCount(context.partDataEndIndex - context.partDataStartIndex, context.renderMode);

+ 4 - 2
src/Canvas2d/babylon.text2d.ts

@@ -37,9 +37,11 @@
                     this.instancingAttributes = this.loadInstancingAttributes(Text2D.TEXT2D_MAINPARTID, effect);
                 }
 
+                let glBuffer = context.instancedBuffers ? context.instancedBuffers[0] : pid._partBuffer;
+                let count = context.instancedBuffers ? context.instancesCount : pid._partData.usedElementCount;
                 canvas._addDrawCallCount(1, context.renderMode);
-                engine.updateAndBindInstancesBuffer(pid._partBuffer, null, this.instancingAttributes);
-                engine.draw(true, 0, 6, pid._partData.usedElementCount);
+                engine.updateAndBindInstancesBuffer(glBuffer, null, this.instancingAttributes);
+                engine.draw(true, 0, 6, count);
                 engine.unbindInstanceAttributes();
             } else {
                 canvas._addDrawCallCount(context.partDataEndIndex - context.partDataStartIndex, context.renderMode);