Change draw segment list to use TArray

This commit is contained in:
Magnus Norddahl 2017-02-03 21:11:55 +01:00
parent 812cc61b16
commit da346427d3
9 changed files with 67 additions and 80 deletions

View file

@ -318,8 +318,6 @@ namespace swrenderer
I_FatalError("Bad R_StoreWallRange: %i to %i", start, stop); I_FatalError("Bad R_StoreWallRange: %i to %i", start, stop);
#endif #endif
DrawSegment *draw_segment = DrawSegmentList::Instance()->Add();
if (!rw_prepped) if (!rw_prepped)
{ {
rw_prepped = true; rw_prepped = true;
@ -331,6 +329,9 @@ namespace swrenderer
RenderPortal *renderportal = RenderPortal::Instance(); RenderPortal *renderportal = RenderPortal::Instance();
DrawSegment *draw_segment = RenderMemory::NewObject<DrawSegment>();
DrawSegmentList::Instance()->Push(draw_segment);
draw_segment->CurrentPortalUniq = renderportal->CurrentPortalUniq; draw_segment->CurrentPortalUniq = renderportal->CurrentPortalUniq;
draw_segment->sx1 = WallC.sx1; draw_segment->sx1 = WallC.sx1;
draw_segment->sx2 = WallC.sx2; draw_segment->sx2 = WallC.sx2;
@ -516,8 +517,7 @@ namespace swrenderer
if (draw_segment->bFogBoundary || draw_segment->maskedtexturecol != nullptr) if (draw_segment->bFogBoundary || draw_segment->maskedtexturecol != nullptr)
{ {
size_t drawsegnum = draw_segment - DrawSegmentList::Instance()->drawsegs; DrawSegmentList::Instance()->PushInteresting(draw_segment);
DrawSegmentList::Instance()->InterestingDrawsegs.Push(drawsegnum);
} }
} }
} }

View file

@ -104,8 +104,6 @@ namespace swrenderer
int savedextralight = extralight; int savedextralight = extralight;
DVector3 savedpos = ViewPos; DVector3 savedpos = ViewPos;
DAngle savedangle = ViewAngle; DAngle savedangle = ViewAngle;
ptrdiff_t savedds_p = drawseglist->ds_p - drawseglist->drawsegs;
size_t savedinteresting = drawseglist->FirstInterestingDrawseg;
double savedvisibility = LightVisibility::Instance()->GetVisibility(); double savedvisibility = LightVisibility::Instance()->GetVisibility();
AActor *savedcamera = camera; AActor *savedcamera = camera;
sector_t *savedsector = viewsector; sector_t *savedsector = viewsector;
@ -188,7 +186,7 @@ namespace swrenderer
} }
// Create a drawseg to clip sprites to the sky plane // Create a drawseg to clip sprites to the sky plane
DrawSegment *draw_segment = drawseglist->Add(); DrawSegment *draw_segment = RenderMemory::NewObject<DrawSegment>();
draw_segment->CurrentPortalUniq = CurrentPortalUniq; draw_segment->CurrentPortalUniq = CurrentPortalUniq;
draw_segment->siz1 = INT_MAX; draw_segment->siz1 = INT_MAX;
draw_segment->siz2 = INT_MAX; draw_segment->siz2 = INT_MAX;
@ -207,13 +205,9 @@ namespace swrenderer
draw_segment->foggy = false; draw_segment->foggy = false;
memcpy(draw_segment->sprbottomclip, floorclip + pl->left, (pl->right - pl->left) * sizeof(short)); 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)); memcpy(draw_segment->sprtopclip, ceilingclip + pl->left, (pl->right - pl->left) * sizeof(short));
drawseglist->Push(draw_segment);
drawseglist->firstdrawseg = draw_segment; drawseglist->PushPortal();
drawseglist->FirstInterestingDrawseg = drawseglist->InterestingDrawsegs.Size();
interestingStack.Push(drawseglist->FirstInterestingDrawseg);
ptrdiff_t diffnum = drawseglist->firstdrawseg - drawseglist->drawsegs;
drawsegStack.Push(diffnum);
VisibleSpriteList::Instance()->PushPortal(); VisibleSpriteList::Instance()->PushPortal();
viewposStack.Push(ViewPos); viewposStack.Push(ViewPos);
visplaneStack.Push(pl); visplaneStack.Push(pl);
@ -229,33 +223,23 @@ namespace swrenderer
// Draw all the masked textures in a second pass, in the reverse order they // 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 // were added. This must be done separately from the previous step for the
// sake of nested skyboxes. // 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. // Masked textures and planes need the view coordinates restored for proper positioning.
viewposStack.Pop(ViewPos); viewposStack.Pop(ViewPos);
RenderTranslucentPass::Instance()->Render(); RenderTranslucentPass::Instance()->Render();
drawseglist->ds_p = drawseglist->firstdrawseg;
VisibleSpriteList::Instance()->PopPortal();
VisiblePlane *pl; VisiblePlane *pl;
visplaneStack.Pop(pl); visplaneStack.Pop(pl);
if (pl->Alpha > 0 && pl->picnum != skyflatnum) if (pl->Alpha > 0 && pl->picnum != skyflatnum)
{ {
pl->Render(pl->Alpha, pl->Additive, true); 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; camera = savedcamera;
viewsector = savedsector; viewsector = savedsector;

View file

@ -55,8 +55,6 @@ namespace swrenderer
void RenderLinePortal(PortalDrawseg* pds, int depth); void RenderLinePortal(PortalDrawseg* pds, int depth);
void RenderLinePortalHighlight(PortalDrawseg* pds); void RenderLinePortalHighlight(PortalDrawseg* pds);
TArray<size_t> interestingStack;
TArray<ptrdiff_t> drawsegStack;
TArray<DVector3> viewposStack; TArray<DVector3> viewposStack;
TArray<VisiblePlane *> visplaneStack; TArray<VisiblePlane *> visplaneStack;
TArray<PortalDrawseg *> WallPortals; TArray<PortalDrawseg *> WallPortals;

View file

@ -248,7 +248,6 @@ namespace swrenderer
{ {
RenderTranslucentPass::Instance()->Deinit(); RenderTranslucentPass::Instance()->Deinit();
Clip3DFloors::Instance()->Cleanup(); Clip3DFloors::Instance()->Cleanup();
DrawSegmentList::Instance()->Deinit();
} }
///////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////

View file

@ -72,8 +72,10 @@ namespace swrenderer
// b) skip most of the collected drawsegs which have no portal attached. // b) skip most of the collected drawsegs which have no portal attached.
portaldrawsegs.Clear(); portaldrawsegs.Clear();
DrawSegmentList *drawseglist = DrawSegmentList::Instance(); 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...) // 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 // crashes at the first frame of the first map of Action2.wad
if (!seg->curline) continue; if (!seg->curline) continue;
@ -141,9 +143,12 @@ namespace swrenderer
{ {
Clip3DFloors::Instance()->fake3D |= FAKE3D_REFRESHCLIP; Clip3DFloors::Instance()->fake3D |= FAKE3D_REFRESHCLIP;
} }
DrawSegmentList *drawseglist = DrawSegmentList::Instance(); 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 // [ZZ] the same as above
if (ds->CurrentPortalUniq != renderportal->CurrentPortalUniq) if (ds->CurrentPortalUniq != renderportal->CurrentPortalUniq)
continue; continue;

View file

@ -49,40 +49,39 @@ namespace swrenderer
return &instance; return &instance;
} }
void DrawSegmentList::Deinit()
{
if (drawsegs != nullptr)
{
M_Free(drawsegs);
drawsegs = nullptr;
}
}
void DrawSegmentList::Clear() void DrawSegmentList::Clear()
{ {
if (drawsegs == nullptr) Segments.Clear();
{ StartIndices.Clear();
MaxDrawSegs = 256; // [RH] Default. Increased as needed. StartIndices.Push(0);
firstdrawseg = drawsegs = (DrawSegment *)M_Malloc (MaxDrawSegs * sizeof(DrawSegment));
} InterestingSegments.Clear();
FirstInterestingDrawseg = 0; StartInterestingIndices.Clear();
InterestingDrawsegs.Clear (); StartInterestingIndices.Push(0);
ds_p = drawsegs;
} }
DrawSegment *DrawSegmentList::Add() void DrawSegmentList::PushPortal()
{ {
if (ds_p == &drawsegs[MaxDrawSegs]) StartIndices.Push(Segments.Size());
{ // [RH] Grab some more drawsegs StartInterestingIndices.Push(InterestingSegments.Size());
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);
} }
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);
} }
} }

View file

@ -52,19 +52,25 @@ namespace swrenderer
public: public:
static DrawSegmentList *Instance(); static DrawSegmentList *Instance();
DrawSegment *firstdrawseg = nullptr; unsigned int BeginIndex() const { return StartIndices.Last(); }
DrawSegment *ds_p = nullptr; unsigned int EndIndex() const { return Segments.Size(); }
DrawSegment *drawsegs = nullptr; DrawSegment *Segment(int index) const { return Segments[Segments.Size() - 1 - index]; }
TArray<size_t> InterestingDrawsegs; // drawsegs that have something drawn on them unsigned int BeginInterestingIndex() const { return StartInterestingIndices.Last(); }
size_t FirstInterestingDrawseg = 0; unsigned int EndInterestingIndex() const { return InterestingSegments.Size(); }
DrawSegment *InterestingSegment(int index) const { return InterestingSegments[Segments.Size() - 1 - index]; }
void Clear(); void Clear();
void Deinit(); void PushPortal();
void PopPortal();
DrawSegment *Add(); void Push(DrawSegment *segment);
void PushInteresting(DrawSegment *segment);
private: private:
size_t MaxDrawSegs = 0; TArray<DrawSegment *> Segments;
TArray<unsigned int> StartIndices;
TArray<DrawSegment *> InterestingSegments; // drawsegs that have something drawn on them
TArray<unsigned int> StartInterestingIndices;
}; };
} }

View file

@ -266,9 +266,10 @@ namespace swrenderer
// Draw any masked textures behind this particle so that when the // Draw any masked textures behind this particle so that when the
// particle is drawn, it will be in front of them. // particle is drawn, it will be in front of them.
DrawSegmentList *segmentlist = DrawSegmentList::Instance(); 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 // kg3D - no fake segs
if (ds->fake) continue; if (ds->fake) continue;
if (ds->x1 >= x2 || ds->x2 <= x1) if (ds->x1 >= x2 || ds->x2 <= x1)

View file

@ -47,7 +47,6 @@ namespace swrenderer
VisibleSprite *spr = this; VisibleSprite *spr = this;
DrawSegment *ds;
int i; int i;
int x1, x2; int x1, x2;
int r1, r2; int r1, r2;
@ -280,15 +279,11 @@ namespace swrenderer
// Scan drawsegs from end to start for obscuring segs. // Scan drawsegs from end to start for obscuring segs.
// The first drawseg that is closer than the sprite is the clip seg. // 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(); 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 // [ZZ] portal handling here
//if (ds->CurrentPortalUniq != spr->CurrentPortalUniq) //if (ds->CurrentPortalUniq != spr->CurrentPortalUniq)
// continue; // continue;