From e8eb8dd5965574045e4f3dd65eabcdaeeeebc0d3 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Sun, 15 Apr 2018 14:24:43 +0200 Subject: [PATCH] - store the wall render nodes as pointers, not as objects. This is mainly for future-proofing because storing these as objects in an array not only has a negative impact when using multithreading due to longer blocking time for the threads but also makes it hard to cache this data for reuse. --- src/gl/compatibility/gl_20.cpp | 3 +- src/gl/scene/gl_drawinfo.cpp | 84 ++++++++++++++++++---------------- src/gl/scene/gl_drawinfo.h | 5 +- src/gl/scene/gl_walls.cpp | 10 ++-- src/tarray.h | 4 ++ 5 files changed, 59 insertions(+), 47 deletions(-) diff --git a/src/gl/compatibility/gl_20.cpp b/src/gl/compatibility/gl_20.cpp index ea32d58c27..815fed99a3 100644 --- a/src/gl/compatibility/gl_20.cpp +++ b/src/gl/compatibility/gl_20.cpp @@ -559,7 +559,8 @@ bool FDrawInfo::PutWallCompat(GLWall *wall, int passflag) bool masked = passflag == 2 && wall->gltexture->isMasked(); int list = list_indices[masked][foggy]; - dldrawlists[list].AddWall(wall); + auto newwall = dldrawlists[list].NewWall(); + *newwall = *wall; return true; } diff --git a/src/gl/scene/gl_drawinfo.cpp b/src/gl/scene/gl_drawinfo.cpp index 91e11c3280..671252baac 100644 --- a/src/gl/scene/gl_drawinfo.cpp +++ b/src/gl/scene/gl_drawinfo.cpp @@ -33,6 +33,7 @@ #include "r_state.h" #include "doomstat.h" #include "g_levellocals.h" +#include "memarena.h" #include "gl/system/gl_cvars.h" #include "gl/data/gl_vertexbuffer.h" @@ -50,6 +51,13 @@ FDrawInfo * gl_drawinfo; FDrawInfoList di_list; +static FMemArena RenderDataAllocator(1024*1024); // Use large blocks to reduce allocation time. + +void ResetAllocator() +{ + RenderDataAllocator.FreeAll(); +} + //========================================================================== // // @@ -244,7 +252,7 @@ SortNode * GLDrawList::FindSortWall(SortNode * head) GLDrawItem * it = &drawitems[node->itemindex]; if (it->rendertype == GLDIT_WALL) { - float d = walls[it->index].ViewDistance; + float d = walls[it->index]->ViewDistance; if (d > farthest) farthest = d; if (d < nearest) nearest = d; } @@ -258,7 +266,7 @@ SortNode * GLDrawList::FindSortWall(SortNode * head) GLDrawItem * it = &drawitems[node->itemindex]; if (it->rendertype == GLDIT_WALL) { - float di = fabsf(walls[it->index].ViewDistance - farthest); + float di = fabsf(walls[it->index]->ViewDistance - farthest); if (!best || di < bestdist) { best = node; @@ -294,10 +302,10 @@ void GLDrawList::SortPlaneIntoPlane(SortNode * head,SortNode * sort) // // //========================================================================== -void GLDrawList::SortWallIntoPlane(SortNode * head,SortNode * sort) +void GLDrawList::SortWallIntoPlane(SortNode * head, SortNode * sort) { - GLFlat * fh=&flats[drawitems[head->itemindex].index]; - GLWall * ws=&walls[drawitems[sort->itemindex].index]; + GLFlat * fh = &flats[drawitems[head->itemindex].index]; + GLWall * ws = walls[drawitems[sort->itemindex].index]; bool ceiling = fh->z > r_viewpoint.Pos.Z; @@ -305,18 +313,13 @@ void GLDrawList::SortWallIntoPlane(SortNode * head,SortNode * sort) { // We have to split this wall! - // WARNING: NEVER EVER push a member of an array onto the array itself. - // Bad things will happen if the memory must be reallocated! - GLWall w = *ws; - AddWall(&w); - + GLWall *w = NewWall(); + *w = *ws; + // Splitting is done in the shader with clip planes, if available if (gl.flags & RFL_NO_CLIP_PLANES) { - GLWall * ws1; ws->vertcount = 0; // invalidate current vertices. - ws1=&walls[walls.Size()-1]; - ws=&walls[drawitems[sort->itemindex].index]; // may have been reallocated! float newtexv = ws->tcs[GLWall::UPLFT].v + ((ws->tcs[GLWall::LOLFT].v - ws->tcs[GLWall::UPLFT].v) / (ws->zbottom[0] - ws->ztop[0])) * (fh->z - ws->ztop[0]); // I make the very big assumption here that translucent walls in sloped sectors @@ -324,13 +327,13 @@ void GLDrawList::SortWallIntoPlane(SortNode * head,SortNode * sort) // code would become extremely more complicated. if (!ceiling) { - ws->ztop[1] = ws1->zbottom[1] = ws->ztop[0] = ws1->zbottom[0] = fh->z; - ws->tcs[GLWall::UPRGT].v = ws1->tcs[GLWall::LORGT].v = ws->tcs[GLWall::UPLFT].v = ws1->tcs[GLWall::LOLFT].v = newtexv; + ws->ztop[1] = w->zbottom[1] = ws->ztop[0] = w->zbottom[0] = fh->z; + ws->tcs[GLWall::UPRGT].v = w->tcs[GLWall::LORGT].v = ws->tcs[GLWall::UPLFT].v = w->tcs[GLWall::LOLFT].v = newtexv; } else { - ws1->ztop[1] = ws->zbottom[1] = ws1->ztop[0] = ws->zbottom[0] = fh->z; - ws1->tcs[GLWall::UPLFT].v = ws->tcs[GLWall::LOLFT].v = ws1->tcs[GLWall::UPRGT].v = ws->tcs[GLWall::LORGT].v=newtexv; + w->ztop[1] = ws->zbottom[1] = w->ztop[0] = ws->zbottom[0] = fh->z; + w->tcs[GLWall::UPLFT].v = ws->tcs[GLWall::LOLFT].v = w->tcs[GLWall::UPRGT].v = ws->tcs[GLWall::LORGT].v = newtexv; } } @@ -341,7 +344,7 @@ void GLDrawList::SortWallIntoPlane(SortNode * head,SortNode * sort) head->AddToLeft(sort); head->AddToRight(sort2); } - else if ((ws->zbottom[0]z && !ceiling) || (ws->ztop[0]>fh->z && ceiling)) // completely on the left side + else if ((ws->zbottom[0] < fh->z && !ceiling) || (ws->ztop[0] > fh->z && ceiling)) // completely on the left side { head->AddToLeft(sort); } @@ -421,9 +424,8 @@ void GLDrawList::SortSpriteIntoPlane(SortNode * head, SortNode * sort) void GLDrawList::SortWallIntoWall(SortNode * head,SortNode * sort) { - GLWall * wh=&walls[drawitems[head->itemindex].index]; - GLWall * ws=&walls[drawitems[sort->itemindex].index]; - GLWall * ws1; + GLWall * wh= walls[drawitems[head->itemindex].index]; + GLWall * ws= walls[drawitems[sort->itemindex].index]; float v1=wh->PointOnSide(ws->glseg.x1,ws->glseg.y1); float v2=wh->PointOnSide(ws->glseg.x2,ws->glseg.y2); @@ -461,21 +463,18 @@ void GLDrawList::SortWallIntoWall(SortNode * head,SortNode * sort) float izb=(float)(ws->zbottom[0]+r*(ws->zbottom[1]-ws->zbottom[0])); ws->vertcount = 0; // invalidate current vertices. - GLWall w=*ws; - AddWall(&w); - ws1=&walls[walls.Size()-1]; - ws=&walls[drawitems[sort->itemindex].index]; // may have been reallocated! + GLWall *w= NewWall(); - ws1->glseg.x1=ws->glseg.x2=ix; - ws1->glseg.y1=ws->glseg.y2=iy; - ws1->glseg.fracleft = ws->glseg.fracright = ws->glseg.fracleft + r*(ws->glseg.fracright - ws->glseg.fracleft); - ws1->ztop[0]=ws->ztop[1]=izt; - ws1->zbottom[0]=ws->zbottom[1]=izb; - ws1->tcs[GLWall::LOLFT].u = ws1->tcs[GLWall::UPLFT].u = ws->tcs[GLWall::LORGT].u = ws->tcs[GLWall::UPRGT].u = iu; + w->glseg.x1=ws->glseg.x2=ix; + w->glseg.y1=ws->glseg.y2=iy; + w->glseg.fracleft = ws->glseg.fracright = ws->glseg.fracleft + r*(ws->glseg.fracright - ws->glseg.fracleft); + w->ztop[0]=ws->ztop[1]=izt; + w->zbottom[0]=ws->zbottom[1]=izb; + w->tcs[GLWall::LOLFT].u = w->tcs[GLWall::UPLFT].u = ws->tcs[GLWall::LORGT].u = ws->tcs[GLWall::UPRGT].u = iu; if (gl.buffermethod == BM_DEFERRED) { ws->MakeVertices(false); - ws1->MakeVertices(false); + w->MakeVertices(false); } SortNode * sort2=SortNodes.GetNew(); @@ -507,7 +506,7 @@ EXTERN_CVAR(Bool, gl_billboard_particles) void GLDrawList::SortSpriteIntoWall(SortNode * head,SortNode * sort) { - GLWall * wh=&walls[drawitems[head->itemindex].index]; + GLWall *wh= walls[drawitems[head->itemindex].index]; GLSprite * ss=&sprites[drawitems[sort->itemindex].index]; GLSprite * ss1; @@ -731,7 +730,7 @@ void GLDrawList::DoDraw(int pass, int i, bool trans) case GLDIT_WALL: { - GLWall * w=&walls[drawitems[i].index]; + GLWall * w= walls[drawitems[i].index]; RenderWall.Clock(); w->Draw(pass); RenderWall.Unclock(); @@ -863,7 +862,7 @@ void GLDrawList::DrawWalls(int pass) RenderWall.Clock(); for(unsigned i=0;iDraw(pass); } RenderWall.Unclock(); } @@ -892,7 +891,7 @@ void GLDrawList::DrawDecals() { for(unsigned i=0;iDoDrawDecals(); } } @@ -908,8 +907,8 @@ void GLDrawList::SortWalls() { std::sort(drawitems.begin(), drawitems.end(), [=](const GLDrawItem &a, const GLDrawItem &b) -> bool { - GLWall * w1 = &walls[a.index]; - GLWall * w2 = &walls[b.index]; + GLWall * w1 = walls[a.index]; + GLWall * w2 = walls[b.index]; if (w1->gltexture != w2->gltexture) return w1->gltexture < w2->gltexture; return (w1->flags & 3) < (w2->flags & 3); @@ -936,9 +935,12 @@ void GLDrawList::SortFlats() // // //========================================================================== -void GLDrawList::AddWall(GLWall * wall) + +GLWall *GLDrawList::NewWall() { - drawitems.Push(GLDrawItem(GLDIT_WALL,walls.Push(*wall))); + auto wall = (GLWall*)RenderDataAllocator.Alloc(sizeof(GLWall)); + drawitems.Push(GLDrawItem(GLDIT_WALL, walls.Push(wall))); + return wall; } //========================================================================== @@ -1059,6 +1061,8 @@ void FDrawInfo::EndDrawInfo() } gl_drawinfo=di->next; di_list.Release(di); + if (gl_drawinfo == nullptr) + ResetAllocator(); } diff --git a/src/gl/scene/gl_drawinfo.h b/src/gl/scene/gl_drawinfo.h index 0c2607632f..c85648b6a3 100644 --- a/src/gl/scene/gl_drawinfo.h +++ b/src/gl/scene/gl_drawinfo.h @@ -106,7 +106,7 @@ struct SortNode struct GLDrawList { //private: - TArray walls; + TArray walls; TArray flats; TArray sprites; TArray drawitems; @@ -131,7 +131,8 @@ public: return drawitems.Size(); } - void AddWall(GLWall * wall); + GLWall *NewWall(); + //void AddWall(GLWall * wall); void AddFlat(GLFlat * flat); void AddSprite(GLSprite * sprite); void Reset(); diff --git a/src/gl/scene/gl_walls.cpp b/src/gl/scene/gl_walls.cpp index 0b9f6c60fc..95929c5692 100644 --- a/src/gl/scene/gl_walls.cpp +++ b/src/gl/scene/gl_walls.cpp @@ -55,7 +55,8 @@ void FDrawInfo::AddWall(GLWall *wall) { wall->ViewDistance = (r_viewpoint.Pos - (wall->seg->linedef->v1->fPos() + wall->seg->linedef->Delta() / 2)).XY().LengthSquared(); if (gl.buffermethod == BM_DEFERRED) wall->MakeVertices(true); - drawlists[GLDL_TRANSLUCENT].AddWall(wall); + auto newwall = drawlists[GLDL_TRANSLUCENT].NewWall(); + *newwall = *wall; } else { @@ -77,8 +78,8 @@ void FDrawInfo::AddWall(GLWall *wall) list = masked ? GLDL_MASKEDWALLS : GLDL_PLAINWALLS; } if (gl.buffermethod == BM_DEFERRED) wall->MakeVertices(false); - drawlists[list].AddWall(wall); - + auto newwall = drawlists[list].NewWall(); + *newwall = *wall; } } @@ -172,7 +173,8 @@ void GLWall::PutPortal(int ptype) { // draw a reflective layer over the mirror type=RENDERWALL_MIRRORSURFACE; - gl_drawinfo->drawlists[GLDL_TRANSLUCENTBORDER].AddWall(this); + auto newwall = gl_drawinfo->drawlists[GLDL_TRANSLUCENTBORDER].NewWall(); + *newwall = *this; } break; diff --git a/src/tarray.h b/src/tarray.h index 5a11e4a5b9..153fcd0ba5 100644 --- a/src/tarray.h +++ b/src/tarray.h @@ -560,6 +560,10 @@ public: { return Array[index]; } + T &At(size_t index) const + { + return Array[index]; + } unsigned int Size() const { return Count;