Rewrite VisibleSpriteList to use TArray

This commit is contained in:
Magnus Norddahl 2017-01-16 03:46:05 +01:00
parent cd9043fd94
commit 57d8b0e34c
9 changed files with 75 additions and 132 deletions

View File

@ -102,7 +102,6 @@ namespace swrenderer
int savedextralight = extralight; int savedextralight = extralight;
DVector3 savedpos = ViewPos; DVector3 savedpos = ViewPos;
DAngle savedangle = ViewAngle; DAngle savedangle = ViewAngle;
ptrdiff_t savedvissprite_p = VisibleSpriteList::vissprite_p - VisibleSpriteList::vissprites;
ptrdiff_t savedds_p = ds_p - drawsegs; ptrdiff_t savedds_p = ds_p - drawsegs;
size_t savedinteresting = FirstInterestingDrawseg; size_t savedinteresting = FirstInterestingDrawseg;
double savedvisibility = R_GetVisibility(); double savedvisibility = R_GetVisibility();
@ -220,15 +219,13 @@ namespace swrenderer
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));
VisibleSpriteList::firstvissprite = VisibleSpriteList::vissprite_p;
firstdrawseg = draw_segment; firstdrawseg = draw_segment;
FirstInterestingDrawseg = InterestingDrawsegs.Size(); FirstInterestingDrawseg = InterestingDrawsegs.Size();
interestingStack.Push(FirstInterestingDrawseg); interestingStack.Push(FirstInterestingDrawseg);
ptrdiff_t diffnum = firstdrawseg - drawsegs; ptrdiff_t diffnum = firstdrawseg - drawsegs;
drawsegStack.Push(diffnum); drawsegStack.Push(diffnum);
diffnum = VisibleSpriteList::firstvissprite - VisibleSpriteList::vissprites; VisibleSpriteList::Instance()->PushPortal();
visspriteStack.Push(diffnum);
viewposStack.Push(ViewPos); viewposStack.Push(ViewPos);
visplaneStack.Push(pl); visplaneStack.Push(pl);
@ -249,8 +246,6 @@ namespace swrenderer
drawsegStack.Pop(pd); drawsegStack.Pop(pd);
firstdrawseg = drawsegs + pd; firstdrawseg = drawsegs + pd;
visspriteStack.Pop(pd);
VisibleSpriteList::firstvissprite = VisibleSpriteList::vissprites + 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);
@ -258,7 +253,8 @@ namespace swrenderer
RenderTranslucentPass::Render(); RenderTranslucentPass::Render();
ds_p = firstdrawseg; ds_p = firstdrawseg;
VisibleSpriteList::vissprite_p = VisibleSpriteList::firstvissprite;
VisibleSpriteList::Instance()->PopPortal();
visplaneStack.Pop(pl); visplaneStack.Pop(pl);
if (pl->Alpha > 0 && pl->picnum != skyflatnum) if (pl->Alpha > 0 && pl->picnum != skyflatnum)
@ -268,8 +264,6 @@ namespace swrenderer
*planes->freehead = pl; *planes->freehead = pl;
planes->freehead = &pl->next; planes->freehead = &pl->next;
} }
VisibleSpriteList::firstvissprite = VisibleSpriteList::vissprites;
VisibleSpriteList::vissprite_p = VisibleSpriteList::vissprites + savedvissprite_p;
firstdrawseg = drawsegs; firstdrawseg = drawsegs;
ds_p = drawsegs + savedds_p; ds_p = drawsegs + savedds_p;
InterestingDrawsegs.Resize((unsigned int)FirstInterestingDrawseg); InterestingDrawsegs.Resize((unsigned int)FirstInterestingDrawseg);

View File

@ -55,7 +55,6 @@ namespace swrenderer
TArray<size_t> interestingStack; TArray<size_t> interestingStack;
TArray<ptrdiff_t> drawsegStack; TArray<ptrdiff_t> drawsegStack;
TArray<ptrdiff_t> visspriteStack;
TArray<DVector3> viewposStack; TArray<DVector3> viewposStack;
TArray<visplane_t *> visplaneStack; TArray<visplane_t *> visplaneStack;
}; };

View File

@ -51,14 +51,12 @@ namespace swrenderer
void RenderTranslucentPass::Deinit() void RenderTranslucentPass::Deinit()
{ {
VisibleSpriteList::Deinit();
SortedVisibleSpriteList::Deinit();
RenderVoxel::Deinit(); RenderVoxel::Deinit();
} }
void RenderTranslucentPass::Clear() void RenderTranslucentPass::Clear()
{ {
VisibleSpriteList::Clear(); VisibleSpriteList::Instance()->Clear();
DrewAVoxel = false; DrewAVoxel = false;
} }
@ -529,11 +527,12 @@ namespace swrenderer
{ {
RenderPortal *renderportal = RenderPortal::Instance(); RenderPortal *renderportal = RenderPortal::Instance();
for (int i = SortedVisibleSpriteList::vsprcount; i > 0; i--) auto &sortedSprites = VisibleSpriteList::Instance()->SortedSprites;
for (int i = sortedSprites.Size(); i > 0; i--)
{ {
if (SortedVisibleSpriteList::spritesorter[i - 1]->CurrentPortalUniq != renderportal->CurrentPortalUniq) if (sortedSprites[i - 1]->CurrentPortalUniq != renderportal->CurrentPortalUniq)
continue; // probably another time continue; // probably another time
DrawSprite(SortedVisibleSpriteList::spritesorter[i - 1]); DrawSprite(sortedSprites[i - 1]);
} }
// render any remaining masked mid textures // render any remaining masked mid textures
@ -565,7 +564,7 @@ namespace swrenderer
void RenderTranslucentPass::Render() void RenderTranslucentPass::Render()
{ {
CollectPortals(); CollectPortals();
SortedVisibleSpriteList::Sort(DrewAVoxel ? SortedVisibleSpriteList::sv_compare2d : SortedVisibleSpriteList::sv_compare, VisibleSpriteList::firstvissprite - VisibleSpriteList::vissprites); VisibleSpriteList::Instance()->Sort(DrewAVoxel);
Clip3DFloors *clip3d = Clip3DFloors::Instance(); Clip3DFloors *clip3d = Clip3DFloors::Instance();
if (clip3d->height_top == nullptr) if (clip3d->height_top == nullptr)

View File

@ -66,7 +66,6 @@ namespace swrenderer
double tz, tiz; double tz, tiz;
double xscale, yscale; double xscale, yscale;
int x1, x2, y1, y2; int x1, x2, y1, y2;
vissprite_t* vis;
sector_t* heightsec = NULL; sector_t* heightsec = NULL;
FSWColormap* map; FSWColormap* map;
@ -179,7 +178,7 @@ namespace swrenderer
return; return;
// store information in a vissprite // store information in a vissprite
vis = VisibleSpriteList::Add(); vissprite_t *vis = RenderMemory::NewObject<vissprite_t>();
vis->CurrentPortalUniq = renderportal->CurrentPortalUniq; vis->CurrentPortalUniq = renderportal->CurrentPortalUniq;
vis->heightsec = heightsec; vis->heightsec = heightsec;
vis->xscale = FLOAT2FIXED(xscale); vis->xscale = FLOAT2FIXED(xscale);
@ -223,6 +222,8 @@ namespace swrenderer
vis->Style.ColormapNum = GETPALOOKUP(tiz * r_SpriteVisibility * 0.5, shade); vis->Style.ColormapNum = GETPALOOKUP(tiz * r_SpriteVisibility * 0.5, shade);
vis->Style.BaseColormap = map; vis->Style.BaseColormap = map;
} }
VisibleSpriteList::Instance()->Push(vis);
} }
void RenderParticle::Render(vissprite_t *vis) void RenderParticle::Render(vissprite_t *vis)

View File

@ -156,7 +156,7 @@ namespace swrenderer
double yscale = spriteScale.Y / tex->Scale.Y; double yscale = spriteScale.Y / tex->Scale.Y;
// store information in a vissprite // store information in a vissprite
vissprite_t *vis = VisibleSpriteList::Add(); vissprite_t *vis = RenderMemory::NewObject<vissprite_t>();
vis->CurrentPortalUniq = renderportal->CurrentPortalUniq; vis->CurrentPortalUniq = renderportal->CurrentPortalUniq;
vis->xscale = FLOAT2FIXED(xscale); vis->xscale = FLOAT2FIXED(xscale);
@ -274,6 +274,8 @@ namespace swrenderer
vis->Style.BaseColormap = mybasecolormap; vis->Style.BaseColormap = mybasecolormap;
} }
} }
VisibleSpriteList::Instance()->Push(vis);
} }
void RenderSprite::Render(vissprite_t *vis, const short *mfloorclip, const short *mceilingclip) void RenderSprite::Render(vissprite_t *vis, const short *mfloorclip, const short *mceilingclip)

View File

@ -28,118 +28,78 @@
namespace swrenderer namespace swrenderer
{ {
void VisibleSpriteList::Deinit() VisibleSpriteList *VisibleSpriteList::Instance()
{ {
// Free vissprites static VisibleSpriteList instance;
for (int i = 0; i < MaxVisSprites; ++i) return &instance;
{
delete vissprites[i];
}
free(vissprites);
vissprites = nullptr;
vissprite_p = lastvissprite = nullptr;
MaxVisSprites = 0;
} }
void VisibleSpriteList::Clear() void VisibleSpriteList::Clear()
{ {
vissprite_p = firstvissprite; Sprites.Clear();
StartIndices.Clear();
SortedSprites.Clear();
} }
vissprite_t *VisibleSpriteList::Add() void VisibleSpriteList::PushPortal()
{ {
if (vissprite_p == lastvissprite) StartIndices.Push(Sprites.Size());
{
ptrdiff_t firstvisspritenum = firstvissprite - vissprites;
ptrdiff_t prevvisspritenum = vissprite_p - vissprites;
MaxVisSprites = MaxVisSprites ? MaxVisSprites * 2 : 128;
vissprites = (vissprite_t **)M_Realloc(vissprites, MaxVisSprites * sizeof(vissprite_t));
lastvissprite = &vissprites[MaxVisSprites];
firstvissprite = &vissprites[firstvisspritenum];
vissprite_p = &vissprites[prevvisspritenum];
DPrintf(DMSG_NOTIFY, "MaxVisSprites increased to %d\n", MaxVisSprites);
// Allocate sprites from the new pile
for (vissprite_t **p = vissprite_p; p < lastvissprite; ++p)
{
*p = new vissprite_t;
}
}
vissprite_p++;
return *(vissprite_p - 1);
} }
int VisibleSpriteList::MaxVisSprites; void VisibleSpriteList::PopPortal()
vissprite_t **VisibleSpriteList::vissprites;
vissprite_t **VisibleSpriteList::firstvissprite;
vissprite_t **VisibleSpriteList::vissprite_p;
vissprite_t **VisibleSpriteList::lastvissprite;
/////////////////////////////////////////////////////////////////////////
void SortedVisibleSpriteList::Deinit()
{ {
delete[] spritesorter; Sprites.Resize(StartIndices.Last());
spritesortersize = 0; StartIndices.Pop();
spritesorter = nullptr;
} }
// This is the standard version, which does a simple test based on depth. void VisibleSpriteList::Push(vissprite_t *sprite)
bool SortedVisibleSpriteList::sv_compare(vissprite_t *a, vissprite_t *b)
{ {
return a->idepth > b->idepth; Sprites.Push(sprite);
} }
// This is an alternate version, for when one or more voxel is in view. void VisibleSpriteList::Sort(bool compare2d)
// It does a 2D distance test based on whichever one is furthest from
// the viewpoint.
bool SortedVisibleSpriteList::sv_compare2d(vissprite_t *a, vissprite_t *b)
{ {
return DVector2(a->deltax, a->deltay).LengthSquared() < DVector2(b->deltax, b->deltay).LengthSquared(); size_t first = StartIndices.Size() == 0 ? 0 : StartIndices.Last();
} size_t count = Sprites.Size() - first;
void SortedVisibleSpriteList::Sort(bool(*compare)(vissprite_t *, vissprite_t *), size_t first) SortedSprites.Resize(count);
{
int i;
vissprite_t **spr;
vsprcount = int(VisibleSpriteList::vissprite_p - &VisibleSpriteList::vissprites[first]); if (count == 0)
if (vsprcount == 0)
return; return;
if (spritesortersize < VisibleSpriteList::MaxVisSprites)
{
if (spritesorter != nullptr)
delete[] spritesorter;
spritesorter = new vissprite_t *[VisibleSpriteList::MaxVisSprites];
spritesortersize = VisibleSpriteList::MaxVisSprites;
}
if (!(i_compatflags & COMPATF_SPRITESORT)) if (!(i_compatflags & COMPATF_SPRITESORT))
{ {
for (i = 0, spr = VisibleSpriteList::firstvissprite; i < vsprcount; i++, spr++) for (size_t i = 0; i < count; i++)
{ SortedSprites[i] = Sprites[first + i];
spritesorter[i] = *spr;
}
} }
else else
{ {
// If the compatibility option is on sprites of equal distance need to // If the compatibility option is on sprites of equal distance need to
// be sorted in inverse order. This is most easily achieved by // be sorted in inverse order. This is most easily achieved by
// filling the sort array backwards before the sort. // filling the sort array backwards before the sort.
for (i = 0, spr = VisibleSpriteList::firstvissprite + vsprcount - 1; i < vsprcount; i++, spr--) for (size_t i = 0; i < count; i++)
{ SortedSprites[i] = Sprites[first + count - i - 1];
spritesorter[i] = *spr;
}
} }
std::stable_sort(&spritesorter[0], &spritesorter[vsprcount], compare); if (compare2d)
} {
// This is an alternate version, for when one or more voxel is in view.
// It does a 2D distance test based on whichever one is furthest from
// the viewpoint.
vissprite_t **SortedVisibleSpriteList::spritesorter; std::stable_sort(&SortedSprites[0], &SortedSprites[count], [](vissprite_t *a, vissprite_t *b) -> bool
int SortedVisibleSpriteList::spritesortersize = 0; {
int SortedVisibleSpriteList::vsprcount; return DVector2(a->deltax, a->deltay).LengthSquared() < DVector2(b->deltax, b->deltay).LengthSquared();
});
}
else
{
// This is the standard version, which does a simple test based on depth.
std::stable_sort(&SortedSprites[0], &SortedSprites[count], [](vissprite_t *a, vissprite_t *b) -> bool
{
return a->idepth > b->idepth;
});
}
}
} }

View File

@ -21,33 +21,18 @@ namespace swrenderer
class VisibleSpriteList class VisibleSpriteList
{ {
public: public:
static int MaxVisSprites; static VisibleSpriteList *Instance();
static vissprite_t **vissprites;
static vissprite_t **firstvissprite;
static vissprite_t **vissprite_p;
static void Deinit(); void Clear();
static void Clear(); void PushPortal();
static vissprite_t *Add(); void PopPortal();
void Push(vissprite_t *sprite);
void Sort(bool compare2d);
TArray<vissprite_t *> SortedSprites;
private: private:
static vissprite_t **lastvissprite; TArray<vissprite_t *> Sprites;
}; TArray<size_t> StartIndices;
class SortedVisibleSpriteList
{
public:
static void Deinit();
static void Sort(bool(*compare)(vissprite_t *, vissprite_t *), size_t first);
static bool sv_compare(vissprite_t *a, vissprite_t *b);
static bool sv_compare2d(vissprite_t *a, vissprite_t *b);
static vissprite_t **spritesorter;
static int vsprcount;
private:
static int spritesortersize;
}; };
} }

View File

@ -41,6 +41,7 @@
#include "swrenderer/scene/r_scene.h" #include "swrenderer/scene/r_scene.h"
#include "swrenderer/scene/r_viewport.h" #include "swrenderer/scene/r_viewport.h"
#include "swrenderer/scene/r_light.h" #include "swrenderer/scene/r_light.h"
#include "swrenderer/r_memory.h"
EXTERN_CVAR(Bool, r_fullbrightignoresectorcolor) EXTERN_CVAR(Bool, r_fullbrightignoresectorcolor)
@ -104,7 +105,7 @@ namespace swrenderer
} }
} }
vissprite_t *vis = VisibleSpriteList::Add(); vissprite_t *vis = RenderMemory::NewObject<vissprite_t>();
vis->CurrentPortalUniq = renderportal->CurrentPortalUniq; vis->CurrentPortalUniq = renderportal->CurrentPortalUniq;
vis->xscale = FLOAT2FIXED(xscale); vis->xscale = FLOAT2FIXED(xscale);
@ -157,8 +158,6 @@ namespace swrenderer
vis->bWallSprite = false; vis->bWallSprite = false;
vis->foggy = foggy; vis->foggy = foggy;
RenderTranslucentPass::DrewAVoxel = true;
// The software renderer cannot invert the source without inverting the overlay // The software renderer cannot invert the source without inverting the overlay
// too. That means if the source is inverted, we need to do the reverse of what // too. That means if the source is inverted, we need to do the reverse of what
// the invert overlay flag says to do. // the invert overlay flag says to do.
@ -223,6 +222,9 @@ namespace swrenderer
vis->Style.BaseColormap = mybasecolormap; vis->Style.BaseColormap = mybasecolormap;
} }
} }
VisibleSpriteList::Instance()->Push(vis);
RenderTranslucentPass::DrewAVoxel = true;
} }
void RenderVoxel::Render(vissprite_t *sprite, int minZ, int maxZ, short *cliptop, short *clipbottom) void RenderVoxel::Render(vissprite_t *sprite, int minZ, int maxZ, short *cliptop, short *clipbottom)

View File

@ -72,7 +72,6 @@ namespace swrenderer
DAngle ang = thing->Angles.Yaw + 90; DAngle ang = thing->Angles.Yaw + 90;
double angcos = ang.Cos(); double angcos = ang.Cos();
double angsin = ang.Sin(); double angsin = ang.Sin();
vissprite_t *vis;
// Determine left and right edges of sprite. The sprite's angle is its normal, // Determine left and right edges of sprite. The sprite's angle is its normal,
// so the edges are 90 degrees each side of it. // so the edges are 90 degrees each side of it.
@ -105,7 +104,7 @@ namespace swrenderer
gzt = pos.Z + scale.Y * scaled_to; gzt = pos.Z + scale.Y * scaled_to;
gzb = pos.Z + scale.Y * scaled_bo; gzb = pos.Z + scale.Y * scaled_bo;
vis = VisibleSpriteList::Add(); vissprite_t *vis = RenderMemory::NewObject<vissprite_t>();
vis->CurrentPortalUniq = renderportal->CurrentPortalUniq; vis->CurrentPortalUniq = renderportal->CurrentPortalUniq;
vis->x1 = wallc.sx1 < renderportal->WindowLeft ? renderportal->WindowLeft : wallc.sx1; vis->x1 = wallc.sx1 < renderportal->WindowLeft ? renderportal->WindowLeft : wallc.sx1;
vis->x2 = wallc.sx2 >= renderportal->WindowRight ? renderportal->WindowRight : wallc.sx2; vis->x2 = wallc.sx2 >= renderportal->WindowRight ? renderportal->WindowRight : wallc.sx2;
@ -137,6 +136,8 @@ namespace swrenderer
vis->Style.BaseColormap = basecolormap; vis->Style.BaseColormap = basecolormap;
vis->wallc = wallc; vis->wallc = wallc;
vis->foggy = foggy; vis->foggy = foggy;
VisibleSpriteList::Instance()->Push(vis);
} }
void RenderWallSprite::Render(vissprite_t *spr, const short *mfloorclip, const short *mceilingclip) void RenderWallSprite::Render(vissprite_t *spr, const short *mfloorclip, const short *mceilingclip)