Add HWDrawContext so that multiple threads can maintain their own drawinfo without need for synchronization

This commit is contained in:
Magnus Norddahl 2023-06-29 03:33:07 +02:00 committed by Christoph Oelckers
parent 0adb152913
commit dba5399635
25 changed files with 295 additions and 298 deletions

View file

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

View file

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

View file

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

View file

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

View file

@ -39,13 +39,6 @@
#include "g_levellocals.h"
#include "basics.h"
unsigned Clipper::starttime;
Clipper::Clipper()
{
starttime++;
}
//-----------------------------------------------------------------------------
//
// RemoveRange

View file

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

View file

@ -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<SortNode*>::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();
}

View file

@ -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<HWDrawInfo*> mList;
HWDrawInfo* GetNew();
void Release(HWDrawInfo*);
};
class StaticSortNodeArray : public TDeletingArray<SortNode*>
{
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<FDynamicLight*> addedLightsArray;
};

View file

@ -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<HWDrawInfo *> 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<HWPortal *>(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<HWSectorStackPortal*>(portal);

View file

@ -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<int> spriteindex;
HWPortal *mClipPortal;
HWPortal *mCurrentPortal;
//FRotator mAngles;
Clipper *mClipper;
FRenderViewpoint Viewpoint;
HWViewpointUniforms VPUniforms; // per-viewpoint uniform state
@ -165,9 +163,6 @@ struct HWDrawInfo
TMap<int, gl_floodrendernode*> floodFloorSegs;
TMap<int, gl_floodrendernode*> floodCeilingSegs;
//TArray<sector_t *> CeilingStacks;
//TArray<sector_t *> FloorStacks;
TArray<subsector_t *> HandledSubsectors;
TArray<uint8_t> section_renderflags;
@ -182,44 +177,7 @@ struct HWDrawInfo
bool MeshBuilding = false;
private:
// For ProcessLowerMiniseg
bool inview;
subsector_t * viewsubsector;
TArray<seg_t *> 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<seg_t*> 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();

View file

@ -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<SortNode*>
{
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<SortNode*>::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;i<drawitems.Size();i++)
{
n->itemindex=(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;
}

View file

@ -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<HWWall*> walls;
TArray<HWFlat*> flats;
TArray<HWSprite*> sprites;
TArray<HWDrawItem> 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;
} ;

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -73,7 +73,6 @@ CCMD(gl_portalinfo)
}
static FString indent;
FPortalSceneState portalState;
//-----------------------------------------------------------------------------
//

View file

@ -55,7 +55,7 @@ class HWPortal
STP_AllInOne
};
ActorRenderFlags savedvisibility;
ActorRenderFlags savedvisibility = {};
TArray<unsigned int> 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

View file

@ -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<int, gl_subsectorrendernode*>::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<int, gl_floodrendernode*>::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<int, gl_floodrendernode*>::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;j<HandledSubsectors.Size();j++)
{
gl_subsectorrendernode * node = NewSubsectorRenderNode();
gl_subsectorrendernode * node = NewSubsectorRenderNode(drawctx);
node->sub = HandledSubsectors[j];
AddOtherFloorPlane(sub->render_sector->sectornum, node, state);
}
@ -1163,7 +1164,7 @@ void HWDrawInfo::HandleHackedSubsectors(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(sub->render_sector->sectornum, node, state);
}

View file

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

View file

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

View file

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

View file

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

View file

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