Move the visible surface list to HWDrawInfo

This commit is contained in:
Magnus Norddahl 2023-09-15 20:45:03 +02:00 committed by Christoph Oelckers
parent 39312e898f
commit a6ff0a65d0
9 changed files with 58 additions and 75 deletions

View file

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

View file

@ -262,17 +262,12 @@ protected:
EPassType mPassType = NORMAL_PASS;
std::atomic<unsigned> mActiveLightmapSurfaceBufferIndex;
TArray<LevelMeshSurface*> 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

View file

@ -100,8 +100,8 @@ void VkLightmap::SelectSurfaces(const TArray<LevelMeshSurface*>& 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);
@ -115,6 +115,8 @@ void VkLightmap::SelectSurfaces(const TArray<LevelMeshSurface*>& surfaces)
bakeImage.maxX = std::max<uint16_t>(bakeImage.maxX, uint16_t(selected.X + surface->texWidth + spacing));
bakeImage.maxY = std::max<uint16_t>(bakeImage.maxY, uint16_t(selected.Y + surface->texHeight + spacing));
surface->needsUpdate = false;
}
}
}
@ -227,7 +229,14 @@ void VkLightmap::RenderBakeImage()
}
if (buffersFull)
{
while (i < count)
{
selectedSurfaces[i].Surface->needsUpdate = true;
i++;
}
break;
}
selectedSurface.Rendered = true;
}
@ -423,9 +432,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++;
}

View file

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

View file

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

View file

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

View file

@ -148,6 +148,7 @@ struct HWDrawInfo
TArray<HWDecal *> Decals[2]; // the second slot is for mirrors which get rendered in a separate pass.
TArray<HUDSprite> hudsprites; // These may just be stored by value.
TArray<ACorona*> Coronas;
TArray<LevelMeshSurface*> VisibleSurfaces;
uint64_t LastFrameTime = 0;
TArray<MissingTextureInfo> 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();

View file

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

View file

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