diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 885e31356..3032b03b2 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -848,6 +848,7 @@ set( NOT_COMPILED_SOURCE_FILES set( FASTMATH_PCH_SOURCES swrenderer/r_swrenderer.cpp swrenderer/r_memory.cpp + swrenderer/r_renderthread.cpp swrenderer/drawers/r_draw.cpp swrenderer/drawers/r_draw_pal.cpp swrenderer/drawers/r_draw_rgba.cpp diff --git a/src/swrenderer/line/r_line.cpp b/src/swrenderer/line/r_line.cpp index d70ae9869..156c2f3af 100644 --- a/src/swrenderer/line/r_line.cpp +++ b/src/swrenderer/line/r_line.cpp @@ -49,6 +49,7 @@ #include "swrenderer/plane/r_visibleplane.h" #include "swrenderer/plane/r_visibleplanelist.h" #include "swrenderer/things/r_decal.h" +#include "swrenderer/r_renderthread.h" CVAR(Bool, r_fogboundary, true, 0) CVAR(Bool, r_drawmirrors, true, 0) @@ -56,6 +57,11 @@ EXTERN_CVAR(Bool, r_fullbrightignoresectorcolor); namespace swrenderer { + SWRenderLine::SWRenderLine(RenderThread *thread) + { + Thread = thread; + } + void SWRenderLine::Render(seg_t *line, subsector_t *subsector, sector_t *sector, sector_t *fakebacksector, VisiblePlane *linefloorplane, VisiblePlane *lineceilingplane, bool infog, FDynamicColormap *colormap) { static sector_t tempsec; // killough 3/8/98: ceiling/water hack @@ -79,17 +85,17 @@ namespace swrenderer if (pt1.Y * (pt1.X - pt2.X) + pt1.X * (pt2.Y - pt1.Y) >= 0) return; - if (WallC.Init(pt1, pt2, 32.0 / (1 << 12))) + if (WallC.Init(Thread, pt1, pt2, 32.0 / (1 << 12))) return; - RenderPortal *renderportal = RenderPortal::Instance(); + RenderPortal *renderportal = Thread->Portal.get(); if (WallC.sx1 >= renderportal->WindowRight || WallC.sx2 <= renderportal->WindowLeft) return; if (line->linedef == NULL) { - if (RenderClipSegment::Instance()->Check(WallC.sx1, WallC.sx2)) + if (Thread->ClipSegments->Check(WallC.sx1, WallC.sx2)) { InSubsector->flags |= SSECF_DRAWN; } @@ -107,7 +113,7 @@ namespace swrenderer if ((v1 == line->v1 && v2 == line->v2) || (v2 == line->v1 && v1 == line->v2)) { // The seg is the entire wall. - WallT.InitFromWallCoords(&WallC); + WallT.InitFromWallCoords(Thread, &WallC); } else { // The seg is only part of the wall. @@ -115,10 +121,10 @@ namespace swrenderer { swapvalues(v1, v2); } - WallT.InitFromLine(v1->fPos() - ViewPos, v2->fPos() - ViewPos); + WallT.InitFromLine(Thread, v1->fPos() - ViewPos, v2->fPos() - ViewPos); } - Clip3DFloors *clip3d = Clip3DFloors::Instance(); + Clip3DFloors *clip3d = Thread->Clip3DFloors.get(); if (!(clip3d->fake3D & FAKE3D_FAKEBACK)) { @@ -142,7 +148,7 @@ namespace swrenderer // kg3D - its fake, no transfer_heights if (!(clip3d->fake3D & FAKE3D_FAKEBACK)) { // killough 3/8/98, 4/4/98: hack for invisible ceilings / deep water - backsector = RenderOpaquePass::Instance()->FakeFlat(backsector, &tempsec, nullptr, nullptr, curline, WallC.sx1, WallC.sx2, rw_frontcz1, rw_frontcz2); + backsector = Thread->OpaquePass->FakeFlat(backsector, &tempsec, nullptr, nullptr, curline, WallC.sx1, WallC.sx2, rw_frontcz1, rw_frontcz2); } doorclosed = false; // killough 4/16/98 @@ -255,7 +261,7 @@ namespace swrenderer // mark their subsectors as visible for automap texturing. if (hasglnodes && !(InSubsector->flags & SSECF_DRAWN)) { - if (RenderClipSegment::Instance()->Check(WallC.sx1, WallC.sx2)) + if (Thread->ClipSegments->Check(WallC.sx1, WallC.sx2)) { InSubsector->flags |= SSECF_DRAWN; } @@ -279,7 +285,7 @@ namespace swrenderer } static SWRenderLine *self = this; - bool visible = RenderClipSegment::Instance()->Clip(WallC.sx1, WallC.sx2, solid, [](int x1, int x2) -> bool + bool visible = Thread->ClipSegments->Clip(WallC.sx1, WallC.sx2, solid, [](int x1, int x2) -> bool { return self->RenderWallSegment(x1, x2); }); @@ -327,10 +333,10 @@ namespace swrenderer rw_offset = FLOAT2FIXED(sidedef->GetTextureXOffset(side_t::mid)); rw_light = rw_lightleft + rw_lightstep * (start - WallC.sx1); - RenderPortal *renderportal = RenderPortal::Instance(); + RenderPortal *renderportal = Thread->Portal.get(); DrawSegment *draw_segment = RenderMemory::NewObject(); - DrawSegmentList::Instance()->Push(draw_segment); + Thread->DrawSegments->Push(draw_segment); draw_segment->CurrentPortalUniq = renderportal->CurrentPortalUniq; draw_segment->sx1 = WallC.sx1; @@ -351,7 +357,7 @@ namespace swrenderer draw_segment->bFakeBoundary = false; draw_segment->foggy = foggy; - Clip3DFloors *clip3d = Clip3DFloors::Instance(); + Clip3DFloors *clip3d = Thread->Clip3DFloors.get(); if (clip3d->fake3D & FAKE3D_FAKEMASK) draw_segment->fake = 1; else draw_segment->fake = 0; @@ -448,7 +454,7 @@ namespace swrenderer // kg3D - backup for mid and fake walls draw_segment->bkup = RenderMemory::AllocMemory(stop - start); - memcpy(draw_segment->bkup, &RenderOpaquePass::Instance()->ceilingclip[start], sizeof(short)*(stop - start)); + memcpy(draw_segment->bkup, &Thread->OpaquePass->ceilingclip[start], sizeof(short)*(stop - start)); draw_segment->bFogBoundary = IsFogBoundary(frontsector, backsector); if (sidedef->GetTexture(side_t::mid).isValid() || draw_segment->bFakeBoundary) @@ -517,7 +523,7 @@ namespace swrenderer if (draw_segment->bFogBoundary || draw_segment->maskedtexturecol != nullptr) { - DrawSegmentList::Instance()->PushInteresting(draw_segment); + Thread->DrawSegments->PushInteresting(draw_segment); } } } @@ -527,7 +533,7 @@ namespace swrenderer { if (ceilingplane) { // killough 4/11/98: add NULL ptr checks - ceilingplane = VisiblePlaneList::Instance()->GetRange(ceilingplane, start, stop); + ceilingplane = Thread->PlaneList->GetRange(ceilingplane, start, stop); } else { @@ -539,7 +545,7 @@ namespace swrenderer { if (floorplane) { // killough 4/11/98: add NULL ptr checks - floorplane = VisiblePlaneList::Instance()->GetRange(floorplane, start, stop); + floorplane = Thread->PlaneList->GetRange(floorplane, start, stop); } else { @@ -558,13 +564,13 @@ namespace swrenderer if (((draw_segment->silhouette & SIL_TOP) || maskedtexture) && draw_segment->sprtopclip == nullptr) { draw_segment->sprtopclip = RenderMemory::AllocMemory(stop - start); - memcpy(draw_segment->sprtopclip, &RenderOpaquePass::Instance()->ceilingclip[start], sizeof(short)*(stop - start)); + memcpy(draw_segment->sprtopclip, &Thread->OpaquePass->ceilingclip[start], sizeof(short)*(stop - start)); } if (((draw_segment->silhouette & SIL_BOTTOM) || maskedtexture) && draw_segment->sprbottomclip == nullptr) { draw_segment->sprbottomclip = RenderMemory::AllocMemory(stop - start); - memcpy(draw_segment->sprbottomclip, &RenderOpaquePass::Instance()->floorclip[start], sizeof(short)*(stop - start)); + memcpy(draw_segment->sprbottomclip, &Thread->OpaquePass->floorclip[start], sizeof(short)*(stop - start)); } if (maskedtexture && curline->sidedef->GetTexture(side_t::mid).isValid()) @@ -576,12 +582,12 @@ namespace swrenderer // [ZZ] Only if not an active mirror if (!rw_markportal) { - RenderDecal::RenderDecals(curline->sidedef, draw_segment, wallshade, rw_lightleft, rw_lightstep, curline, WallC, foggy, basecolormap, walltop.ScreenY, wallbottom.ScreenY); + RenderDecal::RenderDecals(Thread, curline->sidedef, draw_segment, wallshade, rw_lightleft, rw_lightstep, curline, WallC, foggy, basecolormap, walltop.ScreenY, wallbottom.ScreenY); } if (rw_markportal) { - RenderPortal::Instance()->AddLinePortal(curline->linedef, draw_segment->x1, draw_segment->x2, draw_segment->sprtopclip, draw_segment->sprbottomclip); + Thread->Portal->AddLinePortal(curline->linedef, draw_segment->x1, draw_segment->x2, draw_segment->sprtopclip, draw_segment->sprbottomclip); } return (clip3d->fake3D & FAKE3D_FAKEMASK) == 0; @@ -598,7 +604,7 @@ namespace swrenderer linedef = curline->linedef; // mark the segment as visible for auto map - if (!RenderScene::Instance()->DontMapLines()) linedef->flags |= ML_MAPPED; + if (!Thread->Scene->DontMapLines()) linedef->flags |= ML_MAPPED; midtexture = toptexture = bottomtexture = 0; @@ -686,8 +692,7 @@ namespace swrenderer // wall but nothing to draw for it. // Recalculate walltop so that the wall is clipped by the back sector's // ceiling instead of the front sector's ceiling. - RenderPortal *renderportal = RenderPortal::Instance(); - walltop.Project(backsector->ceilingplane, &WallC, curline, renderportal->MirrorFlags & RF_XFLIP); + walltop.Project(backsector->ceilingplane, &WallC, curline, Thread->Portal->MirrorFlags & RF_XFLIP); } // Putting sky ceilings on the front and back of a line alters the way unpegged // positioning works. @@ -941,8 +946,8 @@ namespace swrenderer drawerargs.SetLight(cameraLight->FixedColormap(), 0, 0); // clip wall to the floor and ceiling - auto ceilingclip = RenderOpaquePass::Instance()->ceilingclip; - auto floorclip = RenderOpaquePass::Instance()->floorclip; + auto ceilingclip = Thread->OpaquePass->ceilingclip; + auto floorclip = Thread->OpaquePass->floorclip; for (x = x1; x < x2; ++x) { if (walltop.ScreenY[x] < ceilingclip[x]) @@ -955,7 +960,7 @@ namespace swrenderer } } - Clip3DFloors *clip3d = Clip3DFloors::Instance(); + Clip3DFloors *clip3d = Thread->Clip3DFloors.get(); // mark ceiling areas if (markceiling) @@ -1046,7 +1051,7 @@ namespace swrenderer rw_offset = -rw_offset; } - RenderWallPart renderWallpart; + RenderWallPart renderWallpart(Thread); renderWallpart.Render(drawerargs, frontsector, curline, WallC, rw_pic, x1, x2, walltop.ScreenY, wallbottom.ScreenY, rw_midtexturemid, walltexcoords.VStep, walltexcoords.UPos, yscale, MAX(rw_frontcz1, rw_frontcz2), MIN(rw_frontfz1, rw_frontfz2), false, wallshade, rw_offset, rw_light, rw_lightstep, light_list, foggy, basecolormap); } fillshort(ceilingclip + x1, x2 - x1, viewheight); @@ -1083,7 +1088,7 @@ namespace swrenderer rw_offset = -rw_offset; } - RenderWallPart renderWallpart; + RenderWallPart renderWallpart(Thread); renderWallpart.Render(drawerargs, frontsector, curline, WallC, rw_pic, x1, x2, walltop.ScreenY, wallupper.ScreenY, rw_toptexturemid, walltexcoords.VStep, walltexcoords.UPos, yscale, MAX(rw_frontcz1, rw_frontcz2), MIN(rw_backcz1, rw_backcz2), false, wallshade, rw_offset, rw_light, rw_lightstep, light_list, foggy, basecolormap); } memcpy(ceilingclip + x1, wallupper.ScreenY + x1, (x2 - x1) * sizeof(short)); @@ -1123,7 +1128,7 @@ namespace swrenderer rw_offset = -rw_offset; } - RenderWallPart renderWallpart; + RenderWallPart renderWallpart(Thread); renderWallpart.Render(drawerargs, frontsector, curline, WallC, rw_pic, x1, x2, walllower.ScreenY, wallbottom.ScreenY, rw_bottomtexturemid, walltexcoords.VStep, walltexcoords.UPos, yscale, MAX(rw_backfz1, rw_backfz2), MIN(rw_frontfz1, rw_frontfz2), false, wallshade, rw_offset, rw_light, rw_lightstep, light_list, foggy, basecolormap); } memcpy(floorclip + x1, walllower.ScreenY + x1, (x2 - x1) * sizeof(short)); @@ -1139,7 +1144,7 @@ namespace swrenderer //////////////////////////////////////////////////////////////////////////// // Transform and clip coordinates. Returns true if it was clipped away - bool FWallCoords::Init(const DVector2 &pt1, const DVector2 &pt2, double too_close) + bool FWallCoords::Init(RenderThread *thread, const DVector2 &pt1, const DVector2 &pt2, double too_close) { tleft.X = float(pt1.X * ViewSin - pt1.Y * ViewCos); tright.X = float(pt2.X * ViewSin - pt2.Y * ViewCos); @@ -1147,7 +1152,7 @@ namespace swrenderer tleft.Y = float(pt1.X * ViewTanCos + pt1.Y * ViewTanSin); tright.Y = float(pt2.X * ViewTanCos + pt2.Y * ViewTanSin); - RenderPortal *renderportal = RenderPortal::Instance(); + RenderPortal *renderportal = thread->Portal.get(); auto viewport = RenderViewport::Instance(); if (renderportal->MirrorFlags & RF_XFLIP) @@ -1201,12 +1206,12 @@ namespace swrenderer ///////////////////////////////////////////////////////////////////////// - void FWallTmapVals::InitFromWallCoords(const FWallCoords *wallc) + void FWallTmapVals::InitFromWallCoords(RenderThread *thread, const FWallCoords *wallc) { const FVector2 *left = &wallc->tleft; const FVector2 *right = &wallc->tright; - RenderPortal *renderportal = RenderPortal::Instance(); + RenderPortal *renderportal = thread->Portal.get(); if (renderportal->MirrorFlags & RF_XFLIP) { @@ -1218,7 +1223,7 @@ namespace swrenderer InvZstep = right->Y - left->Y; } - void FWallTmapVals::InitFromLine(const DVector2 &left, const DVector2 &right) + void FWallTmapVals::InitFromLine(RenderThread *thread, const DVector2 &left, const DVector2 &right) { // Coordinates should have already had viewx,viewy subtracted @@ -1227,7 +1232,7 @@ namespace swrenderer double fully1 = left.X * ViewTanCos + left.Y * ViewTanSin; double fully2 = right.X * ViewTanCos + right.Y * ViewTanSin; - RenderPortal *renderportal = RenderPortal::Instance(); + RenderPortal *renderportal = thread->Portal.get(); if (renderportal->MirrorFlags & RF_XFLIP) { diff --git a/src/swrenderer/line/r_line.h b/src/swrenderer/line/r_line.h index 3da9e0d85..75b6d69b3 100644 --- a/src/swrenderer/line/r_line.h +++ b/src/swrenderer/line/r_line.h @@ -25,6 +25,7 @@ struct FDynamicColormap; namespace swrenderer { + class RenderThread; struct VisiblePlane; struct FWallCoords @@ -35,7 +36,7 @@ namespace swrenderer float sz1, sz2; // depth at left, right of wall in screen space yb1,yb2 short sx1, sx2; // x coords at left, right of wall in screen space xb1,xb2 - bool Init(const DVector2 &pt1, const DVector2 &pt2, double too_close); + bool Init(RenderThread *thread, const DVector2 &pt1, const DVector2 &pt2, double too_close); }; struct FWallTmapVals @@ -43,15 +44,18 @@ namespace swrenderer float UoverZorg, UoverZstep; float InvZorg, InvZstep; - void InitFromWallCoords(const FWallCoords *wallc); - void InitFromLine(const DVector2 &left, const DVector2 &right); + void InitFromWallCoords(RenderThread *thread, const FWallCoords *wallc); + void InitFromLine(RenderThread *thread, const DVector2 &left, const DVector2 &right); }; class SWRenderLine { public: + SWRenderLine(RenderThread *thread); void Render(seg_t *line, subsector_t *subsector, sector_t *sector, sector_t *fakebacksector, VisiblePlane *floorplane, VisiblePlane *ceilingplane, bool foggy, FDynamicColormap *basecolormap); + RenderThread *Thread = nullptr; + private: bool RenderWallSegment(int x1, int x2); void SetWallVariables(bool needlights); diff --git a/src/swrenderer/line/r_renderdrawsegment.cpp b/src/swrenderer/line/r_renderdrawsegment.cpp index a3074f1d3..203e02c44 100644 --- a/src/swrenderer/line/r_renderdrawsegment.cpp +++ b/src/swrenderer/line/r_renderdrawsegment.cpp @@ -29,6 +29,7 @@ #include "r_data/colormaps.h" #include "d_net.h" #include "swrenderer/r_memory.h" +#include "swrenderer/r_renderthread.h" #include "swrenderer/drawers/r_draw.h" #include "swrenderer/scene/r_3dfloors.h" #include "swrenderer/scene/r_opaque_pass.h" @@ -47,6 +48,11 @@ EXTERN_CVAR(Bool, r_fullbrightignoresectorcolor); namespace swrenderer { + RenderDrawSegment::RenderDrawSegment(RenderThread *thread) + { + Thread = thread; + } + void RenderDrawSegment::Render(DrawSegment *ds, int x1, int x2) { auto viewport = RenderViewport::Instance(); @@ -95,7 +101,7 @@ namespace swrenderer } // killough 4/13/98: get correct lightlevel for 2s normal textures - sec = RenderOpaquePass::Instance()->FakeFlat(frontsector, &tempsec, nullptr, nullptr, nullptr, 0, 0, 0, 0); + sec = Thread->OpaquePass->FakeFlat(frontsector, &tempsec, nullptr, nullptr, nullptr, 0, 0, 0, 0); FDynamicColormap *basecolormap = sec->ColorMap; // [RH] Set basecolormap @@ -103,7 +109,7 @@ namespace swrenderer rw_lightstep = ds->lightstep; rw_light = ds->light + (x1 - ds->x1) * rw_lightstep; - Clip3DFloors *clip3d = Clip3DFloors::Instance(); + Clip3DFloors *clip3d = Thread->Clip3DFloors.get(); CameraLight *cameraLight = CameraLight::Instance(); if (cameraLight->FixedLightLevel() < 0) @@ -361,7 +367,7 @@ namespace swrenderer double top, bot; GetMaskedWallTopBottom(ds, top, bot); - RenderWallPart renderWallpart; + RenderWallPart renderWallpart(Thread); renderWallpart.Render(walldrawerargs, frontsector, curline, WallC, rw_pic, x1, x2, mceilingclip, mfloorclip, texturemid, MaskedSWall, maskedtexturecol, ds->yscale, top, bot, true, wallshade, rw_offset, rw_light, rw_lightstep, nullptr, ds->foggy, basecolormap); } @@ -471,7 +477,7 @@ namespace swrenderer WallC.tright.Y = ds->cy + ds->cdy; WallT = ds->tmapvals; - Clip3DFloors *clip3d = Clip3DFloors::Instance(); + Clip3DFloors *clip3d = Thread->Clip3DFloors.get(); wallupper.Project(clip3d->sclipTop - ViewPos.Z, &WallC); walllower.Project(clip3d->sclipBottom - ViewPos.Z, &WallC); @@ -492,7 +498,7 @@ namespace swrenderer double top, bot; GetMaskedWallTopBottom(ds, top, bot); - RenderWallPart renderWallpart; + RenderWallPart renderWallpart(Thread); renderWallpart.Render(drawerargs, frontsector, curline, WallC, rw_pic, x1, x2, wallupper.ScreenY, walllower.ScreenY, texturemid, MaskedSWall, walltexcoords.UPos, yscale, top, bot, true, wallshade, rw_offset, rw_light, rw_lightstep, nullptr, ds->foggy, basecolormap); } @@ -525,7 +531,7 @@ namespace swrenderer floorHeight = backsector->CenterFloor(); ceilingHeight = backsector->CenterCeiling(); - Clip3DFloors *clip3d = Clip3DFloors::Instance(); + Clip3DFloors *clip3d = Thread->Clip3DFloors.get(); // maybe fix clipheights if (!(clip3d->fake3D & FAKE3D_CLIPBOTTOM)) clip3d->sclipBottom = floorHeight; @@ -906,7 +912,7 @@ namespace swrenderer { ProjectedWallLine most; - RenderPortal *renderportal = RenderPortal::Instance(); + RenderPortal *renderportal = Thread->Portal.get(); most.Project(curline->frontsector->ceilingplane, &WallC, curline, renderportal->MirrorFlags & RF_XFLIP); for (int i = x1; i < x2; ++i) @@ -931,7 +937,7 @@ namespace swrenderer top = MAX(frontcz1, frontcz2); bot = MIN(frontfz1, frontfz2); - Clip3DFloors *clip3d = Clip3DFloors::Instance(); + Clip3DFloors *clip3d = Thread->Clip3DFloors.get(); if (clip3d->fake3D & FAKE3D_CLIPTOP) { top = MIN(top, clip3d->sclipTop); diff --git a/src/swrenderer/line/r_renderdrawsegment.h b/src/swrenderer/line/r_renderdrawsegment.h index b3a3ee6c0..a13d1341d 100644 --- a/src/swrenderer/line/r_renderdrawsegment.h +++ b/src/swrenderer/line/r_renderdrawsegment.h @@ -17,11 +17,16 @@ namespace swrenderer { + class RenderThread; + class RenderDrawSegment { public: + RenderDrawSegment(RenderThread *thread); void Render(DrawSegment *ds, int x1, int x2); + RenderThread *Thread = nullptr; + private: void ClipMidtex(int x1, int x2); void RenderFakeWall(DrawSegment *ds, int x1, int x2, F3DFloor *rover, int wallshade, FDynamicColormap *basecolormap); diff --git a/src/swrenderer/line/r_walldraw.cpp b/src/swrenderer/line/r_walldraw.cpp index 2261fa71a..ec7ea38f6 100644 --- a/src/swrenderer/line/r_walldraw.cpp +++ b/src/swrenderer/line/r_walldraw.cpp @@ -40,6 +40,7 @@ #include "swrenderer/viewport/r_viewport.h" #include "swrenderer/line/r_walldraw.h" #include "swrenderer/line/r_wallsetup.h" +#include "swrenderer/r_renderthread.h" namespace swrenderer { @@ -376,7 +377,7 @@ namespace swrenderer assert(WallC.sx1 <= x1); assert(WallC.sx2 >= x2); - RenderPortal *renderportal = RenderPortal::Instance(); + RenderPortal *renderportal = Thread->Portal.get(); // kg3D - fake floors instead of zdoom light list for (unsigned int i = 0; i < frontsector->e->XFloor.lightlist.Size(); i++) @@ -520,4 +521,9 @@ namespace swrenderer ProcessWall(walltop, wallbottom, texturemid, swall, lwall); } } + + RenderWallPart::RenderWallPart(RenderThread *thread) + { + Thread = thread; + } } diff --git a/src/swrenderer/line/r_walldraw.h b/src/swrenderer/line/r_walldraw.h index bc5b2b3e9..79d7ffc91 100644 --- a/src/swrenderer/line/r_walldraw.h +++ b/src/swrenderer/line/r_walldraw.h @@ -24,6 +24,7 @@ struct FDynamicColormap; namespace swrenderer { + class RenderThread; struct DrawSegment; struct FWallCoords; class ProjectedWallLine; @@ -33,6 +34,8 @@ namespace swrenderer class RenderWallPart { public: + RenderWallPart(RenderThread *thread); + void Render( const WallDrawerArgs &drawerargs, sector_t *frontsector, @@ -58,6 +61,8 @@ namespace swrenderer bool foggy, FDynamicColormap *basecolormap); + RenderThread *Thread = nullptr; + private: void ProcessWallNP2(const short *uwal, const short *dwal, double texturemid, float *swal, fixed_t *lwal, double top, double bot); void ProcessWall(const short *uwal, const short *dwal, double texturemid, float *swal, fixed_t *lwal); diff --git a/src/swrenderer/plane/r_flatplane.cpp b/src/swrenderer/plane/r_flatplane.cpp index 3e630c13c..85e339e84 100644 --- a/src/swrenderer/plane/r_flatplane.cpp +++ b/src/swrenderer/plane/r_flatplane.cpp @@ -41,9 +41,15 @@ #include "swrenderer/plane/r_visibleplane.h" #include "swrenderer/viewport/r_viewport.h" #include "swrenderer/r_memory.h" +#include "swrenderer/r_renderthread.h" namespace swrenderer { + RenderFlatPlane::RenderFlatPlane(RenderThread *thread) + { + Thread = thread; + } + void RenderFlatPlane::Render(VisiblePlane *pl, double _xscale, double _yscale, fixed_t alpha, bool additive, bool masked, FDynamicColormap *colormap, FTexture *texture) { if (alpha <= 0) @@ -85,7 +91,7 @@ namespace swrenderer ystep = -sin(planeang) / viewport->FocalLengthX; // [RH] flip for mirrors - RenderPortal *renderportal = RenderPortal::Instance(); + RenderPortal *renderportal = Thread->Portal.get(); if (renderportal->MirrorFlags & RF_XFLIP) { xstep = -xstep; diff --git a/src/swrenderer/plane/r_flatplane.h b/src/swrenderer/plane/r_flatplane.h index c164ba862..72a48d334 100644 --- a/src/swrenderer/plane/r_flatplane.h +++ b/src/swrenderer/plane/r_flatplane.h @@ -18,15 +18,19 @@ namespace swrenderer { + class RenderThread; struct VisiblePlaneLight; class RenderFlatPlane : PlaneRenderer { public: + RenderFlatPlane(RenderThread *thread); void Render(VisiblePlane *pl, double _xscale, double _yscale, fixed_t alpha, bool additive, bool masked, FDynamicColormap *basecolormap, FTexture *texture); static void SetupSlope(); + RenderThread *Thread = nullptr; + private: void RenderLine(int y, int x1, int x2) override; void StepColumn() override; diff --git a/src/swrenderer/plane/r_skyplane.cpp b/src/swrenderer/plane/r_skyplane.cpp index 091182c49..8eefdb708 100644 --- a/src/swrenderer/plane/r_skyplane.cpp +++ b/src/swrenderer/plane/r_skyplane.cpp @@ -42,6 +42,7 @@ #include "swrenderer/scene/r_light.h" #include "swrenderer/viewport/r_viewport.h" #include "swrenderer/r_memory.h" +#include "swrenderer/r_renderthread.h" #include "g_levellocals.h" CVAR(Bool, r_linearsky, false, CVAR_ARCHIVE | CVAR_GLOBALCONFIG); @@ -49,6 +50,11 @@ EXTERN_CVAR(Int, r_skymode) namespace swrenderer { + RenderSkyPlane::RenderSkyPlane(RenderThread *thread) + { + Thread = thread; + } + void RenderSkyPlane::Render(VisiblePlane *pl) { FTextureID sky1tex, sky2tex; @@ -162,7 +168,7 @@ namespace swrenderer void RenderSkyPlane::DrawSkyColumnStripe(int start_x, int y1, int y2, double scale, double texturemid, double yrepeat) { - RenderPortal *renderportal = RenderPortal::Instance(); + RenderPortal *renderportal = Thread->Portal.get(); auto viewport = RenderViewport::Instance(); uint32_t height = frontskytex->GetHeight(); diff --git a/src/swrenderer/plane/r_skyplane.h b/src/swrenderer/plane/r_skyplane.h index a1f8a4550..9a79b1e96 100644 --- a/src/swrenderer/plane/r_skyplane.h +++ b/src/swrenderer/plane/r_skyplane.h @@ -21,8 +21,12 @@ namespace swrenderer class RenderSkyPlane { public: + RenderSkyPlane(RenderThread *thread); + void Render(VisiblePlane *pl); + RenderThread *Thread = nullptr; + private: void DrawSky(VisiblePlane *pl); void DrawSkyColumnStripe(int start_x, int y1, int y2, double scale, double texturemid, double yrepeat); diff --git a/src/swrenderer/plane/r_slopeplane.cpp b/src/swrenderer/plane/r_slopeplane.cpp index c51bf0276..ccb7e6107 100644 --- a/src/swrenderer/plane/r_slopeplane.cpp +++ b/src/swrenderer/plane/r_slopeplane.cpp @@ -39,8 +39,9 @@ #include "swrenderer/scene/r_scene.h" #include "swrenderer/scene/r_light.h" #include "swrenderer/viewport/r_viewport.h" -#include "swrenderer/r_memory.h" #include "swrenderer/plane/r_visibleplane.h" +#include "swrenderer/r_memory.h" +#include "swrenderer/r_renderthread.h" #ifdef _MSC_VER #pragma warning(disable:4244) @@ -48,6 +49,11 @@ namespace swrenderer { + RenderSlopePlane::RenderSlopePlane(RenderThread *thread) + { + Thread = thread; + } + void RenderSlopePlane::Render(VisiblePlane *pl, double _xscale, double _yscale, fixed_t alpha, bool additive, bool masked, FDynamicColormap *colormap, FTexture *texture) { static const float ifloatpow2[16] = @@ -138,7 +144,7 @@ namespace swrenderer plane_su *= 4294967296.f; plane_sv *= 4294967296.f; - RenderPortal *renderportal = RenderPortal::Instance(); + RenderPortal *renderportal = Thread->Portal.get(); if (renderportal->MirrorFlags & RF_XFLIP) { plane_su[0] = -plane_su[0]; diff --git a/src/swrenderer/plane/r_slopeplane.h b/src/swrenderer/plane/r_slopeplane.h index b06f525a2..b707a3f7c 100644 --- a/src/swrenderer/plane/r_slopeplane.h +++ b/src/swrenderer/plane/r_slopeplane.h @@ -18,11 +18,16 @@ namespace swrenderer { + class RenderThread; + class RenderSlopePlane : PlaneRenderer { public: + RenderSlopePlane(RenderThread *thread); void Render(VisiblePlane *pl, double _xscale, double _yscale, fixed_t alpha, bool additive, bool masked, FDynamicColormap *basecolormap, FTexture *texture); + RenderThread *Thread = nullptr; + private: void RenderLine(int y, int x1, int x2) override; diff --git a/src/swrenderer/plane/r_visibleplane.cpp b/src/swrenderer/plane/r_visibleplane.cpp index 8f6d93d37..0d9e97ef3 100644 --- a/src/swrenderer/plane/r_visibleplane.cpp +++ b/src/swrenderer/plane/r_visibleplane.cpp @@ -87,14 +87,14 @@ namespace swrenderer } } - void VisiblePlane::Render(fixed_t alpha, bool additive, bool masked) + void VisiblePlane::Render(RenderThread *thread, fixed_t alpha, bool additive, bool masked) { if (left >= right) return; if (picnum == skyflatnum) // sky flat { - RenderSkyPlane renderer; + RenderSkyPlane renderer(thread); renderer.Render(this); } else // regular flat @@ -119,12 +119,12 @@ namespace swrenderer if (!height.isSlope() && !tilt) { - RenderFlatPlane renderer; + RenderFlatPlane renderer(thread); renderer.Render(this, xscale, yscale, alpha, additive, masked, colormap, tex); } else { - RenderSlopePlane renderer; + RenderSlopePlane renderer(thread); renderer.Render(this, xscale, yscale, alpha, additive, masked, colormap, tex); } } diff --git a/src/swrenderer/plane/r_visibleplane.h b/src/swrenderer/plane/r_visibleplane.h index d26f0fdfd..5e1c9230b 100644 --- a/src/swrenderer/plane/r_visibleplane.h +++ b/src/swrenderer/plane/r_visibleplane.h @@ -25,6 +25,8 @@ struct FSectorPortal; namespace swrenderer { + class RenderThread; + struct VisiblePlaneLight { ADynamicLight *lightsource; @@ -36,7 +38,7 @@ namespace swrenderer VisiblePlane(); void AddLights(FLightNode *node); - void Render(fixed_t alpha, bool additive, bool masked); + void Render(RenderThread *thread, fixed_t alpha, bool additive, bool masked); VisiblePlane *next = nullptr; // Next visplane in hash chain -- killough diff --git a/src/swrenderer/plane/r_visibleplanelist.cpp b/src/swrenderer/plane/r_visibleplanelist.cpp index 03eb386f6..7ecd745bf 100644 --- a/src/swrenderer/plane/r_visibleplanelist.cpp +++ b/src/swrenderer/plane/r_visibleplanelist.cpp @@ -41,13 +41,13 @@ #include "swrenderer/plane/r_visibleplanelist.h" #include "swrenderer/drawers/r_draw.h" #include "swrenderer/viewport/r_viewport.h" +#include "swrenderer/r_renderthread.h" namespace swrenderer { - VisiblePlaneList *VisiblePlaneList::Instance() + VisiblePlaneList::VisiblePlaneList(RenderThread *thread) { - static VisiblePlaneList instance; - return &instance; + Thread = thread; } VisiblePlaneList::VisiblePlaneList() @@ -129,7 +129,7 @@ namespace swrenderer // kg3D - hack, store alpha in sky // i know there is ->alpha, but this also allows to identify fake plane // and ->alpha is for stacked sectors - Clip3DFloors *clip3d = Clip3DFloors::Instance(); + Clip3DFloors *clip3d = Thread->Clip3DFloors.get(); if (clip3d->fake3D & (FAKE3D_FAKEFLOOR | FAKE3D_FAKECEILING)) sky = 0x80000000 | clip3d->fakeAlpha; else sky = 0; // not skyflatnum so it can't be a sky portal = nullptr; @@ -139,7 +139,7 @@ namespace swrenderer // New visplane algorithm uses hash table -- killough hash = isskybox ? ((unsigned)MAXVISPLANES) : CalcHash(picnum.GetIndex(), lightlevel, height); - RenderPortal *renderportal = RenderPortal::Instance(); + RenderPortal *renderportal = Thread->Portal.get(); for (check = visplanes[hash]; check; check = check->next) // killough { @@ -190,7 +190,7 @@ namespace swrenderer sky == check->sky && renderportal->CurrentPortalUniq == check->CurrentPortalUniq && renderportal->MirrorFlags == check->MirrorFlags && - Clip3DFloors::Instance()->CurrentSkybox == check->CurrentSkybox && + Thread->Clip3DFloors->CurrentSkybox == check->CurrentSkybox && ViewPos == check->viewpos ) { @@ -215,7 +215,7 @@ namespace swrenderer check->Additive = additive; check->CurrentPortalUniq = renderportal->CurrentPortalUniq; check->MirrorFlags = renderportal->MirrorFlags; - check->CurrentSkybox = Clip3DFloors::Instance()->CurrentSkybox; + check->CurrentSkybox = Thread->Clip3DFloors->CurrentSkybox; return check; } @@ -326,19 +326,19 @@ namespace swrenderer int i; int vpcount = 0; - RenderPortal *renderportal = RenderPortal::Instance(); + RenderPortal *renderportal = Thread->Portal.get(); for (i = 0; i < MAXVISPLANES; i++) { for (pl = visplanes[i]; pl; pl = pl->next) { // kg3D - draw only correct planes - if (pl->CurrentPortalUniq != renderportal->CurrentPortalUniq || pl->CurrentSkybox != Clip3DFloors::Instance()->CurrentSkybox) + if (pl->CurrentPortalUniq != renderportal->CurrentPortalUniq || pl->CurrentSkybox != Thread->Clip3DFloors->CurrentSkybox) continue; // kg3D - draw only real planes now if (pl->sky >= 0) { vpcount++; - pl->Render(OPAQUE, false, false); + pl->Render(Thread, OPAQUE, false, false); } } } @@ -353,13 +353,13 @@ namespace swrenderer DVector3 oViewPos = ViewPos; DAngle oViewAngle = ViewAngle; - RenderPortal *renderportal = RenderPortal::Instance(); + RenderPortal *renderportal = Thread->Portal.get(); for (i = 0; i < MAXVISPLANES; i++) { for (pl = visplanes[i]; pl; pl = pl->next) { - if (pl->CurrentSkybox != Clip3DFloors::Instance()->CurrentSkybox || pl->CurrentPortalUniq != renderportal->CurrentPortalUniq) + if (pl->CurrentSkybox != Thread->Clip3DFloors->CurrentSkybox || pl->CurrentPortalUniq != renderportal->CurrentPortalUniq) continue; if (pl->sky < 0 && pl->height.Zat0() == height) @@ -368,7 +368,7 @@ namespace swrenderer ViewAngle = pl->viewangle; renderportal->MirrorFlags = pl->MirrorFlags; - pl->Render(pl->sky & 0x7FFFFFFF, pl->Additive, true); + pl->Render(Thread, pl->sky & 0x7FFFFFFF, pl->Additive, true); } } } diff --git a/src/swrenderer/plane/r_visibleplanelist.h b/src/swrenderer/plane/r_visibleplanelist.h index 3a3134fbd..e07a086fd 100644 --- a/src/swrenderer/plane/r_visibleplanelist.h +++ b/src/swrenderer/plane/r_visibleplanelist.h @@ -20,12 +20,13 @@ struct FSectorPortal; namespace swrenderer { + class RenderThread; struct VisiblePlane; class VisiblePlaneList { public: - static VisiblePlaneList *Instance(); + VisiblePlaneList(RenderThread *thread); void Clear(); void ClearKeepFakePlanes(); @@ -40,6 +41,8 @@ namespace swrenderer int Render(); void RenderHeight(double height); + RenderThread *Thread = nullptr; + private: VisiblePlaneList(); VisiblePlane *Add(unsigned hash); diff --git a/src/swrenderer/r_renderthread.cpp b/src/swrenderer/r_renderthread.cpp new file mode 100644 index 000000000..057c09632 --- /dev/null +++ b/src/swrenderer/r_renderthread.cpp @@ -0,0 +1,70 @@ +/* +** Renderer multithreading framework +** 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 "r_renderthread.h" +#include "swrenderer/things/r_visiblespritelist.h" +#include "swrenderer/scene/r_portal.h" +#include "swrenderer/scene/r_opaque_pass.h" +#include "swrenderer/scene/r_translucent_pass.h" +#include "swrenderer/scene/r_3dfloors.h" +#include "swrenderer/scene/r_scene.h" +#include "swrenderer/things/r_playersprite.h" +#include "swrenderer/plane/r_visibleplanelist.h" +#include "swrenderer/segments/r_drawsegment.h" +#include "swrenderer/segments/r_clipsegment.h" + +namespace swrenderer +{ + RenderThread::RenderThread() + { + OpaquePass = std::make_unique(this); + TranslucentPass = std::make_unique(this); + SpriteList = std::make_unique(); + Portal = std::make_unique(this); + Clip3DFloors = std::make_unique(this); + PlayerSprites = std::make_unique(this); + PlaneList = std::make_unique(this); + Scene = std::make_unique(this); + DrawSegments = std::make_unique(this); + ClipSegments = std::make_unique(); + } + + RenderThread::~RenderThread() + { + } +} diff --git a/src/swrenderer/r_renderthread.h b/src/swrenderer/r_renderthread.h new file mode 100644 index 000000000..21bb4b6fa --- /dev/null +++ b/src/swrenderer/r_renderthread.h @@ -0,0 +1,57 @@ +/* +** Renderer multithreading framework +** 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 + +namespace swrenderer +{ + class VisibleSpriteList; + class RenderPortal; + class RenderOpaquePass; + class RenderTranslucentPass; + class RenderPlayerSprites; + class RenderScene; + class Clip3DFloors; + class VisiblePlaneList; + class DrawSegmentList; + class RenderClipSegment; + + class RenderThread + { + public: + RenderThread(); + ~RenderThread(); + + std::unique_ptr OpaquePass; + std::unique_ptr TranslucentPass; + std::unique_ptr SpriteList; + std::unique_ptr Portal; + std::unique_ptr Clip3DFloors; + std::unique_ptr PlayerSprites; + std::unique_ptr PlaneList; + std::unique_ptr Scene; + std::unique_ptr DrawSegments; + std::unique_ptr ClipSegments; + }; +} diff --git a/src/swrenderer/r_swrenderer.cpp b/src/swrenderer/r_swrenderer.cpp index b334df796..a12a5ae00 100644 --- a/src/swrenderer/r_swrenderer.cpp +++ b/src/swrenderer/r_swrenderer.cpp @@ -88,7 +88,7 @@ void FSoftwareRenderer::Init() { gl_ParseDefs(); - RenderScene::Instance()->Init(); + mMainThread.Scene->Init(); } bool FSoftwareRenderer::UsesColormap() const @@ -178,7 +178,7 @@ void FSoftwareRenderer::RenderView(player_t *player) if (r_polyrenderer) PolyRenderer::Instance()->RenderView(player); else - RenderScene::Instance()->RenderView(player); + mMainThread.Scene->RenderView(player); FCanvasTextureInfo::UpdateAll(); } @@ -202,7 +202,7 @@ void FSoftwareRenderer::WriteSavePic (player_t *player, FileWriter *file, int wi if (r_polyrenderer) PolyRenderer::Instance()->RenderViewToCanvas(player->mo, pic, 0, 0, width, height, true); else - RenderScene::Instance()->RenderViewToCanvas (player->mo, pic, 0, 0, width, height); + mMainThread.Scene->RenderViewToCanvas (player->mo, pic, 0, 0, width, height); screen->GetFlashedPalette (palette); M_CreatePNG (file, pic->GetBuffer(), palette, SS_PAL, width, height, pic->GetPitch()); pic->Unlock (); @@ -215,7 +215,7 @@ void FSoftwareRenderer::DrawRemainingPlayerSprites() { if (!r_polyrenderer) { - RenderPlayerSprites::Instance()->RenderRemaining(); + mMainThread.PlayerSprites->RenderRemaining(); } else { @@ -237,12 +237,12 @@ bool FSoftwareRenderer::RequireGLNodes() void FSoftwareRenderer::OnModeSet () { - RenderScene::Instance()->ScreenResized(); + mMainThread.Scene->ScreenResized(); } void FSoftwareRenderer::SetClearColor(int color) { - RenderScene::Instance()->SetClearColor(color); + mMainThread.Scene->SetClearColor(color); } void FSoftwareRenderer::RenderTextureView (FCanvasTexture *tex, AActor *viewpoint, int fov) @@ -262,7 +262,7 @@ void FSoftwareRenderer::RenderTextureView (FCanvasTexture *tex, AActor *viewpoin if (r_polyrenderer) PolyRenderer::Instance()->RenderViewToCanvas(viewpoint, Canvas, 0, 0, tex->GetWidth(), tex->GetHeight(), tex->bFirstUpdate); else - RenderScene::Instance()->RenderViewToCanvas(viewpoint, Canvas, 0, 0, tex->GetWidth(), tex->GetHeight(), tex->bFirstUpdate); + mMainThread.Scene->RenderViewToCanvas(viewpoint, Canvas, 0, 0, tex->GetWidth(), tex->GetHeight(), tex->bFirstUpdate); R_SetFOV (savedfov); @@ -319,7 +319,7 @@ void FSoftwareRenderer::RenderTextureView (FCanvasTexture *tex, AActor *viewpoin sector_t *FSoftwareRenderer::FakeFlat(sector_t *sec, sector_t *tempsec, int *floorlightlevel, int *ceilinglightlevel) { - return RenderOpaquePass::Instance()->FakeFlat(sec, tempsec, floorlightlevel, ceilinglightlevel, nullptr, 0, 0, 0, 0); + return mMainThread.OpaquePass->FakeFlat(sec, tempsec, floorlightlevel, ceilinglightlevel, nullptr, 0, 0, 0, 0); } void FSoftwareRenderer::StateChanged(AActor *actor) diff --git a/src/swrenderer/r_swrenderer.h b/src/swrenderer/r_swrenderer.h index c4d81c1d0..9cdc0c9be 100644 --- a/src/swrenderer/r_swrenderer.h +++ b/src/swrenderer/r_swrenderer.h @@ -2,6 +2,7 @@ #pragma once #include "r_renderer.h" +#include "r_renderthread.h" struct FSoftwareRenderer : public FRenderer { @@ -41,4 +42,6 @@ struct FSoftwareRenderer : public FRenderer private: void PrecacheTexture(FTexture *tex, int cache); + + swrenderer::RenderThread mMainThread; }; diff --git a/src/swrenderer/scene/r_3dfloors.cpp b/src/swrenderer/scene/r_3dfloors.cpp index 3feb7b91c..69618f9f4 100644 --- a/src/swrenderer/scene/r_3dfloors.cpp +++ b/src/swrenderer/scene/r_3dfloors.cpp @@ -13,15 +13,15 @@ #include "c_cvars.h" #include "r_3dfloors.h" #include "r_utility.h" +#include "swrenderer/r_renderthread.h" CVAR(Int, r_3dfloors, true, 0); namespace swrenderer { - Clip3DFloors *Clip3DFloors::Instance() + Clip3DFloors::Clip3DFloors(RenderThread *thread) { - static Clip3DFloors clip; - return &clip; + Thread = thread; } void Clip3DFloors::Cleanup() @@ -102,8 +102,8 @@ namespace swrenderer curr = (ClipStack*)M_Malloc(sizeof(ClipStack)); curr->next = 0; - memcpy(curr->floorclip, RenderOpaquePass::Instance()->floorclip, sizeof(short) * MAXWIDTH); - memcpy(curr->ceilingclip, RenderOpaquePass::Instance()->ceilingclip, sizeof(short) * MAXWIDTH); + memcpy(curr->floorclip, Thread->OpaquePass->floorclip, sizeof(short) * MAXWIDTH); + memcpy(curr->ceilingclip, Thread->OpaquePass->ceilingclip, sizeof(short) * MAXWIDTH); curr->ffloor = fakeFloor; assert(fakeFloor->floorclip == nullptr); assert(fakeFloor->ceilingclip == nullptr); diff --git a/src/swrenderer/scene/r_3dfloors.h b/src/swrenderer/scene/r_3dfloors.h index ca8f9830b..f49d6c80a 100644 --- a/src/swrenderer/scene/r_3dfloors.h +++ b/src/swrenderer/scene/r_3dfloors.h @@ -7,6 +7,8 @@ EXTERN_CVAR(Int, r_3dfloors); namespace swrenderer { + class RenderThread; + struct HeightLevel { double height; @@ -52,7 +54,7 @@ namespace swrenderer class Clip3DFloors { public: - static Clip3DFloors *Instance(); + Clip3DFloors(RenderThread *thread); void Cleanup(); @@ -63,6 +65,8 @@ namespace swrenderer void EnterSkybox(); void LeaveSkybox(); + RenderThread *Thread = nullptr; + int fake3D = 0; F3DFloor *fakeFloor = nullptr; diff --git a/src/swrenderer/scene/r_opaque_pass.cpp b/src/swrenderer/scene/r_opaque_pass.cpp index 58e804519..f2aca7a49 100644 --- a/src/swrenderer/scene/r_opaque_pass.cpp +++ b/src/swrenderer/scene/r_opaque_pass.cpp @@ -44,6 +44,7 @@ #include "swrenderer/scene/r_scene.h" #include "swrenderer/scene/r_light.h" #include "swrenderer/viewport/r_viewport.h" +#include "swrenderer/r_renderthread.h" #include "r_3dfloors.h" #include "r_portal.h" #include "a_sharedglobal.h" @@ -67,10 +68,9 @@ EXTERN_CVAR(Bool, r_drawvoxels); namespace swrenderer { - RenderOpaquePass *RenderOpaquePass::Instance() + RenderOpaquePass::RenderOpaquePass(RenderThread *thread) : renderline(thread) { - static RenderOpaquePass instance; - return &instance; + Thread = thread; } sector_t *RenderOpaquePass::FakeFlat(sector_t *sec, sector_t *tempsec, int *floorlightlevel, int *ceilinglightlevel, seg_t *backline, int backx1, int backx2, double frontcz1, double frontcz2) @@ -341,7 +341,7 @@ namespace swrenderer ry1 = x1 * ViewTanCos + y1 * ViewTanSin; ry2 = x2 * ViewTanCos + y2 * ViewTanSin; - if (RenderPortal::Instance()->MirrorFlags & RF_XFLIP) + if (Thread->Portal->MirrorFlags & RF_XFLIP) { double t = -rx1; rx1 = -rx2; @@ -380,7 +380,7 @@ namespace swrenderer // Find the first clippost that touches the source post // (adjacent pixels are touching). - return RenderClipSegment::Instance()->IsVisible(sx1, sx2); + return Thread->ClipSegments->IsVisible(sx1, sx2); } void RenderOpaquePass::AddPolyobjs(subsector_t *sub) @@ -507,7 +507,7 @@ namespace swrenderer (frontsector->heightsec && !(frontsector->heightsec->MoreFlags & SECF_IGNOREHEIGHTSEC) && frontsector->heightsec->GetTexture(sector_t::floor) == skyflatnum) ? - VisiblePlaneList::Instance()->FindPlane(frontsector->ceilingplane, // killough 3/8/98 + Thread->PlaneList->FindPlane(frontsector->ceilingplane, // killough 3/8/98 frontsector->GetTexture(sector_t::ceiling), ceilinglightlevel + R_ActualExtraLight(foggy), // killough 4/11/98 frontsector->GetAlpha(sector_t::ceiling), @@ -548,7 +548,7 @@ namespace swrenderer (frontsector->heightsec && !(frontsector->heightsec->MoreFlags & SECF_IGNOREHEIGHTSEC) && frontsector->heightsec->GetTexture(sector_t::ceiling) == skyflatnum) ? - VisiblePlaneList::Instance()->FindPlane(frontsector->floorplane, + Thread->PlaneList->FindPlane(frontsector->floorplane, frontsector->GetTexture(sector_t::floor), floorlightlevel + R_ActualExtraLight(foggy), // killough 3/16/98 frontsector->GetAlpha(sector_t::floor), @@ -568,7 +568,7 @@ namespace swrenderer backupfp = floorplane; backupcp = ceilingplane; - Clip3DFloors *clip3d = Clip3DFloors::Instance(); + Clip3DFloors *clip3d = Thread->Clip3DFloors.get(); // first check all floors for (int i = 0; i < (int)frontsector->e->XFloor.ffloors.Size(); i++) @@ -614,7 +614,7 @@ namespace swrenderer } ceilingplane = nullptr; - floorplane = VisiblePlaneList::Instance()->FindPlane(frontsector->floorplane, + floorplane = Thread->PlaneList->FindPlane(frontsector->floorplane, frontsector->GetTexture(sector_t::floor), floorlightlevel + R_ActualExtraLight(foggy), // killough 3/16/98 frontsector->GetAlpha(sector_t::floor), @@ -680,7 +680,7 @@ namespace swrenderer tempsec.ceilingplane.ChangeHeight(1 / 65536.); floorplane = nullptr; - ceilingplane = VisiblePlaneList::Instance()->FindPlane(frontsector->ceilingplane, // killough 3/8/98 + ceilingplane = Thread->PlaneList->FindPlane(frontsector->ceilingplane, // killough 3/8/98 frontsector->GetTexture(sector_t::ceiling), ceilinglightlevel + R_ActualExtraLight(foggy), // killough 4/11/98 frontsector->GetAlpha(sector_t::ceiling), @@ -720,7 +720,7 @@ namespace swrenderer int shade = LIGHT2SHADE((floorlightlevel + ceilinglightlevel) / 2 + R_ActualExtraLight(foggy)); for (WORD i = ParticlesInSubsec[(unsigned int)(sub - subsectors)]; i != NO_PARTICLE; i = Particles[i].snext) { - RenderParticle::Project(Particles + i, subsectors[sub - subsectors].sector, shade, FakeSide, foggy); + RenderParticle::Project(Thread, Particles + i, subsectors[sub - subsectors].sector, shade, FakeSide, foggy); } } @@ -738,7 +738,7 @@ namespace swrenderer backupcp = ceilingplane; floorplane = nullptr; ceilingplane = nullptr; - Clip3DFloors *clip3d = Clip3DFloors::Instance(); + Clip3DFloors *clip3d = Thread->Clip3DFloors.get(); for (unsigned int i = 0; i < line->backsector->e->XFloor.ffloors.Size(); i++) { clip3d->fakeFloor = line->backsector->e->XFloor.ffloors[i]; @@ -886,15 +886,15 @@ namespace swrenderer if ((sprite.renderflags & RF_SPRITETYPEMASK) == RF_WALLSPRITE) { - RenderWallSprite::Project(thing, sprite.pos, sprite.picnum, sprite.spriteScale, sprite.renderflags, thingShade, foggy, thingColormap); + RenderWallSprite::Project(Thread, thing, sprite.pos, sprite.picnum, sprite.spriteScale, sprite.renderflags, thingShade, foggy, thingColormap); } else if (sprite.voxel) { - RenderVoxel::Project(thing, sprite.pos, sprite.voxel, sprite.spriteScale, sprite.renderflags, fakeside, fakefloor, fakeceiling, sec, thingShade, foggy, thingColormap); + RenderVoxel::Project(Thread, thing, sprite.pos, sprite.voxel, sprite.spriteScale, sprite.renderflags, fakeside, fakefloor, fakeceiling, sec, thingShade, foggy, thingColormap); } else { - RenderSprite::Project(thing, sprite.pos, sprite.tex, sprite.spriteScale, sprite.renderflags, fakeside, fakefloor, fakeceiling, sec, thingShade, foggy, thingColormap); + RenderSprite::Project(Thread, thing, sprite.pos, sprite.tex, sprite.spriteScale, sprite.renderflags, fakeside, fakefloor, fakeceiling, sec, thingShade, foggy, thingColormap); } } } @@ -915,7 +915,7 @@ namespace swrenderer // [ZZ] Or less definitely not visible (hue) // [ZZ] 10.01.2016: don't try to clip stuff inside a skybox against the current portal. - RenderPortal *renderportal = RenderPortal::Instance(); + RenderPortal *renderportal = Thread->Portal.get(); if (!renderportal->CurrentPortalInSkybox && renderportal->CurrentPortal && !!P_PointOnLineSidePrecise(thing->Pos(), renderportal->CurrentPortal->dst)) return false; diff --git a/src/swrenderer/scene/r_opaque_pass.h b/src/swrenderer/scene/r_opaque_pass.h index a009cc772..fcb6a5859 100644 --- a/src/swrenderer/scene/r_opaque_pass.h +++ b/src/swrenderer/scene/r_opaque_pass.h @@ -23,6 +23,7 @@ struct FVoxelDef; namespace swrenderer { + class RenderThread; struct VisiblePlane; // The 3072 below is just an arbitrary value picked to avoid @@ -51,7 +52,7 @@ namespace swrenderer class RenderOpaquePass { public: - static RenderOpaquePass *Instance(); + RenderOpaquePass(RenderThread *thread); void ClearClip(); void RenderScene(); @@ -62,6 +63,8 @@ namespace swrenderer short floorclip[MAXWIDTH]; short ceilingclip[MAXWIDTH]; + RenderThread *Thread = nullptr; + private: void RenderBSPNode(void *node); void RenderSubsector(subsector_t *sub); @@ -72,7 +75,7 @@ namespace swrenderer void AddSprites(sector_t *sec, int lightlevel, WaterFakeSide fakeside, bool foggy, FDynamicColormap *basecolormap); - static bool IsPotentiallyVisible(AActor *thing); + bool IsPotentiallyVisible(AActor *thing); static bool GetThingSprite(AActor *thing, ThingSprite &sprite); subsector_t *InSubsector = nullptr; diff --git a/src/swrenderer/scene/r_portal.cpp b/src/swrenderer/scene/r_portal.cpp index d6c802255..38a9ffc1b 100644 --- a/src/swrenderer/scene/r_portal.cpp +++ b/src/swrenderer/scene/r_portal.cpp @@ -57,6 +57,7 @@ #include "swrenderer/scene/r_light.h" #include "swrenderer/viewport/r_viewport.h" #include "swrenderer/r_memory.h" +#include "swrenderer/r_renderthread.h" CVAR(Int, r_portal_recursions, 4, CVAR_ARCHIVE) CVAR(Bool, r_highlight_portals, false, CVAR_ARCHIVE) @@ -67,10 +68,9 @@ CVAR(Bool, r_skyboxes, true, 0) namespace swrenderer { - RenderPortal *RenderPortal::Instance() + RenderPortal::RenderPortal(RenderThread *thread) { - static RenderPortal renderportal; - return &renderportal; + Thread = thread; } // Draws any recorded sky boxes and then frees them. @@ -92,13 +92,13 @@ namespace swrenderer { numskyboxes = 0; - VisiblePlaneList *planes = VisiblePlaneList::Instance(); - DrawSegmentList *drawseglist = DrawSegmentList::Instance(); + VisiblePlaneList *planes = Thread->PlaneList.get(); + DrawSegmentList *drawseglist = Thread->DrawSegments.get(); if (!planes->HasPortalPlanes()) return; - Clip3DFloors::Instance()->EnterSkybox(); + Thread->Clip3DFloors->EnterSkybox(); CurrentPortalInSkybox = true; int savedextralight = extralight; @@ -112,7 +112,7 @@ namespace swrenderer { if (pl->right < pl->left || !r_skyboxes || numskyboxes == MAX_SKYBOX_PLANES || pl->portal == nullptr) { - pl->Render(OPAQUE, false, false); + pl->Render(Thread, OPAQUE, false, false); continue; } @@ -151,7 +151,7 @@ namespace swrenderer // not implemented yet default: - pl->Render(OPAQUE, false, false); + pl->Render(Thread, OPAQUE, false, false); numskyboxes--; continue; } @@ -165,12 +165,12 @@ namespace swrenderer validcount++; // Make sure we see all sprites planes->ClearKeepFakePlanes(); - RenderClipSegment::Instance()->Clear(pl->left, pl->right); + Thread->ClipSegments->Clear(pl->left, pl->right); WindowLeft = pl->left; WindowRight = pl->right; - auto ceilingclip = RenderOpaquePass::Instance()->ceilingclip; - auto floorclip = RenderOpaquePass::Instance()->floorclip; + auto ceilingclip = Thread->OpaquePass->ceilingclip; + auto floorclip = Thread->OpaquePass->floorclip; for (int i = pl->left; i < pl->right; i++) { if (pl->top[i] == 0x7fff) @@ -208,12 +208,12 @@ namespace swrenderer drawseglist->Push(draw_segment); drawseglist->PushPortal(); - VisibleSpriteList::Instance()->PushPortal(); + Thread->SpriteList->PushPortal(); viewposStack.Push(ViewPos); visplaneStack.Push(pl); - RenderOpaquePass::Instance()->RenderScene(); - Clip3DFloors::Instance()->ResetClip(); // reset clips (floor/ceiling) + Thread->OpaquePass->RenderScene(); + Thread->Clip3DFloors->ResetClip(); // reset clips (floor/ceiling) planes->Render(); port->mFlags &= ~PORTSF_INSKYBOX; @@ -228,16 +228,16 @@ namespace swrenderer // Masked textures and planes need the view coordinates restored for proper positioning. viewposStack.Pop(ViewPos); - RenderTranslucentPass::Instance()->Render(); + Thread->TranslucentPass->Render(); VisiblePlane *pl; visplaneStack.Pop(pl); if (pl->Alpha > 0 && pl->picnum != skyflatnum) { - pl->Render(pl->Alpha, pl->Additive, true); + pl->Render(Thread, pl->Alpha, pl->Additive, true); } - VisibleSpriteList::Instance()->PopPortal(); + Thread->SpriteList->PopPortal(); drawseglist->PopPortal(); } @@ -250,9 +250,9 @@ namespace swrenderer R_SetViewAngle(); CurrentPortalInSkybox = false; - Clip3DFloors::Instance()->LeaveSkybox(); + Thread->Clip3DFloors->LeaveSkybox(); - if (Clip3DFloors::Instance()->fakeActive) return; + if (Thread->Clip3DFloors->fakeActive) return; planes->ClearPortalPlanes(); } @@ -395,8 +395,8 @@ namespace swrenderer PortalDrawseg* prevpds = CurrentPortal; CurrentPortal = pds; - VisiblePlaneList::Instance()->ClearKeepFakePlanes(); - RenderClipSegment::Instance()->Clear(pds->x1, pds->x2); + Thread->PlaneList->ClearKeepFakePlanes(); + Thread->ClipSegments->Clear(pds->x1, pds->x2); WindowLeft = pds->x1; WindowRight = pds->x2; @@ -411,21 +411,21 @@ namespace swrenderer } // some portals have height differences, account for this here - Clip3DFloors::Instance()->EnterSkybox(); // push 3D floor height map + Thread->Clip3DFloors->EnterSkybox(); // push 3D floor height map CurrentPortalInSkybox = false; // first portal in a skybox should set this variable to false for proper clipping in skyboxes. // first pass, set clipping - auto ceilingclip = RenderOpaquePass::Instance()->ceilingclip; - auto floorclip = RenderOpaquePass::Instance()->floorclip; + auto ceilingclip = Thread->OpaquePass->ceilingclip; + auto floorclip = Thread->OpaquePass->floorclip; memcpy(ceilingclip + pds->x1, &pds->ceilingclip[0], pds->len * sizeof(*ceilingclip)); memcpy(floorclip + pds->x1, &pds->floorclip[0], pds->len * sizeof(*floorclip)); - RenderOpaquePass::Instance()->RenderScene(); - Clip3DFloors::Instance()->ResetClip(); // reset clips (floor/ceiling) + Thread->OpaquePass->RenderScene(); + Thread->Clip3DFloors->ResetClip(); // reset clips (floor/ceiling) if (!savedvisibility && camera) camera->renderflags &= ~RF_INVISIBLE; PlaneCycles.Clock(); - VisiblePlaneList::Instance()->Render(); + Thread->PlaneList->Render(); RenderPlanePortals(); PlaneCycles.Unclock(); @@ -444,12 +444,12 @@ namespace swrenderer NetUpdate(); MaskedCycles.Clock(); // [ZZ] count sprites in portals/mirrors along with normal ones. - RenderTranslucentPass::Instance()->Render(); // this is required since with portals there often will be cases when more than 80% of the view is inside a portal. + Thread->TranslucentPass->Render(); // this is required since with portals there often will be cases when more than 80% of the view is inside a portal. MaskedCycles.Unclock(); NetUpdate(); - Clip3DFloors::Instance()->LeaveSkybox(); // pop 3D floor height map + Thread->Clip3DFloors->LeaveSkybox(); // pop 3D floor height map CurrentPortalUniq = prevuniq2; // draw a red line around a portal if it's being highlighted @@ -529,10 +529,11 @@ namespace swrenderer WallPortals.Push(RenderMemory::NewObject(linedef, x1, x2, topclip, bottomclip)); } } - +/* ADD_STAT(skyboxes) { FString out; out.Format("%d skybox planes", swrenderer::RenderPortal::Instance()->numskyboxes); return out; } +*/ diff --git a/src/swrenderer/scene/r_portal.h b/src/swrenderer/scene/r_portal.h index f3e1b9bbe..0d65bfa74 100644 --- a/src/swrenderer/scene/r_portal.h +++ b/src/swrenderer/scene/r_portal.h @@ -17,12 +17,13 @@ namespace swrenderer { + class RenderThread; struct VisiblePlane; class RenderPortal { public: - static RenderPortal *Instance(); + RenderPortal(RenderThread *thread); void SetMainPortal(); void CopyStackedViewParameters(); @@ -31,6 +32,8 @@ namespace swrenderer void RenderLinePortals(); void AddLinePortal(line_t *linedef, int x1, int x2, const short *topclip, const short *bottomclip); + + RenderThread *Thread = nullptr; int WindowLeft = 0; int WindowRight = 0; diff --git a/src/swrenderer/scene/r_scene.cpp b/src/swrenderer/scene/r_scene.cpp index fae0762c6..7e8d20f78 100644 --- a/src/swrenderer/scene/r_scene.cpp +++ b/src/swrenderer/scene/r_scene.cpp @@ -47,6 +47,7 @@ #include "swrenderer/drawers/r_draw_rgba.h" #include "swrenderer/drawers/r_thread.h" #include "swrenderer/r_memory.h" +#include "swrenderer/r_renderthread.h" EXTERN_CVAR(Bool, r_shadercolormaps) EXTERN_CVAR(Int, r_clearbuffer) @@ -55,10 +56,9 @@ namespace swrenderer { cycle_t WallCycles, PlaneCycles, MaskedCycles, WallScanCycles; - RenderScene *RenderScene::Instance() + RenderScene::RenderScene(RenderThread *thread) { - static RenderScene instance; - return &instance; + Thread = thread; } void RenderScene::SetClearColor(int color) @@ -115,7 +115,7 @@ namespace swrenderer RenderMemory::Clear(); - Clip3DFloors *clip3d = Clip3DFloors::Instance(); + Clip3DFloors *clip3d = Thread->Clip3DFloors.get(); clip3d->Cleanup(); clip3d->ResetClip(); // reset clips (floor/ceiling) @@ -123,25 +123,25 @@ namespace swrenderer CameraLight::Instance()->SetCamera(actor); RenderViewport::Instance()->SetupFreelook(); - RenderPortal::Instance()->CopyStackedViewParameters(); + Thread->Portal->CopyStackedViewParameters(); // Clear buffers. - RenderClipSegment::Instance()->Clear(0, viewwidth); - DrawSegmentList::Instance()->Clear(); - VisiblePlaneList::Instance()->Clear(); - RenderTranslucentPass::Instance()->Clear(); + Thread->ClipSegments->Clear(0, viewwidth); + Thread->DrawSegments->Clear(); + Thread->PlaneList->Clear(); + Thread->TranslucentPass->Clear(); // opening / clipping determination - RenderOpaquePass::Instance()->ClearClip(); + Thread->OpaquePass->ClearClip(); NetUpdate(); - RenderPortal::Instance()->SetMainPortal(); + Thread->Portal->SetMainPortal(); this->dontmaplines = dontmaplines; // [RH] Hack to make windows into underwater areas possible - RenderOpaquePass::Instance()->ResetFakingUnderwater(); + Thread->OpaquePass->ResetFakingUnderwater(); // [RH] Setup particles for this frame P_FindParticleSubsectors(); @@ -155,8 +155,8 @@ namespace swrenderer } // Link the polyobjects right before drawing the scene to reduce the amounts of calls to this function PO_LinkToSubsectors(); - RenderOpaquePass::Instance()->RenderScene(); - Clip3DFloors::Instance()->ResetClip(); // reset clips (floor/ceiling) + Thread->OpaquePass->RenderScene(); + Thread->Clip3DFloors->ResetClip(); // reset clips (floor/ceiling) camera->renderflags = savedflags; WallCycles.Unclock(); @@ -165,16 +165,16 @@ namespace swrenderer if (viewactive) { PlaneCycles.Clock(); - VisiblePlaneList::Instance()->Render(); - RenderPortal::Instance()->RenderPlanePortals(); + Thread->PlaneList->Render(); + Thread->Portal->RenderPlanePortals(); PlaneCycles.Unclock(); - RenderPortal::Instance()->RenderLinePortals(); + Thread->Portal->RenderLinePortals(); NetUpdate(); MaskedCycles.Clock(); - RenderTranslucentPass::Instance()->Render(); + Thread->TranslucentPass->Render(); MaskedCycles.Unclock(); NetUpdate(); @@ -237,7 +237,6 @@ namespace swrenderer void RenderScene::Init() { - atterm([]() { RenderScene::Instance()->Deinit(); }); // viewwidth / viewheight are set by the defaults fillshort(zeroarray, MAXWIDTH, 0); @@ -246,8 +245,8 @@ namespace swrenderer void RenderScene::Deinit() { - RenderTranslucentPass::Instance()->Deinit(); - Clip3DFloors::Instance()->Cleanup(); + Thread->TranslucentPass->Deinit(); + Thread->Clip3DFloors->Cleanup(); } ///////////////////////////////////////////////////////////////////////// diff --git a/src/swrenderer/scene/r_scene.h b/src/swrenderer/scene/r_scene.h index 599ef55fb..231fd7a4a 100644 --- a/src/swrenderer/scene/r_scene.h +++ b/src/swrenderer/scene/r_scene.h @@ -22,11 +22,13 @@ extern cycle_t FrameCycles; namespace swrenderer { extern cycle_t WallCycles, PlaneCycles, MaskedCycles, WallScanCycles; + + class RenderThread; class RenderScene { public: - static RenderScene *Instance(); + RenderScene(RenderThread *thread); void Init(); void ScreenResized(); @@ -39,6 +41,8 @@ namespace swrenderer bool DontMapLines() const { return dontmaplines; } + RenderThread *Thread = nullptr; + private: void RenderActorView(AActor *actor, bool dontmaplines = false); diff --git a/src/swrenderer/scene/r_translucent_pass.cpp b/src/swrenderer/scene/r_translucent_pass.cpp index dcf99f3f7..d102d6c18 100644 --- a/src/swrenderer/scene/r_translucent_pass.cpp +++ b/src/swrenderer/scene/r_translucent_pass.cpp @@ -38,6 +38,7 @@ #include "swrenderer/line/r_renderdrawsegment.h" #include "swrenderer/viewport/r_viewport.h" #include "swrenderer/r_memory.h" +#include "swrenderer/r_renderthread.h" EXTERN_CVAR(Int, r_drawfuzz) EXTERN_CVAR(Bool, r_drawvoxels) @@ -47,10 +48,9 @@ CVAR(Bool, r_fullbrightignoresectorcolor, true, CVAR_ARCHIVE | CVAR_GLOBALCONFIG namespace swrenderer { - RenderTranslucentPass *RenderTranslucentPass::Instance() + RenderTranslucentPass::RenderTranslucentPass(RenderThread *thread) { - static RenderTranslucentPass instance; - return &instance; + Thread = thread; } void RenderTranslucentPass::Deinit() @@ -60,7 +60,7 @@ namespace swrenderer void RenderTranslucentPass::Clear() { - VisibleSpriteList::Instance()->Clear(); + Thread->SpriteList->Clear(); } void RenderTranslucentPass::CollectPortals() @@ -71,7 +71,7 @@ namespace swrenderer // a) exit early if no relevant info is found and // b) skip most of the collected drawsegs which have no portal attached. portaldrawsegs.Clear(); - DrawSegmentList *drawseglist = DrawSegmentList::Instance(); + DrawSegmentList *drawseglist = Thread->DrawSegments.get(); for (auto index = drawseglist->BeginIndex(); index != drawseglist->EndIndex(); index++) { DrawSegment *seg = drawseglist->Segment(index); @@ -98,7 +98,7 @@ namespace swrenderer bool RenderTranslucentPass::ClipSpriteColumnWithPortals(int x, VisibleSprite *spr) { - RenderPortal *renderportal = RenderPortal::Instance(); + RenderPortal *renderportal = Thread->Portal.get(); // [ZZ] 10.01.2016: don't clip sprites from the root of a skybox. if (renderportal->CurrentPortalInSkybox) @@ -126,14 +126,14 @@ namespace swrenderer void RenderTranslucentPass::DrawMaskedSingle(bool renew) { - RenderPortal *renderportal = RenderPortal::Instance(); + RenderPortal *renderportal = Thread->Portal.get(); - auto &sortedSprites = VisibleSpriteList::Instance()->SortedSprites; + auto &sortedSprites = Thread->SpriteList->SortedSprites; for (int i = sortedSprites.Size(); i > 0; i--) { if (sortedSprites[i - 1]->IsCurrentPortalUniq(renderportal->CurrentPortalUniq)) { - sortedSprites[i - 1]->Render(); + sortedSprites[i - 1]->Render(Thread); } } @@ -141,10 +141,10 @@ namespace swrenderer if (renew) { - Clip3DFloors::Instance()->fake3D |= FAKE3D_REFRESHCLIP; + Thread->Clip3DFloors->fake3D |= FAKE3D_REFRESHCLIP; } - DrawSegmentList *drawseglist = DrawSegmentList::Instance(); + DrawSegmentList *drawseglist = Thread->DrawSegments.get(); for (auto index = drawseglist->BeginIndex(); index != drawseglist->EndIndex(); index++) { DrawSegment *ds = drawseglist->Segment(index); @@ -156,7 +156,7 @@ namespace swrenderer if (ds->fake) continue; if (ds->maskedtexturecol != nullptr || ds->bFogBoundary) { - RenderDrawSegment renderer; + RenderDrawSegment renderer(Thread); renderer.Render(ds, ds->x1, ds->x2); } } @@ -165,9 +165,9 @@ namespace swrenderer void RenderTranslucentPass::Render() { CollectPortals(); - VisibleSpriteList::Instance()->Sort(); + Thread->SpriteList->Sort(); - Clip3DFloors *clip3d = Clip3DFloors::Instance(); + Clip3DFloors *clip3d = Thread->Clip3DFloors.get(); if (clip3d->height_top == nullptr) { // kg3D - no visible 3D floors, normal rendering DrawMaskedSingle(false); @@ -188,7 +188,7 @@ namespace swrenderer } clip3d->sclipBottom = hl->height; DrawMaskedSingle(true); - VisiblePlaneList::Instance()->RenderHeight(hl->height); + Thread->PlaneList->RenderHeight(hl->height); } // floors @@ -197,7 +197,7 @@ namespace swrenderer DrawMaskedSingle(true); for (HeightLevel *hl = clip3d->height_top; hl != nullptr && hl->height < ViewPos.Z; hl = hl->next) { - VisiblePlaneList::Instance()->RenderHeight(hl->height); + Thread->PlaneList->RenderHeight(hl->height); if (hl->next) { clip3d->fake3D = FAKE3D_DOWN2UP | FAKE3D_CLIPTOP | FAKE3D_CLIPBOTTOM; @@ -214,6 +214,6 @@ namespace swrenderer clip3d->fake3D = 0; } - RenderPlayerSprites::Instance()->Render(); + Thread->PlayerSprites->Render(); } } diff --git a/src/swrenderer/scene/r_translucent_pass.h b/src/swrenderer/scene/r_translucent_pass.h index 64695e0db..44551b286 100644 --- a/src/swrenderer/scene/r_translucent_pass.h +++ b/src/swrenderer/scene/r_translucent_pass.h @@ -22,13 +22,14 @@ struct FVoxel; namespace swrenderer { + class RenderThread; class VisibleSprite; struct DrawSegment; class RenderTranslucentPass { public: - static RenderTranslucentPass *Instance(); + RenderTranslucentPass(RenderThread *thread); void Deinit(); void Clear(); @@ -36,6 +37,8 @@ namespace swrenderer bool ClipSpriteColumnWithPortals(int x, VisibleSprite *spr); + RenderThread *Thread = nullptr; + private: void CollectPortals(); void DrawMaskedSingle(bool renew); diff --git a/src/swrenderer/segments/r_clipsegment.cpp b/src/swrenderer/segments/r_clipsegment.cpp index 517d2ee07..6cfaaa2a0 100644 --- a/src/swrenderer/segments/r_clipsegment.cpp +++ b/src/swrenderer/segments/r_clipsegment.cpp @@ -34,12 +34,6 @@ namespace swrenderer { - RenderClipSegment *RenderClipSegment::Instance() - { - static RenderClipSegment instance; - return &instance; - } - void RenderClipSegment::Clear(short left, short right) { solidsegs[0].first = -0x7fff; diff --git a/src/swrenderer/segments/r_clipsegment.h b/src/swrenderer/segments/r_clipsegment.h index 33ec0525d..b2fde462e 100644 --- a/src/swrenderer/segments/r_clipsegment.h +++ b/src/swrenderer/segments/r_clipsegment.h @@ -20,8 +20,6 @@ namespace swrenderer class RenderClipSegment { public: - static RenderClipSegment *Instance(); - void Clear(short left, short right); bool Clip(int x1, int x2, bool solid, VisibleSegmentCallback callback); bool Check(int first, int last); diff --git a/src/swrenderer/segments/r_drawsegment.cpp b/src/swrenderer/segments/r_drawsegment.cpp index c4a03ac00..f84d48a7a 100644 --- a/src/swrenderer/segments/r_drawsegment.cpp +++ b/src/swrenderer/segments/r_drawsegment.cpp @@ -43,10 +43,9 @@ namespace swrenderer { - DrawSegmentList *DrawSegmentList::Instance() + DrawSegmentList::DrawSegmentList(RenderThread *thread) { - static DrawSegmentList instance; - return &instance; + Thread = thread; } void DrawSegmentList::Clear() diff --git a/src/swrenderer/segments/r_drawsegment.h b/src/swrenderer/segments/r_drawsegment.h index e0710619a..2fa41cd94 100644 --- a/src/swrenderer/segments/r_drawsegment.h +++ b/src/swrenderer/segments/r_drawsegment.h @@ -50,7 +50,7 @@ namespace swrenderer class DrawSegmentList { public: - static DrawSegmentList *Instance(); + DrawSegmentList(RenderThread *thread); unsigned int BeginIndex() const { return StartIndices.Last(); } unsigned int EndIndex() const { return Segments.Size(); } @@ -66,6 +66,8 @@ namespace swrenderer void Push(DrawSegment *segment); void PushInteresting(DrawSegment *segment); + RenderThread *Thread = nullptr; + private: TArray Segments; TArray StartIndices; diff --git a/src/swrenderer/things/r_decal.cpp b/src/swrenderer/things/r_decal.cpp index 098de1dc2..6e3fdb761 100644 --- a/src/swrenderer/things/r_decal.cpp +++ b/src/swrenderer/things/r_decal.cpp @@ -43,16 +43,17 @@ #include "swrenderer/viewport/r_viewport.h" #include "swrenderer/viewport/r_spritedrawer.h" #include "swrenderer/r_memory.h" +#include "swrenderer/r_renderthread.h" EXTERN_CVAR(Bool, r_fullbrightignoresectorcolor); namespace swrenderer { - void RenderDecal::RenderDecals(side_t *sidedef, DrawSegment *draw_segment, int wallshade, float lightleft, float lightstep, seg_t *curline, const FWallCoords &wallC, bool foggy, FDynamicColormap *basecolormap, const short *walltop, const short *wallbottom) + void RenderDecal::RenderDecals(RenderThread *thread, side_t *sidedef, DrawSegment *draw_segment, int wallshade, float lightleft, float lightstep, seg_t *curline, const FWallCoords &wallC, bool foggy, FDynamicColormap *basecolormap, const short *walltop, const short *wallbottom) { for (DBaseDecal *decal = sidedef->AttachedDecals; decal != NULL; decal = decal->WallNext) { - Render(sidedef, decal, draw_segment, wallshade, lightleft, lightstep, curline, wallC, foggy, basecolormap, walltop, wallbottom, 0); + Render(thread, sidedef, decal, draw_segment, wallshade, lightleft, lightstep, curline, wallC, foggy, basecolormap, walltop, wallbottom, 0); } } @@ -60,7 +61,7 @@ namespace swrenderer // = 1: drawing masked textures (including sprites) // Currently, only pass = 0 is done or used - void RenderDecal::Render(side_t *wall, DBaseDecal *decal, DrawSegment *clipper, int wallshade, float lightleft, float lightstep, seg_t *curline, const FWallCoords &savecoord, bool foggy, FDynamicColormap *basecolormap, const short *walltop, const short *wallbottom, int pass) + void RenderDecal::Render(RenderThread *thread, side_t *wall, DBaseDecal *decal, DrawSegment *clipper, int wallshade, float lightleft, float lightstep, seg_t *curline, const FWallCoords &savecoord, bool foggy, FDynamicColormap *basecolormap, const short *walltop, const short *wallbottom, int pass) { DVector2 decal_left, decal_right, decal_pos; int x1, x2; @@ -150,7 +151,7 @@ namespace swrenderer double texturemid; FWallCoords WallC; - if (WallC.Init(decal_left, decal_right, TOO_CLOSE_Z)) + if (WallC.Init(thread, decal_left, decal_right, TOO_CLOSE_Z)) return; x1 = WallC.sx1; @@ -160,7 +161,7 @@ namespace swrenderer return; FWallTmapVals WallT; - WallT.InitFromWallCoords(&WallC); + WallT.InitFromWallCoords(thread, &WallC); // Get the top and bottom clipping arrays switch (decal->RenderFlags & RF_CLIPMASK) @@ -178,7 +179,7 @@ namespace swrenderer else if (pass == 0) { mceilingclip = walltop; - mfloorclip = RenderOpaquePass::Instance()->ceilingclip; + mfloorclip = thread->OpaquePass->ceilingclip; needrepeat = 1; } else @@ -194,7 +195,7 @@ namespace swrenderer return; } mceilingclip = walltop; - mfloorclip = RenderOpaquePass::Instance()->ceilingclip; + mfloorclip = thread->OpaquePass->ceilingclip; break; case RF_CLIPMID: @@ -211,7 +212,7 @@ namespace swrenderer { return; } - mceilingclip = RenderOpaquePass::Instance()->floorclip; + mceilingclip = thread->OpaquePass->floorclip; mfloorclip = wallbottom; break; } @@ -302,7 +303,7 @@ namespace swrenderer { // calculate lighting drawerargs.SetLight(usecolormap, light, wallshade); } - DrawColumn(drawerargs, x, WallSpriteTile, walltexcoords, texturemid, maskedScaleY, sprflipvert, mfloorclip, mceilingclip); + DrawColumn(thread, drawerargs, x, WallSpriteTile, walltexcoords, texturemid, maskedScaleY, sprflipvert, mfloorclip, mceilingclip); light += lightstep; x++; } @@ -311,12 +312,12 @@ namespace swrenderer // If this sprite is RF_CLIPFULL on a two-sided line, needrepeat will // be set 1 if we need to draw on the lower wall. In all other cases, // needrepeat will be 0, and the while will fail. - mceilingclip = RenderOpaquePass::Instance()->floorclip; + mceilingclip = thread->OpaquePass->floorclip; mfloorclip = wallbottom; } while (needrepeat--); } - void RenderDecal::DrawColumn(SpriteDrawerArgs &drawerargs, int x, FTexture *WallSpriteTile, const ProjectedWallTexcoords &walltexcoords, double texturemid, float maskedScaleY, bool sprflipvert, const short *mfloorclip, const short *mceilingclip) + void RenderDecal::DrawColumn(RenderThread *thread, SpriteDrawerArgs &drawerargs, int x, FTexture *WallSpriteTile, const ProjectedWallTexcoords &walltexcoords, double texturemid, float maskedScaleY, bool sprflipvert, const short *mfloorclip, const short *mceilingclip) { auto viewport = RenderViewport::Instance(); diff --git a/src/swrenderer/things/r_decal.h b/src/swrenderer/things/r_decal.h index 4d14a85c9..4694014b7 100644 --- a/src/swrenderer/things/r_decal.h +++ b/src/swrenderer/things/r_decal.h @@ -25,10 +25,10 @@ namespace swrenderer class RenderDecal { public: - static void RenderDecals(side_t *wall, DrawSegment *draw_segment, int wallshade, float lightleft, float lightstep, seg_t *curline, const FWallCoords &wallC, bool foggy, FDynamicColormap *basecolormap, const short *walltop, const short *wallbottom); + static void RenderDecals(RenderThread *thread, side_t *wall, DrawSegment *draw_segment, int wallshade, float lightleft, float lightstep, seg_t *curline, const FWallCoords &wallC, bool foggy, FDynamicColormap *basecolormap, const short *walltop, const short *wallbottom); private: - static void Render(side_t *wall, DBaseDecal *first, DrawSegment *clipper, int wallshade, float lightleft, float lightstep, seg_t *curline, const FWallCoords &wallC, bool foggy, FDynamicColormap *basecolormap, const short *walltop, const short *wallbottom, int pass); - static void DrawColumn(SpriteDrawerArgs &drawerargs, int x, FTexture *WallSpriteTile, const ProjectedWallTexcoords &walltexcoords, double texturemid, float maskedScaleY, bool sprflipvert, const short *mfloorclip, const short *mceilingclip); + static void Render(RenderThread *thread, side_t *wall, DBaseDecal *first, DrawSegment *clipper, int wallshade, float lightleft, float lightstep, seg_t *curline, const FWallCoords &wallC, bool foggy, FDynamicColormap *basecolormap, const short *walltop, const short *wallbottom, int pass); + static void DrawColumn(RenderThread *thread, SpriteDrawerArgs &drawerargs, int x, FTexture *WallSpriteTile, const ProjectedWallTexcoords &walltexcoords, double texturemid, float maskedScaleY, bool sprflipvert, const short *mfloorclip, const short *mceilingclip); }; } diff --git a/src/swrenderer/things/r_particle.cpp b/src/swrenderer/things/r_particle.cpp index 2b2eae50e..7d2672368 100644 --- a/src/swrenderer/things/r_particle.cpp +++ b/src/swrenderer/things/r_particle.cpp @@ -55,12 +55,13 @@ #include "swrenderer/drawers/r_draw_rgba.h" #include "swrenderer/drawers/r_draw_pal.h" #include "swrenderer/r_memory.h" +#include "swrenderer/r_renderthread.h" EXTERN_CVAR(Bool, r_fullbrightignoresectorcolor); namespace swrenderer { - void RenderParticle::Project(particle_t *particle, const sector_t *sector, int shade, WaterFakeSide fakeside, bool foggy) + void RenderParticle::Project(RenderThread *thread, particle_t *particle, const sector_t *sector, int shade, WaterFakeSide fakeside, bool foggy) { double tr_x, tr_y; double tx, ty; @@ -69,7 +70,7 @@ namespace swrenderer int x1, x2, y1, y2; sector_t* heightsec = NULL; - RenderPortal *renderportal = RenderPortal::Instance(); + RenderPortal *renderportal = thread->Portal.get(); // [ZZ] Particle not visible through the portal plane if (renderportal->CurrentPortal && !!P_PointOnLineSide(particle->Pos, renderportal->CurrentPortal->dst)) @@ -120,8 +121,8 @@ namespace swrenderer // entered, we don't need to clip it to drawsegs like a normal sprite. // Clip particles behind walls. - auto ceilingclip = RenderOpaquePass::Instance()->ceilingclip; - auto floorclip = RenderOpaquePass::Instance()->floorclip; + auto ceilingclip = thread->OpaquePass->ceilingclip; + auto floorclip = thread->OpaquePass->floorclip; if (y1 < ceilingclip[x1]) y1 = ceilingclip[x1]; if (y1 < ceilingclip[x2 - 1]) y1 = ceilingclip[x2 - 1]; if (y2 >= floorclip[x1]) y2 = floorclip[x1] - 1; @@ -205,10 +206,10 @@ namespace swrenderer vis->Light.SetColormap(tiz * LightVisibility::Instance()->ParticleGlobVis(), shade, map, particle->bright != 0, false, false); - VisibleSpriteList::Instance()->Push(vis); + thread->SpriteList->Push(vis); } - void RenderParticle::Render(short *cliptop, short *clipbottom, int minZ, int maxZ) + void RenderParticle::Render(RenderThread *thread, short *cliptop, short *clipbottom, int minZ, int maxZ) { auto vis = this; @@ -222,7 +223,7 @@ namespace swrenderer if (ycount <= 0 || countbase <= 0) return; - DrawMaskedSegsBehindParticle(); + DrawMaskedSegsBehindParticle(thread); uint32_t fg = LightBgra::shade_pal_index_simple(color, LightBgra::calc_light_multiplier(LIGHTSCALE(0, vis->Light.ColormapNum << FRACBITS))); @@ -237,7 +238,7 @@ namespace swrenderer uint32_t fracstepx = PARTICLE_TEXTURE_SIZE * FRACUNIT / countbase; uint32_t fracposx = fracstepx / 2; - RenderTranslucentPass *translucentPass = RenderTranslucentPass::Instance(); + RenderTranslucentPass *translucentPass = thread->TranslucentPass.get(); if (viewport->RenderTarget->IsBgra()) { @@ -261,11 +262,11 @@ namespace swrenderer } } - void RenderParticle::DrawMaskedSegsBehindParticle() + void RenderParticle::DrawMaskedSegsBehindParticle(RenderThread *thread) { // Draw any masked textures behind this particle so that when the // particle is drawn, it will be in front of them. - DrawSegmentList *segmentlist = DrawSegmentList::Instance(); + DrawSegmentList *segmentlist = thread->DrawSegments.get(); for (unsigned int index = segmentlist->BeginInterestingIndex(); index != segmentlist->EndInterestingIndex(); index++) { DrawSegment *ds = segmentlist->InterestingSegment(index); @@ -281,7 +282,7 @@ namespace swrenderer // [ZZ] only draw stuff that's inside the same portal as the particle, other portals will care for themselves if (ds->CurrentPortalUniq == CurrentPortalUniq) { - RenderDrawSegment renderer; + RenderDrawSegment renderer(thread); renderer.Render(ds, MAX(ds->x1, x1), MIN(ds->x2, x2)); } } diff --git a/src/swrenderer/things/r_particle.h b/src/swrenderer/things/r_particle.h index 211522074..af2f59e6c 100644 --- a/src/swrenderer/things/r_particle.h +++ b/src/swrenderer/things/r_particle.h @@ -23,14 +23,14 @@ namespace swrenderer class RenderParticle : public VisibleSprite { public: - static void Project(particle_t *, const sector_t *sector, int shade, WaterFakeSide fakeside, bool foggy); + static void Project(RenderThread *thread, particle_t *, const sector_t *sector, int shade, WaterFakeSide fakeside, bool foggy); protected: bool IsParticle() const override { return true; } - void Render(short *cliptop, short *clipbottom, int minZ, int maxZ) override; + void Render(RenderThread *thread, short *cliptop, short *clipbottom, int minZ, int maxZ) override; private: - void DrawMaskedSegsBehindParticle(); + void DrawMaskedSegsBehindParticle(RenderThread *thread); fixed_t xscale = 0; fixed_t startfrac = 0; // horizontal position of x1 diff --git a/src/swrenderer/things/r_playersprite.cpp b/src/swrenderer/things/r_playersprite.cpp index 0b8661e52..3521f115f 100644 --- a/src/swrenderer/things/r_playersprite.cpp +++ b/src/swrenderer/things/r_playersprite.cpp @@ -55,6 +55,7 @@ #include "swrenderer/things/r_sprite.h" #include "swrenderer/viewport/r_viewport.h" #include "swrenderer/r_memory.h" +#include "swrenderer/r_renderthread.h" #include "g_levellocals.h" EXTERN_CVAR(Bool, st_scale) @@ -65,10 +66,9 @@ EXTERN_CVAR(Bool, r_fullbrightignoresectorcolor) namespace swrenderer { - RenderPlayerSprites *RenderPlayerSprites::Instance() + RenderPlayerSprites::RenderPlayerSprites(RenderThread *thread) { - static RenderPlayerSprites instance; - return &instance; + Thread = thread; } void RenderPlayerSprites::Render() @@ -121,7 +121,7 @@ namespace swrenderer else { // This used to use camera->Sector but due to interpolation that can be incorrect // when the interpolated viewpoint is in a different sector than the camera. - sec = RenderOpaquePass::Instance()->FakeFlat(viewsector, &tempsec, &floorlight, &ceilinglight, nullptr, 0, 0, 0, 0); + sec = Thread->OpaquePass->FakeFlat(viewsector, &tempsec, &floorlight, &ceilinglight, nullptr, 0, 0, 0, 0); // [RH] set basecolormap basecolormap = sec->ColorMap; diff --git a/src/swrenderer/things/r_playersprite.h b/src/swrenderer/things/r_playersprite.h index 7c821f742..0a3d8903d 100644 --- a/src/swrenderer/things/r_playersprite.h +++ b/src/swrenderer/things/r_playersprite.h @@ -74,11 +74,13 @@ namespace swrenderer class RenderPlayerSprites { public: - static RenderPlayerSprites *Instance(); + RenderPlayerSprites(RenderThread *thread); void Render(); void RenderRemaining(); + RenderThread *Thread = nullptr; + private: void RenderSprite(DPSprite *pspr, AActor *owner, float bobx, float boby, double wx, double wy, double ticfrac, int spriteshade, FDynamicColormap *basecolormap, bool foggy); diff --git a/src/swrenderer/things/r_sprite.cpp b/src/swrenderer/things/r_sprite.cpp index 897af41cd..6b02a0ec1 100644 --- a/src/swrenderer/things/r_sprite.cpp +++ b/src/swrenderer/things/r_sprite.cpp @@ -55,12 +55,13 @@ #include "swrenderer/things/r_sprite.h" #include "swrenderer/viewport/r_viewport.h" #include "swrenderer/r_memory.h" +#include "swrenderer/r_renderthread.h" EXTERN_CVAR(Bool, r_fullbrightignoresectorcolor) namespace swrenderer { - void RenderSprite::Project(AActor *thing, const DVector3 &pos, FTexture *tex, const DVector2 &spriteScale, int renderflags, WaterFakeSide fakeside, F3DFloor *fakefloor, F3DFloor *fakeceiling, sector_t *current_sector, int spriteshade, bool foggy, FDynamicColormap *basecolormap) + void RenderSprite::Project(RenderThread *thread, AActor *thing, const DVector3 &pos, FTexture *tex, const DVector2 &spriteScale, int renderflags, WaterFakeSide fakeside, F3DFloor *fakefloor, F3DFloor *fakeceiling, sector_t *current_sector, int spriteshade, bool foggy, FDynamicColormap *basecolormap) { // transform the origin point double tr_x = pos.X - ViewPos.X; @@ -75,7 +76,7 @@ namespace swrenderer double tx = tr_x * ViewSin - tr_y * ViewCos; // [RH] Flip for mirrors - RenderPortal *renderportal = RenderPortal::Instance(); + RenderPortal *renderportal = thread->Portal.get(); if (renderportal->MirrorFlags & RF_XFLIP) { tx = -tx; @@ -227,10 +228,10 @@ namespace swrenderer vis->Light.SetColormap(LightVisibility::Instance()->SpriteGlobVis() / MAX(tz, MINZ), spriteshade, basecolormap, fullbright, invertcolormap, fadeToBlack); - VisibleSpriteList::Instance()->Push(vis); + thread->SpriteList->Push(vis); } - void RenderSprite::Render(short *mfloorclip, short *mceilingclip, int, int) + void RenderSprite::Render(RenderThread *thread, short *mfloorclip, short *mceilingclip, int, int) { auto vis = this; @@ -285,7 +286,7 @@ namespace swrenderer if (x < x2) { - RenderTranslucentPass *translucentPass = RenderTranslucentPass::Instance(); + RenderTranslucentPass *translucentPass = thread->TranslucentPass.get(); while (x < x2) { diff --git a/src/swrenderer/things/r_sprite.h b/src/swrenderer/things/r_sprite.h index b6298d571..776af54fa 100644 --- a/src/swrenderer/things/r_sprite.h +++ b/src/swrenderer/things/r_sprite.h @@ -20,10 +20,10 @@ namespace swrenderer class RenderSprite : public VisibleSprite { public: - static void Project(AActor *thing, const DVector3 &pos, FTexture *tex, const DVector2 &spriteScale, int renderflags, WaterFakeSide fakeside, F3DFloor *fakefloor, F3DFloor *fakeceiling, sector_t *current_sector, int spriteshade, bool foggy, FDynamicColormap *basecolormap); + static void Project(RenderThread *thread, AActor *thing, const DVector3 &pos, FTexture *tex, const DVector2 &spriteScale, int renderflags, WaterFakeSide fakeside, F3DFloor *fakefloor, F3DFloor *fakeceiling, sector_t *current_sector, int spriteshade, bool foggy, FDynamicColormap *basecolormap); protected: - void Render(short *cliptop, short *clipbottom, int minZ, int maxZ) override; + void Render(RenderThread *thread, short *cliptop, short *clipbottom, int minZ, int maxZ) override; private: fixed_t xscale = 0; diff --git a/src/swrenderer/things/r_visiblesprite.cpp b/src/swrenderer/things/r_visiblesprite.cpp index 7d19e1460..ac411db57 100644 --- a/src/swrenderer/things/r_visiblesprite.cpp +++ b/src/swrenderer/things/r_visiblesprite.cpp @@ -35,12 +35,13 @@ #include "swrenderer/scene/r_light.h" #include "swrenderer/viewport/r_viewport.h" #include "swrenderer/r_memory.h" +#include "swrenderer/r_renderthread.h" EXTERN_CVAR(Bool, r_fullbrightignoresectorcolor); namespace swrenderer { - void VisibleSprite::Render() + void VisibleSprite::Render(RenderThread *thread) { static short clipbot[MAXWIDTH]; static short cliptop[MAXWIDTH]; @@ -56,7 +57,7 @@ namespace swrenderer int colormapnum = spr->Light.ColormapNum; F3DFloor *rover; - Clip3DFloors *clip3d = Clip3DFloors::Instance(); + Clip3DFloors *clip3d = thread->Clip3DFloors.get(); // [RH] Check for particles if (spr->IsParticle()) @@ -65,7 +66,7 @@ namespace swrenderer if ((clip3d->fake3D & FAKE3D_CLIPBOTTOM) && spr->gpos.Z <= clip3d->sclipBottom) return; if ((clip3d->fake3D & FAKE3D_CLIPTOP) && spr->gpos.Z >= clip3d->sclipTop) return; - spr->Render(nullptr, nullptr, 0, 0); + spr->Render(thread, nullptr, nullptr, 0, 0); return; } @@ -279,7 +280,7 @@ namespace swrenderer // Scan drawsegs from end to start for obscuring segs. // The first drawseg that is closer than the sprite is the clip seg. - DrawSegmentList *segmentlist = DrawSegmentList::Instance(); + DrawSegmentList *segmentlist = thread->DrawSegments.get(); for (unsigned int index = segmentlist->BeginIndex(); index != segmentlist->EndIndex(); index++) { DrawSegment *ds = segmentlist->Segment(index); @@ -322,13 +323,13 @@ namespace swrenderer (spr->gpos.Y - ds->curline->v1->fY()) * (ds->curline->v2->fX() - ds->curline->v1->fX()) - (spr->gpos.X - ds->curline->v1->fX()) * (ds->curline->v2->fY() - ds->curline->v1->fY()) <= 0)) { - RenderPortal *renderportal = RenderPortal::Instance(); + RenderPortal *renderportal = thread->Portal.get(); // seg is behind sprite, so draw the mid texture if it has one if (ds->CurrentPortalUniq == renderportal->CurrentPortalUniq && // [ZZ] instead, portal uniq check is made here (ds->maskedtexturecol != nullptr || ds->bFogBoundary)) { - RenderDrawSegment renderer; + RenderDrawSegment renderer(thread); renderer.Render(ds, r1, r2); } @@ -373,7 +374,7 @@ namespace swrenderer if (!spr->IsVoxel()) { - spr->Render(clipbot, cliptop, 0, 0); + spr->Render(thread, clipbot, cliptop, 0, 0); } else { @@ -406,7 +407,7 @@ namespace swrenderer } int minvoxely = spr->gzt <= hzt ? 0 : xs_RoundToInt((spr->gzt - hzt) / spr->yscale); int maxvoxely = spr->gzb > hzb ? INT_MAX : xs_RoundToInt((spr->gzt - hzb) / spr->yscale); - spr->Render(cliptop, clipbot, minvoxely, maxvoxely); + spr->Render(thread, cliptop, clipbot, minvoxely, maxvoxely); } spr->Light.BaseColormap = colormap; spr->Light.ColormapNum = colormapnum; diff --git a/src/swrenderer/things/r_visiblesprite.h b/src/swrenderer/things/r_visiblesprite.h index 87abe767a..7bd5b9de2 100644 --- a/src/swrenderer/things/r_visiblesprite.h +++ b/src/swrenderer/things/r_visiblesprite.h @@ -22,13 +22,15 @@ namespace swrenderer { + class RenderThread; + class VisibleSprite { public: VisibleSprite() { RenderStyle = STYLE_Normal; } virtual ~VisibleSprite() { } - void Render(); + void Render(RenderThread *thread); bool IsCurrentPortalUniq(int portalUniq) const { return CurrentPortalUniq == portalUniq; } const FVector3 &WorldPos() const { return gpos; } @@ -41,7 +43,7 @@ namespace swrenderer virtual bool IsVoxel() const { return false; } virtual bool IsWallSprite() const { return false; } - virtual void Render(short *cliptop, short *clipbottom, int minZ, int maxZ) = 0; + virtual void Render(RenderThread *thread, short *cliptop, short *clipbottom, int minZ, int maxZ) = 0; FTexture *pic = nullptr; diff --git a/src/swrenderer/things/r_visiblespritelist.cpp b/src/swrenderer/things/r_visiblespritelist.cpp index 76706d7bc..eac6c91f3 100644 --- a/src/swrenderer/things/r_visiblespritelist.cpp +++ b/src/swrenderer/things/r_visiblespritelist.cpp @@ -28,12 +28,6 @@ namespace swrenderer { - VisibleSpriteList *VisibleSpriteList::Instance() - { - static VisibleSpriteList instance; - return &instance; - } - void VisibleSpriteList::Clear() { Sprites.Clear(); diff --git a/src/swrenderer/things/r_visiblespritelist.h b/src/swrenderer/things/r_visiblespritelist.h index 99370c250..2f53514fa 100644 --- a/src/swrenderer/things/r_visiblespritelist.h +++ b/src/swrenderer/things/r_visiblespritelist.h @@ -21,8 +21,6 @@ namespace swrenderer class VisibleSpriteList { public: - static VisibleSpriteList *Instance(); - void Clear(); void PushPortal(); void PopPortal(); diff --git a/src/swrenderer/things/r_voxel.cpp b/src/swrenderer/things/r_voxel.cpp index e3e101c4a..0a2d8e074 100644 --- a/src/swrenderer/things/r_voxel.cpp +++ b/src/swrenderer/things/r_voxel.cpp @@ -43,12 +43,13 @@ #include "swrenderer/viewport/r_viewport.h" #include "swrenderer/viewport/r_spritedrawer.h" #include "swrenderer/r_memory.h" +#include "swrenderer/r_renderthread.h" EXTERN_CVAR(Bool, r_fullbrightignoresectorcolor) namespace swrenderer { - void RenderVoxel::Project(AActor *thing, DVector3 pos, FVoxelDef *voxel, const DVector2 &spriteScale, int renderflags, WaterFakeSide fakeside, F3DFloor *fakefloor, F3DFloor *fakeceiling, sector_t *current_sector, int spriteshade, bool foggy, FDynamicColormap *basecolormap) + void RenderVoxel::Project(RenderThread *thread, AActor *thing, DVector3 pos, FVoxelDef *voxel, const DVector2 &spriteScale, int renderflags, WaterFakeSide fakeside, F3DFloor *fakefloor, F3DFloor *fakeceiling, sector_t *current_sector, int spriteshade, bool foggy, FDynamicColormap *basecolormap) { // transform the origin point double tr_x = pos.X - ViewPos.X; @@ -58,7 +59,7 @@ namespace swrenderer double tx = tr_x * ViewSin - tr_y * ViewCos; // [RH] Flip for mirrors - RenderPortal *renderportal = RenderPortal::Instance(); + RenderPortal *renderportal = thread->Portal.get(); if (renderportal->MirrorFlags & RF_XFLIP) { tx = -tx; @@ -178,10 +179,10 @@ namespace swrenderer vis->Light.SetColormap(LightVisibility::Instance()->SpriteGlobVis() / MAX(tz, MINZ), spriteshade, basecolormap, fullbright, invertcolormap, fadeToBlack); - VisibleSpriteList::Instance()->Push(vis, true); + thread->SpriteList->Push(vis, true); } - void RenderVoxel::Render(short *cliptop, short *clipbottom, int minZ, int maxZ) + void RenderVoxel::Render(RenderThread *thread, short *cliptop, short *clipbottom, int minZ, int maxZ) { auto sprite = this; auto viewport = RenderViewport::Instance(); diff --git a/src/swrenderer/things/r_voxel.h b/src/swrenderer/things/r_voxel.h index 7d5fd621f..0bca0fb87 100644 --- a/src/swrenderer/things/r_voxel.h +++ b/src/swrenderer/things/r_voxel.h @@ -58,13 +58,13 @@ namespace swrenderer class RenderVoxel : public VisibleSprite { public: - static void Project(AActor *thing, DVector3 pos, FVoxelDef *voxel, const DVector2 &spriteScale, int renderflags, WaterFakeSide fakeside, F3DFloor *fakefloor, F3DFloor *fakeceiling, sector_t *current_sector, int spriteshade, bool foggy, FDynamicColormap *basecolormap); + static void Project(RenderThread *thread, AActor *thing, DVector3 pos, FVoxelDef *voxel, const DVector2 &spriteScale, int renderflags, WaterFakeSide fakeside, F3DFloor *fakefloor, F3DFloor *fakeceiling, sector_t *current_sector, int spriteshade, bool foggy, FDynamicColormap *basecolormap); static void Deinit(); protected: bool IsVoxel() const override { return true; } - void Render(short *cliptop, short *clipbottom, int minZ, int maxZ) override; + void Render(RenderThread *thread, short *cliptop, short *clipbottom, int minZ, int maxZ) override; private: struct posang diff --git a/src/swrenderer/things/r_wallsprite.cpp b/src/swrenderer/things/r_wallsprite.cpp index 8c813f479..8b0dc16cc 100644 --- a/src/swrenderer/things/r_wallsprite.cpp +++ b/src/swrenderer/things/r_wallsprite.cpp @@ -57,12 +57,13 @@ #include "swrenderer/line/r_walldraw.h" #include "swrenderer/viewport/r_viewport.h" #include "swrenderer/r_memory.h" +#include "swrenderer/r_renderthread.h" EXTERN_CVAR(Bool, r_fullbrightignoresectorcolor); namespace swrenderer { - void RenderWallSprite::Project(AActor *thing, const DVector3 &pos, FTextureID picnum, const DVector2 &scale, int renderflags, int spriteshade, bool foggy, FDynamicColormap *basecolormap) + void RenderWallSprite::Project(RenderThread *thread, AActor *thing, const DVector3 &pos, FTextureID picnum, const DVector2 &scale, int renderflags, int spriteshade, bool foggy, FDynamicColormap *basecolormap) { FWallCoords wallc; double x1, x2; @@ -87,10 +88,10 @@ namespace swrenderer right.Y = right.Y + x2 * angsin; // Is it off-screen? - if (wallc.Init(left, right, TOO_CLOSE_Z)) + if (wallc.Init(thread, left, right, TOO_CLOSE_Z)) return; - RenderPortal *renderportal = RenderPortal::Instance(); + RenderPortal *renderportal = thread->Portal.get(); if (wallc.sx1 >= renderportal->WindowRight || wallc.sx2 <= renderportal->WindowLeft) return; @@ -134,10 +135,10 @@ namespace swrenderer vis->Light.SetColormap(LightVisibility::Instance()->SpriteGlobVis() / MAX(tz, MINZ), spriteshade, basecolormap, false, false, false); - VisibleSpriteList::Instance()->Push(vis); + thread->SpriteList->Push(vis); } - void RenderWallSprite::Render(short *mfloorclip, short *mceilingclip, int, int) + void RenderWallSprite::Render(RenderThread *thread, short *mfloorclip, short *mceilingclip, int, int) { auto spr = this; @@ -151,7 +152,7 @@ namespace swrenderer return; FWallTmapVals WallT; - WallT.InitFromWallCoords(&spr->wallc); + WallT.InitFromWallCoords(thread, &spr->wallc); ProjectedWallTexcoords walltexcoords; walltexcoords.Project(spr->pic->GetWidth() << FRACBITS, x1, x2, WallT); @@ -229,7 +230,7 @@ namespace swrenderer } else { - RenderTranslucentPass *translucentPass = RenderTranslucentPass::Instance(); + RenderTranslucentPass *translucentPass = thread->TranslucentPass.get(); while (x < x2) { diff --git a/src/swrenderer/things/r_wallsprite.h b/src/swrenderer/things/r_wallsprite.h index 1a0c87b70..796a9a2bd 100644 --- a/src/swrenderer/things/r_wallsprite.h +++ b/src/swrenderer/things/r_wallsprite.h @@ -23,11 +23,11 @@ namespace swrenderer class RenderWallSprite : public VisibleSprite { public: - static void Project(AActor *thing, const DVector3 &pos, FTextureID picnum, const DVector2 &scale, int renderflags, int spriteshade, bool foggy, FDynamicColormap *basecolormap); + static void Project(RenderThread *thread, AActor *thing, const DVector3 &pos, FTextureID picnum, const DVector2 &scale, int renderflags, int spriteshade, bool foggy, FDynamicColormap *basecolormap); protected: bool IsWallSprite() const override { return true; } - void Render(short *cliptop, short *clipbottom, int minZ, int maxZ) override; + void Render(RenderThread *thread, short *cliptop, short *clipbottom, int minZ, int maxZ) override; private: static void DrawColumn(SpriteDrawerArgs &drawerargs, int x, FTexture *WallSpriteTile, const ProjectedWallTexcoords &walltexcoords, double texturemid, float maskedScaleY, bool sprflipvert, const short *mfloorclip, const short *mceilingclip);