diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 1c5192a4a..38a701dc0 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -744,6 +744,7 @@ set ( SWRENDER_SOURCES set( POLYRENDER_SOURCES polyrenderer/poly_renderer.cpp + polyrenderer/poly_renderthread.cpp polyrenderer/scene/poly_scene.cpp polyrenderer/scene/poly_portal.cpp polyrenderer/scene/poly_cull.cpp diff --git a/src/polyrenderer/drawers/poly_draw_args.cpp b/src/polyrenderer/drawers/poly_draw_args.cpp index 1bd478da9..0df28f9aa 100644 --- a/src/polyrenderer/drawers/poly_draw_args.cpp +++ b/src/polyrenderer/drawers/poly_draw_args.cpp @@ -36,6 +36,7 @@ #include "swrenderer/r_swcolormaps.h" #include "poly_draw_args.h" #include "swrenderer/viewport/r_viewport.h" +#include "polyrenderer/poly_renderthread.h" void PolyDrawArgs::SetTexture(const uint8_t *texels, int width, int height) { @@ -125,12 +126,12 @@ void PolyDrawArgs::SetColor(uint32_t bgra, uint8_t palindex) } } -void PolyDrawArgs::DrawArray(const TriVertex *vertices, int vcount, PolyDrawMode mode) +void PolyDrawArgs::DrawArray(PolyRenderThread *thread, const TriVertex *vertices, int vcount, PolyDrawMode mode) { mVertices = vertices; mVertexCount = vcount; mDrawMode = mode; - PolyRenderer::Instance()->DrawQueue->Push(*this, PolyTriangleDrawer::is_mirror()); + thread->DrawQueue->Push(*this, PolyTriangleDrawer::is_mirror()); } void PolyDrawArgs::SetStyle(const FRenderStyle &renderstyle, double alpha, uint32_t fillcolor, uint32_t translationID, FTexture *tex, bool fullbright) @@ -273,7 +274,7 @@ void RectDrawArgs::SetColor(uint32_t bgra, uint8_t palindex) } } -void RectDrawArgs::Draw(double x0, double x1, double y0, double y1, double u0, double u1, double v0, double v1) +void RectDrawArgs::Draw(PolyRenderThread *thread, double x0, double x1, double y0, double y1, double u0, double u1, double v0, double v1) { mX0 = (float)x0; mX1 = (float)x1; @@ -283,7 +284,7 @@ void RectDrawArgs::Draw(double x0, double x1, double y0, double y1, double u0, d mU1 = (float)u1; mV0 = (float)v0; mV1 = (float)v1; - PolyRenderer::Instance()->DrawQueue->Push(*this); + thread->DrawQueue->Push(*this); } void RectDrawArgs::SetStyle(const FRenderStyle &renderstyle, double alpha, uint32_t fillcolor, uint32_t translationID, FTexture *tex, bool fullbright) diff --git a/src/polyrenderer/drawers/poly_draw_args.h b/src/polyrenderer/drawers/poly_draw_args.h index 9563d484d..69b89a053 100644 --- a/src/polyrenderer/drawers/poly_draw_args.h +++ b/src/polyrenderer/drawers/poly_draw_args.h @@ -26,6 +26,7 @@ #include "r_data/colormaps.h" #include "screen_triangle.h" +class PolyRenderThread; class FTexture; struct TriMatrix; @@ -63,7 +64,7 @@ public: void SetStyle(const FRenderStyle &renderstyle, double alpha, uint32_t fillcolor, uint32_t translationID, FTexture *texture, bool fullbright); void SetTransform(const TriMatrix *objectToClip) { mObjectToClip = objectToClip; } void SetColor(uint32_t bgra, uint8_t palindex); - void DrawArray(const TriVertex *vertices, int vcount, PolyDrawMode mode = PolyDrawMode::Triangles); + void DrawArray(PolyRenderThread *thread, const TriVertex *vertices, int vcount, PolyDrawMode mode = PolyDrawMode::Triangles); const TriMatrix *ObjectToClip() const { return mObjectToClip; } const PolyClipPlane &ClipPlane(int index) const { return mClipPlane[index]; } @@ -157,7 +158,7 @@ public: void SetStyle(TriBlendMode blendmode, double srcalpha = 1.0, double destalpha = 1.0) { mBlendMode = blendmode; mSrcAlpha = (uint32_t)(srcalpha * 256.0 + 0.5); mDestAlpha = (uint32_t)(destalpha * 256.0 + 0.5); } void SetStyle(const FRenderStyle &renderstyle, double alpha, uint32_t fillcolor, uint32_t translationID, FTexture *texture, bool fullbright); void SetColor(uint32_t bgra, uint8_t palindex); - void Draw(double x0, double x1, double y0, double y1, double u0, double u1, double v0, double v1); + void Draw(PolyRenderThread *thread, double x0, double x1, double y0, double y1, double u0, double u1, double v0, double v1); const uint8_t *TexturePixels() const { return mTexturePixels; } int TextureWidth() const { return mTextureWidth; } diff --git a/src/polyrenderer/poly_all.cpp b/src/polyrenderer/poly_all.cpp index 286dae4cb..62d63c2d3 100644 --- a/src/polyrenderer/poly_all.cpp +++ b/src/polyrenderer/poly_all.cpp @@ -1,4 +1,5 @@ #include "poly_renderer.cpp" +#include "poly_renderthread.cpp" #include "drawers/poly_buffer.cpp" #include "drawers/poly_draw_args.cpp" #include "drawers/poly_triangle.cpp" diff --git a/src/polyrenderer/poly_renderer.cpp b/src/polyrenderer/poly_renderer.cpp index 184cb9697..c3389bba5 100644 --- a/src/polyrenderer/poly_renderer.cpp +++ b/src/polyrenderer/poly_renderer.cpp @@ -54,7 +54,6 @@ PolyRenderer *PolyRenderer::Instance() PolyRenderer::PolyRenderer() { - DrawQueue = std::make_shared(&FrameMemory); } void PolyRenderer::RenderView(player_t *player) @@ -75,12 +74,11 @@ void PolyRenderer::RenderView(player_t *player) CameraLight *cameraLight = CameraLight::Instance(); if (cameraLight->ShaderColormap() && RenderTarget->IsBgra() && !(r_shadercolormaps && screen->Accel2D)) { - DrawQueue->Push(cameraLight->ShaderColormap(), screen); + Threads.MainThread()->DrawQueue->Push(cameraLight->ShaderColormap(), screen); } - DrawerThreads::Execute(DrawQueue); + Threads.MainThread()->FlushDrawQueue(); DrawerThreads::WaitForWorkers(); - DrawQueue->Clear(); } void PolyRenderer::RenderViewToCanvas(AActor *actor, DCanvas *canvas, int x, int y, int width, int height, bool dontmaplines) @@ -98,7 +96,7 @@ void PolyRenderer::RenderViewToCanvas(AActor *actor, DCanvas *canvas, int x, int canvas->Lock(true); RenderActorView(actor, dontmaplines); - DrawerThreads::Execute(DrawQueue); + Threads.MainThread()->FlushDrawQueue(); DrawerThreads::WaitForWorkers(); canvas->Unlock(); @@ -141,9 +139,9 @@ void PolyRenderer::RenderActorView(AActor *actor, bool dontmaplines) SetupPerspectiveMatrix(); MainPortal.SetViewpoint(WorldToClip, PolyClipPlane(0.0f, 0.0f, 0.0f, 1.0f), GetNextStencilValue()); MainPortal.Render(0); - Skydome.Render(WorldToClip); + Skydome.Render(Threads.MainThread(), WorldToClip); MainPortal.RenderTranslucent(0); - PlayerSprites.Render(); + PlayerSprites.Render(Threads.MainThread()); Viewpoint.camera->renderflags = savedflags; interpolator.RestoreInterpolations (); @@ -158,7 +156,7 @@ void PolyRenderer::RenderRemainingPlayerSprites() void PolyRenderer::ClearBuffers() { - FrameMemory.Clear(); + Threads.Clear(); PolyStencilBuffer::Instance()->Clear(RenderTarget->GetWidth(), RenderTarget->GetHeight(), 0); PolyZBuffer::Instance()->Resize(RenderTarget->GetPitch(), RenderTarget->GetHeight()); NextStencilValue = 0; diff --git a/src/polyrenderer/poly_renderer.h b/src/polyrenderer/poly_renderer.h index efd1bbf67..8e5011782 100644 --- a/src/polyrenderer/poly_renderer.h +++ b/src/polyrenderer/poly_renderer.h @@ -33,6 +33,7 @@ #include "scene/poly_sky.h" #include "scene/poly_light.h" #include "swrenderer/r_memory.h" +#include "poly_renderthread.h" class AActor; class DCanvas; @@ -54,8 +55,7 @@ public: bool DontMapLines = false; - RenderMemory FrameMemory; - DrawerCommandQueuePtr DrawQueue; + PolyRenderThreads Threads; DCanvas *RenderTarget = nullptr; FViewWindow Viewwindow; FRenderViewpoint Viewpoint; diff --git a/src/polyrenderer/poly_renderthread.cpp b/src/polyrenderer/poly_renderthread.cpp new file mode 100644 index 000000000..6691a4f5c --- /dev/null +++ b/src/polyrenderer/poly_renderthread.cpp @@ -0,0 +1,265 @@ +/* +** Polygon Doom software renderer +** Copyright (c) 2016 Magnus Norddahl +** +** This software is provided 'as-is', without any express or implied +** warranty. In no event will the authors be held liable for any damages +** arising from the use of this software. +** +** Permission is granted to anyone to use this software for any purpose, +** including commercial applications, and to alter it and redistribute it +** freely, subject to the following restrictions: +** +** 1. The origin of this software must not be misrepresented; you must not +** claim that you wrote the original software. If you use this software +** in a product, an acknowledgment in the product documentation would be +** appreciated but is not required. +** 2. Altered source versions must be plainly marked as such, and must not be +** misrepresented as being the original software. +** 3. This notice may not be removed or altered from any source distribution. +** +*/ + +#include +#include "templates.h" +#include "doomdef.h" +#include "m_bbox.h" +#include "i_system.h" +#include "p_lnspec.h" +#include "p_setup.h" +#include "a_sharedglobal.h" +#include "g_level.h" +#include "p_effect.h" +#include "doomstat.h" +#include "r_state.h" +#include "v_palette.h" +#include "r_sky.h" +#include "po_man.h" +#include "r_data/colormaps.h" +#include "poly_renderthread.h" +#include "poly_renderer.h" +#include + +#ifdef WIN32 +void PeekThreadedErrorPane(); +#endif + +EXTERN_CVAR(Bool, r_scene_multithreaded); + +PolyRenderThread::PolyRenderThread(bool mainThread) +{ + MainThread = mainThread; + FrameMemory.reset(new RenderMemory()); + DrawQueue = std::make_shared(FrameMemory.get()); +} + +PolyRenderThread::~PolyRenderThread() +{ +} + +void PolyRenderThread::FlushDrawQueue() +{ + DrawerThreads::Execute(DrawQueue); + + UsedDrawQueues.push_back(DrawQueue); + DrawQueue.reset(); + + if (!FreeDrawQueues.empty()) + { + DrawQueue = FreeDrawQueues.back(); + FreeDrawQueues.pop_back(); + } + else + { + DrawQueue = std::make_shared(FrameMemory.get()); + } +} + +void PolyRenderThread::PrepareTexture(FTexture *texture) +{ + if (texture == nullptr) + return; + + // Textures may not have loaded/refreshed yet. The shared code doing + // this is not thread safe. By calling GetPixels in a mutex lock we + // make sure that only one thread is loading a texture at any given + // time. + // + // It is critical that this function is called before any direct + // calls to GetPixels for this to work. + + static std::mutex loadmutex; + + std::unique_lock lock(loadmutex); + + texture->GetPixels(); + const FTexture::Span *spans; + texture->GetColumn(0, &spans); + if (PolyRenderer::Instance()->RenderTarget->IsBgra()) + { + texture->GetPixelsBgra(); + texture->GetColumnBgra(0, &spans); + } +} + +void PolyRenderThread::PreparePolyObject(subsector_t *sub) +{ + static std::mutex polyobjmutex; + + std::unique_lock lock(polyobjmutex); + + if (sub->BSP == nullptr || sub->BSP->bDirty) + { + sub->BuildPolyBSP(); + } +} + +///////////////////////////////////////////////////////////////////////////// + +PolyRenderThreads::PolyRenderThreads() +{ + std::unique_ptr thread(new PolyRenderThread(true)); + Threads.push_back(std::move(thread)); +} + +PolyRenderThreads::~PolyRenderThreads() +{ + StopThreads(); +} + +void PolyRenderThreads::Clear() +{ + for (auto &thread : Threads) + { + thread->FrameMemory->Clear(); + thread->DrawQueue->Clear(); + + while (!thread->UsedDrawQueues.empty()) + { + auto queue = thread->UsedDrawQueues.back(); + thread->UsedDrawQueues.pop_back(); + queue->Clear(); + thread->FreeDrawQueues.push_back(queue); + } + } +} + +void PolyRenderThreads::RenderThreadSlices(int totalcount, std::function workerCallback, std::function collectCallback) +{ + WorkerCallback = workerCallback; + + int numThreads = std::thread::hardware_concurrency(); + if (numThreads == 0) + numThreads = 4; + + if (!r_scene_multithreaded || !r_multithreaded) + numThreads = 1; + + if (numThreads != (int)Threads.size()) + { + StopThreads(); + StartThreads(numThreads); + } + + // Setup threads: + std::unique_lock start_lock(start_mutex); + for (int i = 0; i < numThreads; i++) + { + Threads[i]->Start = totalcount * i / numThreads; + Threads[i]->End = totalcount * (i + 1) / numThreads; + } + run_id++; + start_lock.unlock(); + + // Notify threads to run + if (Threads.size() > 1) + { + start_condition.notify_all(); + } + + // Do the main thread ourselves: + RenderThreadSlice(MainThread()); + + // Wait for everyone to finish: + if (Threads.size() > 1) + { + using namespace std::chrono_literals; + std::unique_lock end_lock(end_mutex); + finished_threads++; + if (!end_condition.wait_for(end_lock, 5s, [&]() { return finished_threads == Threads.size(); })) + { +#ifdef WIN32 + PeekThreadedErrorPane(); +#endif + // Invoke the crash reporter so that we can capture the call stack of whatever the hung worker thread is doing + int *threadCrashed = nullptr; + *threadCrashed = 0xdeadbeef; + } + finished_threads = 0; + } + + for (int i = 0; i < numThreads; i++) + { + Threads[i]->FlushDrawQueue(); + } + + WorkerCallback = {}; + + for (int i = 1; i < numThreads; i++) + { + collectCallback(Threads[i].get()); + } +} + +void PolyRenderThreads::RenderThreadSlice(PolyRenderThread *thread) +{ + WorkerCallback(thread); +} + +void PolyRenderThreads::StartThreads(size_t numThreads) +{ + while (Threads.size() < (size_t)numThreads) + { + std::unique_ptr thread(new PolyRenderThread(false)); + auto renderthread = thread.get(); + int start_run_id = run_id; + thread->thread = std::thread([=]() + { + int last_run_id = start_run_id; + while (true) + { + // Wait until we are signalled to run: + std::unique_lock start_lock(start_mutex); + start_condition.wait(start_lock, [&]() { return run_id != last_run_id || shutdown_flag; }); + if (shutdown_flag) + break; + last_run_id = run_id; + start_lock.unlock(); + + RenderThreadSlice(renderthread); + + // Notify main thread that we finished: + std::unique_lock end_lock(end_mutex); + finished_threads++; + end_lock.unlock(); + end_condition.notify_all(); + } + }); + Threads.push_back(std::move(thread)); + } +} + +void PolyRenderThreads::StopThreads() +{ + std::unique_lock lock(start_mutex); + shutdown_flag = true; + lock.unlock(); + start_condition.notify_all(); + while (Threads.size() > 1) + { + Threads.back()->thread.join(); + Threads.pop_back(); + } + lock.lock(); + shutdown_flag = false; +} diff --git a/src/polyrenderer/poly_renderthread.h b/src/polyrenderer/poly_renderthread.h new file mode 100644 index 000000000..ec0562c09 --- /dev/null +++ b/src/polyrenderer/poly_renderthread.h @@ -0,0 +1,94 @@ +/* +** Polygon Doom software renderer +** Copyright (c) 2016 Magnus Norddahl +** +** This software is provided 'as-is', without any express or implied +** warranty. In no event will the authors be held liable for any damages +** arising from the use of this software. +** +** Permission is granted to anyone to use this software for any purpose, +** including commercial applications, and to alter it and redistribute it +** freely, subject to the following restrictions: +** +** 1. The origin of this software must not be misrepresented; you must not +** claim that you wrote the original software. If you use this software +** in a product, an acknowledgment in the product documentation would be +** appreciated but is not required. +** 2. Altered source versions must be plainly marked as such, and must not be +** misrepresented as being the original software. +** 3. This notice may not be removed or altered from any source distribution. +** +*/ + +#pragma once + +#include +#include +#include "swrenderer/r_memory.h" + +class DrawerCommandQueue; +typedef std::shared_ptr DrawerCommandQueuePtr; +class RenderMemory; + +class PolyRenderThread +{ +public: + PolyRenderThread(bool mainThread = true); + ~PolyRenderThread(); + + void FlushDrawQueue(); + + int Start = 0; + int End = 0; + bool MainThread = false; + + 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); + + // Setup poly object in a threadsafe manner + void PreparePolyObject(subsector_t *sub); + +private: + std::thread thread; + std::vector UsedDrawQueues; + std::vector FreeDrawQueues; + + friend class PolyRenderThreads; +}; + +class PolyRenderThreads +{ +public: + PolyRenderThreads(); + ~PolyRenderThreads(); + + void Clear(); + void RenderThreadSlices(int totalcount, std::function workerCallback, std::function collectCallback); + + PolyRenderThread *MainThread() { return Threads.front().get(); } + +private: + void RenderThreadSlice(PolyRenderThread *thread); + + void StartThreads(size_t numThreads); + void StopThreads(); + + std::function WorkerCallback; + + std::vector> Threads; + std::mutex start_mutex; + std::condition_variable start_condition; + bool shutdown_flag = false; + int run_id = 0; + std::mutex end_mutex; + std::condition_variable end_condition; + size_t finished_threads = 0; +}; diff --git a/src/polyrenderer/scene/poly_cull.cpp b/src/polyrenderer/scene/poly_cull.cpp index 6d4114bb3..93041650d 100644 --- a/src/polyrenderer/scene/poly_cull.cpp +++ b/src/polyrenderer/scene/poly_cull.cpp @@ -30,7 +30,14 @@ void PolyCull::CullScene(const TriMatrix &worldToClip, const PolyClipPlane &portalClipPlane) { + ClearSolidSegments(); + MarkViewFrustum(); + PvsSectors.clear(); + PvsLineStart.clear(); + PvsLineVisible.clear(); + SeenSectors.clear(); + SubsectorDepths.clear(); PortalClipPlane = portalClipPlane; // Cull front to back @@ -97,35 +104,49 @@ void PolyCull::CullSubsector(subsector_t *sub) FirstSkyHeight = false; } + uint32_t subsectorDepth = (uint32_t)PvsSectors.size(); + // Mark that we need to render this PvsSectors.push_back(sub); + PvsLineStart.push_back((uint32_t)PvsLineVisible.size()); + + DVector3 viewpos = PolyRenderer::Instance()->Viewpoint.Pos; // Update culling info for further bsp clipping for (uint32_t i = 0; i < sub->numlines; i++) { seg_t *line = &sub->firstline[i]; - if ((line->sidedef == nullptr || !(line->sidedef->Flags & WALLF_POLYOBJ)) && line->backsector == nullptr) + + // Skip lines not facing viewer + DVector2 pt1 = line->v1->fPos() - viewpos; + DVector2 pt2 = line->v2->fPos() - viewpos; + if (pt1.Y * (pt1.X - pt2.X) + pt1.X * (pt2.Y - pt1.Y) >= 0) { - // Skip lines not facing viewer - DVector2 pt1 = line->v1->fPos() - PolyRenderer::Instance()->Viewpoint.Pos; - DVector2 pt2 = line->v2->fPos() - PolyRenderer::Instance()->Viewpoint.Pos; - if (pt1.Y * (pt1.X - pt2.X) + pt1.X * (pt2.Y - pt1.Y) >= 0) - continue; - - // Skip line if entirely behind portal clipping plane - if ((PortalClipPlane.A * line->v1->fX() + PortalClipPlane.B * line->v1->fY() + PortalClipPlane.D <= 0.0) || - (PortalClipPlane.A * line->v2->fX() + PortalClipPlane.B * line->v2->fY() + PortalClipPlane.D <= 0.0)) - { - continue; - } - - angle_t angle1, angle2; - if (GetAnglesForLine(line->v1->fX(), line->v1->fY(), line->v2->fX(), line->v2->fY(), angle1, angle2)) - { - MarkSegmentCulled(angle1, angle2); - } + PvsLineVisible.push_back(false); + continue; } + + // Skip line if entirely behind portal clipping plane + if ((PortalClipPlane.A * line->v1->fX() + PortalClipPlane.B * line->v1->fY() + PortalClipPlane.D <= 0.0) || + (PortalClipPlane.A * line->v2->fX() + PortalClipPlane.B * line->v2->fY() + PortalClipPlane.D <= 0.0)) + { + PvsLineVisible.push_back(false); + continue; + } + + angle_t angle1, angle2; + bool lineVisible = GetAnglesForLine(line->v1->fX(), line->v1->fY(), line->v2->fX(), line->v2->fY(), angle1, angle2); + if (lineVisible && line->backsector == nullptr) + { + MarkSegmentCulled(angle1, angle2); + } + + // Mark if this line was visible + PvsLineVisible.push_back(lineVisible); } + + SeenSectors.insert(sub->sector); + SubsectorDepths[sub] = subsectorDepth; } void PolyCull::ClearSolidSegments() diff --git a/src/polyrenderer/scene/poly_cull.h b/src/polyrenderer/scene/poly_cull.h index 57741a0b9..29c47134d 100644 --- a/src/polyrenderer/scene/poly_cull.h +++ b/src/polyrenderer/scene/poly_cull.h @@ -23,23 +23,26 @@ #pragma once #include "polyrenderer/drawers/poly_triangle.h" +#include +#include class PolyCull { public: - void ClearSolidSegments(); void CullScene(const TriMatrix &worldToClip, const PolyClipPlane &portalClipPlane); - bool GetAnglesForLine(double x1, double y1, double x2, double y2, angle_t &angle1, angle_t &angle2) const; - void MarkSegmentCulled(angle_t angle1, angle_t angle2); - bool IsSegmentCulled(angle_t angle1, angle_t angle2) const; - void InvertSegments(); - void MarkViewFrustum(); + bool IsLineSegVisible(uint32_t subsectorDepth, uint32_t lineIndex) + { + return PvsLineVisible[PvsLineStart[subsectorDepth] + lineIndex]; + } std::vector PvsSectors; double MaxCeilingHeight = 0.0; double MinFloorHeight = 0.0; + std::set SeenSectors; + std::unordered_map SubsectorDepths; + static angle_t PointToPseudoAngle(double x, double y); private: @@ -49,6 +52,13 @@ private: angle_t Start, End; }; + void ClearSolidSegments(); + void MarkViewFrustum(); + + bool GetAnglesForLine(double x1, double y1, double x2, double y2, angle_t &angle1, angle_t &angle2) const; + bool IsSegmentCulled(angle_t angle1, angle_t angle2) const; + void InvertSegments(); + void CullNode(void *node); void CullSubsector(subsector_t *sub); int PointOnSide(const DVector2 &pos, const node_t *node); @@ -57,6 +67,8 @@ private: // Returns true if some part of the bbox might be visible. bool CheckBBox(float *bspcoord); + void MarkSegmentCulled(angle_t angle1, angle_t angle2); + std::vector SolidSegments; std::vector TempInvertSolidSegments; const int SolidCullScale = 3000; @@ -64,5 +76,8 @@ private: PolyClipPlane PortalClipPlane; + std::vector PvsLineStart; + std::vector PvsLineVisible; + static angle_t AngleToPseudo(angle_t ang); }; diff --git a/src/polyrenderer/scene/poly_decal.cpp b/src/polyrenderer/scene/poly_decal.cpp index ade1def57..6c20e24af 100644 --- a/src/polyrenderer/scene/poly_decal.cpp +++ b/src/polyrenderer/scene/poly_decal.cpp @@ -28,10 +28,11 @@ #include "poly_decal.h" #include "polyrenderer/poly_renderer.h" #include "polyrenderer/scene/poly_light.h" +#include "polyrenderer/poly_renderthread.h" #include "a_sharedglobal.h" #include "swrenderer/scene/r_scene.h" -void RenderPolyDecal::RenderWallDecals(const TriMatrix &worldToClip, const PolyClipPlane &clipPlane, const seg_t *line, uint32_t stencilValue) +void RenderPolyDecal::RenderWallDecals(PolyRenderThread *thread, const TriMatrix &worldToClip, const PolyClipPlane &clipPlane, const seg_t *line, uint32_t stencilValue) { if (line->linedef == nullptr && line->sidedef == nullptr) return; @@ -39,11 +40,11 @@ void RenderPolyDecal::RenderWallDecals(const TriMatrix &worldToClip, const PolyC for (DBaseDecal *decal = line->sidedef->AttachedDecals; decal != nullptr; decal = decal->WallNext) { RenderPolyDecal render; - render.Render(worldToClip, clipPlane, decal, line, stencilValue); + render.Render(thread, worldToClip, clipPlane, decal, line, stencilValue); } } -void RenderPolyDecal::Render(const TriMatrix &worldToClip, const PolyClipPlane &clipPlane, DBaseDecal *decal, const seg_t *line, uint32_t stencilValue) +void RenderPolyDecal::Render(PolyRenderThread *thread, const TriMatrix &worldToClip, const PolyClipPlane &clipPlane, DBaseDecal *decal, const seg_t *line, uint32_t stencilValue) { if (decal->RenderFlags & RF_INVISIBLE || !viewactive || !decal->PicNum.isValid()) return; @@ -148,7 +149,7 @@ void RenderPolyDecal::Render(const TriMatrix &worldToClip, const PolyClipPlane & // Generate vertices for the decal - TriVertex *vertices = PolyRenderer::Instance()->FrameMemory.AllocMemory(4); + TriVertex *vertices = thread->FrameMemory->AllocMemory(4); vertices[0].x = (float)decal_left.X; vertices[0].y = (float)decal_left.Y; vertices[0].z = (float)ztop; @@ -193,7 +194,7 @@ void RenderPolyDecal::Render(const TriMatrix &worldToClip, const PolyClipPlane & args.SetDepthTest(true); args.SetWriteStencil(false); args.SetWriteDepth(false); - args.DrawArray(vertices, 4, PolyDrawMode::TriangleFan); + args.DrawArray(thread, vertices, 4, PolyDrawMode::TriangleFan); } void RenderPolyDecal::GetDecalSectors(DBaseDecal *decal, const seg_t *line, sector_t **front, sector_t **back) diff --git a/src/polyrenderer/scene/poly_decal.h b/src/polyrenderer/scene/poly_decal.h index 79ee3fa71..0317e14a9 100644 --- a/src/polyrenderer/scene/poly_decal.h +++ b/src/polyrenderer/scene/poly_decal.h @@ -27,10 +27,10 @@ class RenderPolyDecal { public: - static void RenderWallDecals(const TriMatrix &worldToClip, const PolyClipPlane &clipPlane, const seg_t *line, uint32_t stencilValue); + static void RenderWallDecals(PolyRenderThread *thread, const TriMatrix &worldToClip, const PolyClipPlane &clipPlane, const seg_t *line, uint32_t stencilValue); private: - void Render(const TriMatrix &worldToClip, const PolyClipPlane &clipPlane, DBaseDecal *decal, const seg_t *line, uint32_t stencilValue); + void Render(PolyRenderThread *thread, const TriMatrix &worldToClip, const PolyClipPlane &clipPlane, DBaseDecal *decal, const seg_t *line, uint32_t stencilValue); void GetDecalSectors(DBaseDecal *decal, const seg_t *line, sector_t **front, sector_t **back); double GetDecalZ(DBaseDecal *decal, const seg_t *line, sector_t *front, sector_t *back); diff --git a/src/polyrenderer/scene/poly_particle.cpp b/src/polyrenderer/scene/poly_particle.cpp index 8a78a8a64..6b5e1e9c5 100644 --- a/src/polyrenderer/scene/poly_particle.cpp +++ b/src/polyrenderer/scene/poly_particle.cpp @@ -28,10 +28,11 @@ #include "poly_particle.h" #include "polyrenderer/poly_renderer.h" #include "polyrenderer/scene/poly_light.h" +#include "polyrenderer/poly_renderthread.h" EXTERN_CVAR(Int, gl_particles_style) -void RenderPolyParticle::Render(const TriMatrix &worldToClip, const PolyClipPlane &clipPlane, particle_t *particle, subsector_t *sub, uint32_t stencilValue) +void RenderPolyParticle::Render(PolyRenderThread *thread, const TriMatrix &worldToClip, const PolyClipPlane &clipPlane, particle_t *particle, subsector_t *sub, uint32_t stencilValue) { DVector3 pos = particle->Pos; double psize = particle->size / 8.0; @@ -45,7 +46,7 @@ void RenderPolyParticle::Render(const TriMatrix &worldToClip, const PolyClipPlan { pos.X + viewpoint.Sin * psize, pos.Y - viewpoint.Cos * psize } }; - TriVertex *vertices = PolyRenderer::Instance()->FrameMemory.AllocMemory(4); + TriVertex *vertices = thread->FrameMemory->AllocMemory(4); bool foggy = false; int actualextralight = foggy ? 0 : viewpoint.extralight << 4; @@ -85,7 +86,7 @@ void RenderPolyParticle::Render(const TriMatrix &worldToClip, const PolyClipPlan args.SetWriteDepth(false); args.SetClipPlane(0, clipPlane); args.SetTexture(GetParticleTexture(), ParticleTextureSize, ParticleTextureSize); - args.DrawArray(vertices, 4, PolyDrawMode::TriangleFan); + args.DrawArray(thread, vertices, 4, PolyDrawMode::TriangleFan); } uint8_t *RenderPolyParticle::GetParticleTexture() diff --git a/src/polyrenderer/scene/poly_particle.h b/src/polyrenderer/scene/poly_particle.h index f94cdc781..3847b0fef 100644 --- a/src/polyrenderer/scene/poly_particle.h +++ b/src/polyrenderer/scene/poly_particle.h @@ -28,7 +28,7 @@ class RenderPolyParticle { public: - void Render(const TriMatrix &worldToClip, const PolyClipPlane &clipPlane, particle_t *particle, subsector_t *sub, uint32_t stencilValue); + void Render(PolyRenderThread *thread, const TriMatrix &worldToClip, const PolyClipPlane &clipPlane, particle_t *particle, subsector_t *sub, uint32_t stencilValue); private: static uint8_t *GetParticleTexture(); @@ -45,10 +45,10 @@ class PolyTranslucentParticle : public PolyTranslucentObject public: PolyTranslucentParticle(particle_t *particle, subsector_t *sub, uint32_t subsectorDepth, uint32_t stencilValue) : PolyTranslucentObject(subsectorDepth, 0.0), particle(particle), sub(sub), StencilValue(stencilValue) { } - void Render(const TriMatrix &worldToClip, const PolyClipPlane &portalPlane) override + void Render(PolyRenderThread *thread, const TriMatrix &worldToClip, const PolyClipPlane &portalPlane) override { RenderPolyParticle spr; - spr.Render(worldToClip, portalPlane, particle, sub, StencilValue + 1); + spr.Render(thread, worldToClip, portalPlane, particle, sub, StencilValue + 1); } particle_t *particle = nullptr; diff --git a/src/polyrenderer/scene/poly_plane.cpp b/src/polyrenderer/scene/poly_plane.cpp index 2754e701a..bc7d46d9e 100644 --- a/src/polyrenderer/scene/poly_plane.cpp +++ b/src/polyrenderer/scene/poly_plane.cpp @@ -30,21 +30,22 @@ #include "polyrenderer/poly_renderer.h" #include "r_sky.h" #include "polyrenderer/scene/poly_light.h" +#include "polyrenderer/poly_renderthread.h" #include "p_lnspec.h" EXTERN_CVAR(Int, r_3dfloors) -void RenderPolyPlane::RenderPlanes(const TriMatrix &worldToClip, const PolyClipPlane &clipPlane, subsector_t *sub, uint32_t stencilValue, double skyCeilingHeight, double skyFloorHeight, std::vector> §orPortals) +void RenderPolyPlane::RenderPlanes(PolyRenderThread *thread, const TriMatrix &worldToClip, const PolyClipPlane &clipPlane, subsector_t *sub, uint32_t stencilValue, double skyCeilingHeight, double skyFloorHeight, std::vector> §orPortals) { if (sub->sector->CenterFloor() == sub->sector->CenterCeiling()) return; RenderPolyPlane plane; - plane.Render(worldToClip, clipPlane, sub, stencilValue, true, skyCeilingHeight, sectorPortals); - plane.Render(worldToClip, clipPlane, sub, stencilValue, false, skyFloorHeight, sectorPortals); + plane.Render(thread, worldToClip, clipPlane, sub, stencilValue, true, skyCeilingHeight, sectorPortals); + plane.Render(thread, worldToClip, clipPlane, sub, stencilValue, false, skyFloorHeight, sectorPortals); } -void RenderPolyPlane::Render(const TriMatrix &worldToClip, const PolyClipPlane &clipPlane, subsector_t *sub, uint32_t stencilValue, bool ceiling, double skyHeight, std::vector> §orPortals) +void RenderPolyPlane::Render(PolyRenderThread *thread, const TriMatrix &worldToClip, const PolyClipPlane &clipPlane, subsector_t *sub, uint32_t stencilValue, bool ceiling, double skyHeight, std::vector> §orPortals) { const auto &viewpoint = PolyRenderer::Instance()->Viewpoint; @@ -182,7 +183,7 @@ void RenderPolyPlane::Render(const TriMatrix &worldToClip, const PolyClipPlane & PolyPlaneUVTransform transform(ceiling ? frontsector->planes[sector_t::ceiling].xform : frontsector->planes[sector_t::floor].xform, tex); - TriVertex *vertices = PolyRenderer::Instance()->FrameMemory.AllocMemory(sub->numlines); + TriVertex *vertices = thread->FrameMemory->AllocMemory(sub->numlines); if (ceiling) { @@ -232,7 +233,7 @@ void RenderPolyPlane::Render(const TriMatrix &worldToClip, const PolyClipPlane & { args.SetTexture(tex); args.SetStyle(TriBlendMode::TextureOpaque); - args.DrawArray(vertices, sub->numlines, PolyDrawMode::TriangleFan); + args.DrawArray(thread, vertices, sub->numlines, PolyDrawMode::TriangleFan); } else { @@ -248,17 +249,17 @@ void RenderPolyPlane::Render(const TriMatrix &worldToClip, const PolyClipPlane & args.SetWriteColor(false); args.SetWriteDepth(false); - args.DrawArray(vertices, sub->numlines, PolyDrawMode::TriangleFan); + args.DrawArray(thread, vertices, sub->numlines, PolyDrawMode::TriangleFan); - RenderSkyWalls(args, sub, frontsector, portal, polyportal, ceiling, skyHeight, transform); + RenderSkyWalls(thread, args, sub, frontsector, portal, polyportal, ceiling, skyHeight, transform); } } -void RenderPolyPlane::RenderSkyWalls(PolyDrawArgs &args, subsector_t *sub, sector_t *frontsector, FSectorPortal *portal, PolyDrawSectorPortal *polyportal, bool ceiling, double skyHeight, const PolyPlaneUVTransform &transform) +void RenderPolyPlane::RenderSkyWalls(PolyRenderThread *thread, PolyDrawArgs &args, subsector_t *sub, sector_t *frontsector, FSectorPortal *portal, PolyDrawSectorPortal *polyportal, bool ceiling, double skyHeight, const PolyPlaneUVTransform &transform) { for (uint32_t i = 0; i < sub->numlines; i++) { - TriVertex *wallvert = PolyRenderer::Instance()->FrameMemory.AllocMemory(4); + TriVertex *wallvert = thread->FrameMemory->AllocMemory(4); seg_t *line = &sub->firstline[i]; @@ -324,7 +325,7 @@ void RenderPolyPlane::RenderSkyWalls(PolyDrawArgs &args, subsector_t *sub, secto wallvert[3] = transform.GetVertex(line->v1, skyHeight); } - args.DrawArray(wallvert, 4, PolyDrawMode::TriangleFan); + args.DrawArray(thread, wallvert, 4, PolyDrawMode::TriangleFan); if (portal) { @@ -384,7 +385,7 @@ float PolyPlaneUVTransform::GetV(float x, float y) const ///////////////////////////////////////////////////////////////////////////// -void Render3DFloorPlane::RenderPlanes(const TriMatrix &worldToClip, const PolyClipPlane &clipPlane, subsector_t *sub, uint32_t stencilValue, uint32_t subsectorDepth, std::vector &translucentObjects) +void Render3DFloorPlane::RenderPlanes(PolyRenderThread *thread, const TriMatrix &worldToClip, const PolyClipPlane &clipPlane, subsector_t *sub, uint32_t stencilValue, uint32_t subsectorDepth, std::vector &translucentObjects) { if (!r_3dfloors || sub->sector->CenterFloor() == sub->sector->CenterCeiling()) return; @@ -428,9 +429,9 @@ void Render3DFloorPlane::RenderPlanes(const TriMatrix &worldToClip, const PolyCl } if (!plane.Masked) - plane.Render(worldToClip, clipPlane); + plane.Render(thread, worldToClip, clipPlane); else - translucentObjects.push_back(PolyRenderer::Instance()->FrameMemory.NewObject(plane, subsectorDepth)); + translucentObjects.push_back(thread->FrameMemory->NewObject(plane, subsectorDepth)); } } @@ -468,14 +469,14 @@ void Render3DFloorPlane::RenderPlanes(const TriMatrix &worldToClip, const PolyCl } if (!plane.Masked) - plane.Render(worldToClip, clipPlane); + plane.Render(thread, worldToClip, clipPlane); else - translucentObjects.push_back(PolyRenderer::Instance()->FrameMemory.NewObject(plane, subsectorDepth)); + translucentObjects.push_back(thread->FrameMemory->NewObject(plane, subsectorDepth)); } } } -void Render3DFloorPlane::Render(const TriMatrix &worldToClip, const PolyClipPlane &clipPlane) +void Render3DFloorPlane::Render(PolyRenderThread *thread, const TriMatrix &worldToClip, const PolyClipPlane &clipPlane) { FTextureID picnum = ceiling ? *fakeFloor->bottom.texture : *fakeFloor->top.texture; FTexture *tex = TexMan(picnum); @@ -498,7 +499,7 @@ void Render3DFloorPlane::Render(const TriMatrix &worldToClip, const PolyClipPlan PolyPlaneUVTransform xform(ceiling ? fakeFloor->top.model->planes[sector_t::ceiling].xform : fakeFloor->top.model->planes[sector_t::floor].xform, tex); - TriVertex *vertices = PolyRenderer::Instance()->FrameMemory.AllocMemory(sub->numlines); + TriVertex *vertices = thread->FrameMemory->AllocMemory(sub->numlines); if (ceiling) { for (uint32_t i = 0; i < sub->numlines; i++) @@ -537,5 +538,5 @@ void Render3DFloorPlane::Render(const TriMatrix &worldToClip, const PolyClipPlan args.SetWriteStencil(true, stencilValue + 1); args.SetTexture(tex); args.SetClipPlane(0, clipPlane); - args.DrawArray(vertices, sub->numlines, PolyDrawMode::TriangleFan); + args.DrawArray(thread, vertices, sub->numlines, PolyDrawMode::TriangleFan); } diff --git a/src/polyrenderer/scene/poly_plane.h b/src/polyrenderer/scene/poly_plane.h index 0deca401c..27f671f56 100644 --- a/src/polyrenderer/scene/poly_plane.h +++ b/src/polyrenderer/scene/poly_plane.h @@ -47,19 +47,19 @@ private: class RenderPolyPlane { public: - static void RenderPlanes(const TriMatrix &worldToClip, const PolyClipPlane &clipPlane, subsector_t *sub, uint32_t stencilValue, double skyCeilingHeight, double skyFloorHeight, std::vector> §orPortals); + static void RenderPlanes(PolyRenderThread *thread, const TriMatrix &worldToClip, const PolyClipPlane &clipPlane, subsector_t *sub, uint32_t stencilValue, double skyCeilingHeight, double skyFloorHeight, std::vector> §orPortals); private: - void Render(const TriMatrix &worldToClip, const PolyClipPlane &clipPlane, subsector_t *sub, uint32_t stencilValue, bool ceiling, double skyHeight, std::vector> §orPortals); - void RenderSkyWalls(PolyDrawArgs &args, subsector_t *sub, sector_t *frontsector, FSectorPortal *portal, PolyDrawSectorPortal *polyportal, bool ceiling, double skyHeight, const PolyPlaneUVTransform &transform); + void Render(PolyRenderThread *thread, const TriMatrix &worldToClip, const PolyClipPlane &clipPlane, subsector_t *sub, uint32_t stencilValue, bool ceiling, double skyHeight, std::vector> §orPortals); + void RenderSkyWalls(PolyRenderThread *thread, PolyDrawArgs &args, subsector_t *sub, sector_t *frontsector, FSectorPortal *portal, PolyDrawSectorPortal *polyportal, bool ceiling, double skyHeight, const PolyPlaneUVTransform &transform); }; class Render3DFloorPlane { public: - static void RenderPlanes(const TriMatrix &worldToClip, const PolyClipPlane &clipPlane, subsector_t *sub, uint32_t stencilValue, uint32_t subsectorDepth, std::vector &translucentObjects); + static void RenderPlanes(PolyRenderThread *thread, const TriMatrix &worldToClip, const PolyClipPlane &clipPlane, subsector_t *sub, uint32_t stencilValue, uint32_t subsectorDepth, std::vector &translucentObjects); - void Render(const TriMatrix &worldToClip, const PolyClipPlane &clipPlane); + void Render(PolyRenderThread *thread, const TriMatrix &worldToClip, const PolyClipPlane &clipPlane); subsector_t *sub = nullptr; uint32_t stencilValue = 0; @@ -75,9 +75,9 @@ class PolyTranslucent3DFloorPlane : public PolyTranslucentObject public: PolyTranslucent3DFloorPlane(Render3DFloorPlane plane, uint32_t subsectorDepth) : PolyTranslucentObject(subsectorDepth, 1e7), plane(plane) { } - void Render(const TriMatrix &worldToClip, const PolyClipPlane &portalPlane) override + void Render(PolyRenderThread *thread, const TriMatrix &worldToClip, const PolyClipPlane &portalPlane) override { - plane.Render(worldToClip, portalPlane); + plane.Render(thread, worldToClip, portalPlane); } Render3DFloorPlane plane; diff --git a/src/polyrenderer/scene/poly_playersprite.cpp b/src/polyrenderer/scene/poly_playersprite.cpp index 5976cddf7..1cd987f98 100644 --- a/src/polyrenderer/scene/poly_playersprite.cpp +++ b/src/polyrenderer/scene/poly_playersprite.cpp @@ -35,7 +35,7 @@ EXTERN_CVAR(Bool, r_deathcamera) EXTERN_CVAR(Bool, r_fullbrightignoresectorcolor) EXTERN_CVAR(Bool, r_shadercolormaps) -void RenderPolyPlayerSprites::Render() +void RenderPolyPlayerSprites::Render(PolyRenderThread *thread) { // This code cannot be moved directly to RenderRemainingSprites because the engine // draws the canvas textures between this call and the final call to RenderRemainingSprites.. @@ -143,7 +143,7 @@ void RenderPolyPlayerSprites::Render() if ((psp->GetID() != PSP_TARGETCENTER || CrosshairImage == nullptr) && psp->GetCaller() != nullptr) { - RenderSprite(psp, viewpoint.camera, bobx, boby, wx, wy, viewpoint.TicFrac, spriteshade, basecolormap, foggy); + RenderSprite(thread, psp, viewpoint.camera, bobx, boby, wx, wy, viewpoint.TicFrac, spriteshade, basecolormap, foggy); } psp = psp->GetNext(); @@ -180,7 +180,7 @@ void RenderPolyPlayerSprites::RenderRemainingSprites() AcceleratedSprites.Clear(); } -void RenderPolyPlayerSprites::RenderSprite(DPSprite *pspr, AActor *owner, float bobx, float boby, double wx, double wy, double ticfrac, int spriteshade, FDynamicColormap *basecolormap, bool foggy) +void RenderPolyPlayerSprites::RenderSprite(PolyRenderThread *thread, DPSprite *pspr, AActor *owner, float bobx, float boby, double wx, double wy, double ticfrac, int spriteshade, FDynamicColormap *basecolormap, bool foggy) { double tx; int x1; @@ -454,7 +454,7 @@ void RenderPolyPlayerSprites::RenderSprite(DPSprite *pspr, AActor *owner, float } } - vis.Render(); + vis.Render(thread); } fixed_t RenderPolyPlayerSprites::LightLevelToShade(int lightlevel, bool foggy) @@ -475,7 +475,7 @@ fixed_t RenderPolyPlayerSprites::LightLevelToShade(int lightlevel, bool foggy) ///////////////////////////////////////////////////////////////////////// -void PolyNoAccelPlayerSprite::Render() +void PolyNoAccelPlayerSprite::Render(PolyRenderThread *thread) { if (xscale == 0 || fabs(yscale) < (1.0f / 32000.0f)) { // scaled to 0; can't see @@ -498,7 +498,7 @@ void PolyNoAccelPlayerSprite::Render() y1 = centerY - texturemid * yscale; y2 = y1 + pic->GetHeight() * yscale; } - args.Draw(x1, x2, y1, y2, 0.0f, 1.0f, 0.0f, 1.0f); + args.Draw(thread, x1, x2, y1, y2, 0.0f, 1.0f, 0.0f, 1.0f); } ///////////////////////////////////////////////////////////////////////////// diff --git a/src/polyrenderer/scene/poly_playersprite.h b/src/polyrenderer/scene/poly_playersprite.h index 0f5f83592..b07a86715 100644 --- a/src/polyrenderer/scene/poly_playersprite.h +++ b/src/polyrenderer/scene/poly_playersprite.h @@ -61,7 +61,7 @@ public: short renderflags = 0; - void Render(); + void Render(PolyRenderThread *thread); }; class PolyHWAccelPlayerSprite @@ -90,11 +90,11 @@ public: class RenderPolyPlayerSprites { public: - void Render(); + void Render(PolyRenderThread *thread); void RenderRemainingSprites(); private: - void RenderSprite(DPSprite *pspr, AActor *owner, float bobx, float boby, double wx, double wy, double ticfrac, int spriteshade, FDynamicColormap *basecolormap, bool foggy); + void RenderSprite(PolyRenderThread *thread, DPSprite *pspr, AActor *owner, float bobx, float boby, double wx, double wy, double ticfrac, int spriteshade, FDynamicColormap *basecolormap, bool foggy); static fixed_t LightLevelToShade(int lightlevel, bool foggy); enum { BASEXCENTER = 160 }; diff --git a/src/polyrenderer/scene/poly_portal.cpp b/src/polyrenderer/scene/poly_portal.cpp index ff529895f..8abfb66f5 100644 --- a/src/polyrenderer/scene/poly_portal.cpp +++ b/src/polyrenderer/scene/poly_portal.cpp @@ -68,7 +68,7 @@ void PolyDrawSectorPortal::Render(int portalDepth) PolyClipPlane portalPlane(0.0f, 0.0f, 0.0f, 1.0f); RenderPortal.SetViewpoint(worldToClip, portalPlane, StencilValue); - RenderPortal.SetPortalSegments(Segments); + //RenderPortal.SetPortalSegments(Segments); RenderPortal.Render(portalDepth); RestoreGlobals(); @@ -202,7 +202,7 @@ void PolyDrawLinePortal::Render(int portalDepth) RenderPortal.LastPortalLine = clipLine; RenderPortal.SetViewpoint(worldToClip, portalPlane, StencilValue); - RenderPortal.SetPortalSegments(Segments); + //RenderPortal.SetPortalSegments(Segments); RenderPortal.Render(portalDepth); RestoreGlobals(); diff --git a/src/polyrenderer/scene/poly_portal.h b/src/polyrenderer/scene/poly_portal.h index b62922f56..a91c80d4e 100644 --- a/src/polyrenderer/scene/poly_portal.h +++ b/src/polyrenderer/scene/poly_portal.h @@ -50,7 +50,7 @@ public: FSectorPortal *Portal = nullptr; uint32_t StencilValue = 0; std::vector Shape; - std::vector Segments; + //std::vector Segments; private: void SaveGlobals(); @@ -80,7 +80,7 @@ public: line_t *Mirror = nullptr; uint32_t StencilValue = 0; std::vector Shape; - std::vector Segments; + //std::vector Segments; private: void SaveGlobals(); diff --git a/src/polyrenderer/scene/poly_scene.cpp b/src/polyrenderer/scene/poly_scene.cpp index 1e47d515a..09f92c0d7 100644 --- a/src/polyrenderer/scene/poly_scene.cpp +++ b/src/polyrenderer/scene/poly_scene.cpp @@ -54,57 +54,50 @@ void RenderPolyScene::SetViewpoint(const TriMatrix &worldToClip, const PolyClipP PortalPlane = portalPlane; } -void RenderPolyScene::SetPortalSegments(const std::vector &segments) -{ - if (!segments.empty()) - { - Cull.ClearSolidSegments(); - for (const auto &segment : segments) - { - Cull.MarkSegmentCulled(segment.Start, segment.End); - } - Cull.InvertSegments(); - PortalSegmentsAdded = true; - } - else - { - PortalSegmentsAdded = false; - } -} - void RenderPolyScene::Render(int portalDepth) { - ClearBuffers(); - if (!PortalSegmentsAdded) - Cull.ClearSolidSegments(); - Cull.MarkViewFrustum(); + PolyRenderThread *thread = PolyRenderer::Instance()->Threads.MainThread(); + + ClearBuffers(thread); Cull.CullScene(WorldToClip, PortalPlane); - Cull.ClearSolidSegments(); RenderSectors(); RenderPortals(portalDepth); } -void RenderPolyScene::ClearBuffers() +void RenderPolyScene::ClearBuffers(PolyRenderThread *thread) { - SeenSectors.clear(); - SubsectorDepths.clear(); - TranslucentObjects.clear(); - SectorPortals.clear(); - LinePortals.clear(); + thread->TranslucentObjects.clear(); + thread->SectorPortals.clear(); + thread->LinePortals.clear(); } void RenderPolyScene::RenderSectors() { - int count = (int)Cull.PvsSectors.size(); + PolyRenderThread *mainthread = PolyRenderer::Instance()->Threads.MainThread(); + + int totalcount = (int)Cull.PvsSectors.size(); auto subsectors = Cull.PvsSectors.data(); - for (int i = 0; i < count; i++) + PolyRenderer::Instance()->Threads.RenderThreadSlices(totalcount, [&](PolyRenderThread *thread) { - RenderSubsector(subsectors[i], i); - } + if (!thread->MainThread) + { + ClearBuffers(thread); + } + + int start = thread->Start; + int end = thread->End; + for (int i = start; i < end; i++) + { + RenderSubsector(thread, subsectors[i], i); + } + }, [&](PolyRenderThread *thread) + { + mainthread->TranslucentObjects.insert(mainthread->TranslucentObjects.end(), thread->TranslucentObjects.begin(), thread->TranslucentObjects.end()); + }); } -void RenderPolyScene::RenderSubsector(subsector_t *sub, uint32_t subsectorDepth) +void RenderPolyScene::RenderSubsector(PolyRenderThread *thread, subsector_t *sub, uint32_t subsectorDepth) { sector_t *frontsector = sub->sector; frontsector->MoreFlags |= SECF_DRAWN; @@ -127,44 +120,43 @@ void RenderPolyScene::RenderSubsector(subsector_t *sub, uint32_t subsectorDepth) if (sub->BSP->Nodes.Size() == 0) { - RenderPolySubsector(&sub->BSP->Subsectors[0], subsectorDepth, frontsector); + RenderPolySubsector(thread, &sub->BSP->Subsectors[0], subsectorDepth, frontsector); } else { - RenderPolyNode(&sub->BSP->Nodes.Last(), subsectorDepth, frontsector); + RenderPolyNode(thread, &sub->BSP->Nodes.Last(), subsectorDepth, frontsector); } - Render3DFloorPlane::RenderPlanes(WorldToClip, PortalPlane, sub, StencilValue, subsectorDepth, TranslucentObjects); - RenderPolyPlane::RenderPlanes(WorldToClip, PortalPlane, sub, StencilValue, Cull.MaxCeilingHeight, Cull.MinFloorHeight, SectorPortals); + Render3DFloorPlane::RenderPlanes(thread, WorldToClip, PortalPlane, sub, StencilValue, subsectorDepth, thread->TranslucentObjects); + RenderPolyPlane::RenderPlanes(thread, WorldToClip, PortalPlane, sub, StencilValue, Cull.MaxCeilingHeight, Cull.MinFloorHeight, thread->SectorPortals); } else { - Render3DFloorPlane::RenderPlanes(WorldToClip, PortalPlane, sub, StencilValue, subsectorDepth, TranslucentObjects); - RenderPolyPlane::RenderPlanes(WorldToClip, PortalPlane, sub, StencilValue, Cull.MaxCeilingHeight, Cull.MinFloorHeight, SectorPortals); + Render3DFloorPlane::RenderPlanes(thread, WorldToClip, PortalPlane, sub, StencilValue, subsectorDepth, thread->TranslucentObjects); + RenderPolyPlane::RenderPlanes(thread, WorldToClip, PortalPlane, sub, StencilValue, Cull.MaxCeilingHeight, Cull.MinFloorHeight, thread->SectorPortals); for (uint32_t i = 0; i < sub->numlines; i++) { - seg_t *line = &sub->firstline[i]; - RenderLine(sub, line, frontsector, subsectorDepth); + if (Cull.IsLineSegVisible(subsectorDepth, i)) + { + seg_t *line = &sub->firstline[i]; + RenderLine(thread, sub, line, frontsector, subsectorDepth); + } } } if (mainBSP) { - RenderMemory &memory = PolyRenderer::Instance()->FrameMemory; int subsectorIndex = sub->Index(); for (int i = ParticlesInSubsec[subsectorIndex]; i != NO_PARTICLE; i = Particles[i].snext) { particle_t *particle = Particles + i; - TranslucentObjects.push_back(memory.NewObject(particle, sub, subsectorDepth, StencilValue)); + thread->TranslucentObjects.push_back(thread->FrameMemory->NewObject(particle, sub, subsectorDepth, StencilValue)); } } - - SeenSectors.insert(sub->sector); - SubsectorDepths[sub] = subsectorDepth; } -void RenderPolyScene::RenderPolyNode(void *node, uint32_t subsectorDepth, sector_t *frontsector) +void RenderPolyScene::RenderPolyNode(PolyRenderThread *thread, void *node, uint32_t subsectorDepth, sector_t *frontsector) { while (!((size_t)node & 1)) // Keep going until found a subsector { @@ -174,7 +166,7 @@ void RenderPolyScene::RenderPolyNode(void *node, uint32_t subsectorDepth, sector int side = PointOnSide(PolyRenderer::Instance()->Viewpoint.Pos, bsp); // Recursively divide front space (toward the viewer). - RenderPolyNode(bsp->children[side], subsectorDepth, frontsector); + RenderPolyNode(thread, bsp->children[side], subsectorDepth, frontsector); // Possibly divide back space (away from the viewer). side ^= 1; @@ -187,10 +179,10 @@ void RenderPolyScene::RenderPolyNode(void *node, uint32_t subsectorDepth, sector } subsector_t *sub = (subsector_t *)((uint8_t *)node - 1); - RenderPolySubsector(sub, subsectorDepth, frontsector); + RenderPolySubsector(thread, sub, subsectorDepth, frontsector); } -void RenderPolyScene::RenderPolySubsector(subsector_t *sub, uint32_t subsectorDepth, sector_t *frontsector) +void RenderPolyScene::RenderPolySubsector(PolyRenderThread *thread, subsector_t *sub, uint32_t subsectorDepth, sector_t *frontsector) { const auto &viewpoint = PolyRenderer::Instance()->Viewpoint; @@ -205,11 +197,6 @@ void RenderPolyScene::RenderPolySubsector(subsector_t *sub, uint32_t subsectorDe if (pt1.Y * (pt1.X - pt2.X) + pt1.X * (pt2.Y - pt1.Y) >= 0) continue; - // Cull wall if not visible - angle_t angle1, angle2; - if (!Cull.GetAnglesForLine(line->v1->fX(), line->v1->fY(), line->v2->fX(), line->v2->fY(), angle1, angle2)) - continue; - // Tell automap we saw this if (!PolyRenderer::Instance()->DontMapLines && line->linedef) { @@ -217,11 +204,7 @@ void RenderPolyScene::RenderPolySubsector(subsector_t *sub, uint32_t subsectorDe sub->flags |= SSECF_DRAWN; } - // Render wall, and update culling info if its an occlusion blocker - if (RenderPolyWall::RenderLine(WorldToClip, PortalPlane, line, frontsector, subsectorDepth, StencilValue, TranslucentObjects, LinePortals, LastPortalLine)) - { - Cull.MarkSegmentCulled(angle1, angle2); - } + RenderPolyWall::RenderLine(thread, WorldToClip, PortalPlane, line, frontsector, subsectorDepth, StencilValue, thread->TranslucentObjects, thread->LinePortals, LastPortalLine); } } } @@ -231,22 +214,22 @@ int RenderPolyScene::PointOnSide(const DVector2 &pos, const node_t *node) return DMulScale32(FLOAT2FIXED(pos.Y) - node->y, node->dx, node->x - FLOAT2FIXED(pos.X), node->dy) > 0; } -void RenderPolyScene::RenderSprite(AActor *thing, double sortDistance, const DVector2 &left, const DVector2 &right) +void RenderPolyScene::RenderSprite(PolyRenderThread *thread, AActor *thing, double sortDistance, const DVector2 &left, const DVector2 &right) { if (level.nodes.Size() == 0) { subsector_t *sub = &level.subsectors[0]; - auto it = SubsectorDepths.find(sub); - if (it != SubsectorDepths.end()) - TranslucentObjects.push_back(PolyRenderer::Instance()->FrameMemory.NewObject(thing, sub, it->second, sortDistance, 0.0f, 1.0f, StencilValue)); + 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)); } else { - RenderSprite(thing, sortDistance, left, right, 0.0, 1.0, level.HeadNode()); + RenderSprite(thread, thing, sortDistance, left, right, 0.0, 1.0, level.HeadNode()); } } -void RenderPolyScene::RenderSprite(AActor *thing, double sortDistance, DVector2 left, DVector2 right, double t1, double t2, void *node) +void RenderPolyScene::RenderSprite(PolyRenderThread *thread, AActor *thing, double sortDistance, DVector2 left, DVector2 right, double t1, double t2, void *node) { while (!((size_t)node & 1)) // Keep going until found a subsector { @@ -268,7 +251,7 @@ void RenderPolyScene::RenderSprite(AActor *thing, double sortDistance, DVector2 DVector2 mid = left * (1.0 - t) + right * t; double tmid = t1 * (1.0 - t) + t2 * t; - RenderSprite(thing, sortDistance, mid, right, tmid, t2, bsp->children[sideRight]); + RenderSprite(thread, thing, sortDistance, mid, right, tmid, t2, bsp->children[sideRight]); right = mid; t2 = tmid; } @@ -277,26 +260,13 @@ void RenderPolyScene::RenderSprite(AActor *thing, double sortDistance, DVector2 subsector_t *sub = (subsector_t *)((uint8_t *)node - 1); - auto it = SubsectorDepths.find(sub); - if (it != SubsectorDepths.end()) - TranslucentObjects.push_back(PolyRenderer::Instance()->FrameMemory.NewObject(thing, sub, it->second, sortDistance, (float)t1, (float)t2, StencilValue)); + 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)); } -void RenderPolyScene::RenderLine(subsector_t *sub, seg_t *line, sector_t *frontsector, uint32_t subsectorDepth) +void RenderPolyScene::RenderLine(PolyRenderThread *thread, subsector_t *sub, seg_t *line, sector_t *frontsector, uint32_t subsectorDepth) { - const auto &viewpoint = PolyRenderer::Instance()->Viewpoint; - - // Reject lines not facing viewer - DVector2 pt1 = line->v1->fPos() - viewpoint.Pos; - DVector2 pt2 = line->v2->fPos() - viewpoint.Pos; - if (pt1.Y * (pt1.X - pt2.X) + pt1.X * (pt2.Y - pt1.Y) >= 0) - return; - - // Cull wall if not visible - angle_t angle1, angle2; - if (!Cull.GetAnglesForLine(line->v1->fX(), line->v1->fY(), line->v2->fX(), line->v2->fY(), angle1, angle2)) - return; - // Tell automap we saw this if (!PolyRenderer::Instance()->DontMapLines && line->linedef) { @@ -310,26 +280,25 @@ void RenderPolyScene::RenderLine(subsector_t *sub, seg_t *line, sector_t *fronts for (unsigned int i = 0; i < line->backsector->e->XFloor.ffloors.Size(); i++) { F3DFloor *fakeFloor = line->backsector->e->XFloor.ffloors[i]; - RenderPolyWall::Render3DFloorLine(WorldToClip, PortalPlane, line, frontsector, subsectorDepth, StencilValue, fakeFloor, TranslucentObjects); + RenderPolyWall::Render3DFloorLine(thread, WorldToClip, PortalPlane, line, frontsector, subsectorDepth, StencilValue, fakeFloor, thread->TranslucentObjects); } } // Render wall, and update culling info if its an occlusion blocker - if (RenderPolyWall::RenderLine(WorldToClip, PortalPlane, line, frontsector, subsectorDepth, StencilValue, TranslucentObjects, LinePortals, LastPortalLine)) - { - Cull.MarkSegmentCulled(angle1, angle2); - } + RenderPolyWall::RenderLine(thread, WorldToClip, PortalPlane, line, frontsector, subsectorDepth, StencilValue, thread->TranslucentObjects, thread->LinePortals, LastPortalLine); } void RenderPolyScene::RenderPortals(int portalDepth) { + PolyRenderThread *thread = PolyRenderer::Instance()->Threads.MainThread(); + bool foggy = false; if (portalDepth < r_portal_recursions) { - for (auto &portal : SectorPortals) + for (auto &portal : thread->SectorPortals) portal->Render(portalDepth + 1); - for (auto &portal : LinePortals) + for (auto &portal : thread->LinePortals) portal->Render(portalDepth + 1); } else // Fill with black @@ -341,25 +310,25 @@ void RenderPolyScene::RenderPortals(int portalDepth) args.SetClipPlane(0, PortalPlane); args.SetStyle(TriBlendMode::FillOpaque); - for (auto &portal : SectorPortals) + for (auto &portal : thread->SectorPortals) { args.SetStencilTestValue(portal->StencilValue); args.SetWriteStencil(true, portal->StencilValue + 1); for (const auto &verts : portal->Shape) { args.SetFaceCullCCW(verts.Ccw); - args.DrawArray(verts.Vertices, verts.Count, PolyDrawMode::TriangleFan); + args.DrawArray(thread, verts.Vertices, verts.Count, PolyDrawMode::TriangleFan); } } - for (auto &portal : LinePortals) + for (auto &portal : thread->LinePortals) { args.SetStencilTestValue(portal->StencilValue); args.SetWriteStencil(true, portal->StencilValue + 1); for (const auto &verts : portal->Shape) { args.SetFaceCullCCW(verts.Ccw); - args.DrawArray(verts.Vertices, verts.Count, PolyDrawMode::TriangleFan); + args.DrawArray(thread, verts.Vertices, verts.Count, PolyDrawMode::TriangleFan); } } } @@ -367,9 +336,11 @@ void RenderPolyScene::RenderPortals(int portalDepth) void RenderPolyScene::RenderTranslucent(int portalDepth) { + PolyRenderThread *thread = PolyRenderer::Instance()->Threads.MainThread(); + if (portalDepth < r_portal_recursions) { - for (auto it = SectorPortals.rbegin(); it != SectorPortals.rend(); ++it) + for (auto it = thread->SectorPortals.rbegin(); it != thread->SectorPortals.rend(); ++it) { auto &portal = *it; portal->RenderTranslucent(portalDepth + 1); @@ -383,11 +354,11 @@ void RenderPolyScene::RenderTranslucent(int portalDepth) { args.SetFaceCullCCW(verts.Ccw); args.SetWriteColor(false); - args.DrawArray(verts.Vertices, verts.Count, PolyDrawMode::TriangleFan); + args.DrawArray(thread, verts.Vertices, verts.Count, PolyDrawMode::TriangleFan); } } - for (auto it = LinePortals.rbegin(); it != LinePortals.rend(); ++it) + for (auto it = thread->LinePortals.rbegin(); it != thread->LinePortals.rend(); ++it) { auto &portal = *it; portal->RenderTranslucent(portalDepth + 1); @@ -401,13 +372,13 @@ void RenderPolyScene::RenderTranslucent(int portalDepth) { args.SetFaceCullCCW(verts.Ccw); args.SetWriteColor(false); - args.DrawArray(verts.Vertices, verts.Count, PolyDrawMode::TriangleFan); + args.DrawArray(thread, verts.Vertices, verts.Count, PolyDrawMode::TriangleFan); } } } const auto &viewpoint = PolyRenderer::Instance()->Viewpoint; - for (sector_t *sector : SeenSectors) + for (sector_t *sector : Cull.SeenSectors) { for (AActor *thing = sector->thinglist; thing != nullptr; thing = thing->snext) { @@ -415,18 +386,18 @@ void RenderPolyScene::RenderTranslucent(int portalDepth) if (!RenderPolySprite::GetLine(thing, left, right)) continue; double distanceSquared = (thing->Pos() - viewpoint.Pos).LengthSquared(); - RenderSprite(thing, distanceSquared, left, right); + RenderSprite(thread, thing, distanceSquared, left, right); } } - std::stable_sort(TranslucentObjects.begin(), TranslucentObjects.end(), [](auto a, auto b) { return *a < *b; }); + std::stable_sort(thread->TranslucentObjects.begin(), thread->TranslucentObjects.end(), [](auto a, auto b) { return *a < *b; }); - for (auto it = TranslucentObjects.rbegin(); it != TranslucentObjects.rend(); ++it) + for (auto it = thread->TranslucentObjects.rbegin(); it != thread->TranslucentObjects.rend(); ++it) { PolyTranslucentObject *obj = *it; - obj->Render(WorldToClip, PortalPlane); + obj->Render(thread, WorldToClip, PortalPlane); obj->~PolyTranslucentObject(); } - TranslucentObjects.clear(); + thread->TranslucentObjects.clear(); } diff --git a/src/polyrenderer/scene/poly_scene.h b/src/polyrenderer/scene/poly_scene.h index 2c41d15b7..5dd34dbd9 100644 --- a/src/polyrenderer/scene/poly_scene.h +++ b/src/polyrenderer/scene/poly_scene.h @@ -31,8 +31,6 @@ #include "polyrenderer/drawers/poly_triangle.h" #include "poly_playersprite.h" #include "poly_cull.h" -#include -#include class PolyTranslucentObject { @@ -40,7 +38,7 @@ public: PolyTranslucentObject(uint32_t subsectorDepth = 0, double distanceSquared = 0.0) : subsectorDepth(subsectorDepth), DistanceSquared(distanceSquared) { } virtual ~PolyTranslucentObject() { } - virtual void Render(const TriMatrix &worldToClip, const PolyClipPlane &portalPlane) = 0; + virtual void Render(PolyRenderThread *thread, const TriMatrix &worldToClip, const PolyClipPlane &portalPlane) = 0; bool operator<(const PolyTranslucentObject &other) const { @@ -62,7 +60,6 @@ public: RenderPolyScene(); ~RenderPolyScene(); void SetViewpoint(const TriMatrix &worldToClip, const PolyClipPlane &portalPlane, uint32_t stencilValue); - void SetPortalSegments(const std::vector &segments); void Render(int portalDepth); void RenderTranslucent(int portalDepth); @@ -71,27 +68,21 @@ public: line_t *LastPortalLine = nullptr; private: - void ClearBuffers(); + void ClearBuffers(PolyRenderThread *thread); void RenderPortals(int portalDepth); void RenderSectors(); - void RenderSubsector(subsector_t *sub, uint32_t subsectorDepth); - void RenderLine(subsector_t *sub, seg_t *line, sector_t *frontsector, uint32_t subsectorDepth); - void RenderSprite(AActor *thing, double sortDistance, const DVector2 &left, const DVector2 &right); - void RenderSprite(AActor *thing, double sortDistance, DVector2 left, DVector2 right, double t1, double t2, void *node); + void RenderSubsector(PolyRenderThread *thread, subsector_t *sub, uint32_t subsectorDepth); + void RenderLine(PolyRenderThread *thread, subsector_t *sub, seg_t *line, sector_t *frontsector, uint32_t subsectorDepth); + void RenderSprite(PolyRenderThread *thread, AActor *thing, double sortDistance, const DVector2 &left, const DVector2 &right); + void RenderSprite(PolyRenderThread *thread, AActor *thing, double sortDistance, DVector2 left, DVector2 right, double t1, double t2, void *node); - void RenderPolySubsector(subsector_t *sub, uint32_t subsectorDepth, sector_t *frontsector); - void RenderPolyNode(void *node, uint32_t subsectorDepth, sector_t *frontsector); + void RenderPolySubsector(PolyRenderThread *thread, subsector_t *sub, uint32_t subsectorDepth, sector_t *frontsector); + void RenderPolyNode(PolyRenderThread *thread, void *node, uint32_t subsectorDepth, sector_t *frontsector); static int PointOnSide(const DVector2 &pos, const node_t *node); TriMatrix WorldToClip; PolyClipPlane PortalPlane; uint32_t StencilValue = 0; PolyCull Cull; - std::set SeenSectors; - std::unordered_map SubsectorDepths; - std::vector TranslucentObjects; - - std::vector> SectorPortals; - std::vector> LinePortals; bool PortalSegmentsAdded = false; }; diff --git a/src/polyrenderer/scene/poly_sky.cpp b/src/polyrenderer/scene/poly_sky.cpp index 5b90b623c..06cb7a8ec 100644 --- a/src/polyrenderer/scene/poly_sky.cpp +++ b/src/polyrenderer/scene/poly_sky.cpp @@ -35,7 +35,7 @@ PolySkyDome::PolySkyDome() CreateDome(); } -void PolySkyDome::Render(const TriMatrix &worldToClip) +void PolySkyDome::Render(PolyRenderThread *thread, const TriMatrix &worldToClip) { #ifdef USE_GL_DOME_MATH TriMatrix modelMatrix = GLSkyMath(); @@ -88,8 +88,8 @@ void PolySkyDome::Render(const TriMatrix &worldToClip) args.SetWriteStencil(true, 1); args.SetClipPlane(0, PolyClipPlane(0.0f, 0.0f, 0.0f, 1.0f)); - RenderCapColorRow(args, mCurrentSetup.frontskytex, 0, false); - RenderCapColorRow(args, mCurrentSetup.frontskytex, rc, true); + RenderCapColorRow(thread, args, mCurrentSetup.frontskytex, 0, false); + RenderCapColorRow(thread, args, mCurrentSetup.frontskytex, rc, true); args.SetTexture(mCurrentSetup.frontskytex); @@ -100,20 +100,20 @@ void PolySkyDome::Render(const TriMatrix &worldToClip) for (int i = 1; i <= mRows; i++) { - RenderRow(args, i, topcapcolor, topcapindex); - RenderRow(args, rc + i, bottomcapcolor, bottomcapindex); + RenderRow(thread, args, i, topcapcolor, topcapindex); + RenderRow(thread, args, rc + i, bottomcapcolor, bottomcapindex); } } -void PolySkyDome::RenderRow(PolyDrawArgs &args, int row, uint32_t capcolor, uint8_t capcolorindex) +void PolySkyDome::RenderRow(PolyRenderThread *thread, PolyDrawArgs &args, int row, uint32_t capcolor, uint8_t capcolorindex) { args.SetFaceCullCCW(false); args.SetColor(capcolor, capcolorindex); args.SetStyle(TriBlendMode::Skycap); - args.DrawArray(&mVertices[mPrimStart[row]], mPrimStart[row + 1] - mPrimStart[row], PolyDrawMode::TriangleStrip); + args.DrawArray(thread, &mVertices[mPrimStart[row]], mPrimStart[row + 1] - mPrimStart[row], PolyDrawMode::TriangleStrip); } -void PolySkyDome::RenderCapColorRow(PolyDrawArgs &args, FTexture *skytex, int row, bool bottomCap) +void PolySkyDome::RenderCapColorRow(PolyRenderThread *thread, PolyDrawArgs &args, FTexture *skytex, int row, bool bottomCap) { uint32_t solid = skytex->GetSkyCapColor(bottomCap); uint8_t palsolid = RGB32k.RGB[(RPART(solid) >> 3)][(GPART(solid) >> 3)][(BPART(solid) >> 3)]; @@ -121,7 +121,7 @@ void PolySkyDome::RenderCapColorRow(PolyDrawArgs &args, FTexture *skytex, int ro args.SetFaceCullCCW(bottomCap); args.SetColor(solid, palsolid); args.SetStyle(TriBlendMode::FillOpaque); - args.DrawArray(&mVertices[mPrimStart[row]], mPrimStart[row + 1] - mPrimStart[row], PolyDrawMode::TriangleFan); + args.DrawArray(thread, &mVertices[mPrimStart[row]], mPrimStart[row + 1] - mPrimStart[row], PolyDrawMode::TriangleFan); } void PolySkyDome::CreateDome() diff --git a/src/polyrenderer/scene/poly_sky.h b/src/polyrenderer/scene/poly_sky.h index 4fc30da70..5fcde6cba 100644 --- a/src/polyrenderer/scene/poly_sky.h +++ b/src/polyrenderer/scene/poly_sky.h @@ -46,7 +46,7 @@ class PolySkyDome { public: PolySkyDome(); - void Render(const TriMatrix &worldToClip); + void Render(PolyRenderThread *thread, const TriMatrix &worldToClip); private: TArray mInitialUV; @@ -58,8 +58,8 @@ private: void SkyVertex(int r, int c, bool yflip); void CreateSkyHemisphere(bool zflip); void CreateDome(); - void RenderRow(PolyDrawArgs &args, int row, uint32_t capcolor, uint8_t capcolorindex); - void RenderCapColorRow(PolyDrawArgs &args, FTexture *skytex, int row, bool bottomCap); + void RenderRow(PolyRenderThread *thread, PolyDrawArgs &args, int row, uint32_t capcolor, uint8_t capcolorindex); + void RenderCapColorRow(PolyRenderThread *thread, PolyDrawArgs &args, FTexture *skytex, int row, bool bottomCap); TriVertex SetVertexXYZ(float xx, float yy, float zz, float uu = 0, float vv = 0); diff --git a/src/polyrenderer/scene/poly_sprite.cpp b/src/polyrenderer/scene/poly_sprite.cpp index 95ef0cef0..51a5bca51 100644 --- a/src/polyrenderer/scene/poly_sprite.cpp +++ b/src/polyrenderer/scene/poly_sprite.cpp @@ -28,6 +28,7 @@ #include "poly_sprite.h" #include "polyrenderer/poly_renderer.h" #include "polyrenderer/scene/poly_light.h" +#include "polyrenderer/poly_renderthread.h" #include "r_data/r_vanillatrans.h" #include "actorinlines.h" @@ -71,7 +72,7 @@ bool RenderPolySprite::GetLine(AActor *thing, DVector2 &left, DVector2 &right) return true; } -void RenderPolySprite::Render(const TriMatrix &worldToClip, const PolyClipPlane &clipPlane, AActor *thing, subsector_t *sub, uint32_t stencilValue, float t1, float t2) +void RenderPolySprite::Render(PolyRenderThread *thread, const TriMatrix &worldToClip, const PolyClipPlane &clipPlane, AActor *thing, subsector_t *sub, uint32_t stencilValue, float t1, float t2) { DVector2 line[2]; if (!GetLine(thing, line[0], line[1])) @@ -116,7 +117,7 @@ void RenderPolySprite::Render(const TriMatrix &worldToClip, const PolyClipPlane // Rumor has it that AlterWeaponSprite needs to be called with visstyle passed in somewhere around here.. //R_SetColorMapLight(visstyle.BaseColormap, 0, visstyle.ColormapNum << FRACBITS); - TriVertex *vertices = PolyRenderer::Instance()->FrameMemory.AllocMemory(4); + TriVertex *vertices = thread->FrameMemory->AllocMemory(4); bool foggy = false; int actualextralight = foggy ? 0 : viewpoint.extralight << 4; @@ -166,7 +167,7 @@ void RenderPolySprite::Render(const TriMatrix &worldToClip, const PolyClipPlane args.SetDepthTest(true); args.SetWriteDepth(false); args.SetWriteStencil(false); - args.DrawArray(vertices, 4, PolyDrawMode::TriangleFan); + args.DrawArray(thread, vertices, 4, PolyDrawMode::TriangleFan); } double RenderPolySprite::GetSpriteFloorZ(AActor *thing, const DVector2 &thingpos) diff --git a/src/polyrenderer/scene/poly_sprite.h b/src/polyrenderer/scene/poly_sprite.h index abc5e20a4..f634d7469 100644 --- a/src/polyrenderer/scene/poly_sprite.h +++ b/src/polyrenderer/scene/poly_sprite.h @@ -27,7 +27,7 @@ class RenderPolySprite { public: - void Render(const TriMatrix &worldToClip, const PolyClipPlane &clipPlane, AActor *thing, subsector_t *sub, uint32_t stencilValue, float t1, float t2); + void Render(PolyRenderThread *thread, const TriMatrix &worldToClip, const PolyClipPlane &clipPlane, AActor *thing, subsector_t *sub, uint32_t stencilValue, float t1, float t2); static bool GetLine(AActor *thing, DVector2 &left, DVector2 &right); static bool IsThingCulled(AActor *thing); @@ -44,17 +44,17 @@ class PolyTranslucentThing : public PolyTranslucentObject public: PolyTranslucentThing(AActor *thing, subsector_t *sub, uint32_t subsectorDepth, double dist, float t1, float t2, uint32_t stencilValue) : PolyTranslucentObject(subsectorDepth, dist), thing(thing), sub(sub), SpriteLeft(t1), SpriteRight(t2), StencilValue(stencilValue) { } - void Render(const TriMatrix &worldToClip, const PolyClipPlane &portalPlane) override + void Render(PolyRenderThread *thread, const TriMatrix &worldToClip, const PolyClipPlane &portalPlane) override { if ((thing->renderflags & RF_SPRITETYPEMASK) == RF_WALLSPRITE) { RenderPolyWallSprite wallspr; - wallspr.Render(worldToClip, portalPlane, thing, sub, StencilValue + 1); + wallspr.Render(thread, worldToClip, portalPlane, thing, sub, StencilValue + 1); } else { RenderPolySprite spr; - spr.Render(worldToClip, portalPlane, thing, sub, StencilValue + 1, SpriteLeft, SpriteRight); + spr.Render(thread, worldToClip, portalPlane, thing, sub, StencilValue + 1, SpriteLeft, SpriteRight); } } diff --git a/src/polyrenderer/scene/poly_wall.cpp b/src/polyrenderer/scene/poly_wall.cpp index deaf850fd..09eb09143 100644 --- a/src/polyrenderer/scene/poly_wall.cpp +++ b/src/polyrenderer/scene/poly_wall.cpp @@ -33,12 +33,13 @@ #include "polyrenderer/poly_renderer.h" #include "r_sky.h" #include "polyrenderer/scene/poly_light.h" +#include "polyrenderer/poly_renderthread.h" #include "g_levellocals.h" EXTERN_CVAR(Bool, r_drawmirrors) EXTERN_CVAR(Bool, r_fogboundary) -bool RenderPolyWall::RenderLine(const TriMatrix &worldToClip, const PolyClipPlane &clipPlane, seg_t *line, sector_t *frontsector, uint32_t subsectorDepth, uint32_t stencilValue, std::vector &translucentWallsOutput, std::vector> &linePortals, line_t *lastPortalLine) +bool RenderPolyWall::RenderLine(PolyRenderThread *thread, const TriMatrix &worldToClip, const PolyClipPlane &clipPlane, seg_t *line, sector_t *frontsector, uint32_t subsectorDepth, uint32_t stencilValue, std::vector &translucentWallsOutput, std::vector> &linePortals, line_t *lastPortalLine) { double frontceilz1 = frontsector->ceilingplane.ZatPoint(line->v1); double frontfloorz1 = frontsector->floorplane.ZatPoint(line->v1); @@ -105,7 +106,7 @@ bool RenderPolyWall::RenderLine(const TriMatrix &worldToClip, const PolyClipPlan wall.Wallpart = side_t::mid; wall.Texture = GetTexture(wall.Line, wall.Side, side_t::mid); wall.Polyportal = polyportal; - wall.Render(worldToClip, clipPlane); + wall.Render(thread, worldToClip, clipPlane); return true; } } @@ -141,7 +142,7 @@ bool RenderPolyWall::RenderLine(const TriMatrix &worldToClip, const PolyClipPlan wall.BottomTexZ = MIN(MIN(backceilz1, frontceilz1), MIN(backceilz2, frontceilz2)); wall.Wallpart = side_t::top; wall.Texture = GetTexture(wall.Line, wall.Side, side_t::top); - wall.Render(worldToClip, clipPlane); + wall.Render(thread, worldToClip, clipPlane); } if ((bottomfloorz1 < bottomceilz1 || bottomfloorz2 < bottomceilz2) && line->sidedef && !bothSkyFloor) @@ -153,7 +154,7 @@ bool RenderPolyWall::RenderLine(const TriMatrix &worldToClip, const PolyClipPlan wall.UnpeggedCeil2 = topceilz2; wall.Wallpart = side_t::bottom; wall.Texture = GetTexture(wall.Line, wall.Side, side_t::bottom); - wall.Render(worldToClip, clipPlane); + wall.Render(thread, worldToClip, clipPlane); } if (line->sidedef) @@ -170,12 +171,12 @@ bool RenderPolyWall::RenderLine(const TriMatrix &worldToClip, const PolyClipPlan FTexture *midtex = TexMan(line->sidedef->GetTexture(side_t::mid), true); if ((midtex && midtex->UseType != FTexture::TEX_Null) || wall.FogBoundary) - translucentWallsOutput.push_back(PolyRenderer::Instance()->FrameMemory.NewObject(wall)); + translucentWallsOutput.push_back(thread->FrameMemory->NewObject(wall)); if (polyportal) { wall.Polyportal = polyportal; - wall.Render(worldToClip, clipPlane); + wall.Render(thread, worldToClip, clipPlane); } } } @@ -189,7 +190,7 @@ bool RenderPolyWall::IsFogBoundary(sector_t *front, sector_t *back) (front->GetTexture(sector_t::ceiling) != skyflatnum || back->GetTexture(sector_t::ceiling) != skyflatnum); } -void RenderPolyWall::Render3DFloorLine(const TriMatrix &worldToClip, const PolyClipPlane &clipPlane, seg_t *line, sector_t *frontsector, uint32_t subsectorDepth, uint32_t stencilValue, F3DFloor *fakeFloor, std::vector &translucentWallsOutput) +void RenderPolyWall::Render3DFloorLine(PolyRenderThread *thread, const TriMatrix &worldToClip, const PolyClipPlane &clipPlane, seg_t *line, sector_t *frontsector, uint32_t subsectorDepth, uint32_t stencilValue, F3DFloor *fakeFloor, std::vector &translucentWallsOutput) { if (!(fakeFloor->flags & FF_EXISTS)) return; if (!(fakeFloor->flags & FF_RENDERPLANES)) return; @@ -235,9 +236,9 @@ void RenderPolyWall::Render3DFloorLine(const TriMatrix &worldToClip, const PolyC wall.Texture = GetTexture(wall.Line, wall.Side, side_t::mid); if (!wall.Masked) - wall.Render(worldToClip, clipPlane); + wall.Render(thread, worldToClip, clipPlane); else - translucentWallsOutput.push_back(PolyRenderer::Instance()->FrameMemory.NewObject(wall)); + translucentWallsOutput.push_back(thread->FrameMemory->NewObject(wall)); } void RenderPolyWall::SetCoords(const DVector2 &v1, const DVector2 &v2, double ceil1, double floor1, double ceil2, double floor2) @@ -250,13 +251,13 @@ void RenderPolyWall::SetCoords(const DVector2 &v1, const DVector2 &v2, double ce this->floor2 = floor2; } -void RenderPolyWall::Render(const TriMatrix &worldToClip, const PolyClipPlane &clipPlane) +void RenderPolyWall::Render(PolyRenderThread *thread, const TriMatrix &worldToClip, const PolyClipPlane &clipPlane) { bool foggy = false; if (!Texture && !Polyportal && !FogBoundary) return; - TriVertex *vertices = PolyRenderer::Instance()->FrameMemory.AllocMemory(4); + TriVertex *vertices = thread->FrameMemory->AllocMemory(4); vertices[0].x = (float)v1.X; vertices[0].y = (float)v1.Y; @@ -329,7 +330,7 @@ void RenderPolyWall::Render(const TriMatrix &worldToClip, const PolyClipPlane &c args.SetDepthTest(true); args.SetWriteDepth(true); args.SetWriteStencil(false); - args.DrawArray(vertices, 4, PolyDrawMode::TriangleFan); + args.DrawArray(thread, vertices, 4, PolyDrawMode::TriangleFan); if (!Texture) return; } @@ -339,13 +340,13 @@ void RenderPolyWall::Render(const TriMatrix &worldToClip, const PolyClipPlane &c args.SetWriteStencil(true, Polyportal->StencilValue); args.SetWriteColor(false); args.SetWriteDepth(false); - args.DrawArray(vertices, 4, PolyDrawMode::TriangleFan); + args.DrawArray(thread, vertices, 4, PolyDrawMode::TriangleFan); Polyportal->Shape.push_back({ vertices, 4, true }); } else if (!Masked) { args.SetStyle(TriBlendMode::TextureOpaque); - DrawStripes(args, vertices); + DrawStripes(thread, args, vertices); } else { @@ -355,13 +356,13 @@ void RenderPolyWall::Render(const TriMatrix &worldToClip, const PolyClipPlane &c args.SetDepthTest(true); args.SetWriteDepth(true); args.SetWriteStencil(false); - DrawStripes(args, vertices); + DrawStripes(thread, args, vertices); } - RenderPolyDecal::RenderWallDecals(worldToClip, clipPlane, LineSeg, StencilValue); + RenderPolyDecal::RenderWallDecals(thread, worldToClip, clipPlane, LineSeg, StencilValue); } -void RenderPolyWall::DrawStripes(PolyDrawArgs &args, TriVertex *vertices) +void RenderPolyWall::DrawStripes(PolyRenderThread *thread, PolyDrawArgs &args, TriVertex *vertices) { const auto &lightlist = Line->frontsector->e->XFloor.lightlist; if (lightlist.Size() > 0) @@ -384,7 +385,7 @@ void RenderPolyWall::DrawStripes(PolyDrawArgs &args, TriVertex *vertices) args.SetClipPlane(1, topPlane); args.SetClipPlane(2, bottomPlane); - args.DrawArray(vertices, 4, PolyDrawMode::TriangleFan); + args.DrawArray(thread, vertices, 4, PolyDrawMode::TriangleFan); FDynamicColormap *basecolormap = GetColorTable(lit->extra_colormap, Line->frontsector->SpecialColors[sector_t::walltop]); @@ -407,11 +408,11 @@ void RenderPolyWall::DrawStripes(PolyDrawArgs &args, TriVertex *vertices) args.SetClipPlane(1, topPlane); args.SetClipPlane(2, PolyClipPlane()); - args.DrawArray(vertices, 4, PolyDrawMode::TriangleFan); + args.DrawArray(thread, vertices, 4, PolyDrawMode::TriangleFan); } else { - args.DrawArray(vertices, 4, PolyDrawMode::TriangleFan); + args.DrawArray(thread, vertices, 4, PolyDrawMode::TriangleFan); } } diff --git a/src/polyrenderer/scene/poly_wall.h b/src/polyrenderer/scene/poly_wall.h index 34b46cb6c..40b6d5509 100644 --- a/src/polyrenderer/scene/poly_wall.h +++ b/src/polyrenderer/scene/poly_wall.h @@ -31,11 +31,11 @@ class PolyCull; class RenderPolyWall { public: - static bool RenderLine(const TriMatrix &worldToClip, const PolyClipPlane &clipPlane, seg_t *line, sector_t *frontsector, uint32_t subsectorDepth, uint32_t stencilValue, std::vector &translucentWallsOutput, std::vector> &linePortals, line_t *lastPortalLine); - static void Render3DFloorLine(const TriMatrix &worldToClip, const PolyClipPlane &clipPlane, seg_t *line, sector_t *frontsector, uint32_t subsectorDepth, uint32_t stencilValue, F3DFloor *fakeFloor, std::vector &translucentWallsOutput); + static bool RenderLine(PolyRenderThread *thread, const TriMatrix &worldToClip, const PolyClipPlane &clipPlane, seg_t *line, sector_t *frontsector, uint32_t subsectorDepth, uint32_t stencilValue, std::vector &translucentWallsOutput, std::vector> &linePortals, line_t *lastPortalLine); + static void Render3DFloorLine(PolyRenderThread *thread, const TriMatrix &worldToClip, const PolyClipPlane &clipPlane, seg_t *line, sector_t *frontsector, uint32_t subsectorDepth, uint32_t stencilValue, F3DFloor *fakeFloor, std::vector &translucentWallsOutput); void SetCoords(const DVector2 &v1, const DVector2 &v2, double ceil1, double floor1, double ceil2, double floor2); - void Render(const TriMatrix &worldToClip, const PolyClipPlane &clipPlane); + void Render(PolyRenderThread *thread, const TriMatrix &worldToClip, const PolyClipPlane &clipPlane); DVector2 v1; DVector2 v2; @@ -66,7 +66,7 @@ public: private: void ClampHeight(TriVertex &v1, TriVertex &v2); int GetLightLevel(); - void DrawStripes(PolyDrawArgs &args, TriVertex *vertices); + void DrawStripes(PolyRenderThread *thread, PolyDrawArgs &args, TriVertex *vertices); static bool IsFogBoundary(sector_t *front, sector_t *back); static FTexture *GetTexture(const line_t *Line, const side_t *Side, side_t::ETexpart texpart); @@ -98,9 +98,9 @@ class PolyTranslucentWall : public PolyTranslucentObject public: PolyTranslucentWall(RenderPolyWall wall) : PolyTranslucentObject(wall.SubsectorDepth, 1e6), wall(wall) { } - void Render(const TriMatrix &worldToClip, const PolyClipPlane &portalPlane) override + void Render(PolyRenderThread *thread, const TriMatrix &worldToClip, const PolyClipPlane &portalPlane) override { - wall.Render(worldToClip, portalPlane); + wall.Render(thread, worldToClip, portalPlane); } RenderPolyWall wall; diff --git a/src/polyrenderer/scene/poly_wallsprite.cpp b/src/polyrenderer/scene/poly_wallsprite.cpp index b8b2a9339..846524f9d 100644 --- a/src/polyrenderer/scene/poly_wallsprite.cpp +++ b/src/polyrenderer/scene/poly_wallsprite.cpp @@ -28,8 +28,9 @@ #include "poly_wallsprite.h" #include "polyrenderer/poly_renderer.h" #include "polyrenderer/scene/poly_light.h" +#include "polyrenderer/poly_renderthread.h" -void RenderPolyWallSprite::Render(const TriMatrix &worldToClip, const PolyClipPlane &clipPlane, AActor *thing, subsector_t *sub, uint32_t stencilValue) +void RenderPolyWallSprite::Render(PolyRenderThread *thread, const TriMatrix &worldToClip, const PolyClipPlane &clipPlane, AActor *thing, subsector_t *sub, uint32_t stencilValue) { if (RenderPolySprite::IsThingCulled(thing)) return; @@ -69,7 +70,7 @@ void RenderPolyWallSprite::Render(const TriMatrix &worldToClip, const PolyClipPl DVector2 points[2] = { left, right }; - TriVertex *vertices = PolyRenderer::Instance()->FrameMemory.AllocMemory(4); + TriVertex *vertices = thread->FrameMemory->AllocMemory(4); bool foggy = false; int actualextralight = foggy ? 0 : viewpoint.extralight << 4; @@ -110,5 +111,5 @@ void RenderPolyWallSprite::Render(const TriMatrix &worldToClip, const PolyClipPl args.SetWriteDepth(false); args.SetWriteStencil(false); args.SetStyle(TriBlendMode::TextureMasked); - args.DrawArray(vertices, 4, PolyDrawMode::TriangleFan); + args.DrawArray(thread, vertices, 4, PolyDrawMode::TriangleFan); } diff --git a/src/polyrenderer/scene/poly_wallsprite.h b/src/polyrenderer/scene/poly_wallsprite.h index c1f255f5d..2ee8c3ba5 100644 --- a/src/polyrenderer/scene/poly_wallsprite.h +++ b/src/polyrenderer/scene/poly_wallsprite.h @@ -27,5 +27,5 @@ class RenderPolyWallSprite { public: - void Render(const TriMatrix &worldToClip, const PolyClipPlane &clipPlane, AActor *thing, subsector_t *sub, uint32_t stencilValue); + void Render(PolyRenderThread *thread, const TriMatrix &worldToClip, const PolyClipPlane &clipPlane, AActor *thing, subsector_t *sub, uint32_t stencilValue); };