mirror of
https://git.code.sf.net/p/quake/quakeforge
synced 2025-02-18 09:51:40 +00:00
Make the base vis multi-threaded.
Now multi-threaded qfvis is on par with tyrutils vis (differences usually <1s, sometimes more, sometimes less).
This commit is contained in:
parent
32b6d15931
commit
88e5adcec6
3 changed files with 120 additions and 79 deletions
|
@ -158,6 +158,11 @@ typedef struct threaddata_s {
|
||||||
set_pool_t set_pool;
|
set_pool_t set_pool;
|
||||||
} threaddata_t;
|
} threaddata_t;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
set_t *portalsee;
|
||||||
|
int clustersee;
|
||||||
|
} basethread_t;
|
||||||
|
|
||||||
extern int numportals;
|
extern int numportals;
|
||||||
extern int portalclusters;
|
extern int portalclusters;
|
||||||
extern int numrealleafs;
|
extern int numrealleafs;
|
||||||
|
@ -177,7 +182,7 @@ winding_t *ClipWinding (winding_t *in, const plane_t *split, qboolean keepon);
|
||||||
winding_t *CopyWinding (const winding_t *w);
|
winding_t *CopyWinding (const winding_t *w);
|
||||||
|
|
||||||
void ClusterFlow (int clusternum);
|
void ClusterFlow (int clusternum);
|
||||||
void BasePortalVis (void);
|
void PortalBase (basethread_t *thread, portal_t *portal);
|
||||||
void PortalFlow (threaddata_t *data, portal_t *portal);
|
void PortalFlow (threaddata_t *data, portal_t *portal);
|
||||||
void CalcAmbientSounds (void);
|
void CalcAmbientSounds (void);
|
||||||
|
|
||||||
|
|
|
@ -57,15 +57,12 @@
|
||||||
#include "vis.h"
|
#include "vis.h"
|
||||||
#include "options.h"
|
#include "options.h"
|
||||||
|
|
||||||
static int clustersee;
|
|
||||||
static set_t *portalsee;
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
This is a rough first-order aproximation that is used to trivially reject
|
This is a rough first-order aproximation that is used to trivially reject
|
||||||
some of the final calculations.
|
some of the final calculations.
|
||||||
*/
|
*/
|
||||||
static void
|
static void
|
||||||
SimpleFlood (portal_t *srcportal, int clusternum)
|
SimpleFlood (basethread_t *thread, portal_t *srcportal, int clusternum)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
cluster_t *cluster;
|
cluster_t *cluster;
|
||||||
|
@ -74,15 +71,15 @@ SimpleFlood (portal_t *srcportal, int clusternum)
|
||||||
if (set_is_member (srcportal->mightsee, clusternum))
|
if (set_is_member (srcportal->mightsee, clusternum))
|
||||||
return;
|
return;
|
||||||
set_add (srcportal->mightsee, clusternum);
|
set_add (srcportal->mightsee, clusternum);
|
||||||
clustersee++;
|
thread->clustersee++;
|
||||||
|
|
||||||
cluster = &clusters[clusternum];
|
cluster = &clusters[clusternum];
|
||||||
|
|
||||||
for (i = 0; i < cluster->numportals; i++) {
|
for (i = 0; i < cluster->numportals; i++) {
|
||||||
portal = cluster->portals[i];
|
portal = cluster->portals[i];
|
||||||
if (!set_is_member (portalsee, portal - portals))
|
if (!set_is_member (thread->portalsee, portal - portals))
|
||||||
continue;
|
continue;
|
||||||
SimpleFlood (srcportal, portal->cluster);
|
SimpleFlood (thread, srcportal, portal->cluster);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -99,86 +96,72 @@ test_sphere (sphere_t *sphere, plane_t *plane)
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
BasePortalVis (void)
|
PortalBase (basethread_t *thread, portal_t *portal)
|
||||||
{
|
{
|
||||||
int i, j, k;
|
int i, j, k;
|
||||||
float d;
|
float d;
|
||||||
portal_t *tp, *portal;
|
portal_t *tp;
|
||||||
winding_t *winding;
|
winding_t *winding;
|
||||||
int base_mightsee = 0;
|
|
||||||
int tp_side, portal_side;
|
int tp_side, portal_side;
|
||||||
double start, end;
|
|
||||||
|
|
||||||
start = Sys_DoubleTime ();
|
i = portal - portals;
|
||||||
portalsee = set_new_size (numportals * 2);
|
|
||||||
for (i = 0, portal = portals; i < numportals * 2; i++, portal++) {
|
|
||||||
portal->mightsee = set_new_size (portalclusters);
|
|
||||||
|
|
||||||
set_empty (portalsee);
|
for (j = 0, tp = portals; j < numportals * 2; j++, tp++) {
|
||||||
|
if (j == i)
|
||||||
|
continue;
|
||||||
|
|
||||||
for (j = 0, tp = portals; j < numportals * 2; j++, tp++) {
|
// If the target portal is behind the portals's plane, then it
|
||||||
if (j == i)
|
// can't possibly be seen by the portal.
|
||||||
continue;
|
//
|
||||||
|
// If the portal is in front of the target's plane, then the target
|
||||||
|
// is of no interest as it is facing counter to the flow of
|
||||||
|
// visibility.
|
||||||
|
|
||||||
// If the target portal is behind the portals's plane, then it
|
// First check using the bounding spheres of the two portals.
|
||||||
// can't possibly be seen by the portal.
|
tp_side = test_sphere (&tp->sphere, &portal->plane);
|
||||||
//
|
if (tp_side < 0) {
|
||||||
// If the portal is in front of the target's plane, then the target
|
// The test portal definitely is entirely behind the portal's
|
||||||
// is of no interest as it is facing counter to the flow of
|
// plane.
|
||||||
// visibility.
|
continue; // entirely behind
|
||||||
|
}
|
||||||
// First check using the bounding spheres of the two portals.
|
portal_side = test_sphere (&portal->sphere, &tp->plane);
|
||||||
tp_side = test_sphere (&tp->sphere, &portal->plane);
|
if (portal_side > 0) {
|
||||||
if (tp_side < 0) {
|
// The portal definitely is entirely in front of the test
|
||||||
// The test portal definitely is entirely behind the portal's
|
// portal's plane.
|
||||||
// plane.
|
continue; // entirely in front
|
||||||
continue; // entirely behind
|
|
||||||
}
|
|
||||||
portal_side = test_sphere (&portal->sphere, &tp->plane);
|
|
||||||
if (portal_side > 0) {
|
|
||||||
// The portal definitely is entirely in front of the test
|
|
||||||
// portal's plane.
|
|
||||||
continue; // entirely in front
|
|
||||||
}
|
|
||||||
|
|
||||||
if (tp_side == 0) {
|
|
||||||
// The test portal's sphere touches the portal's plane, so
|
|
||||||
// do a more refined check.
|
|
||||||
winding = tp->winding;
|
|
||||||
for (k = 0; k < winding->numpoints; k++) {
|
|
||||||
d = DotProduct (winding->points[k],
|
|
||||||
portal->plane.normal) - portal->plane.dist;
|
|
||||||
if (d > ON_EPSILON)
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if (k == winding->numpoints)
|
|
||||||
continue; // no points on front
|
|
||||||
}
|
|
||||||
|
|
||||||
if (portal_side == 0) {
|
|
||||||
// The portal's sphere touches the test portal's plane, so
|
|
||||||
// do a more refined check.
|
|
||||||
winding = portal->winding;
|
|
||||||
for (k = 0; k < winding->numpoints; k++) {
|
|
||||||
d = DotProduct (winding->points[k],
|
|
||||||
tp->plane.normal) - tp->plane.dist;
|
|
||||||
if (d < -ON_EPSILON)
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if (k == winding->numpoints)
|
|
||||||
continue; // no points on front
|
|
||||||
}
|
|
||||||
|
|
||||||
set_add (portalsee, j);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
clustersee = 0;
|
if (tp_side == 0) {
|
||||||
SimpleFlood (portal, portal->cluster);
|
// The test portal's sphere touches the portal's plane, so
|
||||||
portal->nummightsee = clustersee;
|
// do a more refined check.
|
||||||
base_mightsee += clustersee;
|
winding = tp->winding;
|
||||||
}
|
for (k = 0; k < winding->numpoints; k++) {
|
||||||
set_delete (portalsee);
|
d = DotProduct (winding->points[k],
|
||||||
end = Sys_DoubleTime ();
|
portal->plane.normal) - portal->plane.dist;
|
||||||
if (options.verbosity > 0)
|
if (d > ON_EPSILON)
|
||||||
printf ("base_mightsee: %d %gs\n", base_mightsee, end - start);
|
break;
|
||||||
|
}
|
||||||
|
if (k == winding->numpoints)
|
||||||
|
continue; // no points on front
|
||||||
|
}
|
||||||
|
|
||||||
|
if (portal_side == 0) {
|
||||||
|
// The portal's sphere touches the test portal's plane, so
|
||||||
|
// do a more refined check.
|
||||||
|
winding = portal->winding;
|
||||||
|
for (k = 0; k < winding->numpoints; k++) {
|
||||||
|
d = DotProduct (winding->points[k],
|
||||||
|
tp->plane.normal) - tp->plane.dist;
|
||||||
|
if (d < -ON_EPSILON)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (k == winding->numpoints)
|
||||||
|
continue; // no points on front
|
||||||
|
}
|
||||||
|
|
||||||
|
set_add (thread->portalsee, j);
|
||||||
|
}
|
||||||
|
|
||||||
|
SimpleFlood (thread, portal, portal->cluster);
|
||||||
|
portal->nummightsee = thread->clustersee;
|
||||||
}
|
}
|
||||||
|
|
|
@ -74,6 +74,7 @@ bsp_t *bsp;
|
||||||
options_t options;
|
options_t options;
|
||||||
|
|
||||||
static visstat_t stats;
|
static visstat_t stats;
|
||||||
|
int base_mightsee;
|
||||||
|
|
||||||
int portal_count;
|
int portal_count;
|
||||||
int numportals;
|
int numportals;
|
||||||
|
@ -408,6 +409,44 @@ LeafThread (void *_thread)
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void *
|
||||||
|
BaseVisThread (void *_thread)
|
||||||
|
{
|
||||||
|
portal_t *portal;
|
||||||
|
int thread = (int) (intptr_t) _thread;
|
||||||
|
basethread_t data;
|
||||||
|
set_pool_t set_pool;
|
||||||
|
int num_mightsee = 0;
|
||||||
|
|
||||||
|
memset (&data, 0, sizeof (data));
|
||||||
|
set_pool_init (&set_pool);
|
||||||
|
data.portalsee = set_new_size_r (&set_pool, numportals * 2);
|
||||||
|
do {
|
||||||
|
portal = GetNextPortal ();
|
||||||
|
if (!portal)
|
||||||
|
break;
|
||||||
|
|
||||||
|
if (working)
|
||||||
|
working[thread] = (int) (portal - portals);
|
||||||
|
|
||||||
|
portal->mightsee = set_new_size_r (&set_pool, portalclusters);
|
||||||
|
set_empty (data.portalsee);
|
||||||
|
|
||||||
|
PortalBase (&data, portal);
|
||||||
|
num_mightsee += data.clustersee;
|
||||||
|
data.clustersee = 0;
|
||||||
|
} while (1);
|
||||||
|
|
||||||
|
WRLOCK (stats_lock);
|
||||||
|
base_mightsee += num_mightsee;
|
||||||
|
UNLOCK (stats_lock);
|
||||||
|
|
||||||
|
printf ("thread %d done\n", thread);
|
||||||
|
if (working)
|
||||||
|
working[thread] = -1;
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
#ifdef USE_PTHREADS
|
#ifdef USE_PTHREADS
|
||||||
static void *
|
static void *
|
||||||
WatchThread (void *_thread)
|
WatchThread (void *_thread)
|
||||||
|
@ -583,6 +622,20 @@ portalcmp (const void *_a, const void *_b)
|
||||||
return a->nummightsee - b->nummightsee;
|
return a->nummightsee - b->nummightsee;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
BasePortalVis (void)
|
||||||
|
{
|
||||||
|
double start, end;
|
||||||
|
|
||||||
|
start = Sys_DoubleTime ();
|
||||||
|
|
||||||
|
RunThreads (BaseVisThread);
|
||||||
|
|
||||||
|
end = Sys_DoubleTime ();
|
||||||
|
if (options.verbosity > 0)
|
||||||
|
printf ("base_mightsee: %d %gs\n", base_mightsee, end - start);
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
CalcPortalVis (void)
|
CalcPortalVis (void)
|
||||||
{
|
{
|
||||||
|
|
Loading…
Reference in a new issue