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;
DVector3 savedpos = ViewPos;
DAngle savedangle = ViewAngle;
ptrdiff_t savedvissprite_p = VisibleSpriteList::vissprite_p - VisibleSpriteList::vissprites;
ptrdiff_t savedds_p = ds_p - drawsegs;
size_t savedinteresting = FirstInterestingDrawseg;
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->sprtopclip, ceilingclip + pl->left, (pl->right - pl->left) * sizeof(short));
VisibleSpriteList::firstvissprite = VisibleSpriteList::vissprite_p;
firstdrawseg = draw_segment;
FirstInterestingDrawseg = InterestingDrawsegs.Size();
interestingStack.Push(FirstInterestingDrawseg);
ptrdiff_t diffnum = firstdrawseg - drawsegs;
drawsegStack.Push(diffnum);
diffnum = VisibleSpriteList::firstvissprite - VisibleSpriteList::vissprites;
visspriteStack.Push(diffnum);
VisibleSpriteList::Instance()->PushPortal();
viewposStack.Push(ViewPos);
visplaneStack.Push(pl);
@ -249,8 +246,6 @@ namespace swrenderer
drawsegStack.Pop(pd);
firstdrawseg = drawsegs + pd;
visspriteStack.Pop(pd);
VisibleSpriteList::firstvissprite = VisibleSpriteList::vissprites + pd;
// Masked textures and planes need the view coordinates restored for proper positioning.
viewposStack.Pop(ViewPos);
@ -258,7 +253,8 @@ namespace swrenderer
RenderTranslucentPass::Render();
ds_p = firstdrawseg;
VisibleSpriteList::vissprite_p = VisibleSpriteList::firstvissprite;
VisibleSpriteList::Instance()->PopPortal();
visplaneStack.Pop(pl);
if (pl->Alpha > 0 && pl->picnum != skyflatnum)
@ -268,8 +264,6 @@ namespace swrenderer
*planes->freehead = pl;
planes->freehead = &pl->next;
}
VisibleSpriteList::firstvissprite = VisibleSpriteList::vissprites;
VisibleSpriteList::vissprite_p = VisibleSpriteList::vissprites + savedvissprite_p;
firstdrawseg = drawsegs;
ds_p = drawsegs + savedds_p;
InterestingDrawsegs.Resize((unsigned int)FirstInterestingDrawseg);

View file

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

View file

@ -51,14 +51,12 @@ namespace swrenderer
void RenderTranslucentPass::Deinit()
{
VisibleSpriteList::Deinit();
SortedVisibleSpriteList::Deinit();
RenderVoxel::Deinit();
}
void RenderTranslucentPass::Clear()
{
VisibleSpriteList::Clear();
VisibleSpriteList::Instance()->Clear();
DrewAVoxel = false;
}
@ -529,11 +527,12 @@ namespace swrenderer
{
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
DrawSprite(SortedVisibleSpriteList::spritesorter[i - 1]);
DrawSprite(sortedSprites[i - 1]);
}
// render any remaining masked mid textures
@ -565,7 +564,7 @@ namespace swrenderer
void RenderTranslucentPass::Render()
{
CollectPortals();
SortedVisibleSpriteList::Sort(DrewAVoxel ? SortedVisibleSpriteList::sv_compare2d : SortedVisibleSpriteList::sv_compare, VisibleSpriteList::firstvissprite - VisibleSpriteList::vissprites);
VisibleSpriteList::Instance()->Sort(DrewAVoxel);
Clip3DFloors *clip3d = Clip3DFloors::Instance();
if (clip3d->height_top == nullptr)

View file

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

View file

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

View file

@ -28,118 +28,78 @@
namespace swrenderer
{
void VisibleSpriteList::Deinit()
VisibleSpriteList *VisibleSpriteList::Instance()
{
// Free vissprites
for (int i = 0; i < MaxVisSprites; ++i)
{
delete vissprites[i];
}
free(vissprites);
vissprites = nullptr;
vissprite_p = lastvissprite = nullptr;
MaxVisSprites = 0;
static VisibleSpriteList instance;
return &instance;
}
void VisibleSpriteList::Clear()
{
vissprite_p = firstvissprite;
Sprites.Clear();
StartIndices.Clear();
SortedSprites.Clear();
}
vissprite_t *VisibleSpriteList::Add()
void VisibleSpriteList::PushPortal()
{
if (vissprite_p == lastvissprite)
{
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);
StartIndices.Push(Sprites.Size());
}
int VisibleSpriteList::MaxVisSprites;
vissprite_t **VisibleSpriteList::vissprites;
vissprite_t **VisibleSpriteList::firstvissprite;
vissprite_t **VisibleSpriteList::vissprite_p;
vissprite_t **VisibleSpriteList::lastvissprite;
/////////////////////////////////////////////////////////////////////////
void SortedVisibleSpriteList::Deinit()
void VisibleSpriteList::PopPortal()
{
delete[] spritesorter;
spritesortersize = 0;
spritesorter = nullptr;
Sprites.Resize(StartIndices.Last());
StartIndices.Pop();
}
// This is the standard version, which does a simple test based on depth.
bool SortedVisibleSpriteList::sv_compare(vissprite_t *a, vissprite_t *b)
void VisibleSpriteList::Push(vissprite_t *sprite)
{
return a->idepth > b->idepth;
Sprites.Push(sprite);
}
// 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.
bool SortedVisibleSpriteList::sv_compare2d(vissprite_t *a, vissprite_t *b)
void VisibleSpriteList::Sort(bool compare2d)
{
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)
{
int i;
vissprite_t **spr;
SortedSprites.Resize(count);
vsprcount = int(VisibleSpriteList::vissprite_p - &VisibleSpriteList::vissprites[first]);
if (vsprcount == 0)
if (count == 0)
return;
if (spritesortersize < VisibleSpriteList::MaxVisSprites)
{
if (spritesorter != nullptr)
delete[] spritesorter;
spritesorter = new vissprite_t *[VisibleSpriteList::MaxVisSprites];
spritesortersize = VisibleSpriteList::MaxVisSprites;
}
if (!(i_compatflags & COMPATF_SPRITESORT))
{
for (i = 0, spr = VisibleSpriteList::firstvissprite; i < vsprcount; i++, spr++)
{
spritesorter[i] = *spr;
}
for (size_t i = 0; i < count; i++)
SortedSprites[i] = Sprites[first + i];
}
else
{
// If the compatibility option is on sprites of equal distance need to
// be sorted in inverse order. This is most easily achieved by
// filling the sort array backwards before the sort.
for (i = 0, spr = VisibleSpriteList::firstvissprite + vsprcount - 1; i < vsprcount; i++, spr--)
{
spritesorter[i] = *spr;
}
for (size_t i = 0; i < count; i++)
SortedSprites[i] = Sprites[first + count - i - 1];
}
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;
int SortedVisibleSpriteList::spritesortersize = 0;
int SortedVisibleSpriteList::vsprcount;
std::stable_sort(&SortedSprites[0], &SortedSprites[count], [](vissprite_t *a, vissprite_t *b) -> bool
{
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
{
public:
static int MaxVisSprites;
static vissprite_t **vissprites;
static vissprite_t **firstvissprite;
static vissprite_t **vissprite_p;
static VisibleSpriteList *Instance();
static void Deinit();
static void Clear();
static vissprite_t *Add();
void Clear();
void PushPortal();
void PopPortal();
void Push(vissprite_t *sprite);
void Sort(bool compare2d);
TArray<vissprite_t *> SortedSprites;
private:
static vissprite_t **lastvissprite;
};
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;
TArray<vissprite_t *> Sprites;
TArray<size_t> StartIndices;
};
}

View file

@ -41,6 +41,7 @@
#include "swrenderer/scene/r_scene.h"
#include "swrenderer/scene/r_viewport.h"
#include "swrenderer/scene/r_light.h"
#include "swrenderer/r_memory.h"
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->xscale = FLOAT2FIXED(xscale);
@ -157,8 +158,6 @@ namespace swrenderer
vis->bWallSprite = false;
vis->foggy = foggy;
RenderTranslucentPass::DrewAVoxel = true;
// 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
// the invert overlay flag says to do.
@ -223,6 +222,9 @@ namespace swrenderer
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)

View file

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