Use a sorted queue for portals.

qsort is used to sort the queue by nummightsee. At ~4ms for 20k portals, I
think it's affordable. Using a queue rather than scanning the portal list
each time loses the dynamic sorting when mightsee gets updated, but it
seemed to shave off 4s anyway (~207s to ~203s (maybe, yay random times)).

Another step towards threaded base-vis.
This commit is contained in:
Bill Currie 2013-03-18 21:14:12 +09:00
parent 7e40981dcd
commit 32b6d15931

View file

@ -86,6 +86,8 @@ int bitbytes; // (portalleafs + 63)>>3
int bitlongs; int bitlongs;
int bitbytes_l; // (numrealleafs + 63)>>3 int bitbytes_l; // (numrealleafs + 63)>>3
portal_t **portal_queue;
portal_t *portals; portal_t *portals;
cluster_t *clusters; cluster_t *clusters;
dstring_t *visdata; dstring_t *visdata;
@ -285,40 +287,17 @@ ClipWinding (winding_t *in, const plane_t *split, qboolean keepon)
return neww; return neww;
} }
/*
GetNextPortal
Returns the next portal for a thread to work on
Returns the portals from the least complex, so the later ones can reuse
the earlier information.
*/
static portal_t * static portal_t *
GetNextPortal (void) GetNextPortal (void)
{ {
int min, j; portal_t *p = 0;
portal_t *p, *tp;
WRLOCK (global_lock); WRLOCK (global_lock);
if (portal_count < 2 * numportals) {
min = 99999; p = portal_queue[portal_count++];
p = NULL;
for (j = 0, tp = portals; j < numportals * 2; j++, tp++) {
if (tp->nummightsee < min && tp->status == stat_none) {
min = tp->nummightsee;
p = tp;
}
}
if (p) {
WRLOCK_PORTAL (p);
portal_count++;
p->status = stat_selected; p->status = stat_selected;
UNLOCK_PORTAL (p);
} }
UNLOCK (global_lock); UNLOCK (global_lock);
return p; return p;
} }
@ -596,10 +575,21 @@ ClusterFlow (int clusternum)
dstring_append (visdata, (char *) compressed, i); dstring_append (visdata, (char *) compressed, i);
} }
static int
portalcmp (const void *_a, const void *_b)
{
portal_t *a = *(portal_t **) _a;
portal_t *b = *(portal_t **) _b;
return a->nummightsee - b->nummightsee;
}
static void static void
CalcPortalVis (void) CalcPortalVis (void)
{ {
long i; long i;
double start, end;
portal_count = 0;
// fastvis just uses mightsee for a very loose bound // fastvis just uses mightsee for a very loose bound
if (options.minimal) { if (options.minimal) {
@ -609,6 +599,10 @@ CalcPortalVis (void)
} }
return; return;
} }
start = Sys_DoubleTime ();
qsort (portal_queue, numportals * 2, sizeof (portal_t *), portalcmp);
end = Sys_DoubleTime ();
printf ("qsort: %gs\n", end - start);
RunThreads (LeafThread); RunThreads (LeafThread);
if (options.verbosity > 0) { if (options.verbosity > 0) {
@ -895,6 +889,10 @@ LoadPortals (char *name)
// each file portal is split into two memory portals, one for each // each file portal is split into two memory portals, one for each
// direction // direction
portals = calloc (2 * numportals, sizeof (portal_t)); portals = calloc (2 * numportals, sizeof (portal_t));
portal_queue = malloc (2 * numportals * sizeof (portal_t *));
for (i = 0; i < 2 * numportals; i++) {
portal_queue[i] = &portals[i];
}
#ifdef USE_PTHREADS #ifdef USE_PTHREADS
portal_locks = calloc (2 * numportals, sizeof (pthread_rwlock_t)); portal_locks = calloc (2 * numportals, sizeof (pthread_rwlock_t));
for (i = 0; i < 2 * numportals; i++) { for (i = 0; i < 2 * numportals; i++) {