From 819ea8f937b7ba0721acc6daf4cb43caa65a8461 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Sun, 29 Apr 2018 09:33:36 +0200 Subject: [PATCH] - reduced gl_spritelight.cpp to pure data setup so that it can be moved out of gl/. - added thread_local to some static arrays being used for setting up dynamic lights. Right now it's of little consequence but these will have to be maintained per thread if the render data setup is done by worker tasks. --- src/gl/dynlights/gl_lightbuffer.h | 6 +++- src/gl/renderer/gl_renderstate.h | 2 +- src/gl/scene/gl_flats.cpp | 3 +- src/gl/scene/gl_sprite.cpp | 38 +++++++++++++++++++++- src/gl/scene/gl_spritelight.cpp | 47 ++++++++------------------- src/gl/scene/gl_wall.h | 3 -- src/gl/scene/gl_walls_draw.cpp | 8 +++-- src/gl/scene/gl_weapon.cpp | 11 +++++-- src/hwrenderer/scene/hw_drawstructs.h | 8 +++-- src/hwrenderer/scene/hw_flats.cpp | 5 ++- 10 files changed, 79 insertions(+), 52 deletions(-) diff --git a/src/gl/dynlights/gl_lightbuffer.h b/src/gl/dynlights/gl_lightbuffer.h index 8781ccb57c..49fc87cd9f 100644 --- a/src/gl/dynlights/gl_lightbuffer.h +++ b/src/gl/dynlights/gl_lightbuffer.h @@ -2,7 +2,7 @@ #define __GL_LIGHTBUFFER_H #include "tarray.h" -struct FDynLightData; +#include "hwrenderer/dynlights/hw_dynlightdata.h" class FLightBuffer { @@ -35,5 +35,9 @@ public: int GetIndex(int i) const { return mIndices[i]; } }; +int gl_SetDynModelLight(AActor *self, int dynlightindex); + +extern thread_local FDynLightData lightdata; + #endif diff --git a/src/gl/renderer/gl_renderstate.h b/src/gl/renderer/gl_renderstate.h index 7444e849ec..0903362352 100644 --- a/src/gl/renderer/gl_renderstate.h +++ b/src/gl/renderer/gl_renderstate.h @@ -535,7 +535,7 @@ public: void SetPlaneTextureRotation(GLSectorPlane *plane, FMaterial *texture) { - if (gl_SetPlaneTextureRotation(plane, texture, mTextureMatrix)) + if (hw_SetPlaneTextureRotation(plane, texture, mTextureMatrix)) { EnableTextureMatrix(true); } diff --git a/src/gl/scene/gl_flats.cpp b/src/gl/scene/gl_flats.cpp index 5ceee553b3..8befbfb799 100644 --- a/src/gl/scene/gl_flats.cpp +++ b/src/gl/scene/gl_flats.cpp @@ -53,7 +53,6 @@ // Flats // //========================================================================== -extern FDynLightData lightdata; void FDrawInfo::SetupSubsectorLights(GLFlat *flat, int pass, subsector_t * sub, int *dli) { @@ -63,7 +62,7 @@ void FDrawInfo::SetupSubsectorLights(GLFlat *flat, int pass, subsector_t * sub, (*dli)++; return; } - if (flat->SetupSubsectorLights(pass, sub)) + if (flat->SetupSubsectorLights(pass, sub, lightdata)) { int d = GLRenderer->mLights->UploadLights(lightdata); if (pass == GLPASS_LIGHTSONLY) diff --git a/src/gl/scene/gl_sprite.cpp b/src/gl/scene/gl_sprite.cpp index 380b50f144..042f4817bf 100644 --- a/src/gl/scene/gl_sprite.cpp +++ b/src/gl/scene/gl_sprite.cpp @@ -42,6 +42,7 @@ #include "gl/system/gl_interface.h" #include "hwrenderer/utility/hw_cvars.h" +#include "hwrenderer/scene/hw_drawstructs.h" #include "gl/renderer/gl_lightdata.h" #include "gl/renderer/gl_renderstate.h" #include "gl/renderer/gl_renderer.h" @@ -49,6 +50,7 @@ #include "gl/scene/gl_scenedrawer.h" #include "gl/models/gl_models.h" #include "gl/renderer/gl_quaddrawer.h" +#include "gl/dynlights/gl_lightbuffer.h" extern uint32_t r_renderercaps; @@ -62,6 +64,36 @@ void gl_SetRenderStyle(FRenderStyle style, bool drawopaque, bool allowcolorblend gl_RenderState.SetTextureMode(tm); } +int gl_SetDynModelLight(AActor *self, int dynlightindex) +{ + if (gl.legacyMode) + { + float out[3]; + hw_GetDynSpriteLight(self, nullptr, out); + gl_RenderState.SetDynLight(out[0], out[1], out[2]); + return -1; + } + else + { + // For deferred light mode this function gets called twice. First time for list upload, and second for draw. + if (gl.lightmethod == LM_DEFERRED && dynlightindex != -1) + { + gl_RenderState.SetDynLight(0, 0, 0); + return dynlightindex; + } + hw_GetDynModelLight(self, lightdata); + + dynlightindex = GLRenderer->mLights->UploadLights(lightdata); + + if (gl.lightmethod != LM_DEFERRED) + { + gl_RenderState.SetDynLight(0, 0, 0); + } + return dynlightindex; + + } +} + //========================================================================== // // @@ -164,7 +196,11 @@ void FDrawInfo::DrawSprite(GLSprite *sprite, int pass) if (sprite->modelframe && !sprite->particle) sprite->dynlightindex = gl_SetDynModelLight(gl_light_sprites ? sprite->actor : nullptr, sprite->dynlightindex); else - gl_SetDynSpriteLight(gl_light_sprites ? sprite->actor : nullptr, gl_light_particles ? sprite->particle : nullptr); + { + float out[3]; + hw_GetDynSpriteLight(gl_light_sprites ? sprite->actor : nullptr, gl_light_particles ? sprite->particle : nullptr, out); + gl_RenderState.SetDynLight(out[0], out[1], out[2]); + } } sector_t *cursec = sprite->actor ? sprite->actor->Sector : sprite->particle ? sprite->particle->subsector->sector : nullptr; if (cursec != nullptr) diff --git a/src/gl/scene/gl_spritelight.cpp b/src/gl/scene/gl_spritelight.cpp index af58d037eb..864e74a99f 100644 --- a/src/gl/scene/gl_spritelight.cpp +++ b/src/gl/scene/gl_spritelight.cpp @@ -54,13 +54,13 @@ T smoothstep(const T edge0, const T edge1, const T x) // //========================================================================== -void gl_SetDynSpriteLight(AActor *self, float x, float y, float z, subsector_t * subsec) +void hw_GetDynSpriteLight(AActor *self, float x, float y, float z, subsector_t * subsec, float *out) { ADynamicLight *light; float frac, lr, lg, lb; float radius; - float out[3] = { 0.0f, 0.0f, 0.0f }; + out[0] = out[1] = out[2] = 0.f; // Go through both light lists FLightNode * node = subsec->lighthead; while (node) @@ -131,18 +131,17 @@ void gl_SetDynSpriteLight(AActor *self, float x, float y, float z, subsector_t * } node = node->nextLight; } - gl_RenderState.SetDynLight(out[0], out[1], out[2]); } -void gl_SetDynSpriteLight(AActor *thing, particle_t *particle) +void hw_GetDynSpriteLight(AActor *thing, particle_t *particle, float *out) { if (thing != NULL) { - gl_SetDynSpriteLight(thing, thing->X(), thing->Y(), thing->Center(), thing->subsector); + hw_GetDynSpriteLight(thing, thing->X(), thing->Y(), thing->Center(), thing->subsector, out); } else if (particle != NULL) { - gl_SetDynSpriteLight(NULL, particle->Pos.X, particle->Pos.Y, particle->Pos.Z, particle->subsector); + hw_GetDynSpriteLight(NULL, particle->Pos.X, particle->Pos.Y, particle->Pos.Z, particle->subsector, out); } } @@ -189,31 +188,19 @@ void BSPWalkCircle(float x, float y, float radiusSquared, const Callback &callba BSPNodeWalkCircle(level.HeadNode(), x, y, radiusSquared, callback); } -int gl_SetDynModelLight(AActor *self, int dynlightindex) +// 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) { - static FDynLightData modellightdata; // If this ever gets multithreaded, this variable must either be made non-static or thread_local. - - // For deferred light mode this function gets called twice. First time for list upload, and second for draw. - if (gl.lightmethod == LM_DEFERRED && dynlightindex != -1) - { - gl_RenderState.SetDynLight(0, 0, 0); - return dynlightindex; - } - - // Legacy render path gets the old flat model light - if (gl.lightmethod == LM_LEGACY) - { - gl_SetDynSpriteLight(self, nullptr); - return -1; - } - modellightdata.Clear(); if (self) { - static std::vector addedLights; // static so that we build up a reserve (memory allocations stop) + auto &addedLights = addedLightsArray; // avoid going through the thread local storage for each use. - addedLights.clear(); + addedLights.Clear(); float x = self->X(); float y = self->Y(); @@ -240,7 +227,7 @@ int gl_SetDynModelLight(AActor *self, int dynlightindex) if (std::find(addedLights.begin(), addedLights.end(), light) == addedLights.end()) // Check if we already added this light from a different subsector { modellightdata.AddLightToList(group, light); - addedLights.push_back(light); + addedLights.Push(light); } } } @@ -248,12 +235,4 @@ int gl_SetDynModelLight(AActor *self, int dynlightindex) } }); } - - dynlightindex = GLRenderer->mLights->UploadLights(modellightdata); - - if (gl.lightmethod != LM_DEFERRED) - { - gl_RenderState.SetDynLight(0, 0, 0); - } - return dynlightindex; } diff --git a/src/gl/scene/gl_wall.h b/src/gl/scene/gl_wall.h index 2562aa612d..9b1d421867 100644 --- a/src/gl/scene/gl_wall.h +++ b/src/gl/scene/gl_wall.h @@ -19,8 +19,5 @@ struct particle_t; // Light + color -void gl_SetDynSpriteLight(AActor *self, float x, float y, float z, subsector_t *subsec); -void gl_SetDynSpriteLight(AActor *actor, particle_t *particle); -int gl_SetDynModelLight(AActor *self, int dynlightindex); #endif diff --git a/src/gl/scene/gl_walls_draw.cpp b/src/gl/scene/gl_walls_draw.cpp index 2e62a17376..ebec1bab93 100644 --- a/src/gl/scene/gl_walls_draw.cpp +++ b/src/gl/scene/gl_walls_draw.cpp @@ -42,8 +42,8 @@ EXTERN_CVAR(Bool, gl_seamless) -FDynLightData lightdata; - +// If we want to share the array to avoid constant allocations it needs to be thread local unless it'd be littered with expensive synchronization. +thread_local FDynLightData lightdata; //========================================================================== // @@ -489,8 +489,10 @@ void FDrawInfo::DrawDecal(GLDecal *gldecal) { // Note: This should be replaced with proper shader based lighting. double x, y; + float out[3]; decal->GetXY(seg->sidedef, x, y); - gl_SetDynSpriteLight(nullptr, x, y, gldecal->zcenter, wall->sub); + hw_GetDynSpriteLight(nullptr, x, y, gldecal->zcenter, wall->sub, out); + gl_RenderState.SetDynLight(out[0], out[1], out[2]); } // alpha color only has an effect when using an alpha texture. diff --git a/src/gl/scene/gl_weapon.cpp b/src/gl/scene/gl_weapon.cpp index f781aa8c7c..11fcd27349 100644 --- a/src/gl/scene/gl_weapon.cpp +++ b/src/gl/scene/gl_weapon.cpp @@ -44,6 +44,7 @@ #include "gl/models/gl_models.h" #include "gl/renderer/gl_quaddrawer.h" #include "gl/stereo3d/gl_stereo3d.h" +#include "gl/dynlights/gl_lightbuffer.h" EXTERN_CVAR (Bool, r_drawplayersprites) EXTERN_CVAR(Float, transsouls) @@ -449,10 +450,16 @@ void GLSceneDrawer::DrawPlayerSprites(sector_t * viewsector, bool hudModelStep) if (gl_lights && GLRenderer->mLightCount && FixedColormap == CM_DEFAULT && gl_light_sprites) { FSpriteModelFrame *smf = playermo->player->ReadyWeapon ? gl_FindModelFrame(playermo->player->ReadyWeapon->GetClass(), psp->GetState()->sprite, psp->GetState()->GetFrame(), false) : nullptr; - if (smf) + if (smf && !gl.legacyMode) + { gl_SetDynModelLight(playermo, weapondynlightindex[psp]); + } else - gl_SetDynSpriteLight(playermo, NULL); + { + float out[3]; + hw_GetDynSpriteLight(playermo, nullptr, out); + gl_RenderState.SetDynLight(out[0], out[1], out[2]); + } } SetColor(ll, 0, cmc, trans, true); } diff --git a/src/hwrenderer/scene/hw_drawstructs.h b/src/hwrenderer/scene/hw_drawstructs.h index 5d6d7779f7..1452bc4300 100644 --- a/src/hwrenderer/scene/hw_drawstructs.h +++ b/src/hwrenderer/scene/hw_drawstructs.h @@ -311,7 +311,7 @@ public: int dynlightindex; - bool SetupSubsectorLights(int pass, subsector_t * sub); + bool SetupSubsectorLights(int pass, subsector_t * sub, FDynLightData &lightdata); void PutFlat(HWDrawInfo *di, bool fog = false); void Process(HWDrawInfo *di, sector_t * model, int whichplane, bool notexture); @@ -431,5 +431,9 @@ inline float Dist2(float x1,float y1,float x2,float y2) return sqrtf((x1-x2)*(x1-x2)+(y1-y2)*(y1-y2)); } -bool gl_SetPlaneTextureRotation(const GLSectorPlane * secplane, FMaterial * gltexture, VSMatrix &mat); +bool hw_SetPlaneTextureRotation(const GLSectorPlane * secplane, FMaterial * gltexture, VSMatrix &mat); +void hw_GetDynSpriteLight(AActor *self, float x, float y, float z, subsector_t *subsec, float *out); +void hw_GetDynSpriteLight(AActor *actor, particle_t *particle, float *out); +void hw_GetDynModelLight(AActor *self, FDynLightData &modellightdata); + extern const float LARGE_VALUE; diff --git a/src/hwrenderer/scene/hw_flats.cpp b/src/hwrenderer/scene/hw_flats.cpp index 5f09c63263..050110c9f1 100644 --- a/src/hwrenderer/scene/hw_flats.cpp +++ b/src/hwrenderer/scene/hw_flats.cpp @@ -54,7 +54,7 @@ CVAR(Int, gl_breaksec, -1, 0) // //========================================================================== -bool gl_SetPlaneTextureRotation(const GLSectorPlane * secplane, FMaterial * gltexture, VSMatrix &dest) +bool hw_SetPlaneTextureRotation(const GLSectorPlane * secplane, FMaterial * gltexture, VSMatrix &dest) { // only manipulate the texture matrix if needed. if (!secplane->Offs.isZero() || @@ -92,9 +92,8 @@ bool gl_SetPlaneTextureRotation(const GLSectorPlane * secplane, FMaterial * glte // Flats // //========================================================================== -extern FDynLightData lightdata; -bool GLFlat::SetupSubsectorLights(int pass, subsector_t * sub) +bool GLFlat::SetupSubsectorLights(int pass, subsector_t * sub, FDynLightData &lightdata) { Plane p;