diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index f30bce8470..4895c38476 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -721,6 +721,7 @@ set( FASTMATH_SOURCES rendering/hwrenderer/scene/hw_bsp.cpp rendering/hwrenderer/scene/hw_fakeflat.cpp rendering/hwrenderer/scene/hw_decal.cpp + rendering/hwrenderer/scene/hw_drawcontext.cpp rendering/hwrenderer/scene/hw_drawinfo.cpp rendering/hwrenderer/scene/hw_drawlist.cpp rendering/hwrenderer/scene/hw_clipper.cpp diff --git a/src/rendering/hwrenderer/hw_entrypoint.cpp b/src/rendering/hwrenderer/hw_entrypoint.cpp index 40a52b7318..55a4fe8d5b 100644 --- a/src/rendering/hwrenderer/hw_entrypoint.cpp +++ b/src/rendering/hwrenderer/hw_entrypoint.cpp @@ -48,6 +48,7 @@ #include "hwrenderer/scene/hw_clipper.h" #include "hwrenderer/scene/hw_portal.h" #include "hwrenderer/scene/hw_meshcache.h" +#include "hwrenderer/scene/hw_drawcontext.h" #include "hw_vrmodes.h" EXTERN_CVAR(Bool, cl_capfps) @@ -125,7 +126,11 @@ sector_t* RenderViewpoint(FRenderViewpoint& mainvp, AActor* camera, IntRect* bou screen->SetLevelMesh(camera->Level->levelMesh); - meshcache.Update(mainvp); + static HWDrawContext mainthread_drawctx; + + hw_ClearFakeFlat(&mainthread_drawctx); + + meshcache.Update(&mainthread_drawctx, mainvp); // Update the attenuation flag of all light defaults for each viewpoint. // This function will only do something if the setting differs. @@ -149,7 +154,7 @@ sector_t* RenderViewpoint(FRenderViewpoint& mainvp, AActor* camera, IntRect* bou RenderState.EnableDrawBuffers(RenderState.GetPassDrawBufferCount(), true); } - auto di = HWDrawInfo::StartDrawInfo(mainvp.ViewLevel, nullptr, mainvp, nullptr); + auto di = HWDrawInfo::StartDrawInfo(&mainthread_drawctx, mainvp.ViewLevel, nullptr, mainvp, nullptr); auto& vp = di->Viewpoint; di->Set3DViewport(RenderState); @@ -274,7 +279,6 @@ void WriteSavePic(player_t* player, FileWriter* file, int width, int height) screen->ImageTransitionScene(true); hw_postprocess.SetTonemapMode(level.info ? level.info->tonemap : ETonemapMode::None); - hw_ClearFakeFlat(); RenderState.ResetVertices(); RenderState.SetFlatVertexBuffer(); @@ -327,8 +331,6 @@ sector_t* RenderView(player_t* player) } else { - hw_ClearFakeFlat(); - iter_dlightf = iter_dlight = draw_dlight = draw_dlightf = 0; checkBenchActive(); diff --git a/src/rendering/hwrenderer/hw_models.cpp b/src/rendering/hwrenderer/hw_models.cpp index ebc1fbe447..949fc4f67a 100644 --- a/src/rendering/hwrenderer/hw_models.cpp +++ b/src/rendering/hwrenderer/hw_models.cpp @@ -42,6 +42,7 @@ #include "hw_renderstate.h" #include "hwrenderer/scene/hw_portal.h" #include "hw_models.h" +#include "hwrenderer/scene/hw_drawcontext.h" CVAR(Bool, gl_light_models, true, CVAR_ARCHIVE) EXTERN_CVAR(Bool, gl_texture); @@ -70,7 +71,7 @@ void FHWModelRenderer::BeginDrawModel(FRenderStyle style, FSpriteModelFrame *smf // TO-DO: Implement proper depth sorting. if (!(style == DefaultRenderStyle()) && !(smf->flags & MDL_DONTCULLBACKFACES)) { - state.SetCulling((mirrored ^ portalState.isMirrored()) ? Cull_CCW : Cull_CW); + state.SetCulling((mirrored ^ di->drawctx->portalState.isMirrored()) ? Cull_CCW : Cull_CW); } VSMatrix normalModelMatrix; @@ -105,7 +106,7 @@ void FHWModelRenderer::BeginDrawHUDModel(FRenderStyle style, const VSMatrix &obj // TO-DO: Implement proper depth sorting. if (!(style == DefaultRenderStyle())) { - state.SetCulling((mirrored ^ portalState.isMirrored()) ? Cull_CW : Cull_CCW); + state.SetCulling((mirrored ^ di->drawctx->portalState.isMirrored()) ? Cull_CW : Cull_CCW); } VSMatrix normalModelMatrix; diff --git a/src/rendering/hwrenderer/scene/hw_bsp.cpp b/src/rendering/hwrenderer/scene/hw_bsp.cpp index 684bed8516..49706ca116 100644 --- a/src/rendering/hwrenderer/scene/hw_bsp.cpp +++ b/src/rendering/hwrenderer/scene/hw_bsp.cpp @@ -144,14 +144,14 @@ void HWDrawInfo::WorkerThread() SetupWall.Clock(); wall.sub = job->sub; - front = hw_FakeFlat(job->sub->sector, in_area, false); + front = hw_FakeFlat(drawctx, job->sub->sector, in_area, false); auto seg = job->seg; auto backsector = seg->backsector; if (!backsector && seg->linedef->isVisualPortal() && seg->sidedef == seg->linedef->sidedef[0]) // For one-sided portals use the portal's destination sector as backsector. { auto portal = seg->linedef->getPortal(); backsector = portal->mDestination->frontsector; - back = hw_FakeFlat(backsector, in_area, true); + back = hw_FakeFlat(drawctx, backsector, in_area, true); if (front->floorplane.isSlope() || front->ceilingplane.isSlope() || back->floorplane.isSlope() || back->ceilingplane.isSlope()) { // Having a one-sided portal like this with slopes is too messy so let's ignore that case. @@ -166,7 +166,7 @@ void HWDrawInfo::WorkerThread() } else { - back = hw_FakeFlat(backsector, in_area, true); + back = hw_FakeFlat(drawctx, backsector, in_area, true); } } else back = nullptr; @@ -182,7 +182,7 @@ void HWDrawInfo::WorkerThread() HWFlat flat; SetupFlat.Clock(); flat.section = job->sub->section; - front = hw_FakeFlat(job->sub->render_sector, in_area, false); + front = hw_FakeFlat(drawctx, job->sub->render_sector, in_area, false); flat.ProcessSector(this, state, front); SetupFlat.Unclock(); break; @@ -190,14 +190,14 @@ void HWDrawInfo::WorkerThread() case RenderJob::SpriteJob: SetupSprite.Clock(); - front = hw_FakeFlat(job->sub->sector, in_area, false); + front = hw_FakeFlat(drawctx, job->sub->sector, in_area, false); RenderThings(job->sub, front, state); SetupSprite.Unclock(); break; case RenderJob::ParticleJob: SetupSprite.Clock(); - front = hw_FakeFlat(job->sub->sector, in_area, false); + front = hw_FakeFlat(drawctx, job->sub->sector, in_area, false); RenderParticles(job->sub, front, state); SetupSprite.Unclock(); break; @@ -321,7 +321,7 @@ void HWDrawInfo::AddLine (seg_t *seg, bool portalclip, FRenderState& state) // clipping checks are only needed when the backsector is not the same as the front sector if (in_area == area_default) in_area = hw_CheckViewArea(seg->v1, seg->v2, seg->frontsector, seg->backsector); - backsector = hw_FakeFlat(seg->backsector, in_area, true); + backsector = hw_FakeFlat(drawctx, seg->backsector, in_area, true); if (hw_CheckClip(seg->sidedef, currentsector, backsector)) { @@ -648,7 +648,7 @@ void HWDrawInfo::DoSubsector(subsector_t * sub, FRenderState& state) } if (mClipper->IsBlocked()) return; // if we are inside a stacked sector portal which hasn't unclipped anything yet. - fakesector=hw_FakeFlat(sector, in_area, false); + fakesector=hw_FakeFlat(drawctx, sector, in_area, false); if (mClipPortal) { @@ -725,7 +725,7 @@ void HWDrawInfo::DoSubsector(subsector_t * sub, FRenderState& state) sector = sub->render_sector; // the planes of this subsector are faked to belong to another sector // This means we need the heightsec parts and light info of the render sector, not the actual one. - fakesector = hw_FakeFlat(sector, in_area, false); + fakesector = hw_FakeFlat(drawctx, sector, in_area, false); } uint8_t &srf = section_renderflags[Level->sections.SectionIndex(sub->section)]; diff --git a/src/rendering/hwrenderer/scene/hw_clipper.cpp b/src/rendering/hwrenderer/scene/hw_clipper.cpp index fd69e267c2..b46e7837f4 100644 --- a/src/rendering/hwrenderer/scene/hw_clipper.cpp +++ b/src/rendering/hwrenderer/scene/hw_clipper.cpp @@ -39,13 +39,6 @@ #include "g_levellocals.h" #include "basics.h" -unsigned Clipper::starttime; - -Clipper::Clipper() -{ - starttime++; -} - //----------------------------------------------------------------------------- // // RemoveRange diff --git a/src/rendering/hwrenderer/scene/hw_clipper.h b/src/rendering/hwrenderer/scene/hw_clipper.h index e8da8172cf..4eeff16b35 100644 --- a/src/rendering/hwrenderer/scene/hw_clipper.h +++ b/src/rendering/hwrenderer/scene/hw_clipper.h @@ -1,5 +1,4 @@ -#ifndef __GL_CLIPPER -#define __GL_CLIPPER +#pragma once #include "doomtype.h" #include "xs_Float.h" @@ -22,7 +21,7 @@ class ClipNode class Clipper { - static unsigned starttime; + unsigned int starttime = 1; FMemArena nodearena; ClipNode * freelist = nullptr; @@ -41,8 +40,6 @@ class Clipper public: - Clipper(); - void Clear(); void Free(ClipNode *node) @@ -158,5 +155,3 @@ public: } }; - -#endif diff --git a/src/rendering/hwrenderer/scene/hw_drawcontext.cpp b/src/rendering/hwrenderer/scene/hw_drawcontext.cpp new file mode 100644 index 0000000000..34829b4b80 --- /dev/null +++ b/src/rendering/hwrenderer/scene/hw_drawcontext.cpp @@ -0,0 +1,57 @@ + +#include "hw_drawcontext.h" +#include "hw_drawinfo.h" + +//========================================================================== +// +// Try to reuse the lists as often as possible as they contain resources that +// are expensive to create and delete. +// +// Note: If multithreading gets used, this class needs synchronization. +// +//========================================================================== + +HWDrawInfo* FDrawInfoList::GetNew() +{ + if (mList.Size() > 0) + { + HWDrawInfo* di; + mList.Pop(di); + return di; + } + return new HWDrawInfo(drawctx); +} + +void FDrawInfoList::Release(HWDrawInfo* di) +{ + di->ClearBuffers(); + di->Level = nullptr; + mList.Push(di); +} + +//========================================================================== + +SortNode* StaticSortNodeArray::GetNew() +{ + if (usecount == TArray::Size()) + { + Push(new SortNode); + } + return operator[](usecount++); +} + +//========================================================================== + +HWDrawContext::HWDrawContext() : RenderDataAllocator(1024 * 1024), FakeSectorAllocator(20 * sizeof(sector_t)) +{ + di_list.drawctx = this; +} + +HWDrawContext::~HWDrawContext() +{ +} + +void HWDrawContext::ResetRenderDataAllocator() +{ + RenderDataAllocator.FreeAll(); +} diff --git a/src/rendering/hwrenderer/scene/hw_drawcontext.h b/src/rendering/hwrenderer/scene/hw_drawcontext.h new file mode 100644 index 0000000000..62e971de12 --- /dev/null +++ b/src/rendering/hwrenderer/scene/hw_drawcontext.h @@ -0,0 +1,55 @@ +#pragma once + +#include "common/utility/tarray.h" +#include "hw_clipper.h" +#include "hw_portal.h" + +struct HWDrawInfo; +struct SortNode; +struct FDynamicLight; +class HWDrawContext; + +class FDrawInfoList +{ +public: + HWDrawContext* drawctx = nullptr; + TDeletingArray mList; + + HWDrawInfo* GetNew(); + void Release(HWDrawInfo*); +}; + +class StaticSortNodeArray : public TDeletingArray +{ +public: + unsigned int Size() { return usecount; } + void Clear() { usecount = 0; } + void Release(int start) { usecount = start; } + SortNode* GetNew(); + +private: + unsigned int usecount = 0; +}; + +class HWDrawContext +{ +public: + HWDrawContext(); + ~HWDrawContext(); + + void ResetRenderDataAllocator(); + + FDrawInfoList di_list; + Clipper staticClipper; // Since all scenes are processed sequentially we only need one clipper. + HWDrawInfo* gl_drawinfo = nullptr; // This is a linked list of all active DrawInfos and needed to free the memory arena after the last one goes out of scope. + + FMemArena RenderDataAllocator; // Use large blocks to reduce allocation time. + StaticSortNodeArray SortNodes; + + sector_t** fakesectorbuffer = nullptr; + FMemArena FakeSectorAllocator; + + FPortalSceneState portalState; + + TArray addedLightsArray; +}; diff --git a/src/rendering/hwrenderer/scene/hw_drawinfo.cpp b/src/rendering/hwrenderer/scene/hw_drawinfo.cpp index 8374e2c7fa..d2c2a1eacf 100644 --- a/src/rendering/hwrenderer/scene/hw_drawinfo.cpp +++ b/src/rendering/hwrenderer/scene/hw_drawinfo.cpp @@ -34,6 +34,7 @@ #include "hw_portal.h" #include "hw_renderstate.h" #include "hw_drawinfo.h" +#include "hw_drawcontext.h" #include "po_man.h" #include "models.h" #include "hw_clock.h" @@ -64,50 +65,6 @@ CVAR(Bool, gl_meshcache, false, 0/*CVAR_ARCHIVE | CVAR_GLOBALCONFIG*/) sector_t * hw_FakeFlat(sector_t * sec, sector_t * dest, area_t in_area, bool back); -//========================================================================== -// -// -// -//========================================================================== - -class FDrawInfoList -{ -public: - TDeletingArray mList; - - HWDrawInfo * GetNew(); - void Release(HWDrawInfo *); -}; - - -FDrawInfoList di_list; - -//========================================================================== -// -// Try to reuse the lists as often as possible as they contain resources that -// are expensive to create and delete. -// -// Note: If multithreading gets used, this class needs synchronization. -// -//========================================================================== - -HWDrawInfo *FDrawInfoList::GetNew() -{ - if (mList.Size() > 0) - { - HWDrawInfo *di; - mList.Pop(di); - return di; - } - return new HWDrawInfo(); -} - -void FDrawInfoList::Release(HWDrawInfo * di) -{ - di->ClearBuffers(); - di->Level = nullptr; - mList.Push(di); -} //========================================================================== // @@ -115,28 +72,18 @@ void FDrawInfoList::Release(HWDrawInfo * di) // //========================================================================== -HWDrawInfo *HWDrawInfo::StartDrawInfo(FLevelLocals *lev, HWDrawInfo *parent, FRenderViewpoint &parentvp, HWViewpointUniforms *uniforms) +HWDrawInfo *HWDrawInfo::StartDrawInfo(HWDrawContext* drawctx, FLevelLocals *lev, HWDrawInfo *parent, FRenderViewpoint &parentvp, HWViewpointUniforms *uniforms) { - HWDrawInfo *di = di_list.GetNew(); + HWDrawInfo *di = drawctx->di_list.GetNew(); di->Level = lev; di->StartScene(parentvp, uniforms); return di; } - -//========================================================================== -// -// -// -//========================================================================== - -static Clipper staticClipper; // Since all scenes are processed sequentially we only need one clipper. -static HWDrawInfo * gl_drawinfo; // This is a linked list of all active DrawInfos and needed to free the memory arena after the last one goes out of scope. - void HWDrawInfo::StartScene(FRenderViewpoint &parentvp, HWViewpointUniforms *uniforms) { - staticClipper.Clear(); - mClipper = &staticClipper; + drawctx->staticClipper.Clear(); + mClipper = &drawctx->staticClipper; Viewpoint = parentvp; lightmode = getRealLightmode(Level, true); @@ -181,8 +128,8 @@ void HWDrawInfo::StartScene(FRenderViewpoint &parentvp, HWViewpointUniforms *uni if (outer != nullptr) FullbrightFlags = outer->FullbrightFlags; else FullbrightFlags = 0; - outer = gl_drawinfo; - gl_drawinfo = this; + outer = drawctx->gl_drawinfo; + drawctx->gl_drawinfo = this; } @@ -196,11 +143,11 @@ HWDrawInfo *HWDrawInfo::EndDrawInfo() { assert(this == gl_drawinfo); for (int i = 0; i < GLDL_TYPES; i++) drawlists[i].Reset(); - gl_drawinfo = outer; - di_list.Release(this); - if (gl_drawinfo == nullptr) - ResetRenderDataAllocator(); - return gl_drawinfo; + drawctx->gl_drawinfo = outer; + drawctx->di_list.Release(this); + if (drawctx->gl_drawinfo == nullptr) + drawctx->ResetRenderDataAllocator(); + return drawctx->gl_drawinfo; } @@ -422,7 +369,7 @@ HWPortal * HWDrawInfo::FindPortal(const void * src) HWDecal *HWDrawInfo::AddDecal(bool onmirror) { - auto decal = (HWDecal*)RenderDataAllocator.Alloc(sizeof(HWDecal)); + auto decal = (HWDecal*)drawctx->RenderDataAllocator.Alloc(sizeof(HWDecal)); Decals[onmirror ? 1 : 0].Push(decal); return decal; } @@ -442,7 +389,7 @@ void HWDrawInfo::CreateScene(bool drawpsprites, FRenderState& state) mClipper->SafeAddClipRangeRealAngles(vp.Angles.Yaw.BAMs() + a1, vp.Angles.Yaw.BAMs() - a1); // reset the portal manager - portalState.StartFrame(); + drawctx->portalState.StartFrame(); ProcessAll.Clock(); @@ -583,7 +530,7 @@ void HWDrawInfo::RenderPortal(HWPortal *p, FRenderState &state, bool usestencil) { auto gp = static_cast(p); gp->SetupStencil(this, state, usestencil); - auto new_di = StartDrawInfo(this->Level, this, Viewpoint, &VPUniforms); + auto new_di = StartDrawInfo(drawctx, this->Level, this, Viewpoint, &VPUniforms); new_di->mCurrentPortal = gp; state.SetLightIndex(-1); gp->DrawContents(new_di, state); @@ -840,7 +787,7 @@ void HWDrawInfo::DrawScene(int drawmode, FRenderState& state) } state.SetDepthMask(true); - if (!gl_no_skyclear) portalState.RenderFirstSkyPortal(recursion, this, state); + if (!gl_no_skyclear) drawctx->portalState.RenderFirstSkyPortal(recursion, this, state); RenderScene(state); @@ -853,7 +800,7 @@ void HWDrawInfo::DrawScene(int drawmode, FRenderState& state) // Handle all portals after rendering the opaque objects but before // doing all translucent stuff recursion++; - portalState.EndFrame(this, state); + drawctx->portalState.EndFrame(this, state); recursion--; RenderTranslucent(state); } @@ -867,7 +814,7 @@ void HWDrawInfo::DrawScene(int drawmode, FRenderState& state) void HWDrawInfo::ProcessScene(bool toscreen, FRenderState& state) { - portalState.BeginScene(); + drawctx->portalState.BeginScene(); int mapsection = Level->PointInRenderSubsector(Viewpoint.Pos)->mapsection; CurrentMapSections.Set(mapsection); @@ -886,7 +833,7 @@ void HWDrawInfo::AddSubsectorToPortal(FSectorPortalGroup *ptg, subsector_t *sub) auto portal = FindPortal(ptg); if (!portal) { - portal = new HWSectorStackPortal(&portalState, ptg); + portal = new HWSectorStackPortal(&drawctx->portalState, ptg); Portals.Push(portal); } auto ptl = static_cast(portal); diff --git a/src/rendering/hwrenderer/scene/hw_drawinfo.h b/src/rendering/hwrenderer/scene/hw_drawinfo.h index 268231e76e..6404b78ff3 100644 --- a/src/rendering/hwrenderer/scene/hw_drawinfo.h +++ b/src/rendering/hwrenderer/scene/hw_drawinfo.h @@ -34,12 +34,9 @@ class Clipper; class HWPortal; class HWScenePortalBase; class FRenderState; +class HWDrawContext; -//========================================================================== -// // these are used to link faked planes due to missing textures to a sector -// -//========================================================================== struct gl_subsectorrendernode { gl_subsectorrendernode * next; @@ -132,6 +129,8 @@ struct HWDrawInfo bool isNightvision() const { return !!(FullbrightFlags & Nightvision); } bool isStealthVision() const { return !!(FullbrightFlags & StealthVision); } + HWDrawContext* drawctx = nullptr; + HWDrawList drawlists[GLDL_TYPES]; int vpIndex; ELightMode lightmode; @@ -142,7 +141,6 @@ struct HWDrawInfo std::atomic spriteindex; HWPortal *mClipPortal; HWPortal *mCurrentPortal; - //FRotator mAngles; Clipper *mClipper; FRenderViewpoint Viewpoint; HWViewpointUniforms VPUniforms; // per-viewpoint uniform state @@ -165,9 +163,6 @@ struct HWDrawInfo TMap floodFloorSegs; TMap floodCeilingSegs; - //TArray CeilingStacks; - //TArray FloorStacks; - TArray HandledSubsectors; TArray section_renderflags; @@ -182,44 +177,7 @@ struct HWDrawInfo bool MeshBuilding = false; -private: - // For ProcessLowerMiniseg - bool inview; - subsector_t * viewsubsector; - TArray lowersegs; - - subsector_t *currentsubsector; // used by the line processing code. - sector_t *currentsector; - - void WorkerThread(); - - void UnclipSubsector(subsector_t *sub); - - void AddLine(seg_t *seg, bool portalclip, FRenderState& state); - void PolySubsector(subsector_t * sub, FRenderState& state); - void RenderPolyBSPNode(void *node, FRenderState& state); - void AddPolyobjs(subsector_t *sub, FRenderState& state); - void AddLines(subsector_t * sub, sector_t * sector, FRenderState& state); - void AddSpecialPortalLines(subsector_t * sub, sector_t * sector, linebase_t *line, FRenderState& state); - public: - void RenderThings(subsector_t * sub, sector_t * sector, FRenderState& state); - void RenderParticles(subsector_t *sub, sector_t *front, FRenderState& state); - void DoSubsector(subsector_t * sub, FRenderState& state); - int SetupLightsForOtherPlane(subsector_t * sub, FDynLightData &lightdata, const secplane_t *plane, FRenderState& state); - int CreateOtherPlaneVertices(subsector_t *sub, const secplane_t *plane, FRenderState& state); - void DrawPSprite(HUDSprite *huds, FRenderState &state); - void SetColor(FRenderState &state, int sectorlightlevel, int rellight, bool fullbright, const FColormap &cm, float alpha, bool weapon = false); - void SetFog(FRenderState &state, int lightlevel, int rellight, bool fullbright, const FColormap *cmap, bool isadditive); - void SetShaderLight(FRenderState &state, float level, float olight); - int CalcLightLevel(int lightlevel, int rellight, bool weapon, int blendfactor); - PalEntry CalcLightColor(int light, PalEntry pe, int blendfactor); - float GetFogDensity(int lightlevel, PalEntry fogcolor, int sectorfogdensity, int blendfactor); - bool CheckFog(sector_t *frontsector, sector_t *backsector); - WeaponLighting GetWeaponLighting(sector_t *viewsector, const DVector3 &pos, int cm, area_t in_area, const DVector3 &playerpos); - - void PreparePlayerSprites2D(sector_t * viewsector, area_t in_area, FRenderState& state); - void PreparePlayerSprites3D(sector_t * viewsector, area_t in_area, FRenderState& state); -public: + HWDrawInfo(HWDrawContext* drawctx) : drawctx(drawctx) { for (HWDrawList& list : drawlists) list.drawctx = drawctx; } void SetCameraPos(const DVector3 &pos) { @@ -243,7 +201,7 @@ public: void RenderBSPNode(void *node, FRenderState& state); void RenderBSP(void *node, bool drawpsprites, FRenderState& state); - static HWDrawInfo *StartDrawInfo(FLevelLocals *lev, HWDrawInfo *parent, FRenderViewpoint &parentvp, HWViewpointUniforms *uniforms); + static HWDrawInfo *StartDrawInfo(HWDrawContext* drawctx, FLevelLocals *lev, HWDrawInfo *parent, FRenderViewpoint &parentvp, HWViewpointUniforms *uniforms); void StartScene(FRenderViewpoint &parentvp, HWViewpointUniforms *uniforms); void ClearBuffers(); HWDrawInfo *EndDrawInfo(); @@ -269,8 +227,6 @@ public: bool CollectSubsectorsFloor(subsector_t * sub, sector_t * anchor); bool CheckAnchorCeiling(subsector_t * sub); bool CollectSubsectorsCeiling(subsector_t * sub, sector_t * anchor); - void CollectSectorStacksCeiling(subsector_t * sub, sector_t * anchor, area_t in_area); - void CollectSectorStacksFloor(subsector_t * sub, sector_t * anchor, area_t in_area); void DispatchRenderHacks(FRenderState& state); void AddUpperMissingTexture(side_t * side, subsector_t *sub, float backheight); @@ -284,9 +240,6 @@ public: void AddHackedSubsector(subsector_t * sub); void HandleHackedSubsectors(FRenderState& state); - void AddFloorStack(sector_t * sec); - void AddCeilingStack(sector_t * sec); - void ProcessSectorStacks(area_t in_area); void ProcessActorsInPortal(FLinePortalSpan *glport, area_t in_area, FRenderState& state); @@ -317,6 +270,23 @@ public: void AddFlat(HWFlat *flat, bool fog); void AddSprite(HWSprite *sprite, bool translucent); + void RenderThings(subsector_t* sub, sector_t* sector, FRenderState& state); + void RenderParticles(subsector_t* sub, sector_t* front, FRenderState& state); + void DoSubsector(subsector_t* sub, FRenderState& state); + int SetupLightsForOtherPlane(subsector_t* sub, FDynLightData& lightdata, const secplane_t* plane, FRenderState& state); + int CreateOtherPlaneVertices(subsector_t* sub, const secplane_t* plane, FRenderState& state); + void DrawPSprite(HUDSprite* huds, FRenderState& state); + void SetColor(FRenderState& state, int sectorlightlevel, int rellight, bool fullbright, const FColormap& cm, float alpha, bool weapon = false); + void SetFog(FRenderState& state, int lightlevel, int rellight, bool fullbright, const FColormap* cmap, bool isadditive); + void SetShaderLight(FRenderState& state, float level, float olight); + int CalcLightLevel(int lightlevel, int rellight, bool weapon, int blendfactor); + PalEntry CalcLightColor(int light, PalEntry pe, int blendfactor); + float GetFogDensity(int lightlevel, PalEntry fogcolor, int sectorfogdensity, int blendfactor); + bool CheckFog(sector_t* frontsector, sector_t* backsector); + WeaponLighting GetWeaponLighting(sector_t* viewsector, const DVector3& pos, int cm, area_t in_area, const DVector3& playerpos); + + void PreparePlayerSprites2D(sector_t* viewsector, area_t in_area, FRenderState& state); + void PreparePlayerSprites3D(sector_t* viewsector, area_t in_area, FRenderState& state); HWDecal *AddDecal(bool onmirror); @@ -345,6 +315,25 @@ public: lightmode = ELightMode::Doom; } +private: + // For ProcessLowerMiniseg + bool inview; + subsector_t* viewsubsector; + TArray lowersegs; + + subsector_t* currentsubsector; // used by the line processing code. + sector_t* currentsector; + + void WorkerThread(); + + void UnclipSubsector(subsector_t* sub); + + void AddLine(seg_t* seg, bool portalclip, FRenderState& state); + void PolySubsector(subsector_t* sub, FRenderState& state); + void RenderPolyBSPNode(void* node, FRenderState& state); + void AddPolyobjs(subsector_t* sub, FRenderState& state); + void AddLines(subsector_t* sub, sector_t* sector, FRenderState& state); + void AddSpecialPortalLines(subsector_t* sub, sector_t* sector, linebase_t* line, FRenderState& state); }; void CleanSWDrawer(); diff --git a/src/rendering/hwrenderer/scene/hw_drawlist.cpp b/src/rendering/hwrenderer/scene/hw_drawlist.cpp index 9d524034cf..2d8b85e0b7 100644 --- a/src/rendering/hwrenderer/scene/hw_drawlist.cpp +++ b/src/rendering/hwrenderer/scene/hw_drawlist.cpp @@ -37,41 +37,7 @@ #include "hw_renderstate.h" #include "hw_drawinfo.h" #include "hw_fakeflat.h" - -FMemArena RenderDataAllocator(1024*1024); // Use large blocks to reduce allocation time. - -void ResetRenderDataAllocator() -{ - RenderDataAllocator.FreeAll(); -} - -//========================================================================== -// -// -// -//========================================================================== -class StaticSortNodeArray : public TDeletingArray -{ - unsigned usecount; -public: - unsigned Size() { return usecount; } - void Clear() { usecount=0; } - void Release(int start) { usecount=start; } - SortNode * GetNew(); -}; - - -SortNode * StaticSortNodeArray::GetNew() -{ - if (usecount==TArray::Size()) - { - Push(new SortNode); - } - return operator[](usecount++); -} - - -static StaticSortNodeArray SortNodes; +#include "hw_drawcontext.h" //========================================================================== // @@ -80,7 +46,7 @@ static StaticSortNodeArray SortNodes; //========================================================================== void HWDrawList::Reset() { - if (sorted) SortNodes.Release(SortNodeStart); + if (sorted) drawctx->SortNodes.Release(SortNodeStart); sorted=NULL; walls.Clear(); flats.Clear(); @@ -163,9 +129,9 @@ void HWDrawList::MakeSortList() SortNode * p, * n, * c; unsigned i; - SortNodeStart=SortNodes.Size(); + SortNodeStart=drawctx->SortNodes.Size(); p=NULL; - n=SortNodes.GetNew(); + n=drawctx->SortNodes.GetNew(); for(i=0;iitemindex=(int)i; @@ -174,7 +140,7 @@ void HWDrawList::MakeSortList() p=n; if (i!=drawitems.Size()-1) { - c=SortNodes.GetNew(); + c=drawctx->SortNodes.GetNew(); n->next=c; n=c; } @@ -308,7 +274,7 @@ void HWDrawList::SortWallIntoPlane(HWDrawInfo* di, FRenderState& state, SortNode ws->MakeVertices(di, state, false); } - SortNode * sort2 = SortNodes.GetNew(); + SortNode * sort2 = drawctx->SortNodes.GetNew(); memset(sort2, 0, sizeof(SortNode)); sort2->itemindex = drawitems.Size() - 1; @@ -365,7 +331,7 @@ void HWDrawList::SortSpriteIntoPlane(SortNode * head, SortNode * sort) } } - SortNode * sort2 = SortNodes.GetNew(); + SortNode * sort2 = drawctx->SortNodes.GetNew(); memset(sort2, 0, sizeof(SortNode)); sort2->itemindex = drawitems.Size() - 1; @@ -454,7 +420,7 @@ void HWDrawList::SortWallIntoWall(HWDrawInfo *di, FRenderState& state, SortNode ws->MakeVertices(di, state, false); w->MakeVertices(di, state, false); - SortNode * sort2=SortNodes.GetNew(); + SortNode * sort2=drawctx->SortNodes.GetNew(); memset(sort2,0,sizeof(SortNode)); sort2->itemindex=drawitems.Size()-1; @@ -553,7 +519,7 @@ void HWDrawList::SortSpriteIntoWall(HWDrawInfo *di, FRenderState& state, SortNod s->y1=ss->y2=iy; s->ul=ss->ur=iu; - SortNode * sort2=SortNodes.GetNew(); + SortNode * sort2=drawctx->SortNodes.GetNew(); memset(sort2,0,sizeof(SortNode)); sort2->itemindex=drawitems.Size()-1; @@ -711,7 +677,7 @@ void HWDrawList::Sort(HWDrawInfo *di, FRenderState& state) reverseSort = !!(di->Level->i_compatflags & COMPATF_SPRITESORT); SortZ = di->Viewpoint.Pos.Z; MakeSortList(); - sorted = DoSort(di, state, SortNodes[SortNodeStart]); + sorted = DoSort(di, state, drawctx->SortNodes[SortNodeStart]); } //========================================================================== @@ -758,7 +724,7 @@ void HWDrawList::SortFlats() HWWall *HWDrawList::NewWall() { - auto wall = (HWWall*)RenderDataAllocator.Alloc(sizeof(HWWall)); + auto wall = (HWWall*)drawctx->RenderDataAllocator.Alloc(sizeof(HWWall)); drawitems.Push(HWDrawItem(DrawType_WALL, walls.Push(wall))); return wall; } @@ -770,7 +736,7 @@ HWWall *HWDrawList::NewWall() //========================================================================== HWFlat *HWDrawList::NewFlat() { - auto flat = (HWFlat*)RenderDataAllocator.Alloc(sizeof(HWFlat)); + auto flat = (HWFlat*)drawctx->RenderDataAllocator.Alloc(sizeof(HWFlat)); drawitems.Push(HWDrawItem(DrawType_FLAT,flats.Push(flat))); return flat; } @@ -782,7 +748,7 @@ HWFlat *HWDrawList::NewFlat() //========================================================================== HWSprite *HWDrawList::NewSprite() { - auto sprite = (HWSprite*)RenderDataAllocator.Alloc(sizeof(HWSprite)); + auto sprite = (HWSprite*)drawctx->RenderDataAllocator.Alloc(sizeof(HWSprite)); drawitems.Push(HWDrawItem(DrawType_SPRITE, sprites.Push(sprite))); return sprite; } diff --git a/src/rendering/hwrenderer/scene/hw_drawlist.h b/src/rendering/hwrenderer/scene/hw_drawlist.h index 39a46910ff..ec61c9bc18 100644 --- a/src/rendering/hwrenderer/scene/hw_drawlist.h +++ b/src/rendering/hwrenderer/scene/hw_drawlist.h @@ -2,12 +2,11 @@ #include "memarena.h" -extern FMemArena RenderDataAllocator; -void ResetRenderDataAllocator(); struct HWDrawInfo; class HWWall; class HWFlat; class HWSprite; +class HWDrawContext; class FRenderState; //========================================================================== @@ -60,22 +59,21 @@ struct SortNode struct HWDrawList { - //private: + HWDrawContext* drawctx = nullptr; TArray walls; TArray flats; TArray sprites; TArray drawitems; - int SortNodeStart; - float SortZ; - SortNode * sorted; - bool reverseSort; + int SortNodeStart = 0; + float SortZ = 0.0f; + SortNode* sorted = nullptr; + bool reverseSort = false; -public: HWDrawList() { - next=NULL; + next=nullptr; SortNodeStart=-1; - sorted=NULL; + sorted=nullptr; } ~HWDrawList() @@ -117,7 +115,7 @@ public: void DrawSorted(HWDrawInfo *di, FRenderState &state, SortNode * head); void DrawSorted(HWDrawInfo *di, FRenderState &state); - HWDrawList * next; + HWDrawList *next = nullptr; } ; diff --git a/src/rendering/hwrenderer/scene/hw_drawstructs.h b/src/rendering/hwrenderer/scene/hw_drawstructs.h index 4925daeb10..2104a6b218 100644 --- a/src/rendering/hwrenderer/scene/hw_drawstructs.h +++ b/src/rendering/hwrenderer/scene/hw_drawstructs.h @@ -29,6 +29,7 @@ class FRenderState; struct HWDecal; struct FSection; enum area_t : int; +class HWDrawContext; enum HWRenderStyle { @@ -432,7 +433,7 @@ inline float Dist2(float x1,float y1,float x2,float y2) return sqrtf((x1-x2)*(x1-x2)+(y1-y2)*(y1-y2)); } -void hw_GetDynModelLight(AActor *self, FDynLightData &modellightdata); +void hw_GetDynModelLight(HWDrawContext* drawctx, AActor *self, FDynLightData &modellightdata); extern const float LARGE_VALUE; diff --git a/src/rendering/hwrenderer/scene/hw_fakeflat.cpp b/src/rendering/hwrenderer/scene/hw_fakeflat.cpp index bc51fb3dd8..fe85251388 100644 --- a/src/rendering/hwrenderer/scene/hw_fakeflat.cpp +++ b/src/rendering/hwrenderer/scene/hw_fakeflat.cpp @@ -34,11 +34,10 @@ #include "hw_fakeflat.h" #include "hw_drawinfo.h" #include "hw_cvars.h" +#include "hw_drawcontext.h" #include "r_utility.h" #include "texturemanager.h" -static sector_t **fakesectorbuffer; - extern thread_local bool isWorkerThread; //========================================================================== @@ -186,24 +185,17 @@ area_t hw_CheckViewArea(vertex_t *v1, vertex_t *v2, sector_t *frontsector, secto return area_default; } -//========================================================================== -// -// -// -//========================================================================== -static FMemArena FakeSectorAllocator(20 * sizeof(sector_t)); - -static sector_t *allocateSector(sector_t *sec) +static sector_t *allocateSector(HWDrawContext* drawctx, sector_t *sec) { - if (fakesectorbuffer == nullptr) + if (drawctx->fakesectorbuffer == nullptr) { unsigned numsectors = sec->Level->sectors.Size(); - fakesectorbuffer = (sector_t**)FakeSectorAllocator.Alloc(numsectors * sizeof(sector_t*)); - memset(fakesectorbuffer, 0, numsectors * sizeof(sector_t*)); + drawctx->fakesectorbuffer = (sector_t**)drawctx->FakeSectorAllocator.Alloc(numsectors * sizeof(sector_t*)); + memset(drawctx->fakesectorbuffer, 0, numsectors * sizeof(sector_t*)); } auto sectornum = sec->sectornum; - fakesectorbuffer[sectornum] = (sector_t*)FakeSectorAllocator.Alloc(sizeof(sector_t)); - return fakesectorbuffer[sectornum]; + drawctx->fakesectorbuffer[sectornum] = (sector_t*)drawctx->FakeSectorAllocator.Alloc(sizeof(sector_t)); + return drawctx->fakesectorbuffer[sectornum]; } //========================================================================== @@ -213,7 +205,7 @@ static sector_t *allocateSector(sector_t *sec) // //========================================================================== -sector_t * hw_FakeFlat(sector_t * sec, area_t in_area, bool back, sector_t *localcopy) +sector_t * hw_FakeFlat(HWDrawContext* drawctx, sector_t * sec, area_t in_area, bool back, sector_t *localcopy) { if (!sec->GetHeightSec() || sec->heightsec==sec) { @@ -221,8 +213,8 @@ sector_t * hw_FakeFlat(sector_t * sec, area_t in_area, bool back, sector_t *loca // visual glitches because upper amd lower textures overlap. if (back && (sec->MoreFlags & SECMF_OVERLAPPING)) { - if (fakesectorbuffer && fakesectorbuffer[sec->sectornum]) return fakesectorbuffer[sec->sectornum]; - auto dest = localcopy? localcopy : allocateSector(sec); + if (drawctx->fakesectorbuffer && drawctx->fakesectorbuffer[sec->sectornum]) return drawctx->fakesectorbuffer[sec->sectornum]; + auto dest = localcopy? localcopy : allocateSector(drawctx, sec); *dest = *sec; dest->floorplane = sec->ceilingplane; dest->floorplane.FlipVert(); @@ -241,9 +233,9 @@ sector_t * hw_FakeFlat(sector_t * sec, area_t in_area, bool back, sector_t *loca } #endif - if (fakesectorbuffer && fakesectorbuffer[sec->sectornum]) + if (drawctx->fakesectorbuffer && drawctx->fakesectorbuffer[sec->sectornum]) { - return fakesectorbuffer[sec->sectornum]; + return drawctx->fakesectorbuffer[sec->sectornum]; } assert(!(isWorkerThread && localcopy == nullptr)); @@ -255,7 +247,7 @@ sector_t * hw_FakeFlat(sector_t * sec, area_t in_area, bool back, sector_t *loca int diffTex = (sec->heightsec->MoreFlags & SECMF_CLIPFAKEPLANES); sector_t * s = sec->heightsec; - auto dest = localcopy ? localcopy : allocateSector(sec); + auto dest = localcopy ? localcopy : allocateSector(drawctx, sec); *dest = *sec; // Replace floor and ceiling height with control sector's heights. @@ -417,8 +409,8 @@ sector_t * hw_FakeFlat(sector_t * sec, area_t in_area, bool back, sector_t *loca } -void hw_ClearFakeFlat() +void hw_ClearFakeFlat(HWDrawContext* drawctx) { - FakeSectorAllocator.FreeAll(); - fakesectorbuffer = nullptr; + drawctx->FakeSectorAllocator.FreeAll(); + drawctx->fakesectorbuffer = nullptr; } diff --git a/src/rendering/hwrenderer/scene/hw_fakeflat.h b/src/rendering/hwrenderer/scene/hw_fakeflat.h index 2f670d222a..fdecdf2536 100644 --- a/src/rendering/hwrenderer/scene/hw_fakeflat.h +++ b/src/rendering/hwrenderer/scene/hw_fakeflat.h @@ -1,5 +1,7 @@ #pragma once +class HWDrawContext; + enum area_t : int { area_normal, @@ -8,10 +10,9 @@ enum area_t : int area_default }; - // Global functions. bool hw_CheckClip(side_t * sidedef, sector_t * frontsector, sector_t * backsector); -void hw_ClearFakeFlat(); -sector_t * hw_FakeFlat(sector_t * sec, area_t in_area, bool back, sector_t *localcopy = nullptr); +void hw_ClearFakeFlat(HWDrawContext* drawctx); +sector_t * hw_FakeFlat(HWDrawContext* drawctx, sector_t * sec, area_t in_area, bool back, sector_t *localcopy = nullptr); area_t hw_CheckViewArea(vertex_t *v1, vertex_t *v2, sector_t *frontsector, sector_t *backsector); diff --git a/src/rendering/hwrenderer/scene/hw_meshcache.cpp b/src/rendering/hwrenderer/scene/hw_meshcache.cpp index c838ee21d5..1e82634738 100644 --- a/src/rendering/hwrenderer/scene/hw_meshcache.cpp +++ b/src/rendering/hwrenderer/scene/hw_meshcache.cpp @@ -24,7 +24,7 @@ void HWMeshCache::Clear() TranslucentDepthBiased.reset(); } -void HWMeshCache::Update(FRenderViewpoint& vp) +void HWMeshCache::Update(HWDrawContext* drawctx, FRenderViewpoint& vp) { if (!gl_meshcache) return; @@ -74,7 +74,7 @@ void HWMeshCache::Update(FRenderViewpoint& vp) if (!Opaque) { - HWDrawInfo* di = HWDrawInfo::StartDrawInfo(vp.ViewLevel, nullptr, vp, nullptr); + HWDrawInfo* di = HWDrawInfo::StartDrawInfo(drawctx, vp.ViewLevel, nullptr, vp, nullptr); di->MeshBuilding = true; MeshBuilder state; @@ -98,7 +98,7 @@ void HWMeshCache::Update(FRenderViewpoint& vp) HWFlat flat; flat.section = subsector->section; - sector_t* front = hw_FakeFlat(subsector->render_sector, area_default, false); + sector_t* front = hw_FakeFlat(di->drawctx, subsector->render_sector, area_default, false); flat.ProcessSector(di, state, front); } } diff --git a/src/rendering/hwrenderer/scene/hw_meshcache.h b/src/rendering/hwrenderer/scene/hw_meshcache.h index 5ca6bf269e..03dfcafa06 100644 --- a/src/rendering/hwrenderer/scene/hw_meshcache.h +++ b/src/rendering/hwrenderer/scene/hw_meshcache.h @@ -4,6 +4,7 @@ #include "r_defs.h" struct FRenderViewpoint; +class HWDrawContext; #if 0 class HWCachedSector @@ -21,7 +22,7 @@ class HWMeshCache { public: void Clear(); - void Update(FRenderViewpoint& vp); + void Update(HWDrawContext* drawctx, FRenderViewpoint& vp); #if 0 TArray Sectors; diff --git a/src/rendering/hwrenderer/scene/hw_portal.cpp b/src/rendering/hwrenderer/scene/hw_portal.cpp index 3389487861..b84dc9ae25 100644 --- a/src/rendering/hwrenderer/scene/hw_portal.cpp +++ b/src/rendering/hwrenderer/scene/hw_portal.cpp @@ -73,7 +73,6 @@ CCMD(gl_portalinfo) } static FString indent; -FPortalSceneState portalState; //----------------------------------------------------------------------------- // diff --git a/src/rendering/hwrenderer/scene/hw_portal.h b/src/rendering/hwrenderer/scene/hw_portal.h index 218c09a15f..deb658fca1 100644 --- a/src/rendering/hwrenderer/scene/hw_portal.h +++ b/src/rendering/hwrenderer/scene/hw_portal.h @@ -55,7 +55,7 @@ class HWPortal STP_AllInOne }; - ActorRenderFlags savedvisibility; + ActorRenderFlags savedvisibility = {}; TArray mPrimIndices; unsigned int mTopCap = ~0u, mBottomCap = ~0u; @@ -130,7 +130,6 @@ struct FPortalSceneState void RenderPortal(HWPortal *p, FRenderState &state, bool usestencil, HWDrawInfo *outer_di); }; -extern FPortalSceneState portalState; class HWScenePortalBase : public HWPortal diff --git a/src/rendering/hwrenderer/scene/hw_renderhacks.cpp b/src/rendering/hwrenderer/scene/hw_renderhacks.cpp index 2418fd8828..2c83b1e49a 100644 --- a/src/rendering/hwrenderer/scene/hw_renderhacks.cpp +++ b/src/rendering/hwrenderer/scene/hw_renderhacks.cpp @@ -33,6 +33,7 @@ #include "a_dynlight.h" #include "texturemanager.h" +#include "hw_drawcontext.h" #include "hw_drawinfo.h" #include "hw_drawstructs.h" #include "hw_clock.h" @@ -56,28 +57,28 @@ void HWDrawInfo::DispatchRenderHacks(FRenderState& state) glflat.section = nullptr; while (ofi.NextPair(pair)) { - auto sec = hw_FakeFlat(&Level->sectors[pair->Key], in_area, false); + auto sec = hw_FakeFlat(drawctx, &Level->sectors[pair->Key], in_area, false); glflat.ProcessSector(this, state, sec, SSRF_RENDERFLOOR | SSRF_PLANEHACK); } TMap::Iterator oci(otherCeilingPlanes); while (oci.NextPair(pair)) { - auto sec = hw_FakeFlat(&Level->sectors[pair->Key], in_area, false); + auto sec = hw_FakeFlat(drawctx, &Level->sectors[pair->Key], in_area, false); glflat.ProcessSector(this, state, sec, SSRF_RENDERCEILING | SSRF_PLANEHACK); } TMap::Iterator ffi(floodFloorSegs); while (ffi.NextPair(fpair)) { - auto sec = hw_FakeFlat(&Level->sectors[fpair->Key], in_area, false); + auto sec = hw_FakeFlat(drawctx, &Level->sectors[fpair->Key], in_area, false); glflat.ProcessSector(this, state, sec, SSRF_RENDERFLOOR | SSRF_FLOODHACK); } TMap::Iterator fci(floodCeilingSegs); while (fci.NextPair(fpair)) { - auto sec = hw_FakeFlat(&Level->sectors[fpair->Key], in_area, false); + auto sec = hw_FakeFlat(drawctx, &Level->sectors[fpair->Key], in_area, false); glflat.ProcessSector(this, state, sec, SSRF_RENDERCEILING | SSRF_FLOODHACK); } } @@ -89,14 +90,14 @@ void HWDrawInfo::DispatchRenderHacks(FRenderState& state) // //========================================================================== -static gl_subsectorrendernode *NewSubsectorRenderNode() +static gl_subsectorrendernode *NewSubsectorRenderNode(HWDrawContext* drawctx) { - return (gl_subsectorrendernode*)RenderDataAllocator.Alloc(sizeof(gl_subsectorrendernode)); + return (gl_subsectorrendernode*)drawctx->RenderDataAllocator.Alloc(sizeof(gl_subsectorrendernode)); } -static gl_floodrendernode *NewFloodRenderNode() +static gl_floodrendernode *NewFloodRenderNode(HWDrawContext* drawctx) { - return (gl_floodrendernode*)RenderDataAllocator.Alloc(sizeof(gl_floodrendernode)); + return (gl_floodrendernode*)drawctx->RenderDataAllocator.Alloc(sizeof(gl_floodrendernode)); } //========================================================================== @@ -335,7 +336,7 @@ bool HWDrawInfo::DoOneSectorUpper(subsector_t * subsec, float Planez, area_t in_ // Note: if this is a real line between sectors // we can be sure that render_sector is the real sector! - sector_t * sec = hw_FakeFlat(seg->backsector, in_area, true); + sector_t * sec = hw_FakeFlat(drawctx, seg->backsector, in_area, true); // Don't bother with slopes if (sec->ceilingplane.isSlope()) return false; @@ -393,7 +394,7 @@ bool HWDrawInfo::DoOneSectorLower(subsector_t * subsec, float Planez, area_t in_ // Note: if this is a real line between sectors // we can be sure that render_sector is the real sector! - sector_t * sec = hw_FakeFlat(seg->backsector, in_area, true); + sector_t * sec = hw_FakeFlat(drawctx, seg->backsector, in_area, true); // Don't bother with slopes if (sec->floorplane.isSlope()) return false; @@ -452,7 +453,7 @@ bool HWDrawInfo::DoFakeBridge(subsector_t * subsec, float Planez, area_t in_area // Note: if this is a real line between sectors // we can be sure that render_sector is the real sector! - sector_t * sec = hw_FakeFlat(seg->backsector, in_area, true); + sector_t * sec = hw_FakeFlat(drawctx, seg->backsector, in_area, true); // Don't bother with slopes if (sec->floorplane.isSlope()) return false; @@ -505,7 +506,7 @@ bool HWDrawInfo::DoFakeCeilingBridge(subsector_t * subsec, float Planez, area_t // Note: if this is a real line between sectors // we can be sure that render_sector is the real sector! - sector_t * sec = hw_FakeFlat(seg->backsector, in_area, true); + sector_t * sec = hw_FakeFlat(drawctx, seg->backsector, in_area, true); // Don't bother with slopes if (sec->ceilingplane.isSlope()) return false; @@ -553,7 +554,7 @@ void HWDrawInfo::HandleMissingTextures(area_t in_area, FRenderState& state) sector_t * sec = MissingUpperTextures[i].seg->backsector; for (unsigned int j = 0; j < HandledSubsectors.Size(); j++) { - gl_subsectorrendernode * node = NewSubsectorRenderNode(); + gl_subsectorrendernode * node = NewSubsectorRenderNode(drawctx); node->sub = HandledSubsectors[j]; AddOtherCeilingPlane(sec->sectornum, node, state); @@ -586,7 +587,7 @@ void HWDrawInfo::HandleMissingTextures(area_t in_area, FRenderState& state) { // It isn't a hole. Now check whether it might be a fake bridge - sector_t * fakesector = hw_FakeFlat(MissingUpperTextures[i].seg->frontsector, in_area, false); + sector_t * fakesector = hw_FakeFlat(drawctx, MissingUpperTextures[i].seg->frontsector, in_area, false); float planez = (float)fakesector->GetPlaneTexZ(sector_t::ceiling); backsub->validcount = validcount; @@ -594,7 +595,7 @@ void HWDrawInfo::HandleMissingTextures(area_t in_area, FRenderState& state) { for (unsigned int j = 0; j < HandledSubsectors.Size(); j++) { - gl_subsectorrendernode * node = NewSubsectorRenderNode(); + gl_subsectorrendernode * node = NewSubsectorRenderNode(drawctx); node->sub = HandledSubsectors[j]; AddOtherCeilingPlane(fakesector->sectornum, node, state); } @@ -620,7 +621,7 @@ void HWDrawInfo::HandleMissingTextures(area_t in_area, FRenderState& state) for (unsigned int j = 0; j < HandledSubsectors.Size(); j++) { - gl_subsectorrendernode * node = NewSubsectorRenderNode(); + gl_subsectorrendernode * node = NewSubsectorRenderNode(drawctx); node->sub = HandledSubsectors[j]; AddOtherFloorPlane(sec->sectornum, node, state); } @@ -652,7 +653,7 @@ void HWDrawInfo::HandleMissingTextures(area_t in_area, FRenderState& state) { // It isn't a hole. Now check whether it might be a fake bridge - sector_t * fakesector = hw_FakeFlat(MissingLowerTextures[i].seg->frontsector, in_area, false); + sector_t * fakesector = hw_FakeFlat(drawctx, MissingLowerTextures[i].seg->frontsector, in_area, false); float planez = (float)fakesector->GetPlaneTexZ(sector_t::floor); backsub->validcount = validcount; @@ -660,7 +661,7 @@ void HWDrawInfo::HandleMissingTextures(area_t in_area, FRenderState& state) { for (unsigned int j = 0; j < HandledSubsectors.Size(); j++) { - gl_subsectorrendernode * node = NewSubsectorRenderNode(); + gl_subsectorrendernode * node = NewSubsectorRenderNode(drawctx); node->sub = HandledSubsectors[j]; AddOtherFloorPlane(fakesector->sectornum, node, state); } @@ -726,8 +727,8 @@ void HWDrawInfo::CreateFloodPoly(wallseg * ws, FFlatVertex *vertices, float plan void HWDrawInfo::PrepareUpperGap(seg_t * seg, FRenderState& state) { wallseg ws; - sector_t * fakefsector = hw_FakeFlat(seg->frontsector, in_area, false); - sector_t * fakebsector = hw_FakeFlat(seg->backsector, in_area, true); + sector_t * fakefsector = hw_FakeFlat(drawctx, seg->frontsector, in_area, false); + sector_t * fakebsector = hw_FakeFlat(drawctx, seg->backsector, in_area, true); vertex_t * v1, *v2; @@ -763,7 +764,7 @@ void HWDrawInfo::PrepareUpperGap(seg_t * seg, FRenderState& state) CreateFloodStencilPoly(&ws, vertices.first); CreateFloodPoly(&ws, vertices.first+4, ws.z2, fakebsector, true); - gl_floodrendernode *node = NewFloodRenderNode(); + gl_floodrendernode *node = NewFloodRenderNode(drawctx); auto pNode = floodCeilingSegs.CheckKey(fakebsector->sectornum); node->next = pNode? *pNode : nullptr; @@ -782,8 +783,8 @@ void HWDrawInfo::PrepareUpperGap(seg_t * seg, FRenderState& state) void HWDrawInfo::PrepareLowerGap(seg_t * seg, FRenderState& state) { wallseg ws; - sector_t * fakefsector = hw_FakeFlat(seg->frontsector, in_area, false); - sector_t * fakebsector = hw_FakeFlat(seg->backsector, in_area, true); + sector_t * fakefsector = hw_FakeFlat(drawctx, seg->frontsector, in_area, false); + sector_t * fakebsector = hw_FakeFlat(drawctx, seg->backsector, in_area, true); vertex_t * v1, *v2; @@ -820,7 +821,7 @@ void HWDrawInfo::PrepareLowerGap(seg_t * seg, FRenderState& state) CreateFloodStencilPoly(&ws, vertices.first); CreateFloodPoly(&ws, vertices.first+4, ws.z1, fakebsector, false); - gl_floodrendernode *node = NewFloodRenderNode(); + gl_floodrendernode *node = NewFloodRenderNode(drawctx); auto pNode = floodFloorSegs.CheckKey(fakebsector->sectornum); node->next = pNode? *pNode : nullptr; @@ -1141,7 +1142,7 @@ void HWDrawInfo::HandleHackedSubsectors(FRenderState& state) { for(unsigned int j=0;jsub = HandledSubsectors[j]; AddOtherFloorPlane(sub->render_sector->sectornum, node, state); } @@ -1163,7 +1164,7 @@ void HWDrawInfo::HandleHackedSubsectors(FRenderState& state) { for(unsigned int j=0;jsub = HandledSubsectors[j]; AddOtherCeilingPlane(sub->render_sector->sectornum, node, state); } diff --git a/src/rendering/hwrenderer/scene/hw_setcolor.cpp b/src/rendering/hwrenderer/scene/hw_setcolor.cpp index 2b0783a8fe..946be1c68e 100644 --- a/src/rendering/hwrenderer/scene/hw_setcolor.cpp +++ b/src/rendering/hwrenderer/scene/hw_setcolor.cpp @@ -31,7 +31,7 @@ #include "hw_portal.h" #include "hw_lighting.h" #include "hw_cvars.h" - +#include "hw_drawcontext.h" //========================================================================== // @@ -119,7 +119,7 @@ void HWDrawInfo::SetFog(FRenderState &state, int lightlevel, int rellight, bool } // Make fog a little denser when inside a skybox - if (portalState.inskybox) fogdensity += fogdensity / 2; + if (drawctx->portalState.inskybox) fogdensity += fogdensity / 2; // no fog in enhanced vision modes! diff --git a/src/rendering/hwrenderer/scene/hw_spritelight.cpp b/src/rendering/hwrenderer/scene/hw_spritelight.cpp index 24bbd5f9a9..0a422f020c 100644 --- a/src/rendering/hwrenderer/scene/hw_spritelight.cpp +++ b/src/rendering/hwrenderer/scene/hw_spritelight.cpp @@ -32,6 +32,7 @@ #include "g_level.h" #include "g_levellocals.h" #include "actorinlines.h" +#include "hw_drawcontext.h" #include "hw_dynlightdata.h" #include "hw_shadowmap.h" #include "hwrenderer/scene/hw_drawinfo.h" @@ -217,17 +218,14 @@ void HWDrawInfo::GetDynSpriteLight(AActor *thing, particle_t *particle, float *o } } -// static so that we build up a reserve (memory allocations stop) -// For multithread processing each worker thread needs its own copy, though. -static thread_local TArray addedLightsArray; -void hw_GetDynModelLight(AActor *self, FDynLightData &modellightdata) +void hw_GetDynModelLight(HWDrawContext* drawctx, AActor *self, FDynLightData &modellightdata) { modellightdata.Clear(); if (self) { - auto &addedLights = addedLightsArray; // avoid going through the thread local storage for each use. + auto &addedLights = drawctx->addedLightsArray; addedLights.Clear(); diff --git a/src/rendering/hwrenderer/scene/hw_sprites.cpp b/src/rendering/hwrenderer/scene/hw_sprites.cpp index 12bc95563c..481249ddfb 100644 --- a/src/rendering/hwrenderer/scene/hw_sprites.cpp +++ b/src/rendering/hwrenderer/scene/hw_sprites.cpp @@ -550,7 +550,7 @@ inline void HWSprite::PutSprite(HWDrawInfo *di, FRenderState& state, bool transl // That's a lot of checks... if (modelframe && !modelframe->isVoxel && !(modelframe->flags & MDL_NOPERPIXELLIGHTING) && RenderStyle.BlendOp != STYLEOP_Shadow && gl_light_sprites && di->Level->HasDynamicLights && !di->isFullbrightScene() && !fullbright) { - hw_GetDynModelLight(actor, lightdata); + hw_GetDynModelLight(di->drawctx, actor, lightdata); dynlightindex = state.UploadLights(lightdata); } else @@ -871,7 +871,7 @@ void HWSprite::Process(HWDrawInfo *di, FRenderState& state, AActor* thing, secto { // This cannot create a copy in the fake sector cache because it'd interfere with the main thread, so provide a local buffer for the copy. // Adding synchronization for this one case would cost more than it might save if the result here could be cached. - rendersector = hw_FakeFlat(thing->Sector, in_area, false, &rs); + rendersector = hw_FakeFlat(di->drawctx, thing->Sector, in_area, false, &rs); } else { @@ -1518,11 +1518,11 @@ void HWDrawInfo::ProcessActorsInPortal(FLinePortalSpan *glport, area_t in_area, // [Nash] draw sprite shadow if (R_ShouldDrawSpriteShadow(th)) { - spr.Process(this, state, th, hw_FakeFlat(th->Sector, in_area, false, &fakesector), in_area, 2, true); + spr.Process(this, state, th, hw_FakeFlat(drawctx, th->Sector, in_area, false, &fakesector), in_area, 2, true); } // This is called from the worker thread and must not alter the fake sector cache. - spr.Process(this, state, th, hw_FakeFlat(th->Sector, in_area, false, &fakesector), in_area, 2); + spr.Process(this, state, th, hw_FakeFlat(drawctx, th->Sector, in_area, false, &fakesector), in_area, 2); th->Angles.Yaw = savedangle; th->SetXYZ(savedpos); th->Prev -= newpos - savedpos; diff --git a/src/rendering/hwrenderer/scene/hw_walls.cpp b/src/rendering/hwrenderer/scene/hw_walls.cpp index 999ab6587a..a41ce8384e 100644 --- a/src/rendering/hwrenderer/scene/hw_walls.cpp +++ b/src/rendering/hwrenderer/scene/hw_walls.cpp @@ -37,6 +37,7 @@ #include "hw_cvars.h" #include "hw_clock.h" #include "hw_lighting.h" +#include "hw_drawcontext.h" #include "hwrenderer/scene/hw_drawinfo.h" #include "hwrenderer/scene/hw_drawstructs.h" #include "hwrenderer/scene/hw_portal.h" @@ -572,11 +573,11 @@ void HWWall::PutPortal(HWDrawInfo *di, FRenderState& state, int ptype, int plane // portals don't go into the draw list. // Instead they are added to the portal manager case PORTALTYPE_HORIZON: - horizon = portalState.UniqueHorizons.Get(horizon); + horizon = di->drawctx->portalState.UniqueHorizons.Get(horizon); portal = di->FindPortal(horizon); if (!portal) { - portal = new HWHorizonPortal(&portalState, state, horizon, di->Viewpoint); + portal = new HWHorizonPortal(&di->drawctx->portalState, state, horizon, di->Viewpoint); di->Portals.Push(portal); } portal->AddLine(this); @@ -587,10 +588,10 @@ void HWWall::PutPortal(HWDrawInfo *di, FRenderState& state, int ptype, int plane if (!portal) { // either a regular skybox or an Eternity-style horizon - if (secportal->mType != PORTS_SKYVIEWPOINT) portal = new HWEEHorizonPortal(&portalState, secportal); + if (secportal->mType != PORTS_SKYVIEWPOINT) portal = new HWEEHorizonPortal(&di->drawctx->portalState, secportal); else { - portal = new HWSkyboxPortal(&portalState, secportal); + portal = new HWSkyboxPortal(&di->drawctx->portalState, secportal); di->Portals.Push(portal); } } @@ -601,20 +602,20 @@ void HWWall::PutPortal(HWDrawInfo *di, FRenderState& state, int ptype, int plane portal = di->FindPortal(this->portal); if (!portal) { - portal = new HWSectorStackPortal(&portalState, this->portal); + portal = new HWSectorStackPortal(&di->drawctx->portalState, this->portal); di->Portals.Push(portal); } portal->AddLine(this); break; case PORTALTYPE_PLANEMIRROR: - if (portalState.PlaneMirrorMode * planemirror->fC() <= 0) + if (di->drawctx->portalState.PlaneMirrorMode * planemirror->fC() <= 0) { - planemirror = portalState.UniquePlaneMirrors.Get(planemirror); + planemirror = di->drawctx->portalState.UniquePlaneMirrors.Get(planemirror); portal = di->FindPortal(planemirror); if (!portal) { - portal = new HWPlaneMirrorPortal(&portalState, planemirror); + portal = new HWPlaneMirrorPortal(&di->drawctx->portalState, planemirror); di->Portals.Push(portal); } portal->AddLine(this); @@ -625,7 +626,7 @@ void HWWall::PutPortal(HWDrawInfo *di, FRenderState& state, int ptype, int plane portal = di->FindPortal(seg->linedef); if (!portal) { - portal = new HWMirrorPortal(&portalState, seg->linedef); + portal = new HWMirrorPortal(&di->drawctx->portalState, seg->linedef); di->Portals.Push(portal); } portal->AddLine(this); @@ -647,18 +648,18 @@ void HWWall::PutPortal(HWDrawInfo *di, FRenderState& state, int ptype, int plane { di->ProcessActorsInPortal(otherside->getPortal()->mGroup, di->in_area, state); } - portal = new HWLineToLinePortal(&portalState, lineportal); + portal = new HWLineToLinePortal(&di->drawctx->portalState, lineportal); di->Portals.Push(portal); } portal->AddLine(this); break; case PORTALTYPE_SKY: - sky = portalState.UniqueSkies.Get(sky); + sky = di->drawctx->portalState.UniqueSkies.Get(sky); portal = di->FindPortal(sky); if (!portal) { - portal = new HWSkyPortal(screen->mSkyData, &portalState, sky); + portal = new HWSkyPortal(screen->mSkyData, &di->drawctx->portalState, sky); di->Portals.Push(portal); } portal->AddLine(this); diff --git a/src/rendering/hwrenderer/scene/hw_weapon.cpp b/src/rendering/hwrenderer/scene/hw_weapon.cpp index 6f45323266..c71b34aca9 100644 --- a/src/rendering/hwrenderer/scene/hw_weapon.cpp +++ b/src/rendering/hwrenderer/scene/hw_weapon.cpp @@ -316,7 +316,7 @@ WeaponLighting HWDrawInfo::GetWeaponLighting(sector_t *viewsector, const DVector } else { - auto fakesec = hw_FakeFlat(viewsector, in_area, false); + auto fakesec = hw_FakeFlat(drawctx, viewsector, in_area, false); // calculate light level for weapon sprites l.lightlevel = hw_ClampLight(fakesec->lightlevel); @@ -840,7 +840,7 @@ void HWDrawInfo::PreparePlayerSprites3D(sector_t * viewsector, area_t in_area, F // set the lighting parameters if (hudsprite.RenderStyle.BlendOp != STYLEOP_Shadow && Level->HasDynamicLights && !isFullbrightScene() && gl_light_sprites) { - hw_GetDynModelLight(playermo, lightdata); + hw_GetDynModelLight(drawctx, playermo, lightdata); hudsprite.lightindex = state.UploadLights(lightdata); }