diff --git a/src/common/rendering/hwrenderer/data/hw_levelmesh.h b/src/common/rendering/hwrenderer/data/hw_levelmesh.h index bdd6cbb5d..2b12c54b3 100644 --- a/src/common/rendering/hwrenderer/data/hw_levelmesh.h +++ b/src/common/rendering/hwrenderer/data/hw_levelmesh.h @@ -53,8 +53,8 @@ struct LevelMeshSurface int texWidth = 0; int texHeight = 0; + // True if the surface needs to be rendered into the lightmap texture before it can be used bool needsUpdate = true; - bool alreadyInVisibleList = false; // // Required for internal lightmapper: diff --git a/src/common/rendering/hwrenderer/data/hw_renderstate.h b/src/common/rendering/hwrenderer/data/hw_renderstate.h index 9e2260cfe..4e83604f7 100644 --- a/src/common/rendering/hwrenderer/data/hw_renderstate.h +++ b/src/common/rendering/hwrenderer/data/hw_renderstate.h @@ -262,17 +262,12 @@ protected: EPassType mPassType = NORMAL_PASS; - std::atomic mActiveLightmapSurfaceBufferIndex; - TArray mActiveLightmapSurfacesBuffer; public: uint64_t firstFrame = 0; void Reset() { - mActiveLightmapSurfaceBufferIndex = { 0 }; - mActiveLightmapSurfacesBuffer.Resize(lm_max_updates); - mTextureEnabled = true; mBrightmapEnabled = mGradientEnabled = mFogEnabled = mGlowEnabled = false; mFogColor = 0xffffffff; @@ -739,35 +734,6 @@ public: return SetViewpoint(matrices); } - inline void PushVisibleSurface(LevelMeshSurface* surface) - { - if (surface->needsUpdate && !surface->portalIndex && !surface->bSky) // TODO atomic? - { - auto index = mActiveLightmapSurfaceBufferIndex.fetch_add(1); - if (index < mActiveLightmapSurfacesBuffer.Size()) - { - mActiveLightmapSurfacesBuffer[index] = surface; - surface->needsUpdate = false; - } - } - } - - inline auto& GetVisibleSurfaceList() - { - return mActiveLightmapSurfacesBuffer; - } - - inline unsigned GetVisibleSurfaceListCount() const - { - return mActiveLightmapSurfaceBufferIndex; - } - - inline void ClearVisibleSurfaceList() - { - mActiveLightmapSurfacesBuffer.Resize(lm_max_updates); - mActiveLightmapSurfaceBufferIndex = 0; - } - // API-dependent render interface // Worker threads diff --git a/src/common/rendering/vulkan/accelstructs/vk_lightmap.cpp b/src/common/rendering/vulkan/accelstructs/vk_lightmap.cpp index fd616e54c..a2160cdd4 100644 --- a/src/common/rendering/vulkan/accelstructs/vk_lightmap.cpp +++ b/src/common/rendering/vulkan/accelstructs/vk_lightmap.cpp @@ -99,8 +99,8 @@ void VkLightmap::SelectSurfaces(const TArray& surfaces) { LevelMeshSurface* surface = surfaces[i]; - // All surfaces needs to be updated until we rendered them. - surface->needsUpdate = true; + if (!surface->needsUpdate) + continue; // Only grab surfaces until our bake texture is full auto result = packer.insert(surface->texWidth + 2, surface->texHeight + 2); @@ -114,6 +114,8 @@ void VkLightmap::SelectSurfaces(const TArray& surfaces) bakeImage.maxX = std::max(bakeImage.maxX, uint16_t(selected.X + surface->texWidth + spacing)); bakeImage.maxY = std::max(bakeImage.maxY, uint16_t(selected.Y + surface->texHeight + spacing)); + + surface->needsUpdate = false; } } } @@ -226,7 +228,14 @@ void VkLightmap::RenderBakeImage() } if (buffersFull) + { + while (i < count) + { + selectedSurfaces[i].Surface->needsUpdate = true; + i++; + } break; + } selectedSurface.Rendered = true; } @@ -422,9 +431,6 @@ void VkLightmap::CopyBakeImageResult() regions.push_back(region); seenPages.insert(surface->atlasPageIndex); - // We rendered this surface. Does not need an update anymore. - surface->needsUpdate = false; - pixels += surface->Area(); lastSurfaceCount++; } diff --git a/src/rendering/hwrenderer/doom_levelmesh.cpp b/src/rendering/hwrenderer/doom_levelmesh.cpp index 61c84970f..800bbbe4a 100644 --- a/src/rendering/hwrenderer/doom_levelmesh.cpp +++ b/src/rendering/hwrenderer/doom_levelmesh.cpp @@ -32,7 +32,7 @@ ADD_STAT(lightmap) auto stats = levelMesh->GatherSurfacePixelStats(); out.Format("Surfaces: %u (sky: %u, awaiting updates: %u)\nSurface pixel area to update: %u\nSurface pixel area: %u\nAtlas pixel area: %u\nAtlas efficiency: %.4f%%", - stats.surfaces.total, stats.surfaces.sky, stats.surfaces.dirty, + stats.surfaces.total, stats.surfaces.sky, std::max(stats.surfaces.dirty - stats.surfaces.sky, (uint32_t)0), stats.pixels.dirty, stats.pixels.total, atlasPixelCount, diff --git a/src/rendering/hwrenderer/scene/hw_bsp.cpp b/src/rendering/hwrenderer/scene/hw_bsp.cpp index 42118dc93..b0dbe472a 100644 --- a/src/rendering/hwrenderer/scene/hw_bsp.cpp +++ b/src/rendering/hwrenderer/scene/hw_bsp.cpp @@ -52,7 +52,6 @@ CVAR(Bool, gl_multithread, true, CVAR_ARCHIVE | CVAR_GLOBALCONFIG) EXTERN_CVAR(Float, r_actorspriteshadowdist) EXTERN_CVAR(Bool, gl_meshcache) -EXTERN_CVAR(Int, lm_background_updates); thread_local bool isWorkerThread; ctpl::thread_pool renderPool(1); @@ -857,35 +856,8 @@ void HWDrawInfo::RenderBSPNode (void *node, FRenderState& state) DoSubsector ((subsector_t *)((uint8_t *)node - 1), state); } -void UpdateLightmaps(DFrameBuffer* screen, FRenderState& RenderState) -{ - // Lightmapping stuff - auto& list = RenderState.GetVisibleSurfaceList(); - auto size = RenderState.GetVisibleSurfaceListCount(); - - list.Resize(min(list.Size(), unsigned(size))); - - if (size < unsigned(lm_background_updates)) - { - for (auto& e : level.levelMesh->Surfaces) - { - if (e.needsUpdate && !e.bSky && !e.portalIndex) - { - list.Push(&e); - - if (list.Size() >= unsigned(lm_background_updates)) - break; - } - } - } - - screen->UpdateLightmaps(list); -} - void HWDrawInfo::RenderBSP(void *node, bool drawpsprites, FRenderState& state) { - state.ClearVisibleSurfaceList(); - Bsp.Clock(); // Give the DrawInfo the viewpoint in fixed point because that's what the nodes are. @@ -920,6 +892,4 @@ void HWDrawInfo::RenderBSP(void *node, bool drawpsprites, FRenderState& state) if (drawpsprites) PreparePlayerSprites(Viewpoint.sector, in_area, state); - - UpdateLightmaps(screen, state); } diff --git a/src/rendering/hwrenderer/scene/hw_drawinfo.cpp b/src/rendering/hwrenderer/scene/hw_drawinfo.cpp index 24bd640ee..1b0a0e951 100644 --- a/src/rendering/hwrenderer/scene/hw_drawinfo.cpp +++ b/src/rendering/hwrenderer/scene/hw_drawinfo.cpp @@ -50,6 +50,8 @@ #include "g_levellocals.h" EXTERN_CVAR(Float, r_visibility) +EXTERN_CVAR(Int, lm_background_updates); + CVAR(Bool, gl_bandedswlight, false, CVAR_ARCHIVE) CVAR(Bool, gl_sort_textures, false, CVAR_ARCHIVE | CVAR_GLOBALCONFIG) CVAR(Bool, gl_no_skyclear, false, CVAR_ARCHIVE | CVAR_GLOBALCONFIG) @@ -122,6 +124,7 @@ void HWDrawInfo::StartScene(FRenderViewpoint &parentvp, HWViewpointUniforms *uni for (int i = 0; i < GLDL_TYPES; i++) drawlists[i].Reset(); hudsprites.Clear(); Coronas.Clear(); + VisibleSurfaces.Clear(); vpIndex = 0; // Fullbright information needs to be propagated from the main view. @@ -410,6 +413,25 @@ void HWDrawInfo::CreateScene(bool drawpsprites, FRenderState& state) } +void HWDrawInfo::UpdateLightmaps() +{ + if (VisibleSurfaces.Size() < unsigned(lm_background_updates)) + { + for (auto& e : level.levelMesh->Surfaces) + { + if (e.needsUpdate && !e.bSky && !e.portalIndex) + { + VisibleSurfaces.Push(&e); + + if (VisibleSurfaces.Size() >= unsigned(lm_background_updates)) + break; + } + } + } + + screen->UpdateLightmaps(VisibleSurfaces); +} + //----------------------------------------------------------------------------- // // RenderScene @@ -423,6 +445,8 @@ void HWDrawInfo::RenderScene(FRenderState &state) const auto &vp = Viewpoint; RenderAll.Clock(); + UpdateLightmaps(); + state.SetLightMode((int)lightmode); state.SetDepthMask(true); diff --git a/src/rendering/hwrenderer/scene/hw_drawinfo.h b/src/rendering/hwrenderer/scene/hw_drawinfo.h index b4a462836..91e545c3c 100644 --- a/src/rendering/hwrenderer/scene/hw_drawinfo.h +++ b/src/rendering/hwrenderer/scene/hw_drawinfo.h @@ -148,6 +148,7 @@ struct HWDrawInfo TArray Decals[2]; // the second slot is for mirrors which get rendered in a separate pass. TArray hudsprites; // These may just be stored by value. TArray Coronas; + TArray VisibleSurfaces; uint64_t LastFrameTime = 0; TArray MissingUpperTextures; @@ -198,6 +199,20 @@ struct HWDrawInfo VPUniforms.mClipHeight = 0; } + void PushVisibleSurface(LevelMeshSurface* surface) + { + if (outer) + { + outer->PushVisibleSurface(surface); + return; + } + + if (!surface->portalIndex && !surface->bSky) + { + VisibleSurfaces.Push(surface); + } + } + HWPortal * FindPortal(const void * src); void RenderBSPNode(void *node, FRenderState& state); void RenderBSP(void *node, bool drawpsprites, FRenderState& state); @@ -335,6 +350,8 @@ private: 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 UpdateLightmaps(); }; void CleanSWDrawer(); diff --git a/src/rendering/hwrenderer/scene/hw_flats.cpp b/src/rendering/hwrenderer/scene/hw_flats.cpp index 9bccc2aa4..01f62bb5d 100644 --- a/src/rendering/hwrenderer/scene/hw_flats.cpp +++ b/src/rendering/hwrenderer/scene/hw_flats.cpp @@ -512,7 +512,7 @@ void HWFlat::ProcessSector(HWDrawInfo *di, FRenderState& state, sector_t * front { if (auto lightmap = sector->subsectors[i]->lightmap[plane][0]) { - state.PushVisibleSurface(lightmap); + di->PushVisibleSurface(lightmap); } } } @@ -523,7 +523,7 @@ void HWFlat::ProcessSector(HWDrawInfo *di, FRenderState& state, sector_t * front { if (surface) { - state.PushVisibleSurface(surface); + di->PushVisibleSurface(surface); } } } @@ -538,7 +538,7 @@ void HWFlat::ProcessSector(HWDrawInfo *di, FRenderState& state, sector_t * front { if (surface) { - state.PushVisibleSurface(surface); + di->PushVisibleSurface(surface); } } } diff --git a/src/rendering/hwrenderer/scene/hw_walls.cpp b/src/rendering/hwrenderer/scene/hw_walls.cpp index 87a5685ea..7de7c0a0c 100644 --- a/src/rendering/hwrenderer/scene/hw_walls.cpp +++ b/src/rendering/hwrenderer/scene/hw_walls.cpp @@ -1267,7 +1267,7 @@ void HWWall::DoTexture(HWDrawInfo *di, FRenderState& state, int _type,seg_t * se lightmap = seg->sidedef->lightmap[type - RENDERWALL_TOP]; if (lightmap) { - state.PushVisibleSurface(lightmap); + di->PushVisibleSurface(lightmap); } } else