diff --git a/src/d_main.cpp b/src/d_main.cpp index 943130cdf9..b4849a742c 100644 --- a/src/d_main.cpp +++ b/src/d_main.cpp @@ -79,6 +79,7 @@ #include "cmdlib.h" #include "v_text.h" #include "gi.h" +#include "a_dynlight.h" #include "gameconfigfile.h" #include "sbar.h" #include "decallib.h" @@ -776,6 +777,15 @@ void D_Display () // [ZZ] execute event hook that we just started the frame //E_RenderFrame(); // + + // Check for the presence of dynamic lights at the start of the frame once. + if (gl_lights) + { + TThinkerIterator it(STAT_DLIGHT); + level.HasDynamicLights = !!it.Next(); + } + else level.HasDynamicLights = false; // lights are off so effectively we have none. + screen->RenderView(&players[consoleplayer]); screen->Begin2D(false); // returns with 2S mode set. diff --git a/src/g_levellocals.h b/src/g_levellocals.h index 3d23fb0853..8c3e999805 100644 --- a/src/g_levellocals.h +++ b/src/g_levellocals.h @@ -152,6 +152,7 @@ struct FLevelLocals bool FromSnapshot; // The current map was restored from a snapshot bool HasHeightSecs; // true if some Transfer_Heights effects are present in the map. If this is false, some checks in the renderer can be shortcut. + bool HasDynamicLights; // Another render optimization for maps with no lights at all. double teamdamage; diff --git a/src/gl/compatibility/gl_20.cpp b/src/gl/compatibility/gl_20.cpp index 7c64e8fb8e..72f38465f4 100644 --- a/src/gl/compatibility/gl_20.cpp +++ b/src/gl/compatibility/gl_20.cpp @@ -881,7 +881,7 @@ void GLSceneDrawer::RenderMultipassStuff() // second pass: draw lights glDepthMask(false); - if (GLRenderer->mLightCount && !FixedColormap) + if (level.HasDynamicLights && !FixedColormap) { if (gl_SetupLightTexture()) { diff --git a/src/gl/renderer/gl_renderer.cpp b/src/gl/renderer/gl_renderer.cpp index 98aee05c08..45acc8b10e 100644 --- a/src/gl/renderer/gl_renderer.cpp +++ b/src/gl/renderer/gl_renderer.cpp @@ -90,7 +90,6 @@ FGLRenderer::FGLRenderer(OpenGLFrameBuffer *fb) mCurrentPortal = nullptr; mMirrorCount = 0; mPlaneMirrorCount = 0; - mLightCount = 0; mAngles = FRotator(0.f, 0.f, 0.f); mViewVector = FVector2(0,0); mVBO = nullptr; @@ -446,9 +445,6 @@ void FGLRenderer::RenderView(player_t* player) { fovratio = ratio; } - // Check if there's some lights. If not some code can be skipped. - TThinkerIterator it(STAT_DLIGHT); - mLightCount = ((it.Next()) != NULL); GLSceneDrawer drawer; diff --git a/src/gl/renderer/gl_renderer.h b/src/gl/renderer/gl_renderer.h index 0126c36195..2514992e43 100644 --- a/src/gl/renderer/gl_renderer.h +++ b/src/gl/renderer/gl_renderer.h @@ -104,7 +104,6 @@ public: GLPortal *mCurrentPortal; int mMirrorCount; int mPlaneMirrorCount; - int mLightCount; float mCurrentFoV; AActor *mViewActor; FShaderManager *mShaderManager; diff --git a/src/gl/scene/gl_scene.cpp b/src/gl/scene/gl_scene.cpp index aba12b543c..3216363a36 100644 --- a/src/gl/scene/gl_scene.cpp +++ b/src/gl/scene/gl_scene.cpp @@ -311,8 +311,7 @@ void GLSceneDrawer::RenderScene(int recursion) // if we don't have a persistently mapped buffer, we have to process all the dynamic lights up front, // so that we don't have to do repeated map/unmap calls on the buffer. - bool haslights = GLRenderer->mLightCount > 0 && FixedColormap == CM_DEFAULT && gl_lights; - if (gl.lightmethod == LM_DEFERRED && haslights) + if (gl.lightmethod == LM_DEFERRED && level.HasDynamicLights && FixedColormap == CM_DEFAULT) { GLRenderer->mLights->Begin(); gl_drawinfo->drawlists[GLDL_PLAINFLATS].DrawFlats(gl_drawinfo, GLPASS_LIGHTSONLY); @@ -329,21 +328,17 @@ void GLSceneDrawer::RenderScene(int recursion) int pass; - if (!haslights || gl.lightmethod == LM_DEFERRED) - { - pass = GLPASS_PLAIN; - } - else if (gl.lightmethod == LM_DIRECT) + if (!level.HasDynamicLights || !gl.legacyMode) { pass = GLPASS_ALL; } else // GL 2.x legacy mode { // process everything that needs to handle textured dynamic lights. - if (haslights) RenderMultipassStuff(); + if (level.HasDynamicLights) RenderMultipassStuff(); // The remaining lists which are unaffected by dynamic lights are just processed as normal. - pass = GLPASS_PLAIN; + pass = GLPASS_ALL; } gl_RenderState.EnableTexture(gl_texture); @@ -773,10 +768,6 @@ void GLSceneDrawer::WriteSavePic (player_t *player, FileWriter *file, int width, GLRenderer->mVBO->Reset(); if (!gl.legacyMode) GLRenderer->mLights->Clear(); - // Check if there's some lights. If not some code can be skipped. - TThinkerIterator it(STAT_DLIGHT); - GLRenderer->mLightCount = ((it.Next()) != NULL); - sector_t *viewsector = RenderViewpoint(players[consoleplayer].camera, &bounds, r_viewpoint.FieldOfView.Degrees, 1.6f, 1.6f, true, false); glDisable(GL_STENCIL_TEST); diff --git a/src/gl/scene/gl_sprite.cpp b/src/gl/scene/gl_sprite.cpp index 3df7ac5993..ad4b7eb386 100644 --- a/src/gl/scene/gl_sprite.cpp +++ b/src/gl/scene/gl_sprite.cpp @@ -144,7 +144,7 @@ void FDrawInfo::DrawSprite(GLSprite *sprite, int pass) } if (RenderStyle.BlendOp != STYLEOP_Shadow) { - if (gl_lights && GLRenderer->mLightCount && mDrawer->FixedColormap == CM_DEFAULT && !sprite->fullbright) + if (level.HasDynamicLights && mDrawer->FixedColormap == CM_DEFAULT && !sprite->fullbright) { if ( sprite->dynlightindex == -1) // only set if we got no light buffer index. This covers all cases where sprite lighting is used. { @@ -328,7 +328,7 @@ void FDrawInfo::AddSprite(GLSprite *sprite, bool translucent) } // That's a lot of checks... - if (sprite->modelframe && sprite->RenderStyle.BlendOp != STYLEOP_Shadow && gl_lights && gl_light_sprites && GLRenderer->mLightCount && mDrawer->FixedColormap == CM_DEFAULT && !sprite->fullbright && !gl.legacyMode) + if (sprite->modelframe && sprite->RenderStyle.BlendOp != STYLEOP_Shadow && level.HasDynamicLights && gl_light_sprites && mDrawer->FixedColormap == CM_DEFAULT && !sprite->fullbright && !gl.legacyMode) { hw_GetDynModelLight(sprite->actor, lightdata); sprite->dynlightindex = GLRenderer->mLights->UploadLights(lightdata); diff --git a/src/gl/scene/gl_walls_draw.cpp b/src/gl/scene/gl_walls_draw.cpp index e61886971e..bd03887220 100644 --- a/src/gl/scene/gl_walls_draw.cpp +++ b/src/gl/scene/gl_walls_draw.cpp @@ -42,9 +42,6 @@ EXTERN_CVAR(Bool, gl_seamless) -// 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; - //========================================================================== // // General purpose wall rendering function @@ -473,7 +470,7 @@ void FDrawInfo::DrawDecal(GLDecal *gldecal) auto &seg = wall->seg; // calculate dynamic light effect. - if (gl_lights && GLRenderer->mLightCount && !mDrawer->FixedColormap && gl_light_sprites) + if (level.HasDynamicLights && !mDrawer->FixedColormap && gl_light_sprites) { // Note: This should be replaced with proper shader based lighting. double x, y; diff --git a/src/gl/scene/gl_weapon.cpp b/src/gl/scene/gl_weapon.cpp index 120648e37f..e4de678482 100644 --- a/src/gl/scene/gl_weapon.cpp +++ b/src/gl/scene/gl_weapon.cpp @@ -99,7 +99,7 @@ void GLSceneDrawer::SetupWeaponLight() return; // Check if lighting can be used on this item. - if (camera->RenderStyle.BlendOp == STYLEOP_Shadow || !gl_lights || !gl_light_sprites || !GLRenderer->mLightCount || FixedColormap != CM_DEFAULT || gl.legacyMode) + if (camera->RenderStyle.BlendOp == STYLEOP_Shadow || !level.HasDynamicLights || !gl_light_sprites || FixedColormap != CM_DEFAULT || gl.legacyMode) return; for (DPSprite *psp = player->psprites; psp != nullptr && psp->GetID() < PSP_TARGETCENTER; psp = psp->GetNext()) @@ -179,7 +179,7 @@ void GLSceneDrawer::DrawPlayerSprites(sector_t * viewsector, bool hudModelStep) } else { - if (gl_lights && GLRenderer->mLightCount && FixedColormap == CM_DEFAULT && gl_light_sprites) + if (level.HasDynamicLights && 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 || gl.legacyMode) // For models with per-pixel lighting this was done in a previous pass. diff --git a/src/hwrenderer/dynlights/hw_dynlightdata.cpp b/src/hwrenderer/dynlights/hw_dynlightdata.cpp index e26bd06544..327ab57009 100644 --- a/src/hwrenderer/dynlights/hw_dynlightdata.cpp +++ b/src/hwrenderer/dynlights/hw_dynlightdata.cpp @@ -30,6 +30,8 @@ #include "hw_dynlightdata.h" +// 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; //========================================================================== // diff --git a/src/hwrenderer/dynlights/hw_dynlightdata.h b/src/hwrenderer/dynlights/hw_dynlightdata.h index e63ade4fb8..ec03db05bd 100644 --- a/src/hwrenderer/dynlights/hw_dynlightdata.h +++ b/src/hwrenderer/dynlights/hw_dynlightdata.h @@ -58,5 +58,7 @@ struct FDynLightData }; +extern thread_local FDynLightData lightdata; + #endif