[qfvis] Thread the portal vis compaction

The compaction deals with merging all the portal visibility into cluster
visibility, expanding out to leafs, and final compression.
This commit is contained in:
Bill Currie 2021-08-01 17:06:13 +09:00
parent 80a89c5e1e
commit e671b3f230
3 changed files with 105 additions and 50 deletions

View file

@ -171,7 +171,6 @@ typedef struct threaddata_s {
portal_t *base; ///< portal for which this thread is being run portal_t *base; ///< portal for which this thread is being run
pstack_t pstack_head; pstack_t pstack_head;
sep_t *sep_freelist; ///< per-thread list of free separators sep_t *sep_freelist; ///< per-thread list of free separators
winding_t *winding_freelist; ///< per-thread list of free windings
memsuper_t *memsuper; ///< per-thread memory pool memsuper_t *memsuper; ///< per-thread memory pool
memhunk_t *hunk; memhunk_t *hunk;
dstring_t *str; dstring_t *str;
@ -224,7 +223,7 @@ int CompressRow (struct sizebuf_s *dest, const byte *vis, unsigned num_leafs,
void CalcFatPVS (void); void CalcFatPVS (void);
void RunThreads (void *(*thread_func) (void *), int (*progress)(int, int)); void RunThreads (void *(*thread_func) (void *), int (*calc_progress)(void));
extern const char spinner[]; extern const char spinner[];
extern const char progress[]; extern const char progress[];

View file

@ -69,15 +69,9 @@ update_stats (fatstats_t *stats)
} }
static int static int
print_progress (int prev_prog, int spinner_ind) leaf_progress (void)
{ {
int prog; return work_leaf * 100 / num_leafs;
prog = work_leaf * 50 / num_leafs;
if (prog > prev_prog)
printf ("%.*s", prog - prev_prog, progress + prev_prog);
printf (" %c\b\b", spinner[spinner_ind % 4]);
fflush (stdout);
return prog;
} }
static unsigned static unsigned
@ -258,11 +252,11 @@ CalcFatPVS (void)
}; };
} }
work_leaf = 0; work_leaf = 0;
RunThreads (decompress_thread, print_progress); RunThreads (decompress_thread, leaf_progress);
work_leaf = 0; work_leaf = 0;
RunThreads (fatten_thread, print_progress); RunThreads (fatten_thread, leaf_progress);
work_leaf = 0; work_leaf = 0;
RunThreads (compress_thread, print_progress); RunThreads (compress_thread, leaf_progress);
printf ("Average leafs visible / fat visible / total: %d / %d / %d\n", printf ("Average leafs visible / fat visible / total: %d / %d / %d\n",
(int) (fatstats.pvs_visible / num_leafs), (int) (fatstats.pvs_visible / num_leafs),
(int) (fatstats.fat_visible / num_leafs), num_leafs); (int) (fatstats.fat_visible / num_leafs), num_leafs);

View file

@ -679,11 +679,15 @@ print_thread_stats (const int *local_work, int thread, int spinner_ind)
} }
static int static int
print_progress (int prev_prog, int spinner_ind) portal_progress (void)
{ {
int prog; return portal_count * 100 / (numportals * 2) + 1;
}
prog = portal_count * 50 / (numportals * 2) + 1; static int
print_progress (int prev_prog, int prog, int spinner_ind)
{
prog /= 2;
if (prog > prev_prog) if (prog > prev_prog)
printf ("%.*s", prog - prev_prog, progress + prev_prog); printf ("%.*s", prog - prev_prog, progress + prev_prog);
printf (" %c\b\b", spinner[spinner_ind % 4]); printf (" %c\b\b", spinner[spinner_ind % 4]);
@ -693,7 +697,7 @@ print_progress (int prev_prog, int spinner_ind)
typedef struct { typedef struct {
int thread; int thread;
int (*progress)(int, int); int (*calc_progress)(void);
} watch_data_t; } watch_data_t;
static void * static void *
@ -716,16 +720,18 @@ WatchThread (void *_wd)
break; break;
if (i == thread) if (i == thread)
break; break;
if (count++ == 100) { if (count++ == 50) {
count = 0; count = 0;
for (i = 0; i < thread; i ++) for (i = 0; i < thread; i ++)
local_work[i] = working[i]; local_work[i] = working[i];
if (options.verbosity >= 4) if (options.verbosity >= 4)
print_thread_stats (local_work, thread, spinner_ind); print_thread_stats (local_work, thread, spinner_ind);
else if (options.verbosity >= 0) else if (options.verbosity >= 0) {
prev_prog = wd->progress (prev_prog, spinner_ind); prev_prog = print_progress (prev_prog, wd->calc_progress (),
if (prev_port != portal_count || stalled++ == 10) { spinner_ind);
}
if (prev_port != portal_count || stalled++ == 20) {
prev_port = portal_count; prev_port = portal_count;
stalled = 0; stalled = 0;
spinner_ind++; spinner_ind++;
@ -735,7 +741,8 @@ WatchThread (void *_wd)
if (options.verbosity >= 4) { if (options.verbosity >= 4) {
printf ("watch thread done\n"); printf ("watch thread done\n");
} else if (options.verbosity >= 0) { } else if (options.verbosity >= 0) {
prev_prog = wd->progress (prev_prog, spinner_ind); prev_prog = print_progress (prev_prog, wd->calc_progress (),
spinner_ind);
printf ("\n"); printf ("\n");
} }
free (local_work); free (local_work);
@ -745,7 +752,7 @@ WatchThread (void *_wd)
#endif #endif
void void
RunThreads (void *(*thread_func) (void *), int (*progress)(int, int)) RunThreads (void *(*thread_func) (void *), int (*calc_progress)(void))
{ {
#ifdef USE_PTHREADS #ifdef USE_PTHREADS
pthread_t *work_threads; pthread_t *work_threads;
@ -760,7 +767,7 @@ RunThreads (void *(*thread_func) (void *), int (*progress)(int, int))
thread_func, (void *) (intptr_t) i) == -1) thread_func, (void *) (intptr_t) i) == -1)
Sys_Error ("pthread_create failed"); Sys_Error ("pthread_create failed");
} }
watch_data_t wd = { i, progress }; watch_data_t wd = { i, calc_progress };
if (pthread_create (&work_threads[i], &threads_attrib, if (pthread_create (&work_threads[i], &threads_attrib,
WatchThread, &wd) == -1) WatchThread, &wd) == -1)
Sys_Error ("pthread_create failed"); Sys_Error ("pthread_create failed");
@ -832,6 +839,8 @@ ClusterFlowExpand (const set_t *src, byte *dest)
} }
} }
static sizebuf_t *compressed_vis;
/* /*
ClusterFlow ClusterFlow
@ -840,11 +849,8 @@ ClusterFlowExpand (const set_t *src, byte *dest)
void void
ClusterFlow (int clusternum) ClusterFlow (int clusternum)
{ {
set_t *visclusters; set_t visclusters = SET_STATIC_INIT (portalclusters, alloca);
sizebuf_t compressed = { sizebuf_t *compressed = &compressed_vis[clusternum];
.maxsize = (bitbytes_l * 3) / 2,
.data = alloca ((bitbytes_l * 3) / 2)
};
byte *outbuffer; byte *outbuffer;
int numvis, i; int numvis, i;
@ -854,37 +860,94 @@ ClusterFlow (int clusternum)
outbuffer = uncompressed + clusternum * bitbytes_l; outbuffer = uncompressed + clusternum * bitbytes_l;
cluster = &clusters[clusternum]; cluster = &clusters[clusternum];
// flow through all portals, collecting visible bits set_empty (&visclusters);
memset (compressed.data, 0, compressed.maxsize); // flow through all portals, collecting visible bits
visclusters = set_new ();
for (i = 0; i < cluster->numportals; i++) { for (i = 0; i < cluster->numportals; i++) {
portal = &cluster->portals[i]; portal = &cluster->portals[i];
if (portal->status != stat_done) if (portal->status != stat_done)
Sys_Error ("portal not done"); Sys_Error ("portal not done");
set_union (visclusters, portal->visbits); if (set_is_member (portal->visbits, clusternum)) {
//printf ("cluster %d saw into self via portal %d\n",
// clusternum, (int) (portal - portals));
}
set_union (&visclusters, portal->visbits);
} }
if (set_is_member (visclusters, clusternum)) set_add (&visclusters, clusternum);
Sys_Error ("Cluster portals saw into cluster");
set_add (visclusters, clusternum); numvis = set_count (&visclusters);
numvis = set_count (visclusters);
// expand to cluster->leaf PVS // expand to cluster->leaf PVS
ClusterFlowExpand (visclusters, outbuffer); ClusterFlowExpand (&visclusters, outbuffer);
set_delete (visclusters);
// compress the bit string // compress the bit string
if (options.verbosity >= 4) if (options.verbosity >= 4)
printf ("cluster %4i : %4i visible\n", clusternum, numvis); printf ("cluster %4i : %4i visible\n", clusternum, numvis);
totalvis += numvis; totalvis += numvis;
i = CompressRow (&compressed, outbuffer, numrealleafs, 0); CompressRow (compressed, outbuffer, numrealleafs, 0);
cluster->visofs = visdata->size; }
dstring_append (visdata, (char *) compressed.data, i);
static unsigned work_cluster;
static int
flow_progress (void)
{
return work_cluster * 100 / portalclusters;
}
static unsigned
next_cluster (void)
{
unsigned cluster = ~0;
WRLOCK (global_lock);
if (work_cluster < portalclusters) {
cluster = work_cluster++;
}
UNLOCK (global_lock);
return cluster;
}
static void *
FlowClusters (void *d)
{
int thread = (intptr_t) d;
while (1) {
unsigned clusternum = next_cluster ();
if (working) {
working[thread] = clusternum;
}
if (clusternum == ~0u) {
break;
}
ClusterFlow (clusternum);
}
return 0;
}
static void
CompactPortalVis (void)
{
if (options.verbosity >= 0) {
printf ("Comp vis: ");
}
compressed_vis = malloc (portalclusters * sizeof (sizebuf_t));
for (unsigned i = 0; i < portalclusters; i++) {
compressed_vis[i] = (sizebuf_t) {
.maxsize = (bitbytes_l * 3) / 2,
.data = malloc ((bitbytes_l * 3) / 2)
};
}
RunThreads (FlowClusters, flow_progress);
for (unsigned i = 0; i < portalclusters; i++) {
unsigned size = compressed_vis[i].cursize;
clusters[i].visofs = visdata->size;
dstring_append (visdata, (char *) compressed_vis[i].data, size);
}
} }
static int static int
@ -906,7 +969,7 @@ BasePortalVis (void)
printf ("\n"); printf ("\n");
start = Sys_DoubleTime (); start = Sys_DoubleTime ();
RunThreads (BaseVisThread, print_progress); RunThreads (BaseVisThread, portal_progress);
end = Sys_DoubleTime (); end = Sys_DoubleTime ();
if (options.verbosity >= 1) { if (options.verbosity >= 1) {
@ -953,7 +1016,7 @@ CalcPortalVis (void)
portal_count = 0; portal_count = 0;
RunThreads (LeafThread, print_progress); RunThreads (LeafThread, portal_progress);
if (options.verbosity >= 1) { if (options.verbosity >= 1) {
printf ("portalcheck: %ld portaltest: %ld portalpass: %ld\n", printf ("portalcheck: %ld portaltest: %ld portalpass: %ld\n",
@ -993,8 +1056,7 @@ CalcVis (void)
CalcPortalVis (); CalcPortalVis ();
// assemble the leaf vis lists by oring and compressing the portal lists // assemble the leaf vis lists by oring and compressing the portal lists
for (i = 0; i < portalclusters; i++) CompactPortalVis ();
ClusterFlow (i);
for (i = 0; i < numrealleafs; i++) { for (i = 0; i < numrealleafs; i++) {
bsp->leafs[i + 1].visofs = clusters[leafcluster[i]].visofs; bsp->leafs[i + 1].visofs = clusters[leafcluster[i]].visofs;
@ -1004,7 +1066,7 @@ CalcVis (void)
} }
static void static void
CalcClusterSphers (void) CalcClusterSpheres (void)
{ {
memhunk_t *hunk = main_thread.hunk; memhunk_t *hunk = main_thread.hunk;
@ -1437,7 +1499,7 @@ generate_pvs (void)
uncompressed = calloc (bitbytes_l, portalclusters); uncompressed = calloc (bitbytes_l, portalclusters);
CalcClusterSphers (); CalcClusterSpheres ();
CalcVis (); CalcVis ();
if (options.verbosity >= 1) if (options.verbosity >= 1)