Skip to content

Commit

Permalink
vis: huge speedup from fixing false sharing with stat counters
Browse files Browse the repository at this point in the history
gmsp3v2.bsp, 32 threads 3950x, 157s -> 61s
  • Loading branch information
ericwa committed Nov 8, 2023
1 parent 7e5ad9a commit c9edf4d
Show file tree
Hide file tree
Showing 3 changed files with 93 additions and 62 deletions.
41 changes: 32 additions & 9 deletions include/vis/vis.hh
Original file line number Diff line number Diff line change
Expand Up @@ -196,15 +196,45 @@ struct pstack_t
// important for perf as a ton of these are stack allocated, needs to be be just a pointer bump
static_assert(std::is_trivially_default_constructible_v<pstack_t>);

struct visstats_t
{
int64_t c_portaltest = 0;
int64_t c_portalpass = 0;
int64_t c_portalcheck = 0;
int64_t c_mightseeupdate = 0;
int64_t c_noclip = 0;
int64_t c_vistest = 0;
int64_t c_mighttest = 0;
int64_t c_chains = 0;
int64_t c_leafskip = 0;
int64_t c_portalskip = 0;

visstats_t operator+(const visstats_t& other) const {
visstats_t result;
result.c_portaltest = this->c_portaltest + other.c_portaltest;
result.c_portalpass = this->c_portalpass + other.c_portalpass;
result.c_portalcheck = this->c_portalcheck + other.c_portalcheck;
result.c_mightseeupdate = this->c_mightseeupdate + other.c_mightseeupdate;
result.c_noclip = this->c_noclip + other.c_noclip;
result.c_vistest = this->c_vistest + other.c_vistest;
result.c_mighttest = this->c_mighttest + other.c_mighttest;
result.c_chains = this->c_chains + other.c_chains;
result.c_leafskip = this->c_leafskip + other.c_leafskip;
result.c_portalskip = this->c_portalskip + other.c_portalskip;
return result;
}
};

viswinding_t *AllocStackWinding(pstack_t &stack);
void FreeStackWinding(viswinding_t *&w, pstack_t &stack);
viswinding_t *ClipStackWinding(viswinding_t *in, pstack_t &stack, const qplane3d &split);
viswinding_t *ClipStackWinding(visstats_t &stats, viswinding_t *in, pstack_t &stack, const qplane3d &split);

struct threaddata_t
{
leafbits_t &leafvis;
visportal_t *base;
pstack_t pstack_head;
visstats_t stats;
};

extern int numportals;
Expand All @@ -214,13 +244,6 @@ extern int portalleafs_real;
extern std::vector<visportal_t> portals; // always numportals * 2; front and back
extern std::vector<leaf_t> leafs;

extern int c_noclip;
extern int c_portaltest, c_portalpass, c_portalcheck;
extern int c_vistest, c_mighttest;
extern unsigned long c_chains;

extern bool showgetleaf;

extern std::vector<uint8_t> uncompressed;
extern int leafbytes;
extern int leafbytes_real;
Expand All @@ -230,7 +253,7 @@ extern fs::path portalfile, statefile, statetmpfile;

void BasePortalVis(void);

void PortalFlow(visportal_t *p);
visstats_t PortalFlow(visportal_t *p);

void CalcAmbientSounds(mbsp_t *bsp);

Expand Down
48 changes: 22 additions & 26 deletions vis/flow.cc
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,6 @@
#include <common/parallel.hh>
#include <atomic>

unsigned long c_chains;
int c_vistest, c_mighttest;

static int c_portalskip;
static int c_leafskip;

/*
==============
ClipToSeparators
Expand All @@ -30,7 +24,7 @@ static int c_leafskip;
pointer, was measurably faster
==============
*/
static void ClipToSeparators(const viswinding_t *source, const qplane3d src_pl, const viswinding_t *pass,
static void ClipToSeparators(visstats_t &stats, const viswinding_t *source, const qplane3d src_pl, const viswinding_t *pass,
viswinding_t *&target, unsigned int test, pstack_t &stack)
{
int i, j, k, l;
Expand Down Expand Up @@ -114,7 +108,7 @@ static void ClipToSeparators(const viswinding_t *source, const qplane3d src_pl,
stack.numseparators[test]++;
}

target = ClipStackWinding(target, stack, sep);
target = ClipStackWinding(stats, target, stack, sep);

if (!target)
return; // target is not visible
Expand Down Expand Up @@ -150,7 +144,7 @@ static void RecursiveLeafFlow(int leafnum, threaddata_t *thread, pstack_t &prevs
leaf_t *leaf;
int i, j, err, numblocks;

++c_chains;
++thread->stats.c_chains;

leaf = &leafs[leafnum];

Expand Down Expand Up @@ -193,18 +187,18 @@ static void RecursiveLeafFlow(int leafnum, threaddata_t *thread, pstack_t &prevs
p = leaf->portals[i];

if (!(*prevstack.mightsee)[p->leaf]) {
c_leafskip++;
thread->stats.c_leafskip++;
continue; // can't possibly see it
}

uint32_t *test;

// if the portal can't see anything we haven't allready seen, skip it
if (p->status == pstat_done) {
c_vistest++;
thread->stats.c_vistest++;
test = p->visbits.data();
} else {
c_mighttest++;
thread->stats.c_mighttest++;
test = p->mightsee.data();
}

Expand All @@ -217,7 +211,7 @@ static void RecursiveLeafFlow(int leafnum, threaddata_t *thread, pstack_t &prevs

if (!more) {
// can't see anything new
c_portalskip++;
thread->stats.c_portalskip++;
continue;
}
// get plane of portal, point normal into the neighbor leaf
Expand All @@ -227,7 +221,7 @@ static void RecursiveLeafFlow(int leafnum, threaddata_t *thread, pstack_t &prevs
if (qv::epsilonEqual(prevstack.portalplane.normal, backplane.normal, VIS_EQUAL_EPSILON))
continue; // can't go out a coplanar face

c_portalcheck++;
thread->stats.c_portalcheck++;

stack.portal = p;
stack.next = NULL;
Expand All @@ -244,7 +238,7 @@ static void RecursiveLeafFlow(int leafnum, threaddata_t *thread, pstack_t &prevs
*/

/* Clip any part of the target portal behind the source portal */
stack.pass = ClipStackWinding(p->winding.get(), stack, thread->pstack_head.portalplane);
stack.pass = ClipStackWinding(thread->stats, p->winding.get(), stack, thread->pstack_head.portalplane);
if (!stack.pass)
continue;

Expand All @@ -257,31 +251,31 @@ static void RecursiveLeafFlow(int leafnum, threaddata_t *thread, pstack_t &prevs
}

/* Clip any part of the target portal behind the pass portal */
stack.pass = ClipStackWinding(stack.pass, stack, prevstack.portalplane);
stack.pass = ClipStackWinding(thread->stats, stack.pass, stack, prevstack.portalplane);
if (!stack.pass)
continue;

/* Clip any part of the source portal in front of the target portal */
stack.source = ClipStackWinding(prevstack.source, stack, backplane);
stack.source = ClipStackWinding(thread->stats, prevstack.source, stack, backplane);
if (!stack.source) {
FreeStackWinding(stack.pass, stack);
continue;
}

c_portaltest++;
thread->stats.c_portaltest++;

/* TEST 0 :: source -> pass -> target */
if (vis_options.level.value() > 0) {
if (stack.numseparators[0]) {
for (j = 0; j < stack.numseparators[0]; j++) {
stack.pass = ClipStackWinding(stack.pass, stack, stack.separators[0][j]);
stack.pass = ClipStackWinding(thread->stats, stack.pass, stack, stack.separators[0][j]);
if (!stack.pass)
break;
}
} else {
/* Using prevstack source for separator cache correctness */
ClipToSeparators(
prevstack.source, thread->pstack_head.portalplane, prevstack.pass, stack.pass, 0, stack);
thread->stats, prevstack.source, thread->pstack_head.portalplane, prevstack.pass, stack.pass, 0, stack);
}
if (!stack.pass) {
FreeStackWinding(stack.source, stack);
Expand All @@ -293,13 +287,13 @@ static void RecursiveLeafFlow(int leafnum, threaddata_t *thread, pstack_t &prevs
if (vis_options.level.value() > 1) {
if (stack.numseparators[1]) {
for (j = 0; j < stack.numseparators[1]; j++) {
stack.pass = ClipStackWinding(stack.pass, stack, stack.separators[1][j]);
stack.pass = ClipStackWinding(thread->stats, stack.pass, stack, stack.separators[1][j]);
if (!stack.pass)
break;
}
} else {
/* Using prevstack source for separator cache correctness */
ClipToSeparators(prevstack.pass, prevstack.portalplane, prevstack.source, stack.pass, 1, stack);
ClipToSeparators(thread->stats, prevstack.pass, prevstack.portalplane, prevstack.source, stack.pass, 1, stack);
}
if (!stack.pass) {
FreeStackWinding(stack.source, stack);
Expand All @@ -309,7 +303,7 @@ static void RecursiveLeafFlow(int leafnum, threaddata_t *thread, pstack_t &prevs

/* TEST 2 :: target -> pass -> source */
if (vis_options.level.value() > 2) {
ClipToSeparators(stack.pass, stack.portalplane, prevstack.pass, stack.source, 2, stack);
ClipToSeparators(thread->stats, stack.pass, stack.portalplane, prevstack.pass, stack.source, 2, stack);
if (!stack.source) {
FreeStackWinding(stack.pass, stack);
continue;
Expand All @@ -318,14 +312,14 @@ static void RecursiveLeafFlow(int leafnum, threaddata_t *thread, pstack_t &prevs

/* TEST 3 :: pass -> target -> source */
if (vis_options.level.value() > 3) {
ClipToSeparators(prevstack.pass, prevstack.portalplane, stack.pass, stack.source, 3, stack);
ClipToSeparators(thread->stats, prevstack.pass, prevstack.portalplane, stack.pass, stack.source, 3, stack);
if (!stack.source) {
FreeStackWinding(stack.pass, stack);
continue;
}
}

c_portalpass++;
thread->stats.c_portalpass++;

// flow through it for real
RecursiveLeafFlow(p->leaf, thread, stack);
Expand All @@ -340,7 +334,7 @@ static void RecursiveLeafFlow(int leafnum, threaddata_t *thread, pstack_t &prevs
PortalFlow
===============
*/
void PortalFlow(visportal_t *p)
visstats_t PortalFlow(visportal_t *p)
{
threaddata_t data{p->visbits};

Expand All @@ -357,6 +351,8 @@ void PortalFlow(visportal_t *p)
data.pstack_head.mightsee = &p->mightsee;

RecursiveLeafFlow(p->leaf, &data, data.pstack_head);

return data.stats;
}

/*
Expand Down
Loading

0 comments on commit c9edf4d

Please sign in to comment.