From 57d8b0e34cb46d95ac15cf9b75b0c1618f84477e Mon Sep 17 00:00:00 2001 From: Magnus Norddahl Date: Mon, 16 Jan 2017 03:46:05 +0100 Subject: [PATCH] Rewrite VisibleSpriteList to use TArray --- src/swrenderer/scene/r_portal.cpp | 12 +- src/swrenderer/scene/r_portal.h | 1 - src/swrenderer/scene/r_translucent_pass.cpp | 13 +- src/swrenderer/things/r_particle.cpp | 5 +- src/swrenderer/things/r_sprite.cpp | 4 +- src/swrenderer/things/r_visiblespritelist.cpp | 124 ++++++------------ src/swrenderer/things/r_visiblespritelist.h | 35 ++--- src/swrenderer/things/r_voxel.cpp | 8 +- src/swrenderer/things/r_wallsprite.cpp | 5 +- 9 files changed, 75 insertions(+), 132 deletions(-) diff --git a/src/swrenderer/scene/r_portal.cpp b/src/swrenderer/scene/r_portal.cpp index 69c921716..e799f377c 100644 --- a/src/swrenderer/scene/r_portal.cpp +++ b/src/swrenderer/scene/r_portal.cpp @@ -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); diff --git a/src/swrenderer/scene/r_portal.h b/src/swrenderer/scene/r_portal.h index 178102618..654468d72 100644 --- a/src/swrenderer/scene/r_portal.h +++ b/src/swrenderer/scene/r_portal.h @@ -55,7 +55,6 @@ namespace swrenderer TArray interestingStack; TArray drawsegStack; - TArray visspriteStack; TArray viewposStack; TArray visplaneStack; }; diff --git a/src/swrenderer/scene/r_translucent_pass.cpp b/src/swrenderer/scene/r_translucent_pass.cpp index 1490b9dfa..591b57588 100644 --- a/src/swrenderer/scene/r_translucent_pass.cpp +++ b/src/swrenderer/scene/r_translucent_pass.cpp @@ -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) diff --git a/src/swrenderer/things/r_particle.cpp b/src/swrenderer/things/r_particle.cpp index e8d1cb1b7..60363e980 100644 --- a/src/swrenderer/things/r_particle.cpp +++ b/src/swrenderer/things/r_particle.cpp @@ -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(); 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) diff --git a/src/swrenderer/things/r_sprite.cpp b/src/swrenderer/things/r_sprite.cpp index c7ec7fe2d..d1c55165f 100644 --- a/src/swrenderer/things/r_sprite.cpp +++ b/src/swrenderer/things/r_sprite.cpp @@ -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(); 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) diff --git a/src/swrenderer/things/r_visiblespritelist.cpp b/src/swrenderer/things/r_visiblespritelist.cpp index db6689c80..084f7b49c 100644 --- a/src/swrenderer/things/r_visiblespritelist.cpp +++ b/src/swrenderer/things/r_visiblespritelist.cpp @@ -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; + }); + } + } } diff --git a/src/swrenderer/things/r_visiblespritelist.h b/src/swrenderer/things/r_visiblespritelist.h index 0e3fddfdc..0dd43e000 100644 --- a/src/swrenderer/things/r_visiblespritelist.h +++ b/src/swrenderer/things/r_visiblespritelist.h @@ -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 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 Sprites; + TArray StartIndices; }; } diff --git a/src/swrenderer/things/r_voxel.cpp b/src/swrenderer/things/r_voxel.cpp index c7cdee660..6c4d3322f 100644 --- a/src/swrenderer/things/r_voxel.cpp +++ b/src/swrenderer/things/r_voxel.cpp @@ -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(); 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) diff --git a/src/swrenderer/things/r_wallsprite.cpp b/src/swrenderer/things/r_wallsprite.cpp index 6f4fd79ec..319dcfc89 100644 --- a/src/swrenderer/things/r_wallsprite.cpp +++ b/src/swrenderer/things/r_wallsprite.cpp @@ -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(); 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)