From 4706c566904354e73f977fa37132bf4f07aa7bdd Mon Sep 17 00:00:00 2001 From: Magnus Norddahl Date: Sun, 10 Sep 2017 02:17:18 +0200 Subject: [PATCH] - Fix portals crashing softpoly --- src/polyrenderer/poly_renderthread.cpp | 7 ++-- src/polyrenderer/poly_renderthread.h | 9 ++-- src/polyrenderer/scene/poly_scene.cpp | 58 ++++++++++++-------------- src/polyrenderer/scene/poly_scene.h | 5 ++- 4 files changed, 36 insertions(+), 43 deletions(-) diff --git a/src/polyrenderer/poly_renderthread.cpp b/src/polyrenderer/poly_renderthread.cpp index 6691a4f5c..9c3b33122 100644 --- a/src/polyrenderer/poly_renderthread.cpp +++ b/src/polyrenderer/poly_renderthread.cpp @@ -46,9 +46,8 @@ void PeekThreadedErrorPane(); EXTERN_CVAR(Bool, r_scene_multithreaded); -PolyRenderThread::PolyRenderThread(bool mainThread) +PolyRenderThread::PolyRenderThread(int threadIndex) : MainThread(threadIndex == 0), ThreadIndex(threadIndex) { - MainThread = mainThread; FrameMemory.reset(new RenderMemory()); DrawQueue = std::make_shared(FrameMemory.get()); } @@ -118,7 +117,7 @@ void PolyRenderThread::PreparePolyObject(subsector_t *sub) PolyRenderThreads::PolyRenderThreads() { - std::unique_ptr thread(new PolyRenderThread(true)); + std::unique_ptr thread(new PolyRenderThread(0)); Threads.push_back(std::move(thread)); } @@ -220,7 +219,7 @@ void PolyRenderThreads::StartThreads(size_t numThreads) { while (Threads.size() < (size_t)numThreads) { - std::unique_ptr thread(new PolyRenderThread(false)); + std::unique_ptr thread(new PolyRenderThread((int)Threads.size())); auto renderthread = thread.get(); int start_run_id = run_id; thread->thread = std::thread([=]() diff --git a/src/polyrenderer/poly_renderthread.h b/src/polyrenderer/poly_renderthread.h index ec0562c09..af10fd45c 100644 --- a/src/polyrenderer/poly_renderthread.h +++ b/src/polyrenderer/poly_renderthread.h @@ -33,7 +33,7 @@ class RenderMemory; class PolyRenderThread { public: - PolyRenderThread(bool mainThread = true); + PolyRenderThread(int threadIndex); ~PolyRenderThread(); void FlushDrawQueue(); @@ -41,15 +41,11 @@ public: int Start = 0; int End = 0; bool MainThread = false; + int ThreadIndex = 0; std::unique_ptr FrameMemory; DrawerCommandQueuePtr DrawQueue; - std::vector TranslucentObjects; - - std::vector> SectorPortals; - std::vector> LinePortals; - // Make sure texture can accessed safely void PrepareTexture(FTexture *texture); @@ -74,6 +70,7 @@ public: void RenderThreadSlices(int totalcount, std::function workerCallback, std::function collectCallback); PolyRenderThread *MainThread() { return Threads.front().get(); } + int NumThreads() const { return (int)Threads.size(); } private: void RenderThreadSlice(PolyRenderThread *thread); diff --git a/src/polyrenderer/scene/poly_scene.cpp b/src/polyrenderer/scene/poly_scene.cpp index 09f92c0d7..d315a02e5 100644 --- a/src/polyrenderer/scene/poly_scene.cpp +++ b/src/polyrenderer/scene/poly_scene.cpp @@ -58,19 +58,13 @@ void RenderPolyScene::Render(int portalDepth) { PolyRenderThread *thread = PolyRenderer::Instance()->Threads.MainThread(); - ClearBuffers(thread); + SectorPortals.clear(); + LinePortals.clear(); Cull.CullScene(WorldToClip, PortalPlane); RenderSectors(); RenderPortals(portalDepth); } -void RenderPolyScene::ClearBuffers(PolyRenderThread *thread) -{ - thread->TranslucentObjects.clear(); - thread->SectorPortals.clear(); - thread->LinePortals.clear(); -} - void RenderPolyScene::RenderSectors() { PolyRenderThread *mainthread = PolyRenderer::Instance()->Threads.MainThread(); @@ -78,12 +72,11 @@ void RenderPolyScene::RenderSectors() int totalcount = (int)Cull.PvsSectors.size(); auto subsectors = Cull.PvsSectors.data(); + TranslucentObjects.resize(PolyRenderer::Instance()->Threads.NumThreads()); + PolyRenderer::Instance()->Threads.RenderThreadSlices(totalcount, [&](PolyRenderThread *thread) { - if (!thread->MainThread) - { - ClearBuffers(thread); - } + TranslucentObjects[thread->ThreadIndex].clear(); int start = thread->Start; int end = thread->End; @@ -93,7 +86,8 @@ void RenderPolyScene::RenderSectors() } }, [&](PolyRenderThread *thread) { - mainthread->TranslucentObjects.insert(mainthread->TranslucentObjects.end(), thread->TranslucentObjects.begin(), thread->TranslucentObjects.end()); + const auto &objects = TranslucentObjects[thread->ThreadIndex]; + TranslucentObjects[0].insert(TranslucentObjects[0].end(), objects.begin(), objects.end()); }); } @@ -127,13 +121,13 @@ void RenderPolyScene::RenderSubsector(PolyRenderThread *thread, subsector_t *sub RenderPolyNode(thread, &sub->BSP->Nodes.Last(), subsectorDepth, frontsector); } - Render3DFloorPlane::RenderPlanes(thread, WorldToClip, PortalPlane, sub, StencilValue, subsectorDepth, thread->TranslucentObjects); - RenderPolyPlane::RenderPlanes(thread, WorldToClip, PortalPlane, sub, StencilValue, Cull.MaxCeilingHeight, Cull.MinFloorHeight, thread->SectorPortals); + Render3DFloorPlane::RenderPlanes(thread, WorldToClip, PortalPlane, sub, StencilValue, subsectorDepth, TranslucentObjects[thread->ThreadIndex]); + RenderPolyPlane::RenderPlanes(thread, WorldToClip, PortalPlane, sub, StencilValue, Cull.MaxCeilingHeight, Cull.MinFloorHeight, SectorPortals); } else { - Render3DFloorPlane::RenderPlanes(thread, WorldToClip, PortalPlane, sub, StencilValue, subsectorDepth, thread->TranslucentObjects); - RenderPolyPlane::RenderPlanes(thread, WorldToClip, PortalPlane, sub, StencilValue, Cull.MaxCeilingHeight, Cull.MinFloorHeight, thread->SectorPortals); + Render3DFloorPlane::RenderPlanes(thread, WorldToClip, PortalPlane, sub, StencilValue, subsectorDepth, TranslucentObjects[thread->ThreadIndex]); + RenderPolyPlane::RenderPlanes(thread, WorldToClip, PortalPlane, sub, StencilValue, Cull.MaxCeilingHeight, Cull.MinFloorHeight, SectorPortals); for (uint32_t i = 0; i < sub->numlines; i++) { @@ -151,7 +145,7 @@ void RenderPolyScene::RenderSubsector(PolyRenderThread *thread, subsector_t *sub for (int i = ParticlesInSubsec[subsectorIndex]; i != NO_PARTICLE; i = Particles[i].snext) { particle_t *particle = Particles + i; - thread->TranslucentObjects.push_back(thread->FrameMemory->NewObject(particle, sub, subsectorDepth, StencilValue)); + TranslucentObjects[thread->ThreadIndex].push_back(thread->FrameMemory->NewObject(particle, sub, subsectorDepth, StencilValue)); } } } @@ -204,7 +198,7 @@ void RenderPolyScene::RenderPolySubsector(PolyRenderThread *thread, subsector_t sub->flags |= SSECF_DRAWN; } - RenderPolyWall::RenderLine(thread, WorldToClip, PortalPlane, line, frontsector, subsectorDepth, StencilValue, thread->TranslucentObjects, thread->LinePortals, LastPortalLine); + RenderPolyWall::RenderLine(thread, WorldToClip, PortalPlane, line, frontsector, subsectorDepth, StencilValue, TranslucentObjects[thread->ThreadIndex], LinePortals, LastPortalLine); } } } @@ -221,7 +215,7 @@ void RenderPolyScene::RenderSprite(PolyRenderThread *thread, AActor *thing, doub subsector_t *sub = &level.subsectors[0]; auto it = Cull.SubsectorDepths.find(sub); if (it != Cull.SubsectorDepths.end()) - thread->TranslucentObjects.push_back(thread->FrameMemory->NewObject(thing, sub, it->second, sortDistance, 0.0f, 1.0f, StencilValue)); + TranslucentObjects[thread->ThreadIndex].push_back(thread->FrameMemory->NewObject(thing, sub, it->second, sortDistance, 0.0f, 1.0f, StencilValue)); } else { @@ -262,7 +256,7 @@ void RenderPolyScene::RenderSprite(PolyRenderThread *thread, AActor *thing, doub auto it = Cull.SubsectorDepths.find(sub); if (it != Cull.SubsectorDepths.end()) - thread->TranslucentObjects.push_back(thread->FrameMemory->NewObject(thing, sub, it->second, sortDistance, (float)t1, (float)t2, StencilValue)); + TranslucentObjects[thread->ThreadIndex].push_back(thread->FrameMemory->NewObject(thing, sub, it->second, sortDistance, (float)t1, (float)t2, StencilValue)); } void RenderPolyScene::RenderLine(PolyRenderThread *thread, subsector_t *sub, seg_t *line, sector_t *frontsector, uint32_t subsectorDepth) @@ -280,12 +274,12 @@ void RenderPolyScene::RenderLine(PolyRenderThread *thread, subsector_t *sub, seg for (unsigned int i = 0; i < line->backsector->e->XFloor.ffloors.Size(); i++) { F3DFloor *fakeFloor = line->backsector->e->XFloor.ffloors[i]; - RenderPolyWall::Render3DFloorLine(thread, WorldToClip, PortalPlane, line, frontsector, subsectorDepth, StencilValue, fakeFloor, thread->TranslucentObjects); + RenderPolyWall::Render3DFloorLine(thread, WorldToClip, PortalPlane, line, frontsector, subsectorDepth, StencilValue, fakeFloor, TranslucentObjects[thread->ThreadIndex]); } } // Render wall, and update culling info if its an occlusion blocker - RenderPolyWall::RenderLine(thread, WorldToClip, PortalPlane, line, frontsector, subsectorDepth, StencilValue, thread->TranslucentObjects, thread->LinePortals, LastPortalLine); + RenderPolyWall::RenderLine(thread, WorldToClip, PortalPlane, line, frontsector, subsectorDepth, StencilValue, TranslucentObjects[thread->ThreadIndex], LinePortals, LastPortalLine); } void RenderPolyScene::RenderPortals(int portalDepth) @@ -295,10 +289,10 @@ void RenderPolyScene::RenderPortals(int portalDepth) bool foggy = false; if (portalDepth < r_portal_recursions) { - for (auto &portal : thread->SectorPortals) + for (auto &portal : SectorPortals) portal->Render(portalDepth + 1); - for (auto &portal : thread->LinePortals) + for (auto &portal : LinePortals) portal->Render(portalDepth + 1); } else // Fill with black @@ -310,7 +304,7 @@ void RenderPolyScene::RenderPortals(int portalDepth) args.SetClipPlane(0, PortalPlane); args.SetStyle(TriBlendMode::FillOpaque); - for (auto &portal : thread->SectorPortals) + for (auto &portal : SectorPortals) { args.SetStencilTestValue(portal->StencilValue); args.SetWriteStencil(true, portal->StencilValue + 1); @@ -321,7 +315,7 @@ void RenderPolyScene::RenderPortals(int portalDepth) } } - for (auto &portal : thread->LinePortals) + for (auto &portal : LinePortals) { args.SetStencilTestValue(portal->StencilValue); args.SetWriteStencil(true, portal->StencilValue + 1); @@ -340,7 +334,7 @@ void RenderPolyScene::RenderTranslucent(int portalDepth) if (portalDepth < r_portal_recursions) { - for (auto it = thread->SectorPortals.rbegin(); it != thread->SectorPortals.rend(); ++it) + for (auto it = SectorPortals.rbegin(); it != SectorPortals.rend(); ++it) { auto &portal = *it; portal->RenderTranslucent(portalDepth + 1); @@ -358,7 +352,7 @@ void RenderPolyScene::RenderTranslucent(int portalDepth) } } - for (auto it = thread->LinePortals.rbegin(); it != thread->LinePortals.rend(); ++it) + for (auto it = LinePortals.rbegin(); it != LinePortals.rend(); ++it) { auto &portal = *it; portal->RenderTranslucent(portalDepth + 1); @@ -390,14 +384,14 @@ void RenderPolyScene::RenderTranslucent(int portalDepth) } } - std::stable_sort(thread->TranslucentObjects.begin(), thread->TranslucentObjects.end(), [](auto a, auto b) { return *a < *b; }); + std::stable_sort(TranslucentObjects[0].begin(), TranslucentObjects[0].end(), [](auto a, auto b) { return *a < *b; }); - for (auto it = thread->TranslucentObjects.rbegin(); it != thread->TranslucentObjects.rend(); ++it) + for (auto it = TranslucentObjects[0].rbegin(); it != TranslucentObjects[0].rend(); ++it) { PolyTranslucentObject *obj = *it; obj->Render(thread, WorldToClip, PortalPlane); obj->~PolyTranslucentObject(); } - thread->TranslucentObjects.clear(); + TranslucentObjects[0].clear(); } diff --git a/src/polyrenderer/scene/poly_scene.h b/src/polyrenderer/scene/poly_scene.h index 5dd34dbd9..bf2d1b21d 100644 --- a/src/polyrenderer/scene/poly_scene.h +++ b/src/polyrenderer/scene/poly_scene.h @@ -68,7 +68,6 @@ public: line_t *LastPortalLine = nullptr; private: - void ClearBuffers(PolyRenderThread *thread); void RenderPortals(int portalDepth); void RenderSectors(); void RenderSubsector(PolyRenderThread *thread, subsector_t *sub, uint32_t subsectorDepth); @@ -85,4 +84,8 @@ private: uint32_t StencilValue = 0; PolyCull Cull; bool PortalSegmentsAdded = false; + + std::vector> TranslucentObjects; + std::vector> SectorPortals; + std::vector> LinePortals; };