Skip to content

Commit

Permalink
Sector based culling
Browse files Browse the repository at this point in the history
  • Loading branch information
vs-shirokii committed Jun 16, 2024
1 parent c18e673 commit a478271
Show file tree
Hide file tree
Showing 5 changed files with 256 additions and 29 deletions.
6 changes: 4 additions & 2 deletions src/common/rendering/rt/rt_cvars.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,8 @@
namespace cvar
{

EXTERN_CVAR( Bool, rt_nocull )
EXTERN_CVAR( Int, rt_cpu_cullmode )
EXTERN_CVAR( Float, rt_cpu_nocullradius )

EXTERN_CVAR( Float, rt_classic )

Expand Down Expand Up @@ -38,4 +39,5 @@ extern bool rt_firststart;

}

#define rt_nocull cvar::rt_nocull
#define rt_only_one_side_wall true
#define rt_nocull_flat true
3 changes: 2 additions & 1 deletion src/common/rendering/rt/rt_main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,8 @@ namespace cvar
{
// NOTE: if name start with '_' then the cvar won't be archived

RT_CVAR( rt_nocull, true, "If true, BSP culling is disabled" )
RT_CVAR( rt_cpu_cullmode, 0, "[IMPACTS CPU PERFORMANCE HEAVILY] 0: BSP + all neighbor sectors of visible, 1 - original GZDoom's BSP/clip checks, 2: uploading whole map, no culling at all" )
RT_CVAR( rt_cpu_nocullradius, 10.f, "[IMPACTS CPU PERFORMANCE] Radius (in meters) in which culling must not be applied. Applicable with rt_cpu_cullmode=0" )

RT_CVAR( rt_autoexport, true, "if true: if map's gltf doesn't exist on disk, export to gltf "
"and process the map as if it's static (which improves performance / stability)" )
Expand Down
262 changes: 243 additions & 19 deletions src/rendering/hwrenderer/scene/hw_bsp.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,9 @@ EXTERN_CVAR(Float, r_actorspriteshadowdist)

#if HAVE_RT
#include "rt/rt_cvars.h"

static bool rt_nocull = false;
static std::vector< bool > rt_segdrawn = {};
#endif

thread_local bool isWorkerThread;
Expand Down Expand Up @@ -275,11 +278,10 @@ void HWDrawInfo::AddLine (seg_t *seg, bool portalclip)
angle_t endAngle = clipper.GetClipAngle(seg->v1);

// Back side, i.e. backface culling - read: endAngle >= startAngle!
#if !HAVE_RT
if (startAngle-endAngle<ANGLE_180)
#else
if (!rt_nocull && (startAngle-endAngle<ANGLE_180))
#if HAVE_RT
if( !rt_nocull )
#endif
if (startAngle-endAngle<ANGLE_180)
{
return;
}
Expand All @@ -288,23 +290,21 @@ void HWDrawInfo::AddLine (seg_t *seg, bool portalclip)
{
if (!(currentsubsector->flags & SSECMF_DRAWN))
{
#if !HAVE_RT
if (clipper.SafeCheckRange(startAngle, endAngle))
#else
if (!rt_nocull && (clipper.SafeCheckRange(startAngle, endAngle)))
#if HAVE_RT
if( !rt_nocull )
#endif
if (clipper.SafeCheckRange(startAngle, endAngle))
{
currentsubsector->flags |= SSECMF_DRAWN;
}
}
return;
}

#if !HAVE_RT
if (!clipper.SafeCheckRange(startAngle, endAngle))
#else
if (!rt_nocull && (!clipper.SafeCheckRange(startAngle, endAngle)))
#if HAVE_RT
if( !rt_nocull )
#endif
if (!clipper.SafeCheckRange(startAngle, endAngle))
{
return;
}
Expand All @@ -314,6 +314,9 @@ void HWDrawInfo::AddLine (seg_t *seg, bool portalclip)

if (!seg->backsector)
{
#if HAVE_RT
if( !rt_nocull )
#endif
clipper.SafeAddClipRange(startAngle, endAngle);
}
else if (!ispoly) // Two-sided polyobjects never obstruct the view
Expand Down Expand Up @@ -341,6 +344,9 @@ void HWDrawInfo::AddLine (seg_t *seg, bool portalclip)

if (hw_CheckClip(seg->sidedef, currentsector, backsector))
{
#if HAVE_RT
if( !rt_nocull )
#endif
clipper.SafeAddClipRange(startAngle, endAngle);
}
}
Expand All @@ -353,13 +359,20 @@ void HWDrawInfo::AddLine (seg_t *seg, bool portalclip)

seg->linedef->flags |= ML_MAPPED;

if (ispoly || seg->linedef->validcount!=validcount)
{
#if !HAVE_RT
if (!ispoly) seg->linedef->validcount=validcount;
if (ispoly || seg->linedef->validcount!=validcount)
#else
if (!rt_nocull && !ispoly) seg->linedef->validcount=validcount;
const bool segforce =
rt_nocull && ( seg->segnum >= 0 && seg->segnum < int( rt_segdrawn.size() ) &&
!rt_segdrawn[ seg->segnum ] );

if (ispoly || seg->linedef->validcount!=validcount || segforce)
#endif
{
#if HAVE_RT
if( !rt_nocull )
#endif
if (!ispoly) seg->linedef->validcount=validcount;

if (gl_render_walls)
{
Expand All @@ -377,6 +390,17 @@ void HWDrawInfo::AddLine (seg_t *seg, bool portalclip)
rendered_lines++;
SetupWall.Unclock();
}

#if HAVE_RT
if( seg->segnum >= 0 && seg->segnum < int( rt_segdrawn.size() ) )
{
rt_segdrawn[ seg->segnum ] = true;
}
else
{
assert( 0 );
}
#endif
}
}
}
Expand Down Expand Up @@ -853,14 +877,183 @@ void HWDrawInfo::RenderBSPNode (void *node)
}

#if HAVE_RT
if (rt_nocull)
if( cvar::rt_cpu_cullmode == 2 )
{
for (subsector_t& s : Level->subsectors)
for( subsector_t& s : Level->subsectors )
{
DoSubsector(&s);
DoSubsector( &s );
}
return;
}

if( rt_nocull )
{
assert( cvar::rt_cpu_cullmode != 1 && cvar::rt_cpu_cullmode != 2 );

static auto rt_sectorvis = std::vector< bool >{};
rt_sectorvis.resize( Level->sectors.size() );

rt_sectorvis.assign( rt_sectorvis.size(), false );
for( const seg_t& seg : level.segs )
{
if( seg.segnum < 0 || seg.segnum >= int( rt_segdrawn.size() ) )
{
assert( 0 );
continue;
}

bool visible = rt_segdrawn[ seg.segnum ];

if( visible )
{
int sectornum = seg.Subsector->sector->sectornum;
if( sectornum >= 0 && sectornum < int( rt_sectorvis.size() ) )
{
rt_sectorvis[ sectornum ] = true;
}
else
{
assert( 0 );
}
}
}

static auto sectorvis_expanded = std::vector< bool >{};
sectorvis_expanded.resize( Level->sectors.size() );


// add in radius
if( cvar::rt_cpu_nocullradius > 0.1f )
{
const float nocullradius = 32 * float( cvar::rt_cpu_nocullradius ); // from metric

const auto viewbox = FBoundingBox( Viewpoint.Pos.X, Viewpoint.Pos.Y, nocullradius );

sectorvis_expanded.assign( sectorvis_expanded.size(), false );
for( const sector_t& candidate : Level->sectors )
{
if( candidate.sectornum < 0 && candidate.sectornum >= int( rt_sectorvis.size() ) )
{
assert( 0 );
continue;
}

if( rt_sectorvis[ candidate.sectornum ] )
{
sectorvis_expanded[ candidate.sectornum ] = true;
continue;
}

bool touches = false;
for( const line_t* l : candidate.Lines )
{
if( l && inRange( viewbox, l ) )
{
touches = true;
break;
}
}

if( !touches )
{
continue;
}
for( seg_t& seg : Level->segs )
{
int fs = ( seg.frontsector && seg.frontsector->sectornum >= 0 &&
seg.frontsector->sectornum < int( rt_sectorvis.size() ) )
? seg.frontsector->sectornum
: -1;
if( fs < 0 )
{
continue;
}

int bs = ( seg.backsector && seg.backsector->sectornum >= 0 &&
seg.backsector->sectornum < int( rt_sectorvis.size() ) )
? seg.backsector->sectornum
: -1;
if( bs < 0 )
{
continue;
}

// 'fs' is a neighbor, and 'fs' is visible => candidate is visible
// 'bs' is a neighbor, and 'bs' is visible => candidate is visible
if( ( candidate.sectornum == fs && rt_sectorvis[ bs ] ) ||
( candidate.sectornum == bs && rt_sectorvis[ fs ] ) )
{
sectorvis_expanded[ candidate.sectornum ] = true;
break;
}
}
}

std::swap( sectorvis_expanded, rt_sectorvis );
}


// add neighbor sectors
sectorvis_expanded.assign( sectorvis_expanded.size(), false );
for( seg_t& seg : Level->segs )
{
int fs = ( seg.frontsector && seg.frontsector->sectornum >= 0 &&
seg.frontsector->sectornum < int( rt_sectorvis.size() ) )
? seg.frontsector->sectornum
: -1;

int bs = ( seg.backsector && seg.backsector->sectornum >= 0 &&
seg.backsector->sectornum < int( rt_sectorvis.size() ) )
? seg.backsector->sectornum
: -1;

// front visible
if( fs >= 0 && rt_sectorvis[ fs ] )
{
sectorvis_expanded[ fs ] = true;
// automatically, back is visible too
if( bs >= 0 )
{
sectorvis_expanded[ bs ] = true;
}
}

// back visible
if( bs >= 0 && rt_sectorvis[ bs ] )
{
sectorvis_expanded[ bs ] = true;
// automatically, front is visible too
if( fs >= 0 )
{
sectorvis_expanded[ fs ] = true;
}
}
}

for( const sector_t& sector : Level->sectors )
{
if( sector.sectornum < 0 && sector.sectornum >= int( sectorvis_expanded.size() ) )
{
assert( 0 );
continue;
}
if( !sectorvis_expanded[ sector.sectornum ] )
{
// not visible
continue;
}

for( int i = 0; i < sector.subsectorcount; i++ )
{
if( sector.subsectors[ i ] )
{
DoSubsector( sector.subsectors[ i ] );
}
}
}

return;
}
#endif

while (!((size_t)node & 1)) // Keep going until found a subsector
Expand Down Expand Up @@ -898,14 +1091,32 @@ void HWDrawInfo::RenderBSP(void *node, bool drawpsprites)

validcount++; // used for processing sidedefs only once by the renderer.

#if HAVE_RT
rt_segdrawn.resize( Level ? Level->segs.size() : 0, false );
rt_segdrawn.assign( rt_segdrawn.size(), false );
#endif

multithread = gl_multithread;
if (multithread)
{
jobQueue.ReleaseAll();
auto future = renderPool.push([&](int id) {
WorkerThread();
});
#if !HAVE_RT
RenderBSPNode(node);
#else
if( cvar::rt_cpu_cullmode != 2 )
{
rt_nocull = false;
RenderBSPNode( node );
}
if( cvar::rt_cpu_cullmode != 1 )
{
rt_nocull = true;
RenderBSPNode( node );
}
#endif

jobQueue.AddJob(RenderJob::TerminateJob, nullptr, nullptr);
Bsp.Unclock();
Expand All @@ -915,7 +1126,20 @@ void HWDrawInfo::RenderBSP(void *node, bool drawpsprites)
}
else
{
#if !HAVE_RT
RenderBSPNode(node);
#else
if( cvar::rt_cpu_cullmode != 2 )
{
rt_nocull = false;
RenderBSPNode( node );
}
if( cvar::rt_cpu_cullmode != 1 )
{
rt_nocull = true;
RenderBSPNode( node );
}
#endif
Bsp.Unclock();
}
// Process all the sprites on the current portal's back side which touch the portal.
Expand Down
2 changes: 1 addition & 1 deletion src/rendering/hwrenderer/scene/hw_drawlistadd.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ void HWDrawInfo::AddWall(HWWall *wall)
}

#if HAVE_RT // push only one side of double-sided walls that are alpha-tested
if (rt_nocull)
if (rt_only_one_side_wall)
{
// if alpha-tested
if (list == GLDL_MASKEDWALLS || list == GLDL_MASKEDWALLSOFS)
Expand Down
Loading

0 comments on commit a478271

Please sign in to comment.