From da346427d3cfb9b4bd2b154af8cc25f624970a33 Mon Sep 17 00:00:00 2001 From: Magnus Norddahl Date: Fri, 3 Feb 2017 21:11:55 +0100 Subject: [PATCH] Change draw segment list to use TArray --- src/swrenderer/line/r_line.cpp | 8 +-- src/swrenderer/scene/r_portal.cpp | 30 +++-------- src/swrenderer/scene/r_portal.h | 2 - src/swrenderer/scene/r_scene.cpp | 1 - src/swrenderer/scene/r_translucent_pass.cpp | 9 +++- src/swrenderer/segments/r_drawsegment.cpp | 57 ++++++++++----------- src/swrenderer/segments/r_drawsegment.h | 24 +++++---- src/swrenderer/things/r_particle.cpp | 5 +- src/swrenderer/things/r_visiblesprite.cpp | 11 ++-- 9 files changed, 67 insertions(+), 80 deletions(-) diff --git a/src/swrenderer/line/r_line.cpp b/src/swrenderer/line/r_line.cpp index cd6cb1962d..d70ae98694 100644 --- a/src/swrenderer/line/r_line.cpp +++ b/src/swrenderer/line/r_line.cpp @@ -318,8 +318,6 @@ namespace swrenderer I_FatalError("Bad R_StoreWallRange: %i to %i", start, stop); #endif - DrawSegment *draw_segment = DrawSegmentList::Instance()->Add(); - if (!rw_prepped) { rw_prepped = true; @@ -331,6 +329,9 @@ namespace swrenderer RenderPortal *renderportal = RenderPortal::Instance(); + DrawSegment *draw_segment = RenderMemory::NewObject(); + DrawSegmentList::Instance()->Push(draw_segment); + draw_segment->CurrentPortalUniq = renderportal->CurrentPortalUniq; draw_segment->sx1 = WallC.sx1; draw_segment->sx2 = WallC.sx2; @@ -516,8 +517,7 @@ namespace swrenderer if (draw_segment->bFogBoundary || draw_segment->maskedtexturecol != nullptr) { - size_t drawsegnum = draw_segment - DrawSegmentList::Instance()->drawsegs; - DrawSegmentList::Instance()->InterestingDrawsegs.Push(drawsegnum); + DrawSegmentList::Instance()->PushInteresting(draw_segment); } } } diff --git a/src/swrenderer/scene/r_portal.cpp b/src/swrenderer/scene/r_portal.cpp index dfa7a1bd1d..d6c8022554 100644 --- a/src/swrenderer/scene/r_portal.cpp +++ b/src/swrenderer/scene/r_portal.cpp @@ -104,8 +104,6 @@ namespace swrenderer int savedextralight = extralight; DVector3 savedpos = ViewPos; DAngle savedangle = ViewAngle; - ptrdiff_t savedds_p = drawseglist->ds_p - drawseglist->drawsegs; - size_t savedinteresting = drawseglist->FirstInterestingDrawseg; double savedvisibility = LightVisibility::Instance()->GetVisibility(); AActor *savedcamera = camera; sector_t *savedsector = viewsector; @@ -188,7 +186,7 @@ namespace swrenderer } // Create a drawseg to clip sprites to the sky plane - DrawSegment *draw_segment = drawseglist->Add(); + DrawSegment *draw_segment = RenderMemory::NewObject(); draw_segment->CurrentPortalUniq = CurrentPortalUniq; draw_segment->siz1 = INT_MAX; draw_segment->siz2 = INT_MAX; @@ -207,13 +205,9 @@ namespace swrenderer draw_segment->foggy = false; memcpy(draw_segment->sprbottomclip, floorclip + pl->left, (pl->right - pl->left) * sizeof(short)); memcpy(draw_segment->sprtopclip, ceilingclip + pl->left, (pl->right - pl->left) * sizeof(short)); + drawseglist->Push(draw_segment); - drawseglist->firstdrawseg = draw_segment; - drawseglist->FirstInterestingDrawseg = drawseglist->InterestingDrawsegs.Size(); - - interestingStack.Push(drawseglist->FirstInterestingDrawseg); - ptrdiff_t diffnum = drawseglist->firstdrawseg - drawseglist->drawsegs; - drawsegStack.Push(diffnum); + drawseglist->PushPortal(); VisibleSpriteList::Instance()->PushPortal(); viewposStack.Push(ViewPos); visplaneStack.Push(pl); @@ -229,33 +223,23 @@ namespace swrenderer // Draw all the masked textures in a second pass, in the reverse order they // were added. This must be done separately from the previous step for the // sake of nested skyboxes. - while (interestingStack.Pop(drawseglist->FirstInterestingDrawseg)) + while (viewposStack.Size() > 0) { - ptrdiff_t pd = 0; - - drawsegStack.Pop(pd); - drawseglist->firstdrawseg = drawseglist->drawsegs + pd; - // Masked textures and planes need the view coordinates restored for proper positioning. viewposStack.Pop(ViewPos); RenderTranslucentPass::Instance()->Render(); - drawseglist->ds_p = drawseglist->firstdrawseg; - - VisibleSpriteList::Instance()->PopPortal(); - VisiblePlane *pl; visplaneStack.Pop(pl); if (pl->Alpha > 0 && pl->picnum != skyflatnum) { pl->Render(pl->Alpha, pl->Additive, true); } + + VisibleSpriteList::Instance()->PopPortal(); + drawseglist->PopPortal(); } - drawseglist->firstdrawseg = drawseglist->drawsegs; - drawseglist->ds_p = drawseglist->drawsegs + savedds_p; - drawseglist->InterestingDrawsegs.Resize((unsigned int)drawseglist->FirstInterestingDrawseg); - drawseglist->FirstInterestingDrawseg = savedinteresting; camera = savedcamera; viewsector = savedsector; diff --git a/src/swrenderer/scene/r_portal.h b/src/swrenderer/scene/r_portal.h index f62cab3eb0..f3e1b9bbef 100644 --- a/src/swrenderer/scene/r_portal.h +++ b/src/swrenderer/scene/r_portal.h @@ -55,8 +55,6 @@ namespace swrenderer void RenderLinePortal(PortalDrawseg* pds, int depth); void RenderLinePortalHighlight(PortalDrawseg* pds); - TArray interestingStack; - TArray drawsegStack; TArray viewposStack; TArray visplaneStack; TArray WallPortals; diff --git a/src/swrenderer/scene/r_scene.cpp b/src/swrenderer/scene/r_scene.cpp index f232f443f3..fae0762c6a 100644 --- a/src/swrenderer/scene/r_scene.cpp +++ b/src/swrenderer/scene/r_scene.cpp @@ -248,7 +248,6 @@ namespace swrenderer { RenderTranslucentPass::Instance()->Deinit(); Clip3DFloors::Instance()->Cleanup(); - DrawSegmentList::Instance()->Deinit(); } ///////////////////////////////////////////////////////////////////////// diff --git a/src/swrenderer/scene/r_translucent_pass.cpp b/src/swrenderer/scene/r_translucent_pass.cpp index b8d64c141e..dcf99f3f7e 100644 --- a/src/swrenderer/scene/r_translucent_pass.cpp +++ b/src/swrenderer/scene/r_translucent_pass.cpp @@ -72,8 +72,10 @@ namespace swrenderer // b) skip most of the collected drawsegs which have no portal attached. portaldrawsegs.Clear(); DrawSegmentList *drawseglist = DrawSegmentList::Instance(); - for (DrawSegment* seg = drawseglist->ds_p; seg-- > drawseglist->firstdrawseg; ) + for (auto index = drawseglist->BeginIndex(); index != drawseglist->EndIndex(); index++) { + DrawSegment *seg = drawseglist->Segment(index); + // I don't know what makes this happen (some old top-down portal code or possibly skybox code? something adds null lines...) // crashes at the first frame of the first map of Action2.wad if (!seg->curline) continue; @@ -141,9 +143,12 @@ namespace swrenderer { Clip3DFloors::Instance()->fake3D |= FAKE3D_REFRESHCLIP; } + DrawSegmentList *drawseglist = DrawSegmentList::Instance(); - for (DrawSegment *ds = drawseglist->ds_p; ds-- > drawseglist->firstdrawseg; ) + for (auto index = drawseglist->BeginIndex(); index != drawseglist->EndIndex(); index++) { + DrawSegment *ds = drawseglist->Segment(index); + // [ZZ] the same as above if (ds->CurrentPortalUniq != renderportal->CurrentPortalUniq) continue; diff --git a/src/swrenderer/segments/r_drawsegment.cpp b/src/swrenderer/segments/r_drawsegment.cpp index 8ff4e658fa..c4a03ac000 100644 --- a/src/swrenderer/segments/r_drawsegment.cpp +++ b/src/swrenderer/segments/r_drawsegment.cpp @@ -49,40 +49,39 @@ namespace swrenderer return &instance; } - void DrawSegmentList::Deinit() - { - if (drawsegs != nullptr) - { - M_Free(drawsegs); - drawsegs = nullptr; - } - } - void DrawSegmentList::Clear() { - if (drawsegs == nullptr) - { - MaxDrawSegs = 256; // [RH] Default. Increased as needed. - firstdrawseg = drawsegs = (DrawSegment *)M_Malloc (MaxDrawSegs * sizeof(DrawSegment)); - } - FirstInterestingDrawseg = 0; - InterestingDrawsegs.Clear (); - ds_p = drawsegs; + Segments.Clear(); + StartIndices.Clear(); + StartIndices.Push(0); + + InterestingSegments.Clear(); + StartInterestingIndices.Clear(); + StartInterestingIndices.Push(0); } - DrawSegment *DrawSegmentList::Add() + void DrawSegmentList::PushPortal() { - if (ds_p == &drawsegs[MaxDrawSegs]) - { // [RH] Grab some more drawsegs - size_t newdrawsegs = MaxDrawSegs ? MaxDrawSegs * 2 : 32; - ptrdiff_t firstofs = firstdrawseg - drawsegs; - drawsegs = (DrawSegment *)M_Realloc(drawsegs, newdrawsegs * sizeof(DrawSegment)); - firstdrawseg = drawsegs + firstofs; - ds_p = drawsegs + MaxDrawSegs; - MaxDrawSegs = newdrawsegs; - DPrintf(DMSG_NOTIFY, "MaxDrawSegs increased to %zu\n", MaxDrawSegs); - } + StartIndices.Push(Segments.Size()); + StartInterestingIndices.Push(InterestingSegments.Size()); + } - return ds_p++; + void DrawSegmentList::PopPortal() + { + Segments.Resize(StartIndices.Last()); + StartIndices.Pop(); + + StartInterestingIndices.Resize(StartInterestingIndices.Last()); + StartInterestingIndices.Pop(); + } + + void DrawSegmentList::Push(DrawSegment *segment) + { + Segments.Push(segment); + } + + void DrawSegmentList::PushInteresting(DrawSegment *segment) + { + InterestingSegments.Push(segment); } } diff --git a/src/swrenderer/segments/r_drawsegment.h b/src/swrenderer/segments/r_drawsegment.h index 6282936ac4..b44f190e43 100644 --- a/src/swrenderer/segments/r_drawsegment.h +++ b/src/swrenderer/segments/r_drawsegment.h @@ -52,19 +52,25 @@ namespace swrenderer public: static DrawSegmentList *Instance(); - DrawSegment *firstdrawseg = nullptr; - DrawSegment *ds_p = nullptr; - DrawSegment *drawsegs = nullptr; + unsigned int BeginIndex() const { return StartIndices.Last(); } + unsigned int EndIndex() const { return Segments.Size(); } + DrawSegment *Segment(int index) const { return Segments[Segments.Size() - 1 - index]; } - TArray InterestingDrawsegs; // drawsegs that have something drawn on them - size_t FirstInterestingDrawseg = 0; + unsigned int BeginInterestingIndex() const { return StartInterestingIndices.Last(); } + unsigned int EndInterestingIndex() const { return InterestingSegments.Size(); } + DrawSegment *InterestingSegment(int index) const { return InterestingSegments[Segments.Size() - 1 - index]; } void Clear(); - void Deinit(); - - DrawSegment *Add(); + void PushPortal(); + void PopPortal(); + void Push(DrawSegment *segment); + void PushInteresting(DrawSegment *segment); private: - size_t MaxDrawSegs = 0; + TArray Segments; + TArray StartIndices; + + TArray InterestingSegments; // drawsegs that have something drawn on them + TArray StartInterestingIndices; }; } diff --git a/src/swrenderer/things/r_particle.cpp b/src/swrenderer/things/r_particle.cpp index dd078430be..2b2eae50e2 100644 --- a/src/swrenderer/things/r_particle.cpp +++ b/src/swrenderer/things/r_particle.cpp @@ -266,9 +266,10 @@ namespace swrenderer // Draw any masked textures behind this particle so that when the // particle is drawn, it will be in front of them. DrawSegmentList *segmentlist = DrawSegmentList::Instance(); - for (unsigned int p = segmentlist->InterestingDrawsegs.Size(); p-- > segmentlist->FirstInterestingDrawseg; ) + for (unsigned int index = segmentlist->BeginInterestingIndex(); index != segmentlist->EndInterestingIndex(); index++) { - DrawSegment *ds = &segmentlist->drawsegs[segmentlist->InterestingDrawsegs[p]]; + DrawSegment *ds = segmentlist->InterestingSegment(index); + // kg3D - no fake segs if (ds->fake) continue; if (ds->x1 >= x2 || ds->x2 <= x1) diff --git a/src/swrenderer/things/r_visiblesprite.cpp b/src/swrenderer/things/r_visiblesprite.cpp index 96be5e12c6..7d19e14607 100644 --- a/src/swrenderer/things/r_visiblesprite.cpp +++ b/src/swrenderer/things/r_visiblesprite.cpp @@ -47,7 +47,6 @@ namespace swrenderer VisibleSprite *spr = this; - DrawSegment *ds; int i; int x1, x2; int r1, r2; @@ -280,15 +279,11 @@ namespace swrenderer // Scan drawsegs from end to start for obscuring segs. // The first drawseg that is closer than the sprite is the clip seg. - // Modified by Lee Killough: - // (pointer check was originally nonportable - // and buggy, by going past LEFT end of array): - - // for (ds=ds_p-1 ; ds >= drawsegs ; ds--) old buggy code - DrawSegmentList *segmentlist = DrawSegmentList::Instance(); - for (ds = segmentlist->ds_p; ds-- > segmentlist->firstdrawseg; ) // new -- killough + for (unsigned int index = segmentlist->BeginIndex(); index != segmentlist->EndIndex(); index++) { + DrawSegment *ds = segmentlist->Segment(index); + // [ZZ] portal handling here //if (ds->CurrentPortalUniq != spr->CurrentPortalUniq) // continue;