Get Batch and Triangle count
-
xrgo
- OGRE Expert User

- Posts: 1148
- Joined: Sat Jul 06, 2013 10:59 pm
- Location: Chile
- x 169
Get Batch and Triangle count
Hello! I am not sure if this is something related with Ogre 2.0+.
I am having problems getting current batch and triangle count
I remember while ago (dont remember what ogre version) using this code worked for me:
renderWindow->getStatistics().triangleCount;
renderWindow->getStatistics().batchCount;
or this one
renderWindow->getTriangleCount();
renderWindow->getBatchCount();
but now its always 0
whats the correct way to get this values now??
Thanks in advance!
I am having problems getting current batch and triangle count
I remember while ago (dont remember what ogre version) using this code worked for me:
renderWindow->getStatistics().triangleCount;
renderWindow->getStatistics().batchCount;
or this one
renderWindow->getTriangleCount();
renderWindow->getBatchCount();
but now its always 0
whats the correct way to get this values now??
Thanks in advance!
- dark_sylinc
- OGRE Team Member

- Posts: 5588
- Joined: Sat Jul 21, 2007 4:55 pm
- Location: Buenos Aires, Argentina
- x 1413
- Contact:
Re: Get Batch and Triangle count
This feature just hasn't been implemented yet
We probably should gather the statistics in RenderQueue::renderXX, using the recently deleted VertexArrayObject::mFaceCount variable (should be renamed to mTriangleCount), see VertexArrayObject::VertexArrayObject's commented code.
However "batch" count is now outdated, since it doesn't make sense now.
A more useful statistic would be to gather the number of draws (one Renderable = one draw), and the number of API draw calls (RenderSystem-specific).
We probably should gather the statistics in RenderQueue::renderXX, using the recently deleted VertexArrayObject::mFaceCount variable (should be renamed to mTriangleCount), see VertexArrayObject::VertexArrayObject's commented code.
However "batch" count is now outdated, since it doesn't make sense now.
A more useful statistic would be to gather the number of draws (one Renderable = one draw), and the number of API draw calls (RenderSystem-specific).
- TaaTT4
- OGRE Contributor

- Posts: 267
- Joined: Wed Apr 23, 2014 3:49 pm
- Location: Bologna, Italy
- x 75
- Contact:
Re: Get Batch and Triangle count
Has been any progress on this topic? I'd like to see triangles and draw calls count in real time. I'd prefer to collect these data directly from OGRE, but I'm also open to a 3rd party tool. Since I've never used it before, does Remotery provide these info?
Senior programmer at 505 Games; former senior engine programmer at Sandbox Games
Worked on: Racecraft Esport — Racecraft Coin-Op, Victory: The Age of Racing
-
al2950
- OGRE Expert User

- Posts: 1227
- Joined: Thu Dec 11, 2008 7:56 pm
- Location: Bristol, UK
- x 157
Re: Get Batch and Triangle count
I find these numbers a little tricky in a modern engine architecture. Especially when a customer places a requirement on something like triangle limit, that would have made sense in 2005!
Having said that some things can be useful, and I use render doc which gives a really good breakdown of not only the draw calls, but resource binding calls, shader sets, etc, as well as mem usage. Just need to capture a frame and go to Window->Statistics Viewer.
The only thing it does not do is the number of ogre renderables (for obvious reasons!), due to ogre batching, but to be honest thats not that useful.
Having said that some things can be useful, and I use render doc which gives a really good breakdown of not only the draw calls, but resource binding calls, shader sets, etc, as well as mem usage. Just need to capture a frame and go to Window->Statistics Viewer.
The only thing it does not do is the number of ogre renderables (for obvious reasons!), due to ogre batching, but to be honest thats not that useful.
- TaaTT4
- OGRE Contributor

- Posts: 267
- Joined: Wed Apr 23, 2014 3:49 pm
- Location: Bologna, Italy
- x 75
- Contact:
Re: Get Batch and Triangle count
I could disagree this... Both Unity and Unreal Engine show that old-generation statsal2950 wrote: Mon Oct 28, 2019 5:08 pm I find these numbers a little tricky in a modern engine architecture.
I use Renderdoc too, but the "problem" is that it doesn't work in realtime (you have to dump a frame and then analyze it). Instead I'd like to have a preview of what's happening under the hood (eg draw calls count) so I can track where the issues reside and then inspect them in deep with Renderdoc.al2950 wrote: Mon Oct 28, 2019 5:08 pm I use render doc which gives a really good breakdown of not only the draw calls, but resource binding calls, shader sets, etc, as well as mem usage. Just need to capture a frame and go to Window->Statistics Viewer.
Senior programmer at 505 Games; former senior engine programmer at Sandbox Games
Worked on: Racecraft Esport — Racecraft Coin-Op, Victory: The Age of Racing
-
al2950
- OGRE Expert User

- Posts: 1227
- Joined: Thu Dec 11, 2008 7:56 pm
- Location: Bristol, UK
- x 157
Re: Get Batch and Triangle count
Fair enough!
- dark_sylinc
- OGRE Team Member

- Posts: 5588
- Joined: Sat Jul 21, 2007 4:55 pm
- Location: Buenos Aires, Argentina
- x 1413
- Contact:
Re: Get Batch and Triangle count
To anyone interested in contributing, RenderQueue::renderGL3 & co. perform main rendering.
The main values to consider are in vao->mPrimCount and instanceCount.
Save the value of vao->mPrimCount and instanceCount. When a new mesh is encountered, add to the stats: accumulatedStats += primCount * instanceCount;
Just don't read from drawStripPtr/drawIndexedPtr/drawCountPtr because that pointer may be write-combined.
The main values to consider are in vao->mPrimCount and instanceCount.
Save the value of vao->mPrimCount and instanceCount. When a new mesh is encountered, add to the stats: accumulatedStats += primCount * instanceCount;
Just don't read from drawStripPtr/drawIndexedPtr/drawCountPtr because that pointer may be write-combined.
-
rujialiu
- Goblin
- Posts: 296
- Joined: Mon May 09, 2016 8:21 am
- x 35
Re: Get Batch and Triangle count
I'm following your suggestions but I need further helpdark_sylinc wrote: Wed Oct 30, 2019 3:26 pm To anyone interested in contributing, RenderQueue::renderGL3 & co. perform main rendering.
The main values to consider are in vao->mPrimCount and instanceCount.
Save the value of vao->mPrimCount and instanceCount. When a new mesh is encountered, add to the stats: accumulatedStats += primCount * instanceCount;
Just don't read from drawStripPtr/drawIndexedPtr/drawCountPtr because that pointer may be write-combined.
I added a RenderSystem parameter to both renderGL3 and renderGL3V1 and also add _setFaceCount etc to RenderSystem, but:
* I don't know how to get vertex count
* In the ??? place, I don't know whether/how should I update face count.
* I know "batch count" is a bad name now, but in order to re-use the current interface, I'm increasing the batch count when setting a new Pso. Is it useful and are there other places that I should modify?
Code: Select all
OgreMain/include/OgreRenderQueue.h | 4 ++--
OgreMain/include/OgreRenderSystem.h | 4 ++++
OgreMain/src/OgreRenderQueue.cpp | 16 ++++++++++++----
OgreMain/src/OgreRenderSystem.cpp | 13 +++++++++++++
4 files changed, 31 insertions(+), 6 deletions(-)
diff --git a/OgreMain/include/OgreRenderQueue.h b/OgreMain/include/OgreRenderQueue.h
index 6427ed2..dc3c9a4 100644
--- a/OgreMain/include/OgreRenderQueue.h
+++ b/OgreMain/include/OgreRenderQueue.h
@@ -180,12 +180,12 @@ namespace Ogre {
/// Renders in a compatible way with GL 3.3 and D3D11. Can only render V2 objects
/// (i.e. Items, VertexArrayObject)
- unsigned char* renderGL3( bool casterPass, bool dualParaboloid,
+ unsigned char* renderGL3( RenderSystem *rs, bool casterPass, bool dualParaboloid,
HlmsCache passCache[],
const RenderQueueGroup &renderQueueGroup,
IndirectBufferPacked *indirectBuffer,
unsigned char *indirectDraw, unsigned char *startIndirectDraw );
- void renderGL3V1( bool casterPass, bool dualParaboloid,
+ void renderGL3V1( RenderSystem *rs, bool casterPass, bool dualParaboloid,
HlmsCache passCache[],
const RenderQueueGroup &renderQueueGroup );
diff --git a/OgreMain/include/OgreRenderSystem.h b/OgreMain/include/OgreRenderSystem.h
index dd50098..b0c6966 100644
--- a/OgreMain/include/OgreRenderSystem.h
+++ b/OgreMain/include/OgreRenderSystem.h
@@ -912,6 +912,10 @@ namespace Ogre
/** Reports the number of vertices passed to the renderer since the last _beginGeometryCount call. */
virtual unsigned int _getVertexCount(void) const;
+ virtual void _setFaceCount(unsigned int v);
+ virtual void _setBatchCount(unsigned int v);
+ virtual void _setVertexCount(unsigned int v);
+
/** Generates a packed data version of the passed in ColourValue suitable for
use as with this RenderSystem.
@remarks
diff --git a/OgreMain/src/OgreRenderQueue.cpp b/OgreMain/src/OgreRenderQueue.cpp
index decd154..d410023 100644
--- a/OgreMain/src/OgreRenderQueue.cpp
+++ b/OgreMain/src/OgreRenderQueue.cpp
@@ -441,11 +441,11 @@ namespace Ogre
v1::CbStartV1LegacyRendering();
mLastVaoName = 0;
}
- renderGL3V1( casterPass, dualParaboloid, mPassCache, mRenderQueues[i] );
+ renderGL3V1( rs, casterPass, dualParaboloid, mPassCache, mRenderQueues[i] );
}
else if( numNeededDraws > 0 /*&& mRenderQueues[i].mMode == FAST*/ )
{
- indirectDraw = renderGL3( casterPass, dualParaboloid, mPassCache, mRenderQueues[i],
+ indirectDraw = renderGL3( rs, casterPass, dualParaboloid, mPassCache, mRenderQueues[i],
indirectBuffer, indirectDraw, startIndirectDraw );
}
}
@@ -543,7 +543,7 @@ namespace Ogre
mLastTextureHash = lastTextureHash;
}
//-----------------------------------------------------------------------
- unsigned char* RenderQueue::renderGL3( bool casterPass, bool dualParaboloid, HlmsCache passCache[],
+ unsigned char* RenderQueue::renderGL3(RenderSystem *rs, bool casterPass, bool dualParaboloid, HlmsCache passCache[],
const RenderQueueGroup &renderQueueGroup,
IndirectBufferPacked *indirectBuffer,
unsigned char *indirectDraw,
@@ -598,6 +598,9 @@ namespace Ogre
//Flush the Vao when changing shaders. Needed by D3D11/12 & possibly Vulkan
lastVaoName = 0;
+
+ int b = rs->_getBatchCount();
+ rs->_setBatchCount(b + 1);
}
uint32 baseInstance = hlms->fillBuffersForV2( hlmsCache, queuedRenderable, casterPass,
@@ -670,6 +673,9 @@ namespace Ogre
instanceCount = instancesPerDraw;
}
+ // vc???
+ int fc = rs->_getFaceCount();
+ rs->_setFaceCount(fc + vao->mPrimCount * instancesPerDraw);
lastVao = vao;
}
@@ -679,6 +685,8 @@ namespace Ogre
//an external variable, as the region can be write-combined
instanceCount += instancesPerDraw;
drawCountPtr->instanceCount = instanceCount;
+
+ //????
}
++itor;
@@ -692,7 +700,7 @@ namespace Ogre
return indirectDraw;
}
//-----------------------------------------------------------------------
- void RenderQueue::renderGL3V1( bool casterPass, bool dualParaboloid,
+ void RenderQueue::renderGL3V1( RenderSystem *rs, bool casterPass, bool dualParaboloid,
HlmsCache passCache[],
const RenderQueueGroup &renderQueueGroup )
{
diff --git a/OgreMain/src/OgreRenderSystem.cpp b/OgreMain/src/OgreRenderSystem.cpp
index 7426866..76f302f 100644
--- a/OgreMain/src/OgreRenderSystem.cpp
+++ b/OgreMain/src/OgreRenderSystem.cpp
@@ -693,6 +693,19 @@ namespace Ogre {
{
return static_cast< unsigned int >( mVertexCount );
}
+
+ void RenderSystem::_setFaceCount(unsigned int v) {
+ mFaceCount = v;
+ }
+
+ void RenderSystem::_setBatchCount(unsigned int v) {
+ mBatchCount = v;
+ }
+
+ void RenderSystem::_setVertexCount(unsigned int v) {
+ mVertexCount = v;
+ }
+
//-----------------------------------------------------------------------
void RenderSystem::convertColourValue(const ColourValue& colour, uint32* pDest)
{
-
rujialiu
- Goblin
- Posts: 296
- Joined: Mon May 09, 2016 8:21 am
- x 35
Re: Get Batch and Triangle count
Also, when finding places to accumate face count, I found that in D3D11 VaoManager is initialized this way:
So _supportsIndirectBuffers is always false. What's this?
Code: Select all
mVaoManager = OGRE_NEW D3D11VaoManager( false, mDevice, this, miscParams );
- dark_sylinc
- OGRE Team Member

- Posts: 5588
- Joined: Sat Jul 21, 2007 4:55 pm
- Location: Buenos Aires, Argentina
- x 1413
- Contact:
Re: Get Batch and Triangle count
Your changes to get tri, face and instance count is welcomed.
However your changes are very inneficient.
Keep a counter in the stack, and at the end of the function call renderSystem->_setFaceCount & co.
Otherwise you're needlessly calling getters and setters a lot to perform a simple addition.
However your changes are very inneficient.
Keep a counter in the stack, and at the end of the function call renderSystem->_setFaceCount & co.
Otherwise you're needlessly calling getters and setters a lot to perform a simple addition.
See Dx11 Indirect buffers disabled..?rujialiu wrote: Fri Dec 13, 2019 5:31 am Also, when finding places to accumate face count, I found that in D3D11 VaoManager is initialized this way:So _supportsIndirectBuffers is always false. What's this?Code: Select all
mVaoManager = OGRE_NEW D3D11VaoManager( false, mDevice, this, miscParams );
- SolarPortal
- OGRE Contributor

- Posts: 203
- Joined: Sat Jul 16, 2011 8:29 pm
- Location: UK
- x 51
- Contact:
Re: Get Batch and Triangle count [2.2]
sorry to drag up an older topic, but I recently had a go at this myself on 2.2 and got some good results from it. So thought id share my changes. Its not using setters and getters like the other persons and increases the reference counter directly and so far i have not encountered any performance changes.
Main changes are in OgreRenderQueue.cpp, in renderGL3 and renderGL3V1 more specifically.
Just added the functions directly here: (++ marks the addition)
Added a couple more utility functions to OgreRenderSystem.cpp, some which were there. I didnt use batch count because as you said before
CPP
H
Hope this helps someone 
Main changes are in OgreRenderQueue.cpp, in renderGL3 and renderGL3V1 more specifically.
Just added the functions directly here: (++ marks the addition)
Code: Select all
unsigned char* RenderQueue::renderGL3( RenderSystem* renderSystem, bool casterPass, bool dualParaboloid, HlmsCache passCache[],
const RenderQueueGroup &renderQueueGroup,
IndirectBufferPacked *indirectBuffer,
unsigned char *indirectDraw,
unsigned char *startIndirectDraw )
{
VertexArrayObject *lastVao = 0;
uint32 lastVaoName = mLastVaoName;
HlmsCache const *lastHlmsCache = &c_dummyCache;
uint32 lastHlmsCacheHash = 0;
int baseInstanceAndIndirectBuffers = 0;
if( mVaoManager->supportsIndirectBuffers() )
baseInstanceAndIndirectBuffers = 2;
else if( mVaoManager->supportsBaseInstance() )
baseInstanceAndIndirectBuffers = 1;
const bool isUsingInstancedStereo = mSceneManager->isUsingInstancedStereo();
const uint32 instancesPerDraw = isUsingInstancedStereo ? 2u : 1u;
const uint32 baseInstanceShift = isUsingInstancedStereo ? 1u : 0u;
uint32 instanceCount = instancesPerDraw;
CbDrawCall *drawCmd = 0;
CbSharedDraw *drawCountPtr = 0;
const QueuedRenderableArray &queuedRenderables = renderQueueGroup.mQueuedRenderables;
QueuedRenderableArray::const_iterator itor = queuedRenderables.begin();
QueuedRenderableArray::const_iterator end = queuedRenderables.end();
++ size_t &storeInstances = renderSystem->_getInstanceCountRef();
++ size_t &storeTris = renderSystem->_getFacesCountRef();
++ size_t &storeVertices = renderSystem->_getVertexCountRef();
++ size_t &storeDraws = renderSystem->_getDrawCountRef();
while( itor != end )
{
const QueuedRenderable &queuedRenderable = *itor;
uint8 meshLod = queuedRenderable.movableObject->getCurrentMeshLod();
const VertexArrayObjectArray &vaos = queuedRenderable.renderable->getVaos(
static_cast<VertexPass>(casterPass) );
VertexArrayObject *vao = vaos[meshLod];
const HlmsDatablock *datablock = queuedRenderable.renderable->getDatablock();
Hlms *hlms = mHlmsManager->getHlms( static_cast<HlmsTypes>( datablock->mType ) );
lastHlmsCacheHash = lastHlmsCache->hash;
const HlmsCache *hlmsCache = hlms->getMaterial( lastHlmsCache,
passCache[datablock->mType],
queuedRenderable,
casterPass );
if( lastHlmsCacheHash != hlmsCache->hash )
{
CbPipelineStateObject *psoCmd = mCommandBuffer->addCommand<CbPipelineStateObject>();
*psoCmd = CbPipelineStateObject( &hlmsCache->pso );
lastHlmsCache = hlmsCache;
//Flush the Vao when changing shaders. Needed by D3D11/12 & possibly Vulkan
lastVaoName = 0;
}
uint32 baseInstance = hlms->fillBuffersForV2( hlmsCache, queuedRenderable, casterPass,
lastHlmsCacheHash, mCommandBuffer );
if( drawCmd != mCommandBuffer->getLastCommand() ||
lastVaoName != vao->getVaoName() )
{
//Different mesh, vertex buffers or layout. Make a new draw call.
//(or also the the Hlms made a batch-breaking command)
if( lastVaoName != vao->getVaoName() )
{
*mCommandBuffer->addCommand<CbVao>() = CbVao( vao );
*mCommandBuffer->addCommand<CbIndirectBuffer>() =
CbIndirectBuffer( indirectBuffer );
lastVaoName = vao->getVaoName();
}
void *offset = reinterpret_cast<void*>( indirectBuffer->_getFinalBufferStart() +
(indirectDraw - startIndirectDraw) );
if( vao->getIndexBuffer() )
{
CbDrawCallIndexed *drawCall = mCommandBuffer->addCommand<CbDrawCallIndexed>();
*drawCall = CbDrawCallIndexed( baseInstanceAndIndirectBuffers, vao, offset );
drawCmd = drawCall;
}
else
{
CbDrawCallStrip *drawCall = mCommandBuffer->addCommand<CbDrawCallStrip>();
*drawCall = CbDrawCallStrip( baseInstanceAndIndirectBuffers, vao, offset );
drawCmd = drawCall;
}
lastVao = 0;
++ storeDraws += 1;
}
if( lastVao != vao )
{
//Different mesh, but same vertex buffers & layouts. Advance indirection buffer.
++drawCmd->numDraws;
if( vao->mIndexBuffer )
{
CbDrawIndexed *drawIndexedPtr = reinterpret_cast<CbDrawIndexed*>( indirectDraw );
indirectDraw += sizeof( CbDrawIndexed );
drawCountPtr = drawIndexedPtr;
drawIndexedPtr->primCount = vao->mPrimCount;
drawIndexedPtr->instanceCount = instancesPerDraw;
drawIndexedPtr->firstVertexIndex= vao->mIndexBuffer->_getFinalBufferStart() +
vao->mPrimStart;
drawIndexedPtr->baseVertex = vao->mBaseVertexBuffer->_getFinalBufferStart();
drawIndexedPtr->baseInstance = baseInstance << baseInstanceShift;
instanceCount = instancesPerDraw;
}
else
{
CbDrawStrip *drawStripPtr = reinterpret_cast<CbDrawStrip*>( indirectDraw );
indirectDraw += sizeof( CbDrawStrip );
drawCountPtr = drawStripPtr;
drawStripPtr->primCount = vao->mPrimCount;
drawStripPtr->instanceCount = instancesPerDraw;
drawStripPtr->firstVertexIndex = vao->mBaseVertexBuffer->_getFinalBufferStart() +
vao->mPrimStart;
drawStripPtr->baseInstance = baseInstance << baseInstanceShift;
instanceCount = instancesPerDraw;
}
lastVao = vao;
++ storeInstances += 1;
}
else
{
//Same mesh. Just go with instancing. Keep the counter in
//an external variable, as the region can be write-combined
instanceCount += instancesPerDraw;
drawCountPtr->instanceCount = instanceCount;
++ storeInstances += instancesPerDraw;
}
++ // Store the information from frame to buffer.
++ if(renderSystem->isRecordingMetrics())
++ {
++ const Ogre::OperationType &type = vao->getOperationType();
++ if (type == Ogre::OperationType::OT_TRIANGLE_STRIP || type == Ogre::OperationType::OT_TRIANGLE_LIST)
++ storeTris += (vao->mPrimCount / 3) * instancesPerDraw;
++
++ storeVertices += vao->mPrimCount * instancesPerDraw;
++ }
++itor;
}
mLastVaoName = lastVaoName;
mLastVertexData = 0;
mLastIndexData = 0;
mLastTextureHash = 0;
return indirectDraw;
}
//-----------------------------------------------------------------------
void RenderQueue::renderGL3V1( RenderSystem* renderSystem, bool casterPass, bool dualParaboloid,
HlmsCache passCache[],
const RenderQueueGroup &renderQueueGroup )
{
v1::RenderOperation lastRenderOp;
HlmsCache const *lastHlmsCache = &c_dummyCache;
uint32 lastHlmsCacheHash = 0;
const bool supportsBaseInstance = mVaoManager->supportsBaseInstance();
const bool isUsingInstancedStereo = mSceneManager->isUsingInstancedStereo();
const uint32 instancesPerDraw = isUsingInstancedStereo ? 2u : 1u;
const uint32 baseInstanceShift = isUsingInstancedStereo ? 1u : 0u;
uint32 instanceCount = instancesPerDraw;
v1::CbDrawCall *drawCmd = 0;
const QueuedRenderableArray &queuedRenderables = renderQueueGroup.mQueuedRenderables;
QueuedRenderableArray::const_iterator itor = queuedRenderables.begin();
QueuedRenderableArray::const_iterator end = queuedRenderables.end();
++ size_t &storeInstances = renderSystem->_getInstanceCountRef();
++ size_t &storeTris = renderSystem->_getFacesCountRef();
++ size_t &storeDraws = renderSystem->_getDrawCountRef();
++ size_t &storeVertices = renderSystem->_getVertexCountRef();
while( itor != end )
{
const QueuedRenderable &queuedRenderable = *itor;
const HlmsDatablock *datablock = queuedRenderable.renderable->getDatablock();
v1::RenderOperation renderOp;
queuedRenderable.renderable->getRenderOperation(
renderOp, casterPass & (datablock->getAlphaTest() == CMPF_ALWAYS_PASS) );
Hlms *hlms = mHlmsManager->getHlms( static_cast<HlmsTypes>( datablock->mType ) );
lastHlmsCacheHash = lastHlmsCache->hash;
const HlmsCache *hlmsCache = hlms->getMaterial( lastHlmsCache,
passCache[datablock->mType],
queuedRenderable, casterPass );
if( lastHlmsCache != hlmsCache )
{
CbPipelineStateObject *psoCmd = mCommandBuffer->addCommand<CbPipelineStateObject>();
*psoCmd = CbPipelineStateObject( &hlmsCache->pso );
lastHlmsCache = hlmsCache;
//Flush the RenderOp when changing shaders. Needed by D3D11/12 & possibly Vulkan
lastRenderOp.vertexData = 0;
lastRenderOp.indexData = 0;
}
uint32 baseInstance = hlms->fillBuffersForV1( hlmsCache, queuedRenderable, casterPass,
lastHlmsCacheHash, mCommandBuffer );
bool differentRenderOp = lastRenderOp.vertexData != renderOp.vertexData ||
lastRenderOp.indexData != renderOp.indexData ||
lastRenderOp.operationType != renderOp.operationType ||
lastRenderOp.useGlobalInstancingVertexBufferIsAvailable !=
renderOp.useGlobalInstancingVertexBufferIsAvailable;
if( drawCmd != mCommandBuffer->getLastCommand() || differentRenderOp ||
renderOp.numberOfInstances != 1 )
{
//Different mesh, vertex buffers or layout. If instanced, entities
//likely use their own low level materials. Make a new draw call.
//(or also the the Hlms made a batch-breaking command)
if( differentRenderOp )
{
*mCommandBuffer->addCommand<v1::CbRenderOp>() = v1::CbRenderOp( renderOp );
lastRenderOp = renderOp;
}
if( renderOp.useIndexes )
{
v1::CbDrawCallIndexed *drawCall =
mCommandBuffer->addCommand<v1::CbDrawCallIndexed>();
*drawCall = v1::CbDrawCallIndexed( supportsBaseInstance );
/*drawCall->useGlobalInstancingVertexBufferIsAvailable =
renderOp.useGlobalInstancingVertexBufferIsAvailable;*/
drawCall->primCount = renderOp.indexData->indexCount;
drawCall->instanceCount = instancesPerDraw;
drawCall->firstVertexIndex = renderOp.indexData->indexStart;
drawCall->baseInstance = baseInstance << baseInstanceShift;
instanceCount = instancesPerDraw;
drawCmd = drawCall;
}
else
{
v1::CbDrawCallStrip *drawCall =
mCommandBuffer->addCommand<v1::CbDrawCallStrip>();
*drawCall = v1::CbDrawCallStrip( supportsBaseInstance );
/*drawCall->useGlobalInstancingVertexBufferIsAvailable =
renderOp.useGlobalInstancingVertexBufferIsAvailable;*/
drawCall->primCount = renderOp.vertexData->vertexCount;
drawCall->instanceCount = renderOp.numberOfInstances;
drawCall->firstVertexIndex = renderOp.vertexData->vertexStart;
drawCall->baseInstance = baseInstance << baseInstanceShift;
instanceCount = instancesPerDraw;
drawCmd = drawCall;
}
++ storeDraws += 1;
++ storeInstances += 1;
}
else
{
//Same mesh. Just go with instancing. Keep the counter in
//an external variable, as the region can be write-combined
instanceCount += instancesPerDraw;
drawCmd->instanceCount = instanceCount;
++ storeInstances += 1;
}
++ // Store the information from frame to buffer.
++ if (renderSystem->isRecordingMetrics())
++ {
++ if (renderOp.operationType == Ogre::OperationType::OT_TRIANGLE_STRIP || renderOp.operationType == Ogre::OperationType::OT_TRIANGLE_LIST)
++ storeTris += (renderOp.vertexData->vertexCount / 3) * instancesPerDraw;
++
++ storeVertices += renderOp.vertexData->vertexCount * instancesPerDraw;
++ }
++itor;
}
mLastVaoName = 0;
mLastVertexData = 0;
mLastIndexData = 0;
mLastTextureHash = 0;
}Added a couple more utility functions to OgreRenderSystem.cpp, some which were there. I didnt use batch count because as you said before
CPP
Code: Select all
, mIsRecordingMetrics(false)
, mBatchCount(0)
, mFaceCount(0)
, mVertexCount(0)
, mDrawCount(0)
, mInstanceCount(0)
...
//-----------------------------------------------------------------------
void RenderSystem::_beginGeometryCount(void)
{
mBatchCount = mFaceCount = mVertexCount = mDrawCount = mInstanceCount = 0;
}
//-----------------------------------------------------------------------
unsigned int RenderSystem::_getFaceCount(void) const
{
return static_cast< unsigned int >( mFaceCount );
}
//-----------------------------------------------------------------------
unsigned int RenderSystem::_getBatchCount(void) const
{
return static_cast< unsigned int >( mBatchCount );
}
//-----------------------------------------------------------------------
unsigned int RenderSystem::_getVertexCount(void) const
{
return static_cast< unsigned int >( mVertexCount );
}
//-----------------------------------------------------------------------
unsigned int RenderSystem::_getInstanceCount(void) const
{
return static_cast< unsigned int >(mInstanceCount);
}
//-----------------------------------------------------------------------
unsigned int RenderSystem::_getDrawCount(void) const
{
return static_cast<unsigned int>(mDrawCount);
}
//-----------------------------------------------------------------------
size_t &RenderSystem::_getInstanceCountRef(void)
{
return mInstanceCount;
}
//-----------------------------------------------------------------------
size_t &RenderSystem::_getFacesCountRef(void)
{
return mFaceCount;
}
//-----------------------------------------------------------------------
size_t &RenderSystem::_getBatchCountRef(void)
{
return mBatchCount;
}
//-----------------------------------------------------------------------
size_t &RenderSystem::_getVertexCountRef(void)
{
return mVertexCount;
}
//-----------------------------------------------------------------------
size_t &RenderSystem::_getDrawCountRef(void)
{
return mDrawCount;
}Code: Select all
bool mIsRecordingMetrics;
size_t mBatchCount;
size_t mFaceCount;
size_t mVertexCount;
size_t mDrawCount;
size_t mInstanceCount;
...
/** The RenderSystem will keep a count of tris rendered, this resets the count. */
virtual void _beginGeometryCount(void);
/** Reports the number of tris rendered since the last _beginGeometryCount call. */
virtual unsigned int _getFaceCount(void) const;
/** Reports the number of batches rendered since the last _beginGeometryCount call. */
virtual unsigned int _getBatchCount(void) const;
/** Reports the number of vertices passed to the renderer since the last _beginGeometryCount call. */
virtual unsigned int _getVertexCount(void) const;
/** Reports the number of vertices passed to the renderer since the last _beginGeometryCount call. */
virtual unsigned int _getInstanceCount(void) const;
/** Reports the number of vertices passed to the renderer since the last _beginGeometryCount call. */
virtual unsigned int _getDrawCount(void) const;
size_t& _getInstanceCountRef(void);
size_t& _getDrawCountRef(void);
size_t& _getFacesCountRef(void);
size_t& _getBatchCountRef(void);
size_t& _getVertexCountRef(void);Lead developer of the Skyline Game Engine: https://aurasoft-skyline.co.uk
- dark_sylinc
- OGRE Team Member

- Posts: 5588
- Joined: Sat Jul 21, 2007 4:55 pm
- Location: Buenos Aires, Argentina
- x 1413
- Contact:
Re: Get Batch and Triangle count [2.2]
Added! Thanks for your patch!SolarPortal wrote: Sun Jun 07, 2020 2:44 pm sorry to drag up an older topic, but I recently had a go at this myself on 2.2 and got some good results from it. So thought id share my changes. Its not using setters and getters like the other persons and increases the reference counter directly and so far i have not encountered any performance changes.
I modified it a bit:
- Rather than having a ton of getters, grouped everything into getMetrics()
- It's more efficient to have Metrics accumulate in the stack, then add everything at the end. This is because references force the compile on a slow path, because it must assume the variable could've changed between calls to code it cannot see. Thus it's always "load-increment-store", without even being able to coalesce loads or stores
- I'm not sure what's the objective of mIsRecordingMetrics, you were only using it to not record vertex & tri count. I set it to not record everything (functionally not equivalent) and the boolean is evaluated at the end rather than per iteration, in RenderSystem::_addMetrics
- SolarPortal
- OGRE Contributor

- Posts: 203
- Joined: Sat Jul 16, 2011 8:29 pm
- Location: UK
- x 51
- Contact:
Re: Get Batch and Triangle count
Brilliant
Thanks for the tips too
Simply to stop recording of metrics to make it a little bit faster at the expense of one conditional check. The reason i didnt include the others because they were lightweight enough and it would have taken more checks on those seperate pieces.I'm not sure what's the objective of mIsRecordingMetrics,
Thanks for the tips too
Lead developer of the Skyline Game Engine: https://aurasoft-skyline.co.uk