Browse Source

- Batch renderer now works exclusively with triangles making the quads as special-case of two triangles. The changes remove the single/multiple strict batching therefore this metric has been removed from the DebugStats which causes the changes outside of the BatchRender type.

WildTurkeyUK 12 years ago
parent
commit
dce5130779

+ 255 - 136
engine/source/2d/core/BatchRender.cc

@@ -32,9 +32,9 @@
 //-----------------------------------------------------------------------------
 //-----------------------------------------------------------------------------
 
 
 BatchRender::BatchRender() :
 BatchRender::BatchRender() :
-    mQuadCount( 0 ),
+    mTriangleCount( 0 ),
     mVertexCount( 0 ),
     mVertexCount( 0 ),
-    mTextureResidentCount( 0 ),
+    mTextureCoordCount( 0 ),
     mIndexCount( 0 ),
     mIndexCount( 0 ),
     mColorCount( 0 ),
     mColorCount( 0 ),
     NoColor( -1.0f, -1.0f, -1.0f ),
     NoColor( -1.0f, -1.0f, -1.0f ),
@@ -99,6 +99,125 @@ void BatchRender::setAlphaTestMode( const SceneRenderRequest* pSceneRenderReques
 
 
 //-----------------------------------------------------------------------------
 //-----------------------------------------------------------------------------
 
 
+void BatchRender::SubmitTriangles(
+        const U32 vertexCount,
+        const Vector2* pVertexArray,
+        const Vector2* pTextureArray,
+        TextureHandle& texture,
+        const ColorF& color )
+{
+    // Debug Profiling.
+    PROFILE_SCOPE(BatchRender_SubmitTriangles);
+
+    // Sanity!
+    AssertFatal( mpDebugStats != NULL, "Debug stats have not been configured." );
+    AssertFatal( vertexCount % 3 == 0, "BatchRender::SubmitTriangles() - Invalid vertex count, cannot represent whole triangles." );
+    AssertFatal( vertexCount <= BATCHRENDER_BUFFERSIZE, "BatchRender::SubmitTriangles() - Invalid vertex count." );
+
+    // Calculate triangle count.
+    const U32 triangleCount = vertexCount / 3;
+
+    // Would we exceed the triangle buffer size?
+    if ( (mTriangleCount + triangleCount) > BATCHRENDER_MAXTRIANGLES )
+    {
+        // Yes, so flush.
+        flush( mpDebugStats->batchBufferFullFlush );
+    }
+    // Do we have anything batched?
+    else if ( mTriangleCount > 0 )
+    {
+        // Yes, so do we have any existing colors?
+        if ( mColorCount == 0 )
+        {
+            // No, so flush if color is specified.
+            if ( color != NoColor  )
+                flush( mpDebugStats->batchColorStateFlush );
+        }
+        else
+        {
+            // Yes, so flush if color is not specified.
+            if ( color == NoColor  )
+                flush( mpDebugStats->batchColorStateFlush );
+        }
+    }
+
+    // Strict order mode?
+    if ( mStrictOrderMode )
+    {
+        // Yes, so is there a texture change?
+        if ( texture != mStrictOrderTextureHandle && mTriangleCount > 0 )
+        {
+            // Yes, so flush.
+            flush( mpDebugStats->batchTextureChangeFlush );
+        }
+
+        // Fetch vertex index.
+        U16 vertexIndex = (U16)mVertexCount;
+
+        // Add new indices.
+        for( U32 n = 0; n < triangleCount; ++n )
+        {
+            mIndexBuffer[mIndexCount++] = vertexIndex++;
+            mIndexBuffer[mIndexCount++] = vertexIndex++;
+            mIndexBuffer[mIndexCount++] = vertexIndex++;
+        }
+
+        // Set strict order mode texture handle.
+        mStrictOrderTextureHandle = texture;
+    }
+    else
+    {
+        // No, so add triangle run.
+        findTextureBatch( texture )->push_back( TriangleRun( TriangleRun::TRIANGLE, triangleCount, mVertexCount ) );
+    }
+
+    // Is a color specified?
+    if ( color != NoColor )
+    {
+        // Yes, so add colors.
+        for( U32 n = 0; n < triangleCount; ++n )
+        {
+            mColorBuffer[mColorCount++] = color;
+            mColorBuffer[mColorCount++] = color;
+            mColorBuffer[mColorCount++] = color;
+        }
+    }
+
+    // Add textured vertices.
+    for( U32 n = 0; n < triangleCount; ++n )
+    {
+        mVertexBuffer[mVertexCount++]   = *(pVertexArray++);
+        mVertexBuffer[mVertexCount++]   = *(pVertexArray++);
+        mVertexBuffer[mVertexCount++]   = *(pVertexArray++);
+        mTextureBuffer[mTextureCoordCount++] = *(pTextureArray++);
+        mTextureBuffer[mTextureCoordCount++] = *(pTextureArray++);
+        mTextureBuffer[mTextureCoordCount++] = *(pTextureArray++);
+    }
+
+    // Stats.
+    mpDebugStats->batchTrianglesSubmitted += triangleCount;
+
+    // Increase triangle count.
+    mTriangleCount += triangleCount;
+
+    // Have we reached the buffer limit?
+    if ( mTriangleCount == BATCHRENDER_MAXTRIANGLES )
+    {
+        // Yes, so flush.
+        flush( mpDebugStats->batchBufferFullFlush );
+    }
+    // Is batching enabled?
+    else if ( !mBatchEnabled )
+    {
+        // No, so flush immediately.
+        // NOTE: Technically this is still batching but will still revert to using
+        // more draw calls therefore can be used in comparison.
+        flushInternal();
+    }
+}
+
+//-----------------------------------------------------------------------------
+
 void BatchRender::SubmitQuad(
 void BatchRender::SubmitQuad(
         const Vector2& vertexPos0,
         const Vector2& vertexPos0,
         const Vector2& vertexPos1,
         const Vector2& vertexPos1,
@@ -114,10 +233,17 @@ void BatchRender::SubmitQuad(
     // Sanity!
     // Sanity!
     AssertFatal( mpDebugStats != NULL, "Debug stats have not been configured." );
     AssertFatal( mpDebugStats != NULL, "Debug stats have not been configured." );
 
 
-    PROFILE_START(BatchRender_SubmitQuad);
+    // Debug Profiling.
+    PROFILE_SCOPE(BatchRender_SubmitQuad);
 
 
+    // Would we exceed the triangle buffer size?
+    if ( (mTriangleCount + 2) > BATCHRENDER_MAXTRIANGLES )
+    {
+        // Yes, so flush.
+        flush( mpDebugStats->batchBufferFullFlush );
+    }
     // Do we have anything batched?
     // Do we have anything batched?
-    if ( mQuadCount > 0 )
+    else if ( mTriangleCount > 0 )
     {
     {
         // Yes, so do we have any existing colors?
         // Yes, so do we have any existing colors?
         if ( mColorCount == 0 )
         if ( mColorCount == 0 )
@@ -134,21 +260,11 @@ void BatchRender::SubmitQuad(
         }
         }
     }
     }
 
 
-    // Is a color specified?
-    if ( color != NoColor )
-    {
-        // Yes, so add colors.
-        mColorBuffer[mColorCount++] = color;
-        mColorBuffer[mColorCount++] = color;
-        mColorBuffer[mColorCount++] = color;
-        mColorBuffer[mColorCount++] = color;
-    }
-
     // Strict order mode?
     // Strict order mode?
     if ( mStrictOrderMode )
     if ( mStrictOrderMode )
     {
     {
-        // Is there is a texture change.
-        if ( texture != mStrictOrderTextureHandle )
+        // Yes, so is there a texture change?
+        if ( texture != mStrictOrderTextureHandle && mTriangleCount > 0 )
         {
         {
             // Yes, so flush.
             // Yes, so flush.
             flush( mpDebugStats->batchTextureChangeFlush );
             flush( mpDebugStats->batchTextureChangeFlush );
@@ -167,44 +283,18 @@ void BatchRender::SubmitQuad(
     }
     }
     else
     else
     {
     {
-        // No, so fetch texture binding.
-        const U32 textureBinding = texture.getGLName();
-
-        indexVectorType* pIndexVector = NULL;
-
-        // Find texture binding.
-        textureBatchType::iterator itr = mTextureBatchMap.find( textureBinding );
-
-        // Did we find a texture binding?
-        if ( itr == mTextureBatchMap.end() )
-        {
-            // No, so fetch index vector pool count.
-            const U32 indexVectorPoolCount = mIndexVectorPool.size();
-
-            // Do we have any in the index vector pool?
-            if ( indexVectorPoolCount > 0 )
-            {
-                // Yes, so use it.
-                pIndexVector = mIndexVectorPool[indexVectorPoolCount-1];
-                mIndexVectorPool.pop_back();
-            }
-            else
-            {
-                // No, so generate one.
-                pIndexVector = new indexVectorType( 6 * 6 );
-            }
-
-            // Insert into texture batch map.
-            mTextureBatchMap.insert( textureBinding, pIndexVector );
-        }
-        else
-        {
-            // Yes, so fetch it.
-            pIndexVector = itr->value;
-        }
+        // No, so add triangle run.
+        findTextureBatch( texture )->push_back( TriangleRun( TriangleRun::QUAD, 1, mVertexCount ) );
+    }
 
 
-        // Add vertex start.
-        pIndexVector->push_back( mVertexCount );       
+    // Is a color specified?
+    if ( color != NoColor )
+    {
+        // Yes, so add colors.
+        mColorBuffer[mColorCount++] = color;
+        mColorBuffer[mColorCount++] = color;
+        mColorBuffer[mColorCount++] = color;
+        mColorBuffer[mColorCount++] = color;
     }
     }
 
 
     // Add textured vertices.
     // Add textured vertices.
@@ -213,42 +303,39 @@ void BatchRender::SubmitQuad(
     mVertexBuffer[mVertexCount++]   = vertexPos1;
     mVertexBuffer[mVertexCount++]   = vertexPos1;
     mVertexBuffer[mVertexCount++]   = vertexPos3;
     mVertexBuffer[mVertexCount++]   = vertexPos3;
     mVertexBuffer[mVertexCount++]   = vertexPos2;
     mVertexBuffer[mVertexCount++]   = vertexPos2;
-    mTextureBuffer[mTextureResidentCount++] = texturePos0;
-    mTextureBuffer[mTextureResidentCount++] = texturePos1;
-    mTextureBuffer[mTextureResidentCount++] = texturePos3;
-    mTextureBuffer[mTextureResidentCount++] = texturePos2;
+    mTextureBuffer[mTextureCoordCount++] = texturePos0;
+    mTextureBuffer[mTextureCoordCount++] = texturePos1;
+    mTextureBuffer[mTextureCoordCount++] = texturePos3;
+    mTextureBuffer[mTextureCoordCount++] = texturePos2;
 
 
     // Stats.
     // Stats.
     mpDebugStats->batchTrianglesSubmitted+=2;
     mpDebugStats->batchTrianglesSubmitted+=2;
 
 
-    // Increase quad count.
-    mQuadCount++;
+    // Increase triangle count.
+    mTriangleCount += 2;
 
 
     // Have we reached the buffer limit?
     // Have we reached the buffer limit?
-    if ( mQuadCount == BATCHRENDER_MAXQUADS )
+    if ( mTriangleCount == BATCHRENDER_MAXTRIANGLES )
     {
     {
         // Yes, so flush.
         // Yes, so flush.
         flush( mpDebugStats->batchBufferFullFlush );
         flush( mpDebugStats->batchBufferFullFlush );
     }
     }
-
     // Is batching enabled?
     // Is batching enabled?
-    if ( !mBatchEnabled )
+    else if ( !mBatchEnabled )
     {
     {
         // No, so flush immediately.
         // No, so flush immediately.
         // NOTE: Technically this is still batching but will still revert to using
         // NOTE: Technically this is still batching but will still revert to using
         // more draw calls therefore can be used in comparison.
         // more draw calls therefore can be used in comparison.
         flushInternal();
         flushInternal();
     }
     }
-
-    PROFILE_END();   // BatchRender_SubmitQuad
 }
 }
 
 
 //-----------------------------------------------------------------------------
 //-----------------------------------------------------------------------------
 
 
 void BatchRender::flush( U32& reasonMetric )
 void BatchRender::flush( U32& reasonMetric )
 {
 {
-    // Finish if no quads to flush.
-    if ( mQuadCount == 0 )
+    // Finish if no triangles to flush.
+    if ( mTriangleCount == 0 )
         return;
         return;
 
 
     // Increase reason metric.
     // Increase reason metric.
@@ -262,8 +349,8 @@ void BatchRender::flush( U32& reasonMetric )
 
 
 void BatchRender::flush( void )
 void BatchRender::flush( void )
 {
 {
-    // Finish if no quads to flush.
-    if ( mQuadCount == 0 )
+    // Finish if no triangles to flush.
+    if ( mTriangleCount == 0 )
         return;
         return;
 
 
     // Increase reason metric.
     // Increase reason metric.
@@ -277,11 +364,12 @@ void BatchRender::flush( void )
 
 
 void BatchRender::flushInternal( void )
 void BatchRender::flushInternal( void )
 {
 {
-    // Finish if no quads to flush.
-    if ( mQuadCount == 0 )
-        return;
+    // Debug Profiling.
+    PROFILE_SCOPE(T2D_BatchRender_flush);
 
 
-    PROFILE_START(T2D_BatchRender_flush);
+    // Finish if no triangles to flush.
+    if ( mTriangleCount == 0 )
+        return;
 
 
     // Stats.
     // Stats.
     mpDebugStats->batchFlushes++;
     mpDebugStats->batchFlushes++;
@@ -352,32 +440,16 @@ void BatchRender::flushInternal( void )
         if ( !mWireframeMode )
         if ( !mWireframeMode )
             glBindTexture( GL_TEXTURE_2D, mStrictOrderTextureHandle.getGLName() );
             glBindTexture( GL_TEXTURE_2D, mStrictOrderTextureHandle.getGLName() );
 
 
-        // Yes, so do we have a single quad?
-        if ( mQuadCount == 1 )
-        {
-            // Yes, so draw the quad using a triangle-strip with indexes.
-            glDrawArrays( GL_TRIANGLE_STRIP, 0, 4 );    
-
-            // Stats.
-            mpDebugStats->batchDrawCallsStrictSingle++;
+        // Draw the triangles
+        glDrawElements( GL_TRIANGLES, mIndexCount, GL_UNSIGNED_SHORT, mIndexBuffer );
 
 
-            // Stats.
-            if ( mpDebugStats->batchMaxTriangleDrawn < 2 )
-                mpDebugStats->batchMaxTriangleDrawn = 2;
-        }
-        else
-        {
-            // Draw the quads using triangles with indexes.
-            glDrawElements( GL_TRIANGLES, mIndexCount, GL_UNSIGNED_SHORT, mIndexBuffer );
-
-            // Stats.
-            mpDebugStats->batchDrawCallsStrictMultiple++;
+        // Stats.
+        mpDebugStats->batchDrawCallsStrict++;
 
 
-            // Stats.
-            const U32 trianglesDrawn = mIndexCount / 3;
-            if ( trianglesDrawn > mpDebugStats->batchMaxTriangleDrawn )
-                mpDebugStats->batchMaxTriangleDrawn = trianglesDrawn;
-        }
+        // Stats.
+        const U32 trianglesDrawn = mIndexCount / 3;
+        if ( trianglesDrawn > mpDebugStats->batchMaxTriangleDrawn )
+            mpDebugStats->batchMaxTriangleDrawn = trianglesDrawn;
 
 
         // Stats.
         // Stats.
         if ( mVertexCount > mpDebugStats->batchMaxVertexBuffer )
         if ( mVertexCount > mpDebugStats->batchMaxVertexBuffer )
@@ -388,28 +460,58 @@ void BatchRender::flushInternal( void )
         // No, so iterate texture batch map.
         // No, so iterate texture batch map.
         for( textureBatchType::iterator batchItr = mTextureBatchMap.begin(); batchItr != mTextureBatchMap.end(); ++batchItr )
         for( textureBatchType::iterator batchItr = mTextureBatchMap.begin(); batchItr != mTextureBatchMap.end(); ++batchItr )
         {
         {
-            // Fetch texture binding.
-            const U32 textureBinding = batchItr->key;
+            // Reset index count.
+            mIndexCount = 0;
 
 
             // Fetch index vector.
             // Fetch index vector.
             indexVectorType* pIndexVector = batchItr->value;
             indexVectorType* pIndexVector = batchItr->value;
 
 
-            // Reset index count.
-            mIndexCount = 0;
-
             // Iterate indexes.
             // Iterate indexes.
             for( indexVectorType::iterator indexItr = pIndexVector->begin(); indexItr != pIndexVector->end(); ++indexItr )
             for( indexVectorType::iterator indexItr = pIndexVector->begin(); indexItr != pIndexVector->end(); ++indexItr )
             {
             {
-                // Fetch quad index.
-                U32 quadIndex = (*indexItr);
-
-                // Add new indices.
-                mIndexBuffer[mIndexCount++] = (U16)quadIndex++;
-                mIndexBuffer[mIndexCount++] = (U16)quadIndex++;
-                mIndexBuffer[mIndexCount++] = (U16)quadIndex++;
-                mIndexBuffer[mIndexCount++] = (U16)quadIndex--;
-                mIndexBuffer[mIndexCount++] = (U16)quadIndex--;
-                mIndexBuffer[mIndexCount++] = (U16)quadIndex;
+                // Fetch triangle run.
+                const TriangleRun& triangleRun = *indexItr;
+
+                // Fetch primitivecount.
+                const U32 primitiveCount = triangleRun.mPrimitiveCount;
+
+                // Fetch triangle index start.
+                U16 triangleIndex = (U16)triangleRun.mStartIndex;
+
+                // Fetch primitive mode.
+                const TriangleRun::PrimitiveMode& primitiveMode = triangleRun.mPrimitiveMode;
+
+                // Handle primitive mode.
+                if ( primitiveMode == TriangleRun::QUAD )
+                {
+                    // Add triangle run for quad.
+                    for( U32 n = 0; n < primitiveCount; ++n )
+                    {
+                        // Add new indices.
+                        mIndexBuffer[mIndexCount++] = triangleIndex++;
+                        mIndexBuffer[mIndexCount++] = triangleIndex++;
+                        mIndexBuffer[mIndexCount++] = triangleIndex++;
+                        mIndexBuffer[mIndexCount++] = triangleIndex--;
+                        mIndexBuffer[mIndexCount++] = triangleIndex--;
+                        mIndexBuffer[mIndexCount++] = triangleIndex--;
+                    }
+                }
+                else if ( primitiveMode == TriangleRun::TRIANGLE )
+                {
+                    // Add triangle run for triangles.
+                    for( U32 n = 0; n < primitiveCount; ++n )
+                    {
+                        // Add new indices.
+                        mIndexBuffer[mIndexCount++] = triangleIndex++;
+                        mIndexBuffer[mIndexCount++] = triangleIndex++;
+                        mIndexBuffer[mIndexCount++] = triangleIndex++;
+                    }
+                }
+                else
+                {
+                    // Sanity!
+                    AssertFatal( false, "BatchRender::flushInternal() - Unrecognized primitive mode encountered for triangle run." );
+                }
             }
             }
 
 
             // Sanity!
             // Sanity!
@@ -417,9 +519,9 @@ void BatchRender::flushInternal( void )
 
 
             // Bind the texture if not in wireframe mode.
             // Bind the texture if not in wireframe mode.
             if ( !mWireframeMode )
             if ( !mWireframeMode )
-                glBindTexture( GL_TEXTURE_2D, textureBinding );
+                glBindTexture( GL_TEXTURE_2D, batchItr->key );
 
 
-            // Draw the quads using triangles with indexes.
+            // Draw the triangles.
             glDrawElements( GL_TRIANGLES, mIndexCount, GL_UNSIGNED_SHORT, mIndexBuffer );
             glDrawElements( GL_TRIANGLES, mIndexCount, GL_UNSIGNED_SHORT, mIndexBuffer );
 
 
             // Stats.
             // Stats.
@@ -453,37 +555,54 @@ void BatchRender::flushInternal( void )
     glPolygonMode( GL_FRONT_AND_BACK, GL_FILL );
     glPolygonMode( GL_FRONT_AND_BACK, GL_FILL );
 
 
     // Reset batch state.
     // Reset batch state.
-    mQuadCount = 0;
+    mTriangleCount = 0;
     mVertexCount = 0;
     mVertexCount = 0;
-    mTextureResidentCount = 0;
+    mTextureCoordCount = 0;
     mIndexCount = 0;
     mIndexCount = 0;
     mColorCount = 0;
     mColorCount = 0;
-
-    PROFILE_END();   // T2D_BatchRender_flush
 }
 }
 
 
 //-----------------------------------------------------------------------------
 //-----------------------------------------------------------------------------
 
 
-void BatchRender::RenderQuad(
-        const Vector2& vertexPos0,
-        const Vector2& vertexPos1,
-        const Vector2& vertexPos2,
-        const Vector2& vertexPos3,
-        const Vector2& texturePos0,
-        const Vector2& texturePos1,
-        const Vector2& texturePos2,
-        const Vector2& texturePos3 )
+BatchRender::indexVectorType* BatchRender::findTextureBatch( TextureHandle& handle )
 {
 {
-    glBegin( GL_TRIANGLE_STRIP );
-        glTexCoord2f( texturePos0.x, texturePos0.y );
-        glVertex2f( vertexPos0.x, vertexPos0.y );
-        glTexCoord2f( texturePos1.x, texturePos1.y );
-        glVertex2f( vertexPos1.x, vertexPos1.y );
-        glTexCoord2f( texturePos3.x, texturePos3.y );
-        glVertex2f( vertexPos3.x, vertexPos3.y );
-        glTexCoord2f( texturePos2.x, texturePos2.y );
-        glVertex2f( vertexPos2.x, vertexPos2.y );
-    glEnd();
+    // Fetch texture binding.
+    const U32 textureBinding = handle.getGLName();
+
+    indexVectorType* pIndexVector = NULL;
+
+    // Find texture binding.
+    textureBatchType::iterator itr = mTextureBatchMap.find( textureBinding );
+
+    // Did we find a texture binding?
+    if ( itr == mTextureBatchMap.end() )
+    {
+        // No, so fetch index vector pool count.
+        const U32 indexVectorPoolCount = mIndexVectorPool.size();
+
+        // Do we have any in the index vector pool?
+        if ( indexVectorPoolCount > 0 )
+        {
+            // Yes, so use it.
+            pIndexVector = mIndexVectorPool[indexVectorPoolCount-1];
+            mIndexVectorPool.pop_back();
+        }
+        else
+        {
+            // No, so generate one.
+            pIndexVector = new indexVectorType( 6 * 6 );
+        }
+
+        // Insert into texture batch map.
+        mTextureBatchMap.insert( textureBinding, pIndexVector );
+    }
+    else
+    {
+        // Yes, so fetch it.
+        pIndexVector = itr->value;
+    }
+
+    return pIndexVector;
 }
 }
 
 
 
 

+ 82 - 35
engine/source/2d/core/BatchRender.h

@@ -50,7 +50,7 @@
 //-----------------------------------------------------------------------------
 //-----------------------------------------------------------------------------
 
 
 #define BATCHRENDER_BUFFERSIZE      (65535)
 #define BATCHRENDER_BUFFERSIZE      (65535)
-#define BATCHRENDER_MAXQUADS        (BATCHRENDER_BUFFERSIZE/6)
+#define BATCHRENDER_MAXTRIANGLES    (BATCHRENDER_BUFFERSIZE/3)
 
 
 //-----------------------------------------------------------------------------
 //-----------------------------------------------------------------------------
 
 
@@ -60,6 +60,58 @@ class SceneRenderRequest;
 
 
 class BatchRender
 class BatchRender
 {
 {
+private:
+    struct TriangleRun
+    {
+        enum PrimitiveMode
+        {
+            TRIANGLE,
+            QUAD,
+        };
+
+        TriangleRun( const PrimitiveMode primitive, const U32 primitiveCount, const U32 startIndex ) :
+            mPrimitiveMode( primitive ),
+            mPrimitiveCount( primitiveCount ),
+            mStartIndex( startIndex )
+        { }
+
+        PrimitiveMode mPrimitiveMode;
+        U32 mPrimitiveCount;
+        U32 mStartIndex;
+    };
+
+    typedef Vector<TriangleRun> indexVectorType;
+    typedef HashMap<U32, indexVectorType*> textureBatchType;
+
+    VectorPtr< indexVectorType* > mIndexVectorPool;
+    textureBatchType    mTextureBatchMap;
+
+    const ColorF        NoColor;
+
+    Vector2             mVertexBuffer[ BATCHRENDER_BUFFERSIZE ];
+    Vector2             mTextureBuffer[ BATCHRENDER_BUFFERSIZE ];
+    U16                 mIndexBuffer[ BATCHRENDER_BUFFERSIZE ];
+    ColorF              mColorBuffer[ BATCHRENDER_BUFFERSIZE ];
+   
+    U32                 mTriangleCount;
+    U32                 mVertexCount;
+    U32                 mTextureCoordCount;
+    U32                 mIndexCount;
+    U32                 mColorCount;
+
+    bool                mBlendMode;
+    GLenum              mSrcBlendFactor;
+    GLenum              mDstBlendFactor;
+    ColorF              mBlendColor;
+    F32                 mAlphaTestMode;
+
+    bool                mStrictOrderMode;
+    TextureHandle       mStrictOrderTextureHandle;
+    DebugStats*         mpDebugStats;
+
+    bool                mWireframeMode;
+    bool                mBatchEnabled;
+
 public:
 public:
     BatchRender();
     BatchRender();
     virtual ~BatchRender();
     virtual ~BatchRender();
@@ -117,7 +169,7 @@ public:
     void setBlendMode( const SceneRenderRequest* pSceneRenderRequest );
     void setBlendMode( const SceneRenderRequest* pSceneRenderRequest );
 
 
     /// Set alpha-test mode.
     /// Set alpha-test mode.
-    inline void setAlphaTestMode( const F32 alphaTestMode )
+    void setAlphaTestMode( const F32 alphaTestMode )
     {
     {
         // Ignore no change.
         // Ignore no change.
         if ( mIsEqual( mAlphaTestMode, alphaTestMode ) )
         if ( mIsEqual( mAlphaTestMode, alphaTestMode ) )
@@ -167,6 +219,19 @@ public:
     /// Sets the debug stats to use.
     /// Sets the debug stats to use.
     inline void setDebugStats( DebugStats* pDebugStats ) { mpDebugStats = pDebugStats; }
     inline void setDebugStats( DebugStats* pDebugStats ) { mpDebugStats = pDebugStats; }
 
 
+    /// Submit triangles for batching.
+    /// Vertex and textures are indexed as:
+    ///  2        5
+    ///   |\      |\
+    ///   | \     | \
+    ///  0| _\1  3| _\4
+    void SubmitTriangles(
+            const U32 vertexCount,
+            const Vector2* pVertexArray,
+            const Vector2* pTextureArray,
+            TextureHandle& texture,
+            const ColorF& color = ColorF(-1.0f, -1.0f, -1.0f) );
+
     /// Submit a quad for batching.
     /// Submit a quad for batching.
     /// Vertex and textures are indexed as:
     /// Vertex and textures are indexed as:
     ///  3 ___ 2
     ///  3 ___ 2
@@ -200,7 +265,19 @@ public:
             const Vector2& texturePos0,
             const Vector2& texturePos0,
             const Vector2& texturePos1,
             const Vector2& texturePos1,
             const Vector2& texturePos2,
             const Vector2& texturePos2,
-            const Vector2& texturePos3 );
+            const Vector2& texturePos3 )
+    {
+        glBegin( GL_TRIANGLE_STRIP );
+            glTexCoord2f( texturePos0.x, texturePos0.y );
+            glVertex2f( vertexPos0.x, vertexPos0.y );
+            glTexCoord2f( texturePos1.x, texturePos1.y );
+            glVertex2f( vertexPos1.x, vertexPos1.y );
+            glTexCoord2f( texturePos3.x, texturePos3.y );
+            glVertex2f( vertexPos3.x, vertexPos3.y );
+            glTexCoord2f( texturePos2.x, texturePos2.y );
+            glVertex2f( vertexPos2.x, vertexPos2.y );
+        glEnd();
+    }
 
 
     /// Flush (render) any pending batches with a reason metric.
     /// Flush (render) any pending batches with a reason metric.
     void flush( U32& reasonMetric );
     void flush( U32& reasonMetric );
@@ -212,38 +289,8 @@ private:
     /// Flush (render) any pending batches.
     /// Flush (render) any pending batches.
     void flushInternal( void );
     void flushInternal( void );
 
 
-private:
-    typedef Vector<U32> indexVectorType;
-    typedef HashMap<U32, indexVectorType*> textureBatchType;
-
-    VectorPtr< indexVectorType* > mIndexVectorPool;
-    textureBatchType    mTextureBatchMap;
-
-    const ColorF        NoColor;
-
-    Vector2             mVertexBuffer[ BATCHRENDER_BUFFERSIZE ];
-    Vector2             mTextureBuffer[ BATCHRENDER_BUFFERSIZE ];
-    U16                 mIndexBuffer[ BATCHRENDER_BUFFERSIZE ];
-    ColorF              mColorBuffer[ BATCHRENDER_BUFFERSIZE ];
-   
-    U32                 mQuadCount;
-    U32                 mVertexCount;
-    U32                 mTextureResidentCount;
-    U32                 mIndexCount;
-    U32                 mColorCount;
-
-    bool                mBlendMode;
-    GLenum              mSrcBlendFactor;
-    GLenum              mDstBlendFactor;
-    ColorF              mBlendColor;
-    F32                 mAlphaTestMode;
-
-    bool                mStrictOrderMode;
-    TextureHandle       mStrictOrderTextureHandle;
-    DebugStats*         mpDebugStats;
-
-    bool                mWireframeMode;
-    bool                mBatchEnabled;
+    /// Find texture batch.
+    indexVectorType* findTextureBatch( TextureHandle& handle );
 };
 };
 
 
 #endif
 #endif

+ 2 - 3
engine/source/2d/gui/SceneWindow.cc

@@ -1866,13 +1866,12 @@ void SceneWindow::renderMetricsOverlay( Point2I offset, const RectI& updateRect
 
 
         // Batching #1.
         // Batching #1.
         dglDrawText( font, bannerOffset + Point2I(0,(S32)linePositionY), "Batching", NULL );
         dglDrawText( font, bannerOffset + Point2I(0,(S32)linePositionY), "Batching", NULL );
-        dSprintf( mDebugText, sizeof( mDebugText ), "- %sTris=%d<%d>, MaxTriDraw=%d, MaxVerts=%d, Single=%d<%d>, Mult=%d<%d>, Sorted=%d<%d>",
+        dSprintf( mDebugText, sizeof( mDebugText ), "- %sTris=%d<%d>, MaxTriDraw=%d, MaxVerts=%d, Strict=%d<%d>, Sorted=%d<%d>",
             pScene->getBatchingEnabled() ? "" : "(OFF) ",
             pScene->getBatchingEnabled() ? "" : "(OFF) ",
             debugStats.batchTrianglesSubmitted, debugStats.maxBatchTrianglesSubmitted,
             debugStats.batchTrianglesSubmitted, debugStats.maxBatchTrianglesSubmitted,
             debugStats.batchMaxTriangleDrawn,
             debugStats.batchMaxTriangleDrawn,
             debugStats.batchMaxVertexBuffer,
             debugStats.batchMaxVertexBuffer,
-            debugStats.batchDrawCallsStrictSingle, debugStats.maxBatchDrawCallsStrictSingle,
-            debugStats.batchDrawCallsStrictMultiple, debugStats.maxBatchDrawCallsStrictMultiple,
+            debugStats.batchDrawCallsStrict, debugStats.maxBatchDrawCallsStrict,
             debugStats.batchDrawCallsSorted, debugStats.maxBatchDrawCallsSorted                   
             debugStats.batchDrawCallsSorted, debugStats.maxBatchDrawCallsSorted                   
             );
             );
         dglDrawText( font, bannerOffset + Point2I(metricsOffset,(S32)linePositionY), mDebugText, NULL );
         dglDrawText( font, bannerOffset + Point2I(metricsOffset,(S32)linePositionY), mDebugText, NULL );

+ 5 - 12
engine/source/2d/scene/DebugStats.h

@@ -81,8 +81,7 @@ public:
 
 
         // Batching.
         // Batching.
         if ( batchTrianglesSubmitted > maxBatchTrianglesSubmitted ) maxBatchTrianglesSubmitted = batchTrianglesSubmitted;
         if ( batchTrianglesSubmitted > maxBatchTrianglesSubmitted ) maxBatchTrianglesSubmitted = batchTrianglesSubmitted;
-        if ( batchDrawCallsStrictSingle > maxBatchDrawCallsStrictSingle ) maxBatchDrawCallsStrictSingle = batchDrawCallsStrictSingle;
-        if ( batchDrawCallsStrictMultiple > maxBatchDrawCallsStrictMultiple ) maxBatchDrawCallsStrictMultiple = batchDrawCallsStrictMultiple;
+        if ( batchDrawCallsStrict > maxBatchDrawCallsStrict ) maxBatchDrawCallsStrict = batchDrawCallsStrict;
         if ( batchDrawCallsSorted > maxBatchDrawCallsSorted ) maxBatchDrawCallsSorted = batchDrawCallsSorted;
         if ( batchDrawCallsSorted > maxBatchDrawCallsSorted ) maxBatchDrawCallsSorted = batchDrawCallsSorted;
         if ( batchFlushes > maxBatchFlushes ) maxBatchFlushes = batchFlushes;
         if ( batchFlushes > maxBatchFlushes ) maxBatchFlushes = batchFlushes;
         if ( batchBlendStateFlush > maxBatchBlendStateFlush ) maxBatchBlendStateFlush = batchBlendStateFlush;
         if ( batchBlendStateFlush > maxBatchBlendStateFlush ) maxBatchBlendStateFlush = batchBlendStateFlush;
@@ -151,11 +150,8 @@ public:
         batchMaxVertexBuffer = 0;
         batchMaxVertexBuffer = 0;
         batchMaxTriangleDrawn = 0;
         batchMaxTriangleDrawn = 0;
 
 
-        batchDrawCallsStrictSingle = 0;
-        maxBatchDrawCallsStrictSingle = 0;
-
-        batchDrawCallsStrictMultiple = 0;
-        maxBatchDrawCallsStrictMultiple = 0;
+        batchDrawCallsStrict = 0;
+        maxBatchDrawCallsStrict = 0;
 
 
         batchDrawCallsSorted = 0;
         batchDrawCallsSorted = 0;
         maxBatchDrawCallsSorted = 0;
         maxBatchDrawCallsSorted = 0;
@@ -244,11 +240,8 @@ public:
     U32     batchMaxVertexBuffer;
     U32     batchMaxVertexBuffer;
     U32     batchMaxTriangleDrawn;
     U32     batchMaxTriangleDrawn;
 
 
-    U32     batchDrawCallsStrictSingle;
-    U32     maxBatchDrawCallsStrictSingle;
-
-    U32     batchDrawCallsStrictMultiple;
-    U32     maxBatchDrawCallsStrictMultiple;
+    U32     batchDrawCallsStrict;
+    U32     maxBatchDrawCallsStrict;
 
 
     U32     batchDrawCallsSorted;
     U32     batchDrawCallsSorted;
     U32     maxBatchDrawCallsSorted;
     U32     maxBatchDrawCallsSorted;

+ 1 - 2
engine/source/2d/scene/Scene.cc

@@ -954,8 +954,7 @@ void Scene::sceneRender( const SceneRenderState* pSceneRenderState )
     pDebugStats->renderRequests                 = 0;
     pDebugStats->renderRequests                 = 0;
     pDebugStats->renderFallbacks                = 0;
     pDebugStats->renderFallbacks                = 0;
     pDebugStats->batchTrianglesSubmitted        = 0;
     pDebugStats->batchTrianglesSubmitted        = 0;
-    pDebugStats->batchDrawCallsStrictSingle     = 0;
-    pDebugStats->batchDrawCallsStrictMultiple   = 0;
+    pDebugStats->batchDrawCallsStrict           = 0;
     pDebugStats->batchDrawCallsSorted           = 0;
     pDebugStats->batchDrawCallsSorted           = 0;
     pDebugStats->batchFlushes                   = 0;
     pDebugStats->batchFlushes                   = 0;
     pDebugStats->batchBlendStateFlush           = 0;
     pDebugStats->batchBlendStateFlush           = 0;