From fa4529b4f166a8ca160520c8867320fad7b5357b Mon Sep 17 00:00:00 2001 From: sfan5 Date: Tue, 27 Aug 2024 12:09:08 +0200 Subject: [PATCH] Keep stats on hw buffer uploads --- irr/include/IVideoDriver.h | 23 +++++++++++------------ irr/src/CFPSCounter.cpp | 35 ++--------------------------------- irr/src/CFPSCounter.h | 18 ++---------------- irr/src/CNullDriver.cpp | 17 +++++++---------- irr/src/CNullDriver.h | 14 ++++++++------ irr/src/COpenGLDriver.cpp | 4 ++++ irr/src/OpenGL/Driver.cpp | 25 ++++++++++++++----------- src/client/game.cpp | 5 +++++ 8 files changed, 53 insertions(+), 88 deletions(-) diff --git a/irr/include/IVideoDriver.h b/irr/include/IVideoDriver.h index 888e4a9f7..7b15fdd1b 100644 --- a/irr/include/IVideoDriver.h +++ b/irr/include/IVideoDriver.h @@ -114,6 +114,15 @@ const c8 *const FogTypeNames[] = { 0, }; +struct SFrameStats { + //! Count of primitives drawn + u32 PrimitivesDrawn = 0; + //! Number of hardware buffers uploaded (new or updated) + u32 HWBuffersUploaded = 0; + //! Sum of uploaded hardware buffer size + u32 HWBuffersUploadedSize = 0; +}; + //! Interface to driver which is able to perform 2d and 3d graphics functions. /** This interface is one of the most important interfaces of the Irrlicht Engine: All rendering and texture manipulation is done with @@ -194,12 +203,6 @@ public: */ virtual const io::IAttributes &getDriverAttributes() const = 0; - //! Check if the driver was recently reset. - /** For d3d devices you will need to recreate the RTTs if the - driver was reset. Should be queried right after beginScene(). - */ - virtual bool checkDriverReset() = 0; - //! Sets transformation matrices. /** \param state Transformation type to be set, e.g. view, world, or projection. @@ -855,12 +858,8 @@ public: \return Approximate amount of frames per second drawn. */ virtual s32 getFPS() const = 0; - //! Returns amount of primitives (mostly triangles) which were drawn in the last frame. - /** Together with getFPS() very useful method for statistics. - \param mode Defines if the primitives drawn are accumulated or - counted per frame. - \return Amount of primitives drawn in the last frame. */ - virtual u32 getPrimitiveCountDrawn(u32 mode = 0) const = 0; + //! Return some statistics about the last frame + virtual SFrameStats getFrameStats() const = 0; //! Gets name of this video driver. /** \return Returns the name of the video driver, e.g. in case diff --git a/irr/src/CFPSCounter.cpp b/irr/src/CFPSCounter.cpp index 6717df5c9..0542fc5cb 100644 --- a/irr/src/CFPSCounter.cpp +++ b/irr/src/CFPSCounter.cpp @@ -11,53 +11,22 @@ namespace video { CFPSCounter::CFPSCounter() : - FPS(60), Primitive(0), StartTime(0), FramesCounted(0), - PrimitivesCounted(0), PrimitiveAverage(0), PrimitiveTotal(0) + FPS(0), StartTime(0), FramesCounted(0) { } -//! returns current fps -s32 CFPSCounter::getFPS() const -{ - return FPS; -} - -//! returns current primitive count -u32 CFPSCounter::getPrimitive() const -{ - return Primitive; -} - -//! returns average primitive count of last period -u32 CFPSCounter::getPrimitiveAverage() const -{ - return PrimitiveAverage; -} - -//! returns accumulated primitive count since start -u32 CFPSCounter::getPrimitiveTotal() const -{ - return PrimitiveTotal; -} - //! to be called every frame -void CFPSCounter::registerFrame(u32 now, u32 primitivesDrawn) +void CFPSCounter::registerFrame(u32 now) { ++FramesCounted; - PrimitiveTotal += primitivesDrawn; - PrimitivesCounted += primitivesDrawn; - Primitive = primitivesDrawn; const u32 milliseconds = now - StartTime; - if (milliseconds >= 1500) { const f32 invMilli = core::reciprocal((f32)milliseconds); FPS = core::ceil32((1000 * FramesCounted) * invMilli); - PrimitiveAverage = core::ceil32((1000 * PrimitivesCounted) * invMilli); FramesCounted = 0; - PrimitivesCounted = 0; StartTime = now; } } diff --git a/irr/src/CFPSCounter.h b/irr/src/CFPSCounter.h index e73afb049..692aef6bd 100644 --- a/irr/src/CFPSCounter.h +++ b/irr/src/CFPSCounter.h @@ -17,29 +17,15 @@ public: CFPSCounter(); //! returns current fps - s32 getFPS() const; - - //! returns primitive count - u32 getPrimitive() const; - - //! returns average primitive count of last period - u32 getPrimitiveAverage() const; - - //! returns accumulated primitive count since start - u32 getPrimitiveTotal() const; + s32 getFPS() const { return FPS; } //! to be called every frame - void registerFrame(u32 now, u32 primitive); + void registerFrame(u32 now); private: s32 FPS; - u32 Primitive; u32 StartTime; - u32 FramesCounted; - u32 PrimitivesCounted; - u32 PrimitiveAverage; - u32 PrimitiveTotal; }; } // end namespace video diff --git a/irr/src/CNullDriver.cpp b/irr/src/CNullDriver.cpp index c1cecbe8c..054267711 100644 --- a/irr/src/CNullDriver.cpp +++ b/irr/src/CNullDriver.cpp @@ -53,7 +53,7 @@ public: //! constructor CNullDriver::CNullDriver(io::IFileSystem *io, const core::dimension2d &screenSize) : SharedRenderTarget(0), CurrentRenderTarget(0), CurrentRenderTargetSize(0, 0), FileSystem(io), MeshManipulator(0), - ViewPort(0, 0, 0, 0), ScreenSize(screenSize), PrimitivesDrawn(0), MinVertexCountForVBO(500), + ViewPort(0, 0, 0, 0), ScreenSize(screenSize), MinVertexCountForVBO(500), TextureCreationFlags(0), OverrideMaterial2DEnabled(false), AllowZWriteOnTransparent(false) { #ifdef _DEBUG @@ -222,13 +222,13 @@ void CNullDriver::deleteAllTextures() bool CNullDriver::beginScene(u16 clearFlag, SColor clearColor, f32 clearDepth, u8 clearStencil, const SExposedVideoData &videoData, core::rect *sourceRect) { - PrimitivesDrawn = 0; + FrameStats = {}; return true; } bool CNullDriver::endScene() { - FPSCounter.registerFrame(os::Timer::getRealTime(), PrimitivesDrawn); + FPSCounter.registerFrame(os::Timer::getRealTime()); updateAllHardwareBuffers(); updateAllOcclusionQueries(); return true; @@ -605,7 +605,7 @@ void CNullDriver::drawVertexPrimitiveList(const void *vertices, u32 vertexCount, { if ((iType == EIT_16BIT) && (vertexCount > 65536)) os::Printer::log("Too many vertices for 16bit index type, render artifacts may occur."); - PrimitivesDrawn += primitiveCount; + FrameStats.PrimitivesDrawn += primitiveCount; } //! draws a vertex primitive list in 2d @@ -613,7 +613,7 @@ void CNullDriver::draw2DVertexPrimitiveList(const void *vertices, u32 vertexCoun { if ((iType == EIT_16BIT) && (vertexCount > 65536)) os::Printer::log("Too many vertices for 16bit index type, render artifacts may occur."); - PrimitivesDrawn += primitiveCount; + FrameStats.PrimitivesDrawn += primitiveCount; } //! Draws a 3d line. @@ -743,12 +743,9 @@ s32 CNullDriver::getFPS() const return FPSCounter.getFPS(); } -//! returns amount of primitives (mostly triangles) were drawn in the last frame. -//! very useful method for statistics. -u32 CNullDriver::getPrimitiveCountDrawn(u32 param) const +SFrameStats CNullDriver::getFrameStats() const { - return (0 == param) ? FPSCounter.getPrimitive() : (1 == param) ? FPSCounter.getPrimitiveAverage() - : FPSCounter.getPrimitiveTotal(); + return FrameStats; } //! Sets the dynamic ambient light color. The default color is diff --git a/irr/src/CNullDriver.h b/irr/src/CNullDriver.h index 30911b7a6..302108a1b 100644 --- a/irr/src/CNullDriver.h +++ b/irr/src/CNullDriver.h @@ -195,9 +195,7 @@ public: // get current frames per second value s32 getFPS() const override; - //! returns amount of primitives (mostly triangles) were drawn in the last frame. - //! very useful method for statistics. - u32 getPrimitiveCountDrawn(u32 param = 0) const override; + SFrameStats getFrameStats() const override; //! \return Returns the name of the video driver. Example: In case of the DIRECT3D8 //! driver, it would return "Direct3D8.1". @@ -538,8 +536,6 @@ public: virtual void convertColor(const void *sP, ECOLOR_FORMAT sF, s32 sN, void *dP, ECOLOR_FORMAT dF) const override; - bool checkDriverReset() override { return false; } - protected: //! deletes all textures void deleteAllTextures(); @@ -570,6 +566,12 @@ protected: // prints renderer version void printVersion(); + inline void accountHWBufferUpload(u32 size) + { + FrameStats.HWBuffersUploaded++; + FrameStats.HWBuffersUploadedSize += size; + } + inline bool getWriteZBuffer(const SMaterial &material) const { switch (material.ZWriteEnable) { @@ -696,8 +698,8 @@ protected: core::matrix4 TransformationMatrix; CFPSCounter FPSCounter; + SFrameStats FrameStats; - u32 PrimitivesDrawn; u32 MinVertexCountForVBO; u32 TextureCreationFlags; diff --git a/irr/src/COpenGLDriver.cpp b/irr/src/COpenGLDriver.cpp index 1c6342090..875534a4e 100644 --- a/irr/src/COpenGLDriver.cpp +++ b/irr/src/COpenGLDriver.cpp @@ -266,6 +266,8 @@ bool COpenGLDriver::updateVertexHardwareBuffer(SHWBufferLink_opengl *HWBuffer) const E_VERTEX_TYPE vType = mb->getVertexType(); const u32 vertexSize = getVertexPitchFromType(vType); + accountHWBufferUpload(vertexSize * vertexCount); + const c8 *vbuf = static_cast(vertices); core::array buffer; if (!FeatureAvailable[IRR_ARB_vertex_array_bgra] && !FeatureAvailable[IRR_EXT_vertex_array_bgra]) { @@ -367,6 +369,8 @@ bool COpenGLDriver::updateIndexHardwareBuffer(SHWBufferLink_opengl *HWBuffer) } } + accountHWBufferUpload(indexCount * indexSize); + // get or create buffer bool newBuffer = false; if (!HWBuffer->vbo_indicesID) { diff --git a/irr/src/OpenGL/Driver.cpp b/irr/src/OpenGL/Driver.cpp index 1defa9abc..f681a3de9 100644 --- a/irr/src/OpenGL/Driver.cpp +++ b/irr/src/OpenGL/Driver.cpp @@ -255,10 +255,7 @@ bool COpenGL3DriverBase::genericDriverInit(const core::dimension2d &screenS DriverAttributes->setAttribute("MaxTextures", (s32)Feature.MaxTextureUnits); DriverAttributes->setAttribute("MaxSupportedTextures", (s32)Feature.MaxTextureUnits); - // DriverAttributes->setAttribute("MaxLights", MaxLights); DriverAttributes->setAttribute("MaxAnisotropy", MaxAnisotropy); - // DriverAttributes->setAttribute("MaxAuxBuffers", MaxAuxBuffers); - // DriverAttributes->setAttribute("MaxMultipleRenderTargets", MaxMultipleRenderTargets); DriverAttributes->setAttribute("MaxIndices", (s32)MaxIndices); DriverAttributes->setAttribute("MaxTextureSize", (s32)MaxTextureSize); DriverAttributes->setAttribute("MaxTextureLODBias", MaxTextureLODBias); @@ -493,6 +490,7 @@ bool COpenGL3DriverBase::updateVertexHardwareBuffer(SHWBufferLink_opengl *HWBuff const void *buffer = vertices; size_t bufferSize = vertexSize * vertexCount; + accountHWBufferUpload(bufferSize); // get or create buffer bool newBuffer = false; @@ -551,6 +549,9 @@ bool COpenGL3DriverBase::updateIndexHardwareBuffer(SHWBufferLink_opengl *HWBuffe } } + const size_t bufferSize = indexCount * indexSize; + accountHWBufferUpload(bufferSize); + // get or create buffer bool newBuffer = false; if (!HWBuffer->vbo_indicesID) { @@ -558,7 +559,7 @@ bool COpenGL3DriverBase::updateIndexHardwareBuffer(SHWBufferLink_opengl *HWBuffe if (!HWBuffer->vbo_indicesID) return false; newBuffer = true; - } else if (HWBuffer->vbo_indicesSize < indexCount * indexSize) { + } else if (HWBuffer->vbo_indicesSize < bufferSize) { newBuffer = true; } @@ -566,16 +567,16 @@ bool COpenGL3DriverBase::updateIndexHardwareBuffer(SHWBufferLink_opengl *HWBuffe // copy data to graphics card if (!newBuffer) - GL.BufferSubData(GL_ELEMENT_ARRAY_BUFFER, 0, indexCount * indexSize, indices); + GL.BufferSubData(GL_ELEMENT_ARRAY_BUFFER, 0, bufferSize, indices); else { - HWBuffer->vbo_indicesSize = indexCount * indexSize; + HWBuffer->vbo_indicesSize = bufferSize; GLenum usage = GL_STATIC_DRAW; if (HWBuffer->Mapped_Index == scene::EHM_STREAM) usage = GL_STREAM_DRAW; else if (HWBuffer->Mapped_Index == scene::EHM_DYNAMIC) usage = GL_DYNAMIC_DRAW; - GL.BufferData(GL_ELEMENT_ARRAY_BUFFER, indexCount * indexSize, indices, usage); + GL.BufferData(GL_ELEMENT_ARRAY_BUFFER, bufferSize, indices, usage); } GL.BindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); @@ -589,22 +590,24 @@ bool COpenGL3DriverBase::updateHardwareBuffer(SHWBufferLink *HWBuffer) if (!HWBuffer) return false; + auto *b = static_cast(HWBuffer); + if (HWBuffer->Mapped_Vertex != scene::EHM_NEVER) { - if (HWBuffer->ChangedID_Vertex != HWBuffer->MeshBuffer->getChangedID_Vertex() || !static_cast(HWBuffer)->vbo_verticesID) { + if (HWBuffer->ChangedID_Vertex != HWBuffer->MeshBuffer->getChangedID_Vertex() || !b->vbo_verticesID) { HWBuffer->ChangedID_Vertex = HWBuffer->MeshBuffer->getChangedID_Vertex(); - if (!updateVertexHardwareBuffer(static_cast(HWBuffer))) + if (!updateVertexHardwareBuffer(b)) return false; } } if (HWBuffer->Mapped_Index != scene::EHM_NEVER) { - if (HWBuffer->ChangedID_Index != HWBuffer->MeshBuffer->getChangedID_Index() || !static_cast(HWBuffer)->vbo_indicesID) { + if (HWBuffer->ChangedID_Index != HWBuffer->MeshBuffer->getChangedID_Index() || !b->vbo_indicesID) { HWBuffer->ChangedID_Index = HWBuffer->MeshBuffer->getChangedID_Index(); - if (!updateIndexHardwareBuffer((SHWBufferLink_opengl *)HWBuffer)) + if (!updateIndexHardwareBuffer(b)) return false; } } diff --git a/src/client/game.cpp b/src/client/game.cpp index 41c7972cb..1267b32a9 100644 --- a/src/client/game.cpp +++ b/src/client/game.cpp @@ -1953,6 +1953,11 @@ void Game::updateProfilers(const RunStats &stats, const FpsControl &draw_times, g_profiler->graphAdd("Sleep [us]", draw_times.sleep_time); g_profiler->graphSet("FPS", 1.0f / dtime); + + auto stats2 = driver->getFrameStats(); + g_profiler->avg("Irr: primitives drawn", stats2.PrimitivesDrawn); + g_profiler->avg("Irr: buffers uploaded", stats2.HWBuffersUploaded); + g_profiler->avg("Irr: buffers uploaded (bytes)", stats2.HWBuffersUploadedSize); } void Game::updateStats(RunStats *stats, const FpsControl &draw_times,