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);
#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<DrawSegment>();
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);
}
}
}

View file

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

View file

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

View file

@ -248,7 +248,6 @@ namespace swrenderer
{
RenderTranslucentPass::Instance()->Deinit();
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.
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;

View file

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

View file

@ -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<size_t> 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<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
// 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)

View file

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