diff --git a/src/polyrenderer/poly_renderer.cpp b/src/polyrenderer/poly_renderer.cpp index 1545e6a24..0e4c98028 100644 --- a/src/polyrenderer/poly_renderer.cpp +++ b/src/polyrenderer/poly_renderer.cpp @@ -66,7 +66,7 @@ void PolyRenderer::RenderView(player_t *player) int stHeight = gST_Y; float trueratio; ActiveRatio(width, height, &trueratio); - viewport->SetViewport(width, height, trueratio); + viewport->SetViewport(&Thread, width, height, trueratio); RenderActorView(player->mo, false); @@ -89,7 +89,7 @@ void PolyRenderer::RenderViewToCanvas(AActor *actor, DCanvas *canvas, int x, int viewwidth = width; viewport->RenderTarget = canvas; R_SetWindow(viewport->viewpoint, viewport->viewwindow, 12, width, height, height, true); - viewport->SetViewport(width, height, viewport->viewwindow.WidescreenRatio); + viewport->SetViewport(&Thread, width, height, viewport->viewwindow.WidescreenRatio); viewwindowx = x; viewwindowy = y; viewactive = true; @@ -105,7 +105,7 @@ void PolyRenderer::RenderViewToCanvas(AActor *actor, DCanvas *canvas, int x, int R_ExecuteSetViewSize(viewport->viewpoint, viewport->viewwindow); float trueratio; ActiveRatio(width, height, &trueratio); - viewport->SetViewport(width, height, viewport->viewwindow.WidescreenRatio); + viewport->SetViewport(&Thread, width, height, viewport->viewwindow.WidescreenRatio); viewactive = savedviewactive; } diff --git a/src/polyrenderer/scene/poly_decal.cpp b/src/polyrenderer/scene/poly_decal.cpp index c73def6d0..d8043e2a6 100644 --- a/src/polyrenderer/scene/poly_decal.cpp +++ b/src/polyrenderer/scene/poly_decal.cpp @@ -139,7 +139,7 @@ void RenderPolyDecal::Render(const TriMatrix &worldToClip, const Vec4f &clipPlan args.uniforms.flags = 0; args.SetColormap(front->ColorMap); args.SetTexture(tex, decal->Translation, true); - args.uniforms.globvis = (float)swrenderer::LightVisibility::Instance()->WallGlobVis(foggy); + args.uniforms.globvis = (float)PolyRenderer::Instance()->Thread.Light->WallGlobVis(foggy); if (fullbrightSprite || cameraLight->FixedLightLevel() >= 0 || cameraLight->FixedColormap()) { args.uniforms.light = 256; diff --git a/src/polyrenderer/scene/poly_particle.cpp b/src/polyrenderer/scene/poly_particle.cpp index b3887792e..966c93fcc 100644 --- a/src/polyrenderer/scene/poly_particle.cpp +++ b/src/polyrenderer/scene/poly_particle.cpp @@ -76,7 +76,7 @@ void RenderPolyParticle::Render(const TriMatrix &worldToClip, const Vec4f &clipP PolyDrawArgs args; - args.uniforms.globvis = (float)swrenderer::LightVisibility::Instance()->ParticleGlobVis(foggy); + args.uniforms.globvis = (float)PolyRenderer::Instance()->Thread.Light->ParticleGlobVis(foggy); if (fullbrightSprite || cameraLight->FixedLightLevel() >= 0 || cameraLight->FixedColormap()) { diff --git a/src/polyrenderer/scene/poly_plane.cpp b/src/polyrenderer/scene/poly_plane.cpp index f37e707c7..1c6cd36fc 100644 --- a/src/polyrenderer/scene/poly_plane.cpp +++ b/src/polyrenderer/scene/poly_plane.cpp @@ -112,7 +112,7 @@ void RenderPolyPlane::Render3DFloor(const TriMatrix &worldToClip, const Vec4f &c UVTransform xform(ceiling ? fakeFloor->top.model->planes[sector_t::ceiling].xform : fakeFloor->top.model->planes[sector_t::floor].xform, tex); PolyDrawArgs args; - args.uniforms.globvis = (float)swrenderer::LightVisibility::Instance()->SlopePlaneGlobVis(foggy) * 48.0f; + args.uniforms.globvis = (float)PolyRenderer::Instance()->Thread.Light->SlopePlaneGlobVis(foggy) * 48.0f; args.uniforms.light = (uint32_t)(lightlevel / 255.0f * 256.0f); if (cameraLight->FixedLightLevel() >= 0 || cameraLight->FixedColormap()) args.uniforms.light = 256; @@ -310,7 +310,7 @@ void RenderPolyPlane::Render(const TriMatrix &worldToClip, const Vec4f &clipPlan swrenderer::CameraLight *cameraLight = swrenderer::CameraLight::Instance(); PolyDrawArgs args; - args.uniforms.globvis = (float)swrenderer::LightVisibility::Instance()->SlopePlaneGlobVis(foggy) * 48.0f; + args.uniforms.globvis = (float)PolyRenderer::Instance()->Thread.Light->SlopePlaneGlobVis(foggy) * 48.0f; args.uniforms.light = (uint32_t)(frontsector->lightlevel / 255.0f * 256.0f); if (cameraLight->FixedLightLevel() >= 0 || cameraLight->FixedColormap()) args.uniforms.light = 256; diff --git a/src/polyrenderer/scene/poly_playersprite.cpp b/src/polyrenderer/scene/poly_playersprite.cpp index eb40b05d2..74854e9a5 100644 --- a/src/polyrenderer/scene/poly_playersprite.cpp +++ b/src/polyrenderer/scene/poly_playersprite.cpp @@ -228,7 +228,7 @@ void RenderPolyPlayerSprites::RenderSprite(DPSprite *sprite, AActor *owner, floa int actualextralight = foggy ? 0 : viewpoint.extralight << 4; int spriteshade = swrenderer::LightVisibility::LightLevelToShade(owner->Sector->lightlevel + actualextralight, foggy); double minz = double((2048 * 4) / double(1 << 20)); - ColormapNum = GETPALOOKUP(swrenderer::LightVisibility::Instance()->SpriteGlobVis(foggy) / minz, spriteshade); + ColormapNum = GETPALOOKUP(PolyRenderer::Instance()->Thread.Light->SpriteGlobVis(foggy) / minz, spriteshade); if (sprite->GetID() < PSP_TARGETCENTER) { diff --git a/src/polyrenderer/scene/poly_portal.cpp b/src/polyrenderer/scene/poly_portal.cpp index d89793646..e48399ede 100644 --- a/src/polyrenderer/scene/poly_portal.cpp +++ b/src/polyrenderer/scene/poly_portal.cpp @@ -93,7 +93,7 @@ void PolyDrawSectorPortal::SaveGlobals() savedextralight = viewpoint.extralight; savedpos = viewpoint.Pos; savedangles = viewpoint.Angles; - savedvisibility = swrenderer::LightVisibility::Instance()->GetVisibility(); + savedvisibility = PolyRenderer::Instance()->Thread.Light->GetVisibility(); savedcamera = viewpoint.camera; savedsector = viewpoint.sector; @@ -102,7 +102,7 @@ void PolyDrawSectorPortal::SaveGlobals() // Don't let gun flashes brighten the sky box AActor *sky = Portal->mSkybox; viewpoint.extralight = 0; - swrenderer::LightVisibility::Instance()->SetVisibility(PolyRenderer::Instance()->Thread.Viewport.get(), sky->args[0] * 0.25f); + PolyRenderer::Instance()->Thread.Light->SetVisibility(PolyRenderer::Instance()->Thread.Viewport.get(), sky->args[0] * 0.25f); viewpoint.Pos = sky->InterpolatedPosition(viewpoint.TicFrac); viewpoint.Angles.Yaw = savedangles.Yaw + (sky->PrevAngles.Yaw + deltaangle(sky->PrevAngles.Yaw, sky->Angles.Yaw) * viewpoint.TicFrac); } @@ -133,7 +133,7 @@ void PolyDrawSectorPortal::RestoreGlobals() viewpoint.camera = savedcamera; viewpoint.sector = savedsector; viewpoint.Pos = savedpos; - swrenderer::LightVisibility::Instance()->SetVisibility(PolyRenderer::Instance()->Thread.Viewport.get(), savedvisibility); + PolyRenderer::Instance()->Thread.Light->SetVisibility(PolyRenderer::Instance()->Thread.Viewport.get(), savedvisibility); viewpoint.extralight = savedextralight; viewpoint.Angles = savedangles; R_SetViewAngle(viewpoint, viewwindow); diff --git a/src/polyrenderer/scene/poly_scene.cpp b/src/polyrenderer/scene/poly_scene.cpp index 50d1143d2..2a3b5cc53 100644 --- a/src/polyrenderer/scene/poly_scene.cpp +++ b/src/polyrenderer/scene/poly_scene.cpp @@ -244,7 +244,7 @@ void RenderPolyScene::RenderPortals(int portalDepth) PolyDrawArgs args; args.objectToClip = &WorldToClip; args.mode = TriangleDrawMode::Fan; - args.uniforms.globvis = (float)swrenderer::LightVisibility::Instance()->WallGlobVis(foggy); + args.uniforms.globvis = (float)PolyRenderer::Instance()->Thread.Light->WallGlobVis(foggy); args.uniforms.color = 0; args.uniforms.light = 256; args.uniforms.flags = TriUniforms::fixed_light; diff --git a/src/polyrenderer/scene/poly_sky.cpp b/src/polyrenderer/scene/poly_sky.cpp index ac5647f73..bb574b4ed 100644 --- a/src/polyrenderer/scene/poly_sky.cpp +++ b/src/polyrenderer/scene/poly_sky.cpp @@ -57,7 +57,7 @@ void PolySkyDome::Render(const TriMatrix &worldToClip) int rc = mRows + 1; PolyDrawArgs args; - args.uniforms.globvis = (float)swrenderer::LightVisibility::Instance()->WallGlobVis(foggy); + args.uniforms.globvis = (float)PolyRenderer::Instance()->Thread.Light->WallGlobVis(foggy); args.uniforms.light = 256; args.uniforms.flags = 0; args.uniforms.subsectorDepth = RenderPolyScene::SkySubsectorDepth; diff --git a/src/polyrenderer/scene/poly_sprite.cpp b/src/polyrenderer/scene/poly_sprite.cpp index dbc4387c5..e8f7ab179 100644 --- a/src/polyrenderer/scene/poly_sprite.cpp +++ b/src/polyrenderer/scene/poly_sprite.cpp @@ -141,7 +141,7 @@ void RenderPolySprite::Render(const TriMatrix &worldToClip, const Vec4f &clipPla swrenderer::CameraLight *cameraLight = swrenderer::CameraLight::Instance(); PolyDrawArgs args; - args.uniforms.globvis = (float)swrenderer::LightVisibility::Instance()->SpriteGlobVis(foggy); + args.uniforms.globvis = (float)PolyRenderer::Instance()->Thread.Light->SpriteGlobVis(foggy); args.uniforms.flags = 0; if (fullbrightSprite || cameraLight->FixedLightLevel() >= 0 || cameraLight->FixedColormap()) { diff --git a/src/polyrenderer/scene/poly_wall.cpp b/src/polyrenderer/scene/poly_wall.cpp index 6defccc8d..3246d69ac 100644 --- a/src/polyrenderer/scene/poly_wall.cpp +++ b/src/polyrenderer/scene/poly_wall.cpp @@ -249,7 +249,7 @@ void RenderPolyWall::Render(const TriMatrix &worldToClip, const Vec4f &clipPlane } PolyDrawArgs args; - args.uniforms.globvis = (float)swrenderer::LightVisibility::Instance()->WallGlobVis(foggy); + args.uniforms.globvis = (float)PolyRenderer::Instance()->Thread.Light->WallGlobVis(foggy); args.uniforms.light = (uint32_t)(GetLightLevel() / 255.0f * 256.0f); args.uniforms.flags = 0; args.uniforms.subsectorDepth = SubsectorDepth; diff --git a/src/polyrenderer/scene/poly_wallsprite.cpp b/src/polyrenderer/scene/poly_wallsprite.cpp index 02ed751f1..56d694a6a 100644 --- a/src/polyrenderer/scene/poly_wallsprite.cpp +++ b/src/polyrenderer/scene/poly_wallsprite.cpp @@ -102,7 +102,7 @@ void RenderPolyWallSprite::Render(const TriMatrix &worldToClip, const Vec4f &cli swrenderer::CameraLight *cameraLight = swrenderer::CameraLight::Instance(); PolyDrawArgs args; - args.uniforms.globvis = (float)swrenderer::LightVisibility::Instance()->WallGlobVis(foggy); + args.uniforms.globvis = (float)PolyRenderer::Instance()->Thread.Light->WallGlobVis(foggy); if (fullbrightSprite || cameraLight->FixedLightLevel() >= 0 || cameraLight->FixedColormap()) { args.uniforms.light = 256; diff --git a/src/swrenderer/line/r_line.cpp b/src/swrenderer/line/r_line.cpp index 0352a879f..5eecfed2a 100644 --- a/src/swrenderer/line/r_line.cpp +++ b/src/swrenderer/line/r_line.cpp @@ -782,7 +782,7 @@ namespace swrenderer if (cameraLight->FixedColormap() == nullptr && cameraLight->FixedLightLevel() < 0) { wallshade = LightVisibility::LightLevelToShade(mLineSegment->sidedef->GetLightLevel(foggy, mFrontSector->lightlevel) + LightVisibility::ActualExtraLight(foggy, Thread->Viewport.get()), foggy); - double GlobVis = LightVisibility::Instance()->WallGlobVis(foggy); + double GlobVis = Thread->Light->WallGlobVis(foggy); rw_lightleft = float(GlobVis / WallC.sz1); rw_lightstep = float((GlobVis / WallC.sz2 - rw_lightleft) / (WallC.sx2 - WallC.sx1)); } diff --git a/src/swrenderer/line/r_walldraw.cpp b/src/swrenderer/line/r_walldraw.cpp index d5eacce39..06b096ac1 100644 --- a/src/swrenderer/line/r_walldraw.cpp +++ b/src/swrenderer/line/r_walldraw.cpp @@ -515,6 +515,8 @@ namespace swrenderer this->rw_pic = pic; this->mask = mask; + Thread->PrepareTexture(pic); + if (rw_pic->GetHeight() != 1 << rw_pic->HeightBits) { ProcessWallNP2(walltop, wallbottom, texturemid, swall, lwall, top, bottom); diff --git a/src/swrenderer/plane/r_flatplane.cpp b/src/swrenderer/plane/r_flatplane.cpp index 25d6a5ff6..159d4c45a 100644 --- a/src/swrenderer/plane/r_flatplane.cpp +++ b/src/swrenderer/plane/r_flatplane.cpp @@ -59,7 +59,7 @@ namespace swrenderer } drawerargs.SetSolidColor(3); - drawerargs.SetTexture(Thread->Viewport.get(), texture); + drawerargs.SetTexture(Thread, texture); double planeang = (pl->xform.Angle + pl->xform.baseAngle).Radians(); double xstep, ystep, leftxfrac, leftyfrac, rightxfrac, rightyfrac; @@ -120,7 +120,7 @@ namespace swrenderer // [RH] set foggy flag bool foggy = (level.fadeto || basecolormap->Fade || (level.flags & LEVEL_HASFADETABLE)); - GlobVis = LightVisibility::Instance()->FlatPlaneGlobVis(foggy) / planeheight; + GlobVis = Thread->Light->FlatPlaneGlobVis(foggy) / planeheight; CameraLight *cameraLight = CameraLight::Instance(); if (cameraLight->FixedLightLevel() >= 0) diff --git a/src/swrenderer/plane/r_skyplane.cpp b/src/swrenderer/plane/r_skyplane.cpp index 534a46890..40115a07d 100644 --- a/src/swrenderer/plane/r_skyplane.cpp +++ b/src/swrenderer/plane/r_skyplane.cpp @@ -198,8 +198,8 @@ namespace swrenderer angle1 = (uint32_t)((UMulScale16(ang, frontcyl) + frontpos) >> FRACBITS); angle2 = (uint32_t)((UMulScale16(ang, backcyl) + backpos) >> FRACBITS); - drawerargs.SetFrontTexture(viewport, frontskytex, angle1); - drawerargs.SetBackTexture(viewport, backskytex, angle2); + drawerargs.SetFrontTexture(Thread, frontskytex, angle1); + drawerargs.SetBackTexture(Thread, backskytex, angle2); drawerargs.SetTextureVStep(uv_step); drawerargs.SetTextureVPos(uv_pos); drawerargs.SetDest(viewport, start_x, y1); diff --git a/src/swrenderer/plane/r_slopeplane.cpp b/src/swrenderer/plane/r_slopeplane.cpp index 16e73f0b8..90aaf9cea 100644 --- a/src/swrenderer/plane/r_slopeplane.cpp +++ b/src/swrenderer/plane/r_slopeplane.cpp @@ -80,7 +80,7 @@ namespace swrenderer auto viewport = Thread->Viewport.get(); drawerargs.SetSolidColor(3); - drawerargs.SetTexture(Thread->Viewport.get(), texture); + drawerargs.SetTexture(Thread, texture); lxscale = _xscale * ifloatpow2[drawerargs.TextureWidthBits()]; lyscale = _yscale * ifloatpow2[drawerargs.TextureHeightBits()]; @@ -157,7 +157,7 @@ namespace swrenderer basecolormap = colormap; bool foggy = level.fadeto || basecolormap->Fade || (level.flags & LEVEL_HASFADETABLE);; - planelightfloat = (LightVisibility::Instance()->SlopePlaneGlobVis(foggy) * lxscale * lyscale) / (fabs(pl->height.ZatPoint(Thread->Viewport->viewpoint.Pos) - Thread->Viewport->viewpoint.Pos.Z)) / 65536.f; + planelightfloat = (Thread->Light->SlopePlaneGlobVis(foggy) * lxscale * lyscale) / (fabs(pl->height.ZatPoint(Thread->Viewport->viewpoint.Pos) - Thread->Viewport->viewpoint.Pos.Z)) / 65536.f; if (pl->height.fC() > 0) planelightfloat = -planelightfloat; diff --git a/src/swrenderer/r_renderthread.cpp b/src/swrenderer/r_renderthread.cpp index 559d57ec1..5dc58446e 100644 --- a/src/swrenderer/r_renderthread.cpp +++ b/src/swrenderer/r_renderthread.cpp @@ -62,6 +62,7 @@ namespace swrenderer MainThread = mainThread; FrameMemory = std::make_unique(); Viewport = std::make_unique(); + Light = std::make_unique(); DrawQueue = std::make_shared(this); OpaquePass = std::make_unique(this); TranslucentPass = std::make_unique(this); @@ -87,4 +88,38 @@ namespace swrenderer else return pal_drawers.get(); } + + void RenderThread::PrepareTexture(FTexture *texture) + { + if (texture == nullptr) + return; + + // Textures may not have loaded/refreshed yet. The shared code doing + // this is not thread safe. By calling GetPixels in a mutex lock we + // make sure that only one thread is loading a texture at any given + // time. + // + // It is critical that this function is called before any direct + // calls to GetPixels for this to work. + + static std::mutex loadmutex; + loadmutex.lock(); + try + { + texture->GetPixels(); + const FTexture::Span *spans; + texture->GetColumn(0, &spans); + if (Viewport->RenderTarget->IsBgra()) + { + texture->GetPixelsBgra(); + texture->GetColumnBgra(0, &spans); + } + loadmutex.unlock(); + } + catch (...) + { + loadmutex.unlock(); + throw; + } + } } diff --git a/src/swrenderer/r_renderthread.h b/src/swrenderer/r_renderthread.h index 70dfec342..8c3823c2d 100644 --- a/src/swrenderer/r_renderthread.h +++ b/src/swrenderer/r_renderthread.h @@ -43,6 +43,7 @@ namespace swrenderer class RenderClipSegment; class RenderMemory; class RenderViewport; + class LightVisibility; class SWPixelFormatDrawers; class SWTruecolorDrawers; class SWPalDrawers; @@ -69,6 +70,7 @@ namespace swrenderer std::unique_ptr DrawSegments; std::unique_ptr ClipSegments; std::unique_ptr Viewport; + std::unique_ptr Light; DrawerCommandQueuePtr DrawQueue; std::thread thread; @@ -78,6 +80,9 @@ namespace swrenderer short cliptop[MAXWIDTH]; SWPixelFormatDrawers *Drawers(RenderViewport *viewport); + + // Make sure texture can accessed safely + void PrepareTexture(FTexture *texture); private: std::unique_ptr tc_drawers; diff --git a/src/swrenderer/r_swcanvas.cpp b/src/swrenderer/r_swcanvas.cpp index df17ba5ab..c55c9a737 100644 --- a/src/swrenderer/r_swcanvas.cpp +++ b/src/swrenderer/r_swcanvas.cpp @@ -274,7 +274,7 @@ void SWCanvas::FillSimplePoly(DCanvas *canvas, FTexture *tex, FVector2 *points, // Setup constant texture mapping parameters. SpanDrawerArgs drawerargs; - drawerargs.SetTexture(viewport, tex); + drawerargs.SetTexture(&thread, tex); if (colormap) drawerargs.SetLight(colormap, 0, clamp(shade >> FRACBITS, 0, NUMCOLORMAPS - 1)); else diff --git a/src/swrenderer/r_swrenderer.cpp b/src/swrenderer/r_swrenderer.cpp index 705353ebd..07b6480cf 100644 --- a/src/swrenderer/r_swrenderer.cpp +++ b/src/swrenderer/r_swrenderer.cpp @@ -365,10 +365,10 @@ void FSoftwareRenderer::CleanLevelData() double FSoftwareRenderer::GetVisibility() { - return LightVisibility::Instance()->GetVisibility(); + return mScene.MainThread()->Light->GetVisibility(); } void FSoftwareRenderer::SetVisibility(double vis) { - LightVisibility::Instance()->SetVisibility(mScene.MainThread()->Viewport.get(), vis); + mScene.MainThread()->Light->SetVisibility(mScene.MainThread()->Viewport.get(), vis); } diff --git a/src/swrenderer/scene/r_light.cpp b/src/swrenderer/scene/r_light.cpp index d0f76ee9f..f5243c430 100644 --- a/src/swrenderer/scene/r_light.cpp +++ b/src/swrenderer/scene/r_light.cpp @@ -93,12 +93,6 @@ namespace swrenderer ///////////////////////////////////////////////////////////////////////// - LightVisibility *LightVisibility::Instance() - { - static LightVisibility instance; - return &instance; - } - // Changes how rapidly things get dark with distance void LightVisibility::SetVisibility(RenderViewport *viewport, double vis) { diff --git a/src/swrenderer/scene/r_light.h b/src/swrenderer/scene/r_light.h index be697cc95..59475fecf 100644 --- a/src/swrenderer/scene/r_light.h +++ b/src/swrenderer/scene/r_light.h @@ -69,8 +69,6 @@ namespace swrenderer class LightVisibility { public: - static LightVisibility *Instance(); - void SetVisibility(RenderViewport *viewport, double visibility); double GetVisibility() const { return CurrentVisibility; } diff --git a/src/swrenderer/scene/r_portal.cpp b/src/swrenderer/scene/r_portal.cpp index b34fe374a..6c5d7a552 100644 --- a/src/swrenderer/scene/r_portal.cpp +++ b/src/swrenderer/scene/r_portal.cpp @@ -104,7 +104,7 @@ namespace swrenderer int savedextralight = Thread->Viewport->viewpoint.extralight; DVector3 savedpos = Thread->Viewport->viewpoint.Pos; DRotator savedangles = Thread->Viewport->viewpoint.Angles; - double savedvisibility = LightVisibility::Instance()->GetVisibility(); + double savedvisibility = Thread->Light->GetVisibility(); AActor *savedcamera = Thread->Viewport->viewpoint.camera; sector_t *savedsector = Thread->Viewport->viewpoint.sector; @@ -126,7 +126,7 @@ namespace swrenderer // Don't let gun flashes brighten the sky box AActor *sky = port->mSkybox; Thread->Viewport->viewpoint.extralight = 0; - LightVisibility::Instance()->SetVisibility(Thread->Viewport.get(), sky->args[0] * 0.25f); + Thread->Light->SetVisibility(Thread->Viewport.get(), sky->args[0] * 0.25f); Thread->Viewport->viewpoint.Pos = sky->InterpolatedPosition(Thread->Viewport->viewpoint.TicFrac); Thread->Viewport->viewpoint.Angles.Yaw = savedangles.Yaw + (sky->PrevAngles.Yaw + deltaangle(sky->PrevAngles.Yaw, sky->Angles.Yaw) * Thread->Viewport->viewpoint.TicFrac); @@ -139,7 +139,7 @@ namespace swrenderer case PORTS_PORTAL: case PORTS_LINKEDPORTAL: Thread->Viewport->viewpoint.extralight = pl->extralight; - LightVisibility::Instance()->SetVisibility(Thread->Viewport.get(), pl->visibility); + Thread->Light->SetVisibility(Thread->Viewport.get(), pl->visibility); Thread->Viewport->viewpoint.Pos.X = pl->viewpos.X + port->mDisplacement.X; Thread->Viewport->viewpoint.Pos.Y = pl->viewpos.Y + port->mDisplacement.Y; Thread->Viewport->viewpoint.Pos.Z = pl->viewpos.Z; @@ -245,7 +245,7 @@ namespace swrenderer Thread->Viewport->viewpoint.camera = savedcamera; Thread->Viewport->viewpoint.sector = savedsector; Thread->Viewport->viewpoint.Pos = savedpos; - LightVisibility::Instance()->SetVisibility(Thread->Viewport.get(), savedvisibility); + Thread->Light->SetVisibility(Thread->Viewport.get(), savedvisibility); Thread->Viewport->viewpoint.extralight = savedextralight; Thread->Viewport->viewpoint.Angles = savedangles; R_SetViewAngle(Thread->Viewport->viewpoint, Thread->Viewport->viewwindow); @@ -517,7 +517,7 @@ namespace swrenderer stacked_viewpos = Thread->Viewport->viewpoint.Pos; stacked_angle = Thread->Viewport->viewpoint.Angles; stacked_extralight = Thread->Viewport->viewpoint.extralight; - stacked_visibility = LightVisibility::Instance()->GetVisibility(); + stacked_visibility = Thread->Light->GetVisibility(); } void RenderPortal::SetMainPortal() diff --git a/src/swrenderer/scene/r_scene.cpp b/src/swrenderer/scene/r_scene.cpp index 5f0c41bd6..8d7ae6784 100644 --- a/src/swrenderer/scene/r_scene.cpp +++ b/src/swrenderer/scene/r_scene.cpp @@ -83,7 +83,7 @@ namespace swrenderer int height = SCREENHEIGHT; float trueratio; ActiveRatio(width, height, &trueratio); - viewport->SetViewport(width, height, trueratio); + viewport->SetViewport(MainThread(), width, height, trueratio); if (r_clearbuffer != 0) { @@ -185,6 +185,7 @@ namespace swrenderer for (int i = 0; i < numThreads; i++) { *Threads[i]->Viewport = *MainThread()->Viewport; + *Threads[i]->Light = *MainThread()->Light; Threads[i]->X1 = viewwidth * i / numThreads; Threads[i]->X2 = viewwidth * (i + 1) / numThreads; } @@ -333,7 +334,7 @@ namespace swrenderer viewwindowx = x; viewwindowy = y; viewactive = true; - viewport->SetViewport(width, height, MainThread()->Viewport->viewwindow.WidescreenRatio); + viewport->SetViewport(MainThread(), width, height, MainThread()->Viewport->viewwindow.WidescreenRatio); RenderActorView(actor, dontmaplines); @@ -343,7 +344,7 @@ namespace swrenderer float trueratio; ActiveRatio(width, height, &trueratio); screen->Lock(true); - viewport->SetViewport(width, height, trueratio); + viewport->SetViewport(MainThread(), width, height, trueratio); screen->Unlock(); viewactive = savedviewactive; @@ -358,7 +359,7 @@ namespace swrenderer float trueratio; ActiveRatio(width, height, &trueratio); screen->Lock(true); - viewport->SetViewport(SCREENWIDTH, SCREENHEIGHT, trueratio); + viewport->SetViewport(MainThread(), SCREENWIDTH, SCREENHEIGHT, trueratio); screen->Unlock(); } diff --git a/src/swrenderer/things/r_particle.cpp b/src/swrenderer/things/r_particle.cpp index d3c048653..b6520deb0 100644 --- a/src/swrenderer/things/r_particle.cpp +++ b/src/swrenderer/things/r_particle.cpp @@ -204,7 +204,7 @@ namespace swrenderer vis->floorclip = 0; vis->foggy = foggy; - vis->Light.SetColormap(tiz * LightVisibility::Instance()->ParticleGlobVis(foggy), shade, map, particle->bright != 0, false, false); + vis->Light.SetColormap(tiz * thread->Light->ParticleGlobVis(foggy), shade, map, particle->bright != 0, false, false); thread->SpriteList->Push(vis); } diff --git a/src/swrenderer/things/r_sprite.cpp b/src/swrenderer/things/r_sprite.cpp index 88bec93ce..ca68803e1 100644 --- a/src/swrenderer/things/r_sprite.cpp +++ b/src/swrenderer/things/r_sprite.cpp @@ -280,7 +280,7 @@ namespace swrenderer vis->dynlightcolor = 0; } - vis->Light.SetColormap(LightVisibility::Instance()->SpriteGlobVis(foggy) / MAX(tz, MINZ), spriteshade, basecolormap, fullbright, invertcolormap, fadeToBlack); + vis->Light.SetColormap(thread->Light->SpriteGlobVis(foggy) / MAX(tz, MINZ), spriteshade, basecolormap, fullbright, invertcolormap, fadeToBlack); thread->SpriteList->Push(vis); } diff --git a/src/swrenderer/things/r_visiblesprite.cpp b/src/swrenderer/things/r_visiblesprite.cpp index ea895321a..dd844c5f7 100644 --- a/src/swrenderer/things/r_visiblesprite.cpp +++ b/src/swrenderer/things/r_visiblesprite.cpp @@ -140,7 +140,7 @@ namespace swrenderer int spriteshade = LightVisibility::LightLevelToShade(sec->lightlevel + LightVisibility::ActualExtraLight(spr->foggy, thread->Viewport.get()), foggy); - Light.SetColormap(LightVisibility::Instance()->SpriteGlobVis(foggy) / MAX(MINZ, (double)spr->depth), spriteshade, mybasecolormap, isFullBright, invertcolormap, fadeToBlack); + Light.SetColormap(thread->Light->SpriteGlobVis(foggy) / MAX(MINZ, (double)spr->depth), spriteshade, mybasecolormap, isFullBright, invertcolormap, fadeToBlack); } } diff --git a/src/swrenderer/things/r_voxel.cpp b/src/swrenderer/things/r_voxel.cpp index 46220d9dd..0d639381b 100644 --- a/src/swrenderer/things/r_voxel.cpp +++ b/src/swrenderer/things/r_voxel.cpp @@ -170,7 +170,7 @@ namespace swrenderer bool fullbright = !vis->foggy && ((renderflags & RF_FULLBRIGHT) || (thing->flags5 & MF5_BRIGHT)); bool fadeToBlack = (vis->RenderStyle.Flags & STYLEF_FadeToBlack) != 0; - vis->Light.SetColormap(LightVisibility::Instance()->SpriteGlobVis(foggy) / MAX(tz, MINZ), spriteshade, basecolormap, fullbright, invertcolormap, fadeToBlack); + vis->Light.SetColormap(thread->Light->SpriteGlobVis(foggy) / MAX(tz, MINZ), spriteshade, basecolormap, fullbright, invertcolormap, fadeToBlack); thread->SpriteList->Push(vis, true); } diff --git a/src/swrenderer/things/r_wallsprite.cpp b/src/swrenderer/things/r_wallsprite.cpp index 1c6cdfa59..15757bc86 100644 --- a/src/swrenderer/things/r_wallsprite.cpp +++ b/src/swrenderer/things/r_wallsprite.cpp @@ -133,7 +133,7 @@ namespace swrenderer vis->wallc = wallc; vis->foggy = foggy; - vis->Light.SetColormap(LightVisibility::Instance()->SpriteGlobVis(foggy) / MAX(tz, MINZ), spriteshade, basecolormap, false, false, false); + vis->Light.SetColormap(thread->Light->SpriteGlobVis(foggy) / MAX(tz, MINZ), spriteshade, basecolormap, false, false, false); thread->SpriteList->Push(vis); } @@ -183,7 +183,7 @@ namespace swrenderer SpriteDrawerArgs drawerargs; int shade = LightVisibility::LightLevelToShade(spr->sector->lightlevel + LightVisibility::ActualExtraLight(spr->foggy, thread->Viewport.get()), spr->foggy); - double GlobVis = LightVisibility::Instance()->WallGlobVis(foggy); + double GlobVis = thread->Light->WallGlobVis(foggy); float lightleft = float(GlobVis / spr->wallc.sz1); float lightstep = float((GlobVis / spr->wallc.sz2 - lightleft) / (spr->wallc.sx2 - spr->wallc.sx1)); float light = lightleft + (x1 - spr->wallc.sx1) * lightstep; diff --git a/src/swrenderer/viewport/r_skydrawer.cpp b/src/swrenderer/viewport/r_skydrawer.cpp index df93c6eed..e2ce020e0 100644 --- a/src/swrenderer/viewport/r_skydrawer.cpp +++ b/src/swrenderer/viewport/r_skydrawer.cpp @@ -34,9 +34,10 @@ namespace swrenderer dc_viewport = viewport; } - void SkyDrawerArgs::SetFrontTexture(RenderViewport *viewport, FTexture *texture, uint32_t column) + void SkyDrawerArgs::SetFrontTexture(RenderThread *thread, FTexture *texture, uint32_t column) { - if (viewport->RenderTarget->IsBgra()) + thread->PrepareTexture(texture); + if (thread->Viewport->RenderTarget->IsBgra()) { dc_source = (const uint8_t *)texture->GetColumnBgra(column, nullptr); dc_sourceheight = texture->GetHeight(); @@ -48,14 +49,15 @@ namespace swrenderer } } - void SkyDrawerArgs::SetBackTexture(RenderViewport *viewport, FTexture *texture, uint32_t column) + void SkyDrawerArgs::SetBackTexture(RenderThread *thread, FTexture *texture, uint32_t column) { + thread->PrepareTexture(texture); if (texture == nullptr) { dc_source2 = nullptr; dc_sourceheight2 = 1; } - else if (viewport->RenderTarget->IsBgra()) + else if (thread->Viewport->RenderTarget->IsBgra()) { dc_source2 = (const uint8_t *)texture->GetColumnBgra(column, nullptr); dc_sourceheight2 = texture->GetHeight(); diff --git a/src/swrenderer/viewport/r_skydrawer.h b/src/swrenderer/viewport/r_skydrawer.h index 2f352e939..4d7d44839 100644 --- a/src/swrenderer/viewport/r_skydrawer.h +++ b/src/swrenderer/viewport/r_skydrawer.h @@ -15,8 +15,8 @@ namespace swrenderer public: void SetDest(RenderViewport *viewport, int x, int y); void SetCount(int count) { dc_count = count; } - void SetFrontTexture(RenderViewport *viewport, FTexture *texture, uint32_t column); - void SetBackTexture(RenderViewport *viewport, FTexture *texture, uint32_t column); + void SetFrontTexture(RenderThread *thread, FTexture *texture, uint32_t column); + void SetBackTexture(RenderThread *thread, FTexture *texture, uint32_t column); void SetTextureVPos(uint32_t texturefrac) { dc_texturefrac = texturefrac; } void SetTextureVStep(uint32_t iscale) { dc_iscale = iscale; } void SetSolidTop(uint32_t color) { solid_top = color; } diff --git a/src/swrenderer/viewport/r_spandrawer.cpp b/src/swrenderer/viewport/r_spandrawer.cpp index afe1cbc66..8900dfe25 100644 --- a/src/swrenderer/viewport/r_spandrawer.cpp +++ b/src/swrenderer/viewport/r_spandrawer.cpp @@ -22,8 +22,10 @@ namespace swrenderer spanfunc = &SWPixelFormatDrawers::DrawSpan; } - void SpanDrawerArgs::SetTexture(RenderViewport *viewport, FTexture *tex) + void SpanDrawerArgs::SetTexture(RenderThread *thread, FTexture *tex) { + thread->PrepareTexture(tex); + tex->GetWidth(); ds_xbits = tex->WidthBits; ds_ybits = tex->HeightBits; @@ -36,7 +38,7 @@ namespace swrenderer ds_ybits--; } - ds_source = viewport->RenderTarget->IsBgra() ? (const uint8_t*)tex->GetPixelsBgra() : tex->GetPixels(); + ds_source = thread->Viewport->RenderTarget->IsBgra() ? (const uint8_t*)tex->GetPixelsBgra() : tex->GetPixels(); ds_source_mipmapped = tex->Mipmapped() && tex->GetWidth() > 1 && tex->GetHeight() > 1; } diff --git a/src/swrenderer/viewport/r_spandrawer.h b/src/swrenderer/viewport/r_spandrawer.h index cba3ab0d7..4cb131b37 100644 --- a/src/swrenderer/viewport/r_spandrawer.h +++ b/src/swrenderer/viewport/r_spandrawer.h @@ -19,7 +19,7 @@ namespace swrenderer void SetDestY(RenderViewport *viewport, int y) { ds_viewport = viewport; ds_y = y; } void SetDestX1(int x) { ds_x1 = x; } void SetDestX2(int x) { ds_x2 = x; } - void SetTexture(RenderViewport *viewport, FTexture *tex); + void SetTexture(RenderThread *thread, FTexture *tex); void SetTextureLOD(double lod) { ds_lod = lod; } void SetTextureUPos(dsfixed_t xfrac) { ds_xfrac = xfrac; } void SetTextureVPos(dsfixed_t yfrac) { ds_yfrac = yfrac; } diff --git a/src/swrenderer/viewport/r_spritedrawer.cpp b/src/swrenderer/viewport/r_spritedrawer.cpp index cd5bc44d7..6226c9696 100644 --- a/src/swrenderer/viewport/r_spritedrawer.cpp +++ b/src/swrenderer/viewport/r_spritedrawer.cpp @@ -49,7 +49,7 @@ namespace swrenderer return; auto viewport = thread->Viewport.get(); - + // Handle the linear filtered version in a different function to reduce chances of merge conflicts from zdoom. if (viewport->RenderTarget->IsBgra() && !drawer_needs_pal_input) // To do: add support to R_DrawColumnHoriz_rgba { @@ -62,6 +62,8 @@ namespace swrenderer dc_iscale = iscale; dc_textureheight = tex->GetHeight(); + thread->PrepareTexture(tex); + const FTexture::Span *span; const uint8_t *column; if (viewport->RenderTarget->IsBgra() && !drawer_needs_pal_input) @@ -132,6 +134,8 @@ namespace swrenderer dc_x = x; dc_iscale = iscale; + thread->PrepareTexture(tex); + // Normalize to 0-1 range: double uv_stepd = FIXED2DBL(dc_iscale); double v_step = uv_stepd / tex->GetHeight(); diff --git a/src/swrenderer/viewport/r_viewport.cpp b/src/swrenderer/viewport/r_viewport.cpp index 47599d1f4..c0caa6599 100644 --- a/src/swrenderer/viewport/r_viewport.cpp +++ b/src/swrenderer/viewport/r_viewport.cpp @@ -48,7 +48,7 @@ namespace swrenderer { } - void RenderViewport::SetViewport(int fullWidth, int fullHeight, float trueratio) + void RenderViewport::SetViewport(RenderThread *thread, int fullWidth, int fullHeight, float trueratio) { int virtheight, virtwidth, virtwidth2, virtheight2; @@ -101,8 +101,7 @@ namespace swrenderer InitTextureMapping(); // Reset r_*Visibility vars - LightVisibility *visibility = LightVisibility::Instance(); - visibility->SetVisibility(this, visibility->GetVisibility()); + thread->Light->SetVisibility(this, thread->Light->GetVisibility()); SetupBuffer(); } diff --git a/src/swrenderer/viewport/r_viewport.h b/src/swrenderer/viewport/r_viewport.h index 9898458a5..09f818b9d 100644 --- a/src/swrenderer/viewport/r_viewport.h +++ b/src/swrenderer/viewport/r_viewport.h @@ -19,13 +19,15 @@ namespace swrenderer { + class RenderThread; + class RenderViewport { public: RenderViewport(); ~RenderViewport(); - void SetViewport(int width, int height, float trueratio); + void SetViewport(RenderThread *thread, int width, int height, float trueratio); void SetupFreelook(); DCanvas *RenderTarget = nullptr;