Replace data structure for HW buffer book-keeping

before
  time in endScene ÷ num hw buf ________________  199x   0.128
after
  time in endScene ÷ num hw buf ________________  199x   0.057
This commit is contained in:
sfan5 2024-12-28 14:39:54 +01:00
parent a2058f7f3a
commit 40afc84597
4 changed files with 46 additions and 40 deletions

@ -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;
}

@ -17,7 +17,6 @@
#include "S3DVertex.h"
#include "SVertexIndex.h"
#include "SExposedVideoData.h"
#include <list>
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<size_t>(-1);
u32 ChangedID = 0;
bool IsVertex;
std::list<SHWBufferLink*>::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<video::IImageWriter *> SurfaceWriter;
core::array<SMaterialRenderer> MaterialRenderers;
std::list<SHWBufferLink *> HWBufferList;
std::vector<SHWBufferLink *> HWBufferList;
io::IFileSystem *FileSystem;

@ -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);

@ -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);