From d0ce0218052f44840b1662ff039727a245645a72 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Sun, 16 Dec 2018 09:05:02 +0100 Subject: [PATCH] - fixed: Both main and worker thread were modifying the portal state. The parts in the main thread have been offloaded to a new worker job to avoid having to use a mutex to protect the portal state. --- src/hwrenderer/scene/hw_bsp.cpp | 29 +++++++++++++++++++++++++++-- 1 file changed, 27 insertions(+), 2 deletions(-) diff --git a/src/hwrenderer/scene/hw_bsp.cpp b/src/hwrenderer/scene/hw_bsp.cpp index 4daadd63f2..732af5641f 100644 --- a/src/hwrenderer/scene/hw_bsp.cpp +++ b/src/hwrenderer/scene/hw_bsp.cpp @@ -56,6 +56,7 @@ struct RenderJob WallJob, SpriteJob, ParticleJob, + PortalJob, TerminateJob // inserted when all work is done so that the worker can return. }; @@ -177,7 +178,12 @@ void HWDrawInfo::WorkerThread() RenderParticles(job->sub, front); SetupSprite.Unclock(); break; + + case RenderJob::PortalJob: + AddSubsectorToPortal((FSectorPortalGroup *)job->seg, job->sub); + break; } + } } @@ -706,16 +712,35 @@ void HWDrawInfo::DoSubsector(subsector_t * sub) // This is for portal coverage. FSectorPortalGroup *portal; + // AddSubsectorToPortal cannot be called here when using multithreaded processing, + // because the wall processing code in the worker can also modify the portal state. + // To avoid costly synchronization for every access to the portal list, + // the call to AddSubsectorToPortal will be deferred to the worker. + // (GetPortalGruop only accesses static sector data so this check can be done here, restricting the new job to the minimum possible extent.) portal = fakesector->GetPortalGroup(sector_t::ceiling); if (portal != nullptr) { - AddSubsectorToPortal(portal, sub); + if (multithread) + { + jobQueue.AddJob(RenderJob::PortalJob, sub, (seg_t *)portal); + } + else + { + AddSubsectorToPortal(portal, sub); + } } portal = fakesector->GetPortalGroup(sector_t::floor); if (portal != nullptr) { - AddSubsectorToPortal(portal, sub); + if (multithread) + { + jobQueue.AddJob(RenderJob::PortalJob, sub, (seg_t *)portal); + } + else + { + AddSubsectorToPortal(portal, sub); + } } } }