diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 366fdf980..dafcb994e 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -721,6 +721,7 @@ set( FASTMATH_SOURCES rendering/hwrenderer/scene/hw_clipper.cpp rendering/hwrenderer/scene/hw_flats.cpp rendering/hwrenderer/scene/hw_portal.cpp + rendering/hwrenderer/scene/hw_meshportal.cpp rendering/hwrenderer/scene/hw_renderhacks.cpp rendering/hwrenderer/scene/hw_sky.cpp rendering/hwrenderer/scene/hw_skyportal.cpp diff --git a/src/rendering/hwrenderer/scene/hw_bsp.cpp b/src/rendering/hwrenderer/scene/hw_bsp.cpp index 49706ca11..2236ed10a 100644 --- a/src/rendering/hwrenderer/scene/hw_bsp.cpp +++ b/src/rendering/hwrenderer/scene/hw_bsp.cpp @@ -42,6 +42,7 @@ #include "hw_clock.h" #include "flatvertices.h" #include "hw_vertexbuilder.h" +#include "hw_meshportal.h" #ifdef ARCH_IA32 #include @@ -50,6 +51,7 @@ CVAR(Bool, gl_multithread, true, CVAR_ARCHIVE | CVAR_GLOBALCONFIG) EXTERN_CVAR(Float, r_actorspriteshadowdist) +EXTERN_CVAR(Bool, gl_meshcache) thread_local bool isWorkerThread; ctpl::thread_pool renderPool(1); @@ -347,6 +349,14 @@ void HWDrawInfo::AddLine (seg_t *seg, bool portalclip, FRenderState& state) { jobQueue.AddJob(RenderJob::WallJob, seg->Subsector, seg); } + else if (MeshBSP) + { + SetupWall.Clock(); + HWPortalWall portalwall; + portalwall.Process(this, state, seg, currentsector, backsector); + rendered_lines++; + SetupWall.Unclock(); + } else { HWWall wall; @@ -737,7 +747,7 @@ void HWDrawInfo::DoSubsector(subsector_t * sub, FRenderState& state) { jobQueue.AddJob(RenderJob::FlatJob, sub); } - else + else if (!MeshBSP) { HWFlat flat; flat.section = sub->section; @@ -843,7 +853,8 @@ void HWDrawInfo::RenderBSP(void *node, bool drawpsprites, FRenderState& state) validcount++; // used for processing sidedefs only once by the renderer. - multithread = gl_multithread; + MeshBSP = gl_meshcache; + multithread = gl_multithread && !MeshBSP; if (multithread) { jobQueue.ReleaseAll(); diff --git a/src/rendering/hwrenderer/scene/hw_drawinfo.cpp b/src/rendering/hwrenderer/scene/hw_drawinfo.cpp index a39426009..141247962 100644 --- a/src/rendering/hwrenderer/scene/hw_drawinfo.cpp +++ b/src/rendering/hwrenderer/scene/hw_drawinfo.cpp @@ -140,7 +140,7 @@ void HWDrawInfo::StartScene(FRenderViewpoint &parentvp, HWViewpointUniforms *uni HWDrawInfo *HWDrawInfo::EndDrawInfo() { - assert(this == gl_drawinfo); + assert(this == drawctx->gl_drawinfo); for (int i = 0; i < GLDL_TYPES; i++) drawlists[i].Reset(); drawctx->gl_drawinfo = outer; drawctx->di_list.Release(this); @@ -394,8 +394,7 @@ void HWDrawInfo::CreateScene(bool drawpsprites, FRenderState& state) // clip the scene and fill the drawlists - if (!gl_meshcache) - RenderBSP(Level->HeadNode(), drawpsprites, state); + RenderBSP(Level->HeadNode(), drawpsprites, state); // And now the crappy hacks that have to be done to avoid rendering anomalies. // These cannot be multithreaded when the time comes because all these depend diff --git a/src/rendering/hwrenderer/scene/hw_drawinfo.h b/src/rendering/hwrenderer/scene/hw_drawinfo.h index 6404b78ff..b4a462836 100644 --- a/src/rendering/hwrenderer/scene/hw_drawinfo.h +++ b/src/rendering/hwrenderer/scene/hw_drawinfo.h @@ -175,6 +175,7 @@ struct HWDrawInfo fixed_t viewx, viewy; // since the nodes are still fixed point, keeping the view position also fixed point for node traversal is faster. bool multithread; + bool MeshBSP = false; bool MeshBuilding = false; HWDrawInfo(HWDrawContext* drawctx) : drawctx(drawctx) { for (HWDrawList& list : drawlists) list.drawctx = drawctx; } diff --git a/src/rendering/hwrenderer/scene/hw_meshportal.cpp b/src/rendering/hwrenderer/scene/hw_meshportal.cpp new file mode 100644 index 000000000..34f470e1d --- /dev/null +++ b/src/rendering/hwrenderer/scene/hw_meshportal.cpp @@ -0,0 +1,64 @@ + +#include "hw_meshportal.h" +#include "p_local.h" +#include "p_lnspec.h" +#include "a_dynlight.h" +#include "a_sharedglobal.h" +#include "r_defs.h" +#include "r_sky.h" +#include "r_utility.h" +#include "p_maputl.h" +#include "doomdata.h" +#include "g_levellocals.h" +#include "actorinlines.h" +#include "texturemanager.h" +#include "hw_dynlightdata.h" +#include "hw_material.h" +#include "hw_cvars.h" +#include "hw_clock.h" +#include "hw_lighting.h" +#include "hw_drawcontext.h" +#include "hw_drawinfo.h" +#include "hw_renderstate.h" + +void HWPortalWall::Process(HWDrawInfo* di, FRenderState& state, seg_t* seg, sector_t* frontsector, sector_t* backsector) +{ + // The portal code wants a HWWall struct. + + if (IsPortal(di, state, seg, frontsector, backsector)) + { + HWWall wall; + wall.sub = seg->Subsector; + wall.Process(di, state, seg, frontsector, backsector); + } +} + +bool HWPortalWall::IsPortal(HWDrawInfo* di, FRenderState& state, seg_t* seg, sector_t* frontsector, sector_t* backsector) +{ + // Note: This is incomplete. It assumes a completely valid map. Good luck adding the full range of checks! + + if (seg->linedef->special == Line_Mirror && gl_mirrors) + return true; + + if (seg->linedef->special == Line_Horizon) + return true; + + if (seg->linedef->isVisualPortal() && seg->sidedef == seg->linedef->sidedef[0]) + return true; + + if (seg->linedef->GetTransferredPortal()) + return true; + + for (int plane : { sector_t::floor, sector_t::ceiling }) + { + FSectorPortal* sportal = frontsector->ValidatePortal(plane); + if (frontsector->ValidatePortal(plane) && !(sportal->mFlags & PORTSF_INSKYBOX)) // no recursions + return true; + if (frontsector->GetTexture(plane) == skyflatnum) + return true; + if (frontsector->GetReflect(plane) > 0) + return true; + } + + return false; +} diff --git a/src/rendering/hwrenderer/scene/hw_meshportal.h b/src/rendering/hwrenderer/scene/hw_meshportal.h new file mode 100644 index 000000000..7a4151c03 --- /dev/null +++ b/src/rendering/hwrenderer/scene/hw_meshportal.h @@ -0,0 +1,12 @@ +#pragma once + +#include "hw_drawstructs.h" + +class HWPortalWall +{ +public: + static void Process(HWDrawInfo* di, FRenderState& state, seg_t* seg, sector_t* frontsector, sector_t* backsector); + +private: + static bool IsPortal(HWDrawInfo* di, FRenderState& state, seg_t* seg, sector_t* frontsector, sector_t* backsector); +};