From 40afc845972ad350a04230570eb65f02ebd789ae Mon Sep 17 00:00:00 2001 From: sfan5 Date: Sat, 28 Dec 2024 14:39:54 +0100 Subject: [PATCH] Replace data structure for HW buffer book-keeping MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit before time in endScene ÷ num hw buf ________________ 199x 0.128 after time in endScene ÷ num hw buf ________________ 199x 0.057 --- irr/src/CNullDriver.cpp | 48 ++++++++++++++++++++++++--------------- irr/src/CNullDriver.h | 18 ++++++++------- irr/src/COpenGLDriver.cpp | 8 ++----- irr/src/OpenGL/Driver.cpp | 12 ++++------ 4 files changed, 46 insertions(+), 40 deletions(-) diff --git a/irr/src/CNullDriver.cpp b/irr/src/CNullDriver.cpp index 1191a8a65..65233dec3 100644 --- a/irr/src/CNullDriver.cpp +++ b/irr/src/CNullDriver.cpp @@ -218,7 +218,7 @@ bool CNullDriver::beginScene(u16 clearFlag, SColor clearColor, f32 clearDepth, u bool CNullDriver::endScene() { FPSCounter.registerFrame(os::Timer::getRealTime()); - updateAllHardwareBuffers(); + expireHardwareBuffers(); updateAllOcclusionQueries(); return true; } @@ -1141,25 +1141,28 @@ CNullDriver::SHWBufferLink *CNullDriver::getBufferLink(const scene::IIndexBuffer return createHardwareBuffer(ib); // no hardware links, and mesh wants one, create it } -//! Update all hardware buffers, remove unused ones -void CNullDriver::updateAllHardwareBuffers() +void CNullDriver::registerHardwareBuffer(SHWBufferLink *HWBuffer) { - // FIXME: this method can take a lot of time just doing the refcount - // checks and iteration (too much pointer chasing?) for - // large buffer counts (e.g. 50000) + _IRR_DEBUG_BREAK_IF(!HWBuffer) + HWBuffer->ListPosition = HWBufferList.size(); + HWBufferList.push_back(HWBuffer); +} - auto it = HWBufferList.begin(); - while (it != HWBufferList.end()) { - SHWBufferLink *Link = *it; - ++it; +void CNullDriver::expireHardwareBuffers() +{ + for (size_t i = 0; i < HWBufferList.size(); ) { + auto *Link = HWBufferList[i]; - if (Link->IsVertex) { - if (!Link->VertexBuffer || Link->VertexBuffer->getReferenceCount() == 1) - deleteHardwareBuffer(Link); - } else { - if (!Link->IndexBuffer || Link->IndexBuffer->getReferenceCount() == 1) - deleteHardwareBuffer(Link); - } + bool del; + if (Link->IsVertex) + del = !Link->VertexBuffer || Link->VertexBuffer->getReferenceCount() == 1; + else + del = !Link->IndexBuffer || Link->IndexBuffer->getReferenceCount() == 1; + // deleting can reorder, so don't advance in list + if (del) + deleteHardwareBuffer(Link); + else + i++; } FrameStats.HWBuffersActive = HWBufferList.size(); @@ -1169,7 +1172,16 @@ void CNullDriver::deleteHardwareBuffer(SHWBufferLink *HWBuffer) { if (!HWBuffer) return; - HWBufferList.erase(HWBuffer->listPosition); + const size_t pos = HWBuffer->ListPosition; + _IRR_DEBUG_BREAK_IF(HWBufferList.at(pos) != HWBuffer) + if (HWBufferList.size() < 2 || pos == HWBufferList.size() - 1) { + HWBufferList.erase(HWBufferList.begin() + pos); + } else { + // swap with last + std::swap(HWBufferList[pos], HWBufferList.back()); + HWBufferList.pop_back(); + HWBufferList[pos]->ListPosition = pos; + } delete HWBuffer; } diff --git a/irr/src/CNullDriver.h b/irr/src/CNullDriver.h index a33e1eafe..f42ac5bd6 100644 --- a/irr/src/CNullDriver.h +++ b/irr/src/CNullDriver.h @@ -17,7 +17,6 @@ #include "S3DVertex.h" #include "SVertexIndex.h" #include "SExposedVideoData.h" -#include namespace irr { @@ -293,7 +292,7 @@ protected: struct SHWBufferLink { SHWBufferLink(const scene::IVertexBuffer *vb) : - VertexBuffer(vb), ChangedID(0), IsVertex(true) + VertexBuffer(vb), IsVertex(true) { if (VertexBuffer) { VertexBuffer->grab(); @@ -301,7 +300,7 @@ protected: } } SHWBufferLink(const scene::IIndexBuffer *ib) : - IndexBuffer(ib), ChangedID(0), IsVertex(false) + IndexBuffer(ib), IsVertex(false) { if (IndexBuffer) { IndexBuffer->grab(); @@ -324,9 +323,9 @@ protected: const scene::IVertexBuffer *VertexBuffer; const scene::IIndexBuffer *IndexBuffer; }; - u32 ChangedID; + size_t ListPosition = static_cast(-1); + u32 ChangedID = 0; bool IsVertex; - std::list::iterator listPosition; }; //! Gets hardware buffer link from a vertex buffer (may create or update buffer) @@ -361,8 +360,8 @@ public: //! Remove all hardware buffers void removeAllHardwareBuffers() override; - //! Update all hardware buffers, remove unused ones - virtual void updateAllHardwareBuffers(); + //! Run garbage-collection on all HW buffers + void expireHardwareBuffers(); //! is vbo recommended? virtual bool isHardwareBufferRecommend(const scene::IVertexBuffer *mb); @@ -582,6 +581,9 @@ protected: //! deletes all material renderers void deleteMaterialRenders(); + // adds a created hardware buffer to the relevant data structure + void registerHardwareBuffer(SHWBufferLink *HWBuffer); + // prints renderer version void printVersion(); @@ -705,7 +707,7 @@ protected: core::array SurfaceWriter; core::array MaterialRenderers; - std::list HWBufferList; + std::vector HWBufferList; io::IFileSystem *FileSystem; diff --git a/irr/src/COpenGLDriver.cpp b/irr/src/COpenGLDriver.cpp index 7d98482e8..954c0ec25 100644 --- a/irr/src/COpenGLDriver.cpp +++ b/irr/src/COpenGLDriver.cpp @@ -430,9 +430,7 @@ COpenGLDriver::SHWBufferLink *COpenGLDriver::createHardwareBuffer(const scene::I return 0; SHWBufferLink_opengl *HWBuffer = new SHWBufferLink_opengl(vb); - - // add to map - HWBuffer->listPosition = HWBufferList.insert(HWBufferList.end(), HWBuffer); + registerHardwareBuffer(HWBuffer); if (!updateVertexHardwareBuffer(HWBuffer)) { deleteHardwareBuffer(HWBuffer); @@ -453,9 +451,7 @@ COpenGLDriver::SHWBufferLink *COpenGLDriver::createHardwareBuffer(const scene::I return 0; SHWBufferLink_opengl *HWBuffer = new SHWBufferLink_opengl(ib); - - // add to map - HWBuffer->listPosition = HWBufferList.insert(HWBufferList.end(), HWBuffer); + registerHardwareBuffer(HWBuffer); if (!updateIndexHardwareBuffer(HWBuffer)) { deleteHardwareBuffer(HWBuffer); diff --git a/irr/src/OpenGL/Driver.cpp b/irr/src/OpenGL/Driver.cpp index c1154e11b..a64785a29 100644 --- a/irr/src/OpenGL/Driver.cpp +++ b/irr/src/OpenGL/Driver.cpp @@ -566,10 +566,8 @@ COpenGL3DriverBase::SHWBufferLink *COpenGL3DriverBase::createHardwareBuffer(cons if (!vb || vb->getHardwareMappingHint() == scene::EHM_NEVER) return 0; - SHWBufferLink_opengl *HWBuffer = new SHWBufferLink_opengl(vb); - - // add to map - HWBuffer->listPosition = HWBufferList.insert(HWBufferList.end(), HWBuffer); + auto *HWBuffer = new SHWBufferLink_opengl(vb); + registerHardwareBuffer(HWBuffer); if (!updateVertexHardwareBuffer(HWBuffer)) { deleteHardwareBuffer(HWBuffer); @@ -584,10 +582,8 @@ COpenGL3DriverBase::SHWBufferLink *COpenGL3DriverBase::createHardwareBuffer(cons if (!ib || ib->getHardwareMappingHint() == scene::EHM_NEVER) return 0; - SHWBufferLink_opengl *HWBuffer = new SHWBufferLink_opengl(ib); - - // add to map - HWBuffer->listPosition = HWBufferList.insert(HWBufferList.end(), HWBuffer); + auto *HWBuffer = new SHWBufferLink_opengl(ib); + registerHardwareBuffer(HWBuffer); if (!updateIndexHardwareBuffer(HWBuffer)) { deleteHardwareBuffer(HWBuffer);