Sanchayan Maity
0f4b39775c
During the last commit of splash2 benchmark it seems before committing when we ran "make clean", it effectively undid what the patch at below link did http://www.capsl.udel.edu/splash/Download.html Fix this since without this it is not possible to build the arcane splash2 benchmark.
1188 lines
36 KiB
C
1188 lines
36 KiB
C
/*************************************************************************/
|
|
/* */
|
|
/* Copyright (c) 1994 Stanford University */
|
|
/* */
|
|
/* All rights reserved. */
|
|
/* */
|
|
/* Permission is given to use, copy, and modify this software for any */
|
|
/* non-commercial purpose as long as this copyright notice is not */
|
|
/* removed. All other uses, including redistribution in whole or in */
|
|
/* part, are forbidden without prior written permission. */
|
|
/* */
|
|
/* This software is provided with absolutely no warranty and no */
|
|
/* support. */
|
|
/* */
|
|
/*************************************************************************/
|
|
|
|
/**************************************************************
|
|
*
|
|
* Parallel Hierarchical Radiosity
|
|
*
|
|
* Main program
|
|
*
|
|
***************************************************************/
|
|
|
|
#include <stdio.h>
|
|
#include <string.h>
|
|
#if defined(SGI_GL)
|
|
#include <gl.h>
|
|
#if defined(GL_NASA)
|
|
#include <panel.h>
|
|
#endif
|
|
#endif
|
|
|
|
/* ANL macro initialization */
|
|
|
|
MAIN_ENV;
|
|
|
|
include(radiosity.h)
|
|
|
|
|
|
|
|
/***************************************
|
|
*
|
|
* Global shared variables
|
|
*
|
|
****************************************/
|
|
|
|
Global *global;
|
|
Timing **timing;
|
|
|
|
|
|
/***************************************
|
|
*
|
|
* Global variables (not shared)
|
|
*
|
|
****************************************/
|
|
|
|
long n_processors = DEFAULT_N_PROCESSORS ;
|
|
long n_taskqueues = DEFAULT_N_TASKQUEUES ;
|
|
long n_tasks_per_queue = DEFAULT_N_TASKS_PER_QUEUE ;
|
|
long N_inter_parallel_bf_refine= DEFAULT_N_INTER_PARALLEL_BF_REFINEMENT ;
|
|
long N_visibility_per_task = DEFAULT_N_VISIBILITY_PER_TASK ;
|
|
float Area_epsilon = DEFAULT_AREA_EPSILON ;
|
|
float Energy_epsilon = DEFAULT_ENERGY_EPSILON ;
|
|
float BFepsilon = DEFAULT_BFEPSILON ;
|
|
|
|
long batch_mode = 0 ;
|
|
long verbose_mode = 0 ;
|
|
|
|
/*
|
|
in converting from a fork process model to an sproc (threads) model,
|
|
taskqueue_id and time_process_start are converted to individual arrays
|
|
without worrying about false sharing. This is because taskqueue_id is
|
|
read-only once written by the parent process, and time_process_start
|
|
is written only once by each process.
|
|
*/
|
|
|
|
long taskqueue_id[MAX_PROCESSORS] ; /* Task queue ID */
|
|
long time_rad_start, time_rad_end, time_process_start[MAX_PROCESSORS] ;
|
|
|
|
|
|
/*********************************************************
|
|
*
|
|
* Global variables (used only by the master process)
|
|
*
|
|
**********************************************************/
|
|
|
|
#define N_SLIDERS (5)
|
|
|
|
slider sliders[N_SLIDERS] = {
|
|
{ "View(X) deg ", -100, 100, (long)DFLT_VIEW_ROT_X, 5, change_view_x },
|
|
{ "View(Y) deg ", -100, 100, (long)DFLT_VIEW_ROT_Y, 5, change_view_y },
|
|
{ "View(Zoom) ", 0, 50, (long)DFLT_VIEW_ZOOM*10,6, change_view_zoom },
|
|
{ "BF-e 0.1%", 0, 50, (long)(DEFAULT_BFEPSILON *1000.0),
|
|
11, change_BFepsilon },
|
|
{ "Area-e ", 0, 5000, (long)DEFAULT_AREA_EPSILON,
|
|
11, change_area_epsilon },
|
|
} ;
|
|
|
|
#define N_CHOICES (4)
|
|
|
|
#define CHOICE_RAD_RUN (0)
|
|
#define CHOICE_RAD_STEP (1)
|
|
#define CHOICE_RAD_RESET (2)
|
|
|
|
#define CHOICE_DISP_RADIOSITY (0)
|
|
#define CHOICE_DISP_SHADED (1)
|
|
#define CHOICE_DISP_PATCH (2)
|
|
#define CHOICE_DISP_MESH (3)
|
|
#define CHOICE_DISP_INTERACTION (4)
|
|
|
|
#define CHOICE_UTIL_PS (0)
|
|
#define CHOICE_UTIL_STAT_CRT (1)
|
|
#define CHOICE_UTIL_STAT_FILE (2)
|
|
#define CHOICE_UTIL_CLEAR_RAD (3)
|
|
|
|
choice choices[N_CHOICES] = {
|
|
{ "Run",
|
|
{ "Run", "Step", "Reset", 0 },
|
|
0, start_radiosity },
|
|
{ "Display",
|
|
{ "Filled", "Smooth shading", "Show polygon edges",
|
|
"Show element edges", "Show interactions", 0 },
|
|
0, change_display },
|
|
{ "Models",
|
|
{ "Test", "Room", "LargeRoom", 0 },
|
|
0, select_model },
|
|
{ "Tools",
|
|
{ "HardCopy(PS)", "Statistics", "Statistics(file)",
|
|
"Clear Radiosity Value", 0 },
|
|
0, utility_tools },
|
|
} ;
|
|
|
|
/***************************************
|
|
*
|
|
* Main function.
|
|
*
|
|
****************************************/
|
|
|
|
static void change_view(void);
|
|
static void expose_callback(void);
|
|
static void _init_radavg_tasks(Patch *p, long mode, long process_id);
|
|
static void parse_args(int argc, char *argv[]);
|
|
|
|
static long dostats = 0;
|
|
|
|
int main(int argc, char *argv[])
|
|
{
|
|
long i;
|
|
long total_rad_time, max_rad_time, min_rad_time;
|
|
long total_refine_time, max_refine_time, min_refine_time;
|
|
long total_wait_time, max_wait_time, min_wait_time;
|
|
long total_vertex_time, max_vertex_time, min_vertex_time;
|
|
|
|
/* Parse arguments */
|
|
parse_args(argc, argv) ;
|
|
choices[2].init_value = model_selector ;
|
|
|
|
/* Initialize graphic device */
|
|
if( batch_mode == 0 )
|
|
{
|
|
g_init(argc, argv) ;
|
|
setup_view( DFLT_VIEW_ROT_X, DFLT_VIEW_ROT_Y,
|
|
DFLT_VIEW_DIST, DFLT_VIEW_ZOOM,0 ) ;
|
|
}
|
|
|
|
/* Initialize ANL macro */
|
|
MAIN_INITENV(,60000000) ;
|
|
|
|
/* Allocate global shared memory and initialize */
|
|
global = (Global *) G_MALLOC(sizeof(Global)) ;
|
|
if( global == 0 )
|
|
{
|
|
printf( "Can't allocate memory\n" ) ;
|
|
exit(1) ;
|
|
}
|
|
init_global(0) ;
|
|
|
|
timing = (Timing **) G_MALLOC(n_processors * sizeof(Timing *));
|
|
for (i = 0; i < n_processors; i++)
|
|
timing[i] = (Timing *) G_MALLOC(sizeof(Timing));
|
|
|
|
/* Initialize shared lock */
|
|
init_sharedlock(0) ;
|
|
|
|
/* Initial random testing rays array for visibility test. */
|
|
init_visibility_module(0) ;
|
|
|
|
/* POSSIBLE ENHANCEMENT: Here is where one might distribute the
|
|
sobj_struct, task_struct, and vis_struct data structures across
|
|
physically distributed memories as desired.
|
|
|
|
One way to place data is as follows:
|
|
|
|
long i;
|
|
|
|
for (i=0;i<n_processors;i++) {
|
|
Place all addresses x such that
|
|
&(sobj_struct[i]) <= x < &(sobj_struct[i+1]) on node i
|
|
Place all addresses x such that
|
|
&(task_struct[i]) <= x < &(task_struct[i+1]) on node i
|
|
Place all addresses x such that
|
|
&(vis_struct[i]) <= x < &(vis_struct[i+1]) on node i
|
|
}
|
|
|
|
*/
|
|
|
|
if( batch_mode )
|
|
{
|
|
/* In batch mode, create child processes and start immediately */
|
|
|
|
/* Time stamp */
|
|
CLOCK( time_rad_start );
|
|
|
|
global->index = 0;
|
|
for( i = 0 ; i < n_processors ; i++ )
|
|
{
|
|
taskqueue_id[i] = assign_taskq(0) ;
|
|
}
|
|
|
|
/* And start processing */
|
|
CREATE(radiosity, n_processors);
|
|
WAIT_FOR_END(n_processors);
|
|
|
|
/* Time stamp */
|
|
CLOCK( time_rad_end );
|
|
|
|
/* Print out running time */
|
|
printf("TIMING STATISTICS MEASURED BY MAIN PROCESS:\n");
|
|
|
|
print_running_time(0);
|
|
|
|
if (dostats) {
|
|
printf("\n\n\nPER-PROCESS STATISTICS:\n");
|
|
|
|
printf("%8s%20s%20s%12s%12s\n","Proc","Total","Refine","Wait","Smooth");
|
|
printf("%8s%20s%20s%12s%12s\n\n","","Time","Time","Time","Time");
|
|
for (i = 0; i < n_processors; i++)
|
|
printf("%8ld%20lu%20lu%12lu%12lu\n",i,timing[i]->rad_time, timing[i]->refine_time, timing[i]->wait_time, timing[i]->vertex_time);
|
|
|
|
total_rad_time = timing[0]->rad_time;
|
|
max_rad_time = timing[0]->rad_time;
|
|
min_rad_time = timing[0]->rad_time;
|
|
|
|
total_refine_time = timing[0]->refine_time;
|
|
max_refine_time = timing[0]->refine_time;
|
|
min_refine_time = timing[0]->refine_time;
|
|
|
|
total_wait_time = timing[0]->wait_time;
|
|
max_wait_time = timing[0]->wait_time;
|
|
min_wait_time = timing[0]->wait_time;
|
|
|
|
total_vertex_time = timing[0]->vertex_time;
|
|
max_vertex_time = timing[0]->vertex_time;
|
|
min_vertex_time = timing[0]->vertex_time;
|
|
|
|
for (i = 1; i < n_processors; i++) {
|
|
total_rad_time += timing[i]->rad_time;
|
|
if (timing[i]->rad_time > max_rad_time)
|
|
max_rad_time = timing[i]->rad_time;
|
|
if (timing[i]->rad_time < min_rad_time)
|
|
min_rad_time = timing[i]->rad_time;
|
|
|
|
total_refine_time += timing[i]->refine_time;
|
|
if (timing[i]->refine_time > max_refine_time)
|
|
max_refine_time = timing[i]->refine_time;
|
|
if (timing[i]->refine_time < min_refine_time)
|
|
min_refine_time = timing[i]->refine_time;
|
|
|
|
total_wait_time += timing[i]->wait_time;
|
|
if (timing[i]->wait_time > max_wait_time)
|
|
max_wait_time = timing[i]->wait_time;
|
|
if (timing[i]->wait_time < min_wait_time)
|
|
min_wait_time = timing[i]->wait_time;
|
|
|
|
total_vertex_time += timing[i]->vertex_time;
|
|
if (timing[i]->vertex_time > max_vertex_time)
|
|
max_vertex_time = timing[i]->vertex_time;
|
|
if (timing[i]->vertex_time < min_vertex_time)
|
|
min_vertex_time = timing[i]->vertex_time;
|
|
}
|
|
|
|
printf("\n\n%8s%20lu%20lu%12lu%12lu\n","Max", max_rad_time, max_refine_time, max_wait_time, max_vertex_time);
|
|
printf("\n%8s%20lu%20lu%12lu%12lu\n","Min", min_rad_time, min_refine_time, min_wait_time, min_vertex_time);
|
|
printf("\n%8s%20lu%20lu%12lu%12lu\n","Avg", (long) (((double) total_rad_time) / ((double) (1.0 * n_processors))), (long) (((double) total_refine_time) / ((double) (1.0 * n_processors))), (long) (((double) total_wait_time) / ((double) (1.0 * n_processors))), (long) (((double) total_vertex_time) / ((double) (1.0 * n_processors))));
|
|
printf("\n\n");
|
|
|
|
}
|
|
|
|
/* print_fork_time(0) ; */
|
|
|
|
print_statistics( stdout, 0 ) ;
|
|
}
|
|
else
|
|
{
|
|
/* In interactive mode, start workers, and the master starts
|
|
notification loop */
|
|
|
|
/* Start notification loop */
|
|
g_start( expose_callback,
|
|
N_SLIDERS, sliders, N_CHOICES, choices ) ;
|
|
}
|
|
MAIN_END;
|
|
exit(0) ;
|
|
}
|
|
|
|
|
|
|
|
/***************************************
|
|
*
|
|
* PANEL call back routine
|
|
*
|
|
* start_radiosity() (MASTER only)
|
|
*
|
|
****************************************/
|
|
|
|
static long disp_fill_switch = 1 ;
|
|
static long disp_shade_switch = 0 ;
|
|
static long disp_fill_mode = 1 ;
|
|
static long disp_patch_switch = 0 ;
|
|
static long disp_mesh_switch = 0 ;
|
|
static long disp_interaction_switch = 0 ;
|
|
static long disp_crnt_view_x = (long)DFLT_VIEW_ROT_X ;
|
|
static long disp_crnt_view_y = (long)DFLT_VIEW_ROT_Y ;
|
|
static float disp_crnt_zoom = DFLT_VIEW_ZOOM ;
|
|
|
|
|
|
#if defined(SGI_GL) && defined(GL_NASA)
|
|
void start_radiosity(Actuator *ap)
|
|
#else
|
|
void start_radiosity(long val)
|
|
#endif
|
|
{
|
|
static long state = 0 ;
|
|
long i;
|
|
long total_rad_time, max_rad_time, min_rad_time;
|
|
long total_refine_time, max_refine_time, min_refine_time;
|
|
long total_wait_time, max_wait_time, min_wait_time;
|
|
long total_vertex_time, max_vertex_time, min_vertex_time;
|
|
|
|
#if defined(SGI_GL) && defined(GL_NASA)
|
|
long val ;
|
|
|
|
val = g_get_choice_val( ap, &choices[0] ) ;
|
|
#endif
|
|
|
|
if( val == CHOICE_RAD_RUN )
|
|
{
|
|
if( state == -1 )
|
|
{
|
|
printf( "Please reset first\007\n" ) ;
|
|
return ;
|
|
}
|
|
|
|
/* Time stamp */
|
|
CLOCK( time_rad_start ) ;
|
|
|
|
|
|
global->index = 0;
|
|
|
|
/* Create slave processes */
|
|
for (i = 0 ; i < n_processors ; i++ )
|
|
{
|
|
taskqueue_id[i] = assign_taskq(0) ;
|
|
}
|
|
|
|
/* And start processing */
|
|
CREATE(radiosity, n_processors);
|
|
WAIT_FOR_END(n_processors);
|
|
/* Time stamp */
|
|
CLOCK( time_rad_end );
|
|
|
|
/* Print out running time */
|
|
/* Print out running time */
|
|
printf("TIMING STATISTICS MEASURED BY MAIN PROCESS:\n");
|
|
|
|
print_running_time(0);
|
|
|
|
if (dostats) {
|
|
printf("\n\n\nPER-PROCESS STATISTICS:\n");
|
|
|
|
printf("%8s%20s%20s%12s%12s\n","Proc","Total","Refine","Wait","Smooth");
|
|
printf("%8s%20s%20s%12s%12s\n\n","","Time","Time","Time","Time")
|
|
;
|
|
for (i = 0; i < n_processors; i++)
|
|
printf("%8ld%20lu%20lu%12lu%12lu\n",i,timing[i]->rad_time, timing[i]->refine_time, timing[i]->wait_time, timing[i]->vertex_time);
|
|
|
|
total_rad_time = timing[0]->rad_time;
|
|
max_rad_time = timing[0]->rad_time;
|
|
min_rad_time = timing[0]->rad_time;
|
|
|
|
total_refine_time = timing[0]->refine_time;
|
|
max_refine_time = timing[0]->refine_time;
|
|
min_refine_time = timing[0]->refine_time;
|
|
|
|
total_wait_time = timing[0]->wait_time;
|
|
max_wait_time = timing[0]->wait_time;
|
|
min_wait_time = timing[0]->wait_time;
|
|
|
|
total_vertex_time = timing[0]->vertex_time;
|
|
max_vertex_time = timing[0]->vertex_time;
|
|
min_vertex_time = timing[0]->vertex_time;
|
|
|
|
for (i = 1; i < n_processors; i++) {
|
|
total_rad_time += timing[i]->rad_time;
|
|
if (timing[i]->rad_time > max_rad_time)
|
|
max_rad_time = timing[i]->rad_time;
|
|
if (timing[i]->rad_time < min_rad_time)
|
|
min_rad_time = timing[i]->rad_time;
|
|
|
|
total_refine_time += timing[i]->refine_time;
|
|
if (timing[i]->refine_time > max_refine_time)
|
|
max_refine_time = timing[i]->refine_time;
|
|
if (timing[i]->refine_time < min_refine_time)
|
|
min_refine_time = timing[i]->refine_time;
|
|
|
|
total_wait_time += timing[i]->wait_time;
|
|
if (timing[i]->wait_time > max_wait_time)
|
|
max_wait_time = timing[i]->wait_time;
|
|
if (timing[i]->wait_time < min_wait_time)
|
|
min_wait_time = timing[i]->wait_time;
|
|
|
|
total_vertex_time += timing[i]->vertex_time;
|
|
if (timing[i]->vertex_time > max_vertex_time)
|
|
max_vertex_time = timing[i]->vertex_time;
|
|
if (timing[i]->vertex_time < min_vertex_time)
|
|
min_vertex_time = timing[i]->vertex_time;
|
|
}
|
|
|
|
|
|
printf("\n\n%8s%20lu%20lu%12lu%12lu\n","Max", max_rad_time, max_refine_time, max_wait_time, max_vertex_time);
|
|
printf("\n%8s%20lu%20lu%12lu%12lu\n","Min", min_rad_time, min_refine_time, min_wait_time, min_vertex_time);
|
|
printf("\n%8s%20lu%20lu%12lu%12lu\n","Avg", (long) (((double) total_rad_time) / ((double) (1.0 * n_processors))), (long) (((double) total_refine_time) / ((double) (1.0 * n_processors))), (long) (((double) total_wait_time) / ((double) (1.0 * n_processors))), (long) (((double) total_vertex_time) / ((double) (1.0 * n_processors))));
|
|
printf("\n\n");
|
|
|
|
}
|
|
|
|
/* print_fork_time(0) ; */
|
|
|
|
print_statistics( stdout, 0 ) ;
|
|
|
|
/* Display image */
|
|
display_scene( disp_fill_mode, disp_patch_switch,
|
|
disp_mesh_switch, disp_interaction_switch, 0) ;
|
|
|
|
state = -1 ;
|
|
}
|
|
|
|
else if( val == CHOICE_RAD_STEP )
|
|
{
|
|
if( state == -1 )
|
|
{
|
|
printf( "Please reset first\007\n" ) ;
|
|
return ;
|
|
}
|
|
|
|
/* Step execution */
|
|
switch( state )
|
|
{
|
|
case 0:
|
|
/* Step execute as a single process */
|
|
|
|
global->index = 1;
|
|
/* Create slave processes */
|
|
for ( i = 0 ; i < n_processors ; i++ )
|
|
{
|
|
taskqueue_id[i] = assign_taskq(0) ;
|
|
}
|
|
|
|
CREATE(radiosity, n_processors/* - 1*/);
|
|
|
|
/* Decompose model objects into patches and build
|
|
the BSP tree */
|
|
/* Create the first tasks (MASTER only) */
|
|
init_modeling_tasks(0) ;
|
|
process_tasks(0) ;
|
|
state ++ ;
|
|
break ;
|
|
|
|
case 1:
|
|
if( init_ray_tasks(0) )
|
|
{
|
|
BARRIER(global->barrier, n_processors);
|
|
process_tasks(0) ;
|
|
}
|
|
else
|
|
state++ ;
|
|
break ;
|
|
default:
|
|
BARRIER(global->barrier, n_processors);
|
|
init_radavg_tasks( RAD_AVERAGING_MODE, 0 ) ;
|
|
process_tasks(0) ;
|
|
init_radavg_tasks( RAD_NORMALIZING_MODE, 0 ) ;
|
|
process_tasks(0) ;
|
|
|
|
WAIT_FOR_END(n_processors/* - 1*/)
|
|
state = -1 ;
|
|
}
|
|
|
|
/* Display image */
|
|
display_scene( disp_fill_mode, disp_patch_switch,
|
|
disp_mesh_switch, disp_interaction_switch, 0) ;
|
|
}
|
|
|
|
else if( val == CHOICE_RAD_RESET )
|
|
{
|
|
/* Initialize global variables again */
|
|
init_global(0) ;
|
|
init_visibility_module(0) ;
|
|
g_clear() ;
|
|
state = 0 ;
|
|
}
|
|
}
|
|
|
|
|
|
/***************************************
|
|
*
|
|
* PANEL call back routine
|
|
*
|
|
* change_display() (MASTER only)
|
|
*
|
|
****************************************/
|
|
|
|
|
|
#if defined(SGI_GL) && defined(GL_NASA)
|
|
void change_display(Actuator *ap)
|
|
#else
|
|
void change_display(long val)
|
|
#endif
|
|
{
|
|
#if defined(SGI_GL) && defined(GL_NASA)
|
|
long val ;
|
|
|
|
val = g_get_choice_val( ap, &choices[1] ) ;
|
|
#endif
|
|
|
|
/* Display image */
|
|
switch( val )
|
|
{
|
|
case CHOICE_DISP_RADIOSITY:
|
|
disp_fill_switch = (! disp_fill_switch) ;
|
|
break ;
|
|
case CHOICE_DISP_SHADED:
|
|
disp_shade_switch = (! disp_shade_switch) ;
|
|
break ;
|
|
case CHOICE_DISP_PATCH:
|
|
disp_patch_switch = (! disp_patch_switch) ;
|
|
break ;
|
|
case CHOICE_DISP_MESH:
|
|
disp_mesh_switch = (! disp_mesh_switch) ;
|
|
break ;
|
|
case CHOICE_DISP_INTERACTION:
|
|
disp_interaction_switch = (! disp_interaction_switch) ;
|
|
break ;
|
|
default:
|
|
return ;
|
|
}
|
|
|
|
if( disp_fill_switch == 0 )
|
|
disp_fill_mode = 0 ;
|
|
else
|
|
{
|
|
if( disp_shade_switch == 0 )
|
|
disp_fill_mode = 1 ;
|
|
else
|
|
disp_fill_mode = 2 ;
|
|
}
|
|
|
|
/* Display image */
|
|
display_scene( disp_fill_mode, disp_patch_switch,
|
|
disp_mesh_switch, disp_interaction_switch, 0 ) ;
|
|
}
|
|
|
|
|
|
/*****************************************************
|
|
*
|
|
* PANEL call back routine
|
|
*
|
|
* change_view_y() (MASTER only)
|
|
* change_BFepsilon()
|
|
* change_area_epsilon()
|
|
*
|
|
******************************************************/
|
|
|
|
static void change_view()
|
|
{
|
|
/* Change the view */
|
|
setup_view( (float)disp_crnt_view_x, (float)disp_crnt_view_y,
|
|
DFLT_VIEW_DIST, disp_crnt_zoom, 0 ) ;
|
|
|
|
/* And redraw */
|
|
display_scene( disp_fill_mode, disp_patch_switch,
|
|
disp_mesh_switch, disp_interaction_switch, 0 ) ;
|
|
}
|
|
|
|
|
|
#if defined(SGI_GL) && defined(GL_NASA)
|
|
void change_view_x(Actuator *ap)
|
|
#else
|
|
void change_view_x(long val)
|
|
#endif
|
|
{
|
|
#if defined(SGI_GL) && defined(GL_NASA)
|
|
long val = g_get_slide_val( ap ) ;
|
|
#endif
|
|
|
|
/* Save current rot-X value */
|
|
disp_crnt_view_x = val ;
|
|
change_view() ;
|
|
}
|
|
|
|
|
|
#if defined(SGI_GL) && defined(GL_NASA)
|
|
void change_view_y(Actuator *ap)
|
|
#else
|
|
void change_view_y(long val )
|
|
#endif
|
|
{
|
|
#if defined(SGI_GL) && defined(GL_NASA)
|
|
long val = g_get_slide_val( ap ) ;
|
|
#endif
|
|
|
|
/* Save current rot-Y value */
|
|
disp_crnt_view_y = val ;
|
|
change_view() ;
|
|
}
|
|
|
|
|
|
#if defined(SGI_GL) && defined(GL_NASA)
|
|
void change_view_zoom(Actuator *ap)
|
|
#else
|
|
void change_view_zoom(long val)
|
|
#endif
|
|
{
|
|
#if defined(SGI_GL) && defined(GL_NASA)
|
|
long val = g_get_slide_val( ap ) ;
|
|
#endif
|
|
|
|
/* Save current zoom value */
|
|
disp_crnt_zoom = (float)val / 10.0 ;
|
|
change_view() ;
|
|
}
|
|
|
|
|
|
#if defined(SGI_GL) && defined(GL_NASA)
|
|
void change_BFepsilon(Actuator *ap)
|
|
#else
|
|
void change_BFepsilon(long val)
|
|
#endif
|
|
{
|
|
#if defined(SGI_GL) && defined(GL_NASA)
|
|
long val = g_get_slide_val( ap ) ;
|
|
#endif
|
|
BFepsilon = (float)val / 1000.0 ;
|
|
}
|
|
|
|
|
|
|
|
#if defined(SGI_GL) && defined(GL_NASA)
|
|
void change_area_epsilon(Actuator *ap)
|
|
#else
|
|
void change_area_epsilon(long val)
|
|
#endif
|
|
{
|
|
#if defined(SGI_GL) && defined(GL_NASA)
|
|
long val = g_get_slide_val( ap ) ;
|
|
#endif
|
|
Area_epsilon = (float)val ;
|
|
}
|
|
|
|
|
|
/***************************************
|
|
*
|
|
* PANEL call back routine
|
|
*
|
|
* select_model() (MASTER only)
|
|
*
|
|
****************************************/
|
|
|
|
#if defined(SGI_GL) && defined(GL_NASA)
|
|
void select_model(Actuator *ap)
|
|
#else
|
|
void select_model(long val)
|
|
#endif
|
|
{
|
|
#if defined(SGI_GL) && defined(GL_NASA)
|
|
long val = g_get_choice_val( ap, &choices[2] ) ;
|
|
#endif
|
|
switch( val )
|
|
{
|
|
case MODEL_TEST_DATA:
|
|
model_selector = MODEL_TEST_DATA ;
|
|
break ;
|
|
case MODEL_ROOM_DATA:
|
|
model_selector = MODEL_ROOM_DATA ;
|
|
break ;
|
|
case MODEL_LARGEROOM_DATA:
|
|
model_selector = MODEL_LARGEROOM_DATA ;
|
|
break ;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
/***************************************
|
|
*
|
|
* PANEL call back routine
|
|
*
|
|
* utility_tools() (MASTER only)
|
|
*
|
|
****************************************/
|
|
|
|
|
|
#if defined(SGI_GL) && defined(GL_NASA)
|
|
void utility_tools(Actuator *ap)
|
|
#else
|
|
void utility_tools(long val)
|
|
#endif
|
|
{
|
|
FILE *fd ;
|
|
#if defined(SGI_GL) && defined(GL_NASA)
|
|
long val = g_get_choice_val( ap, &choices[3] ) ;
|
|
#endif
|
|
|
|
switch( val )
|
|
{
|
|
case CHOICE_UTIL_PS:
|
|
/* Open PS file */
|
|
ps_open( "radiosity.ps" ) ;
|
|
|
|
/* Change the view */
|
|
ps_setup_view( DFLT_VIEW_ROT_X, (float)disp_crnt_view_y,
|
|
DFLT_VIEW_DIST, DFLT_VIEW_ZOOM) ;
|
|
|
|
/* And redraw */
|
|
ps_display_scene( disp_fill_mode, disp_patch_switch,
|
|
disp_mesh_switch, disp_interaction_switch, 0 ) ;
|
|
|
|
/* Close */
|
|
ps_close() ;
|
|
break ;
|
|
case CHOICE_UTIL_STAT_CRT:
|
|
print_statistics( stdout, 0 ) ;
|
|
break ;
|
|
case CHOICE_UTIL_STAT_FILE:
|
|
if( (fd = fopen( "radiosity_stat", "w" )) == 0 )
|
|
{
|
|
perror( "radiosity_stat" ) ;
|
|
break ;
|
|
}
|
|
print_statistics( fd, 0 ) ;
|
|
fclose( fd ) ;
|
|
break ;
|
|
case CHOICE_UTIL_CLEAR_RAD:
|
|
clear_radiosity(0) ;
|
|
}
|
|
}
|
|
|
|
|
|
/***************************************
|
|
*
|
|
* Exposure call back
|
|
*
|
|
****************************************/
|
|
|
|
static void expose_callback()
|
|
{
|
|
/* Display image */
|
|
display_scene( disp_fill_mode, disp_patch_switch,
|
|
disp_mesh_switch, disp_interaction_switch, 0 ) ;
|
|
}
|
|
|
|
|
|
/***************************************
|
|
*
|
|
* radiosity() Radiosity task main
|
|
*
|
|
****************************************/
|
|
|
|
|
|
void radiosity()
|
|
{
|
|
long process_id;
|
|
long rad_start, refine_done, vertex_start, vertex_done;
|
|
|
|
LOCK(global->index_lock);
|
|
process_id = global->index++;
|
|
UNLOCK(global->index_lock);
|
|
process_id = process_id % n_processors;
|
|
|
|
BARINCLUDE(global->barrier);
|
|
if ((process_id == 0) || (dostats))
|
|
CLOCK(rad_start);
|
|
|
|
/* POSSIBLE ENHANCEMENT: Here is where one might pin processes to
|
|
processors to avoid migration */
|
|
|
|
/* POSSIBLE ENHANCEMENT: Here is where one might reset the
|
|
statistics that one is measuring about the parallel execution */
|
|
|
|
/* Decompose model objects into patches and build the BSP tree */
|
|
/* Create the initial tasks */
|
|
init_modeling_tasks(process_id) ;
|
|
process_tasks(process_id) ;
|
|
|
|
/* Gather rays & do BF refinement */
|
|
while( init_ray_tasks(process_id) )
|
|
{
|
|
/* Wait till tasks are put in the queue */
|
|
BARRIER(global->barrier, n_processors);
|
|
/* Then perform ray-gathering and BF-refinement till the
|
|
solution converges */
|
|
process_tasks(process_id) ;
|
|
}
|
|
|
|
if ((process_id == 0) || (dostats))
|
|
CLOCK(refine_done);
|
|
|
|
BARRIER(global->barrier, n_processors);
|
|
|
|
if ((process_id == 0) || (dostats))
|
|
CLOCK(vertex_start);
|
|
|
|
/* Compute area-weighted radiosity value at each vertex */
|
|
init_radavg_tasks( RAD_AVERAGING_MODE, process_id ) ;
|
|
process_tasks(process_id) ;
|
|
|
|
/* Then normalize the radiosity at vertices */
|
|
init_radavg_tasks( RAD_NORMALIZING_MODE, process_id ) ;
|
|
process_tasks(process_id) ;
|
|
|
|
if ((process_id == 0) || (dostats))
|
|
CLOCK(vertex_done);
|
|
|
|
if ((process_id == 0) || (dostats)) {
|
|
timing[process_id]->rad_start = rad_start;
|
|
timing[process_id]->rad_time = vertex_done - rad_start;
|
|
timing[process_id]->refine_time = refine_done - rad_start;
|
|
timing[process_id]->vertex_time = vertex_done - vertex_start;
|
|
timing[process_id]->wait_time = vertex_start - refine_done;
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/***************************************************************************
|
|
*
|
|
* init_ray_tasks()
|
|
*
|
|
* Create initial tasks to perform ray gathering.
|
|
*
|
|
****************************************************************************/
|
|
|
|
|
|
#if PATCH_ASSIGNMENT == PATCH_ASSIGNMENT_STATIC
|
|
static void _init_ray_tasks_static(Patch *p, long dummy, long process_id);
|
|
#define _INIT_RAY_TASK _init_ray_tasks_static
|
|
#endif
|
|
|
|
#if PATCH_ASSIGNMENT == PATCH_ASSIGNMENT_COSTBASED
|
|
static long avg_cost_of_q ;
|
|
static long avg_cost_of_patch ;
|
|
static long queue_cost[MAX_TASKQUEUES] ;
|
|
|
|
static void _init_ray_tasks_cost2(Patch *p, long layer, long process_id);
|
|
#define _INIT_RAY_TASK _init_ray_tasks_cost2
|
|
#endif
|
|
|
|
|
|
|
|
|
|
long init_ray_tasks(long process_id)
|
|
{
|
|
long conv ;
|
|
|
|
/* If this is not the first process to initialize, then return */
|
|
LOCK(global->avg_radiosity_lock);
|
|
if( ! check_task_counter() )
|
|
{
|
|
conv = global->converged ;
|
|
UNLOCK(global->avg_radiosity_lock);
|
|
return( conv == 0 ) ;
|
|
}
|
|
|
|
/* Check radiosity convergence */
|
|
conv = radiosity_converged(process_id) ;
|
|
global->converged = conv ;
|
|
|
|
/* Reset total energy variable */
|
|
global->prev_total_energy = global->total_energy ;
|
|
global->total_energy.r = 0.0 ;
|
|
global->total_energy.g = 0.0 ;
|
|
global->total_energy.b = 0.0 ;
|
|
global->total_patch_area = 0.0 ;
|
|
|
|
/* Increment iteration counter */
|
|
global->iteration_count++ ;
|
|
UNLOCK(global->avg_radiosity_lock);
|
|
|
|
/* If radiosity converged, then return 0 */
|
|
if( conv )
|
|
return( 0 ) ;
|
|
|
|
|
|
#if PATCH_ASSIGNMENT == PATCH_ASSIGNMENT_COSTBASED
|
|
/* Compute average cost per queue. Also reset the cost variable.
|
|
The 'cost_sum' is not locked since no one is processing rays
|
|
at this moment */
|
|
|
|
for( crnt_qid = 0 ; crnt_qid < n_taskqueues ; crnt_qid++ )
|
|
queue_cost[ crnt_qid ] = 0 ;
|
|
|
|
avg_cost_of_q = global->cost_estimate_sum / n_taskqueues ;
|
|
avg_cost_of_patch = global->cost_estimate_sum / global->n_total_patches ;
|
|
cost_of_this_q = 0 ;
|
|
crnt_qid = 0 ;
|
|
|
|
global->cost_sum = 0 ;
|
|
global->cost_estimate_sum = 0 ;
|
|
|
|
/* layered selection of tasks */
|
|
foreach_patch_in_bsp( _INIT_RAY_TASK, 2, process_id ) ;
|
|
foreach_patch_in_bsp( _INIT_RAY_TASK, 1, process_id ) ;
|
|
#endif
|
|
|
|
/* Create BF refinement tasks */
|
|
foreach_patch_in_bsp( _INIT_RAY_TASK, 0, process_id ) ;
|
|
|
|
return( 1 ) ;
|
|
}
|
|
|
|
|
|
static void _init_ray_tasks_static(Patch *p, long dummy, long process_id)
|
|
{
|
|
/* Clear incoming energy variable */
|
|
p->el_root->rad_in.r = 0.0 ;
|
|
p->el_root->rad_in.g = 0.0 ;
|
|
p->el_root->rad_in.b = 0.0 ;
|
|
|
|
enqueue_ray_task( (p->seq_no >> 2) % n_taskqueues, p->el_root,
|
|
TASK_APPEND, process_id ) ;
|
|
}
|
|
|
|
#if PATCH_ASSIGNMENT == PATCH_ASSIGNMENT_COSTBASED
|
|
static void _init_ray_tasks_cost2(Patch *p, long layer, long process_id)
|
|
{
|
|
Patch_Cost *pc ;
|
|
long c_est ;
|
|
long qid ;
|
|
long min_cost_q, min_cost ;
|
|
|
|
|
|
pc = &global->patch_cost[ p->seq_no ] ;
|
|
c_est = pc->cost_estimate ;
|
|
|
|
if( c_est < 0 )
|
|
/* Already processed */
|
|
return ;
|
|
|
|
if( c_est < avg_cost_of_patch * layer )
|
|
return ;
|
|
|
|
/* Find the first available queue */
|
|
min_cost_q = 0 ;
|
|
min_cost = queue_cost[ 0 ] ;
|
|
for( qid = 0 ; qid < n_taskqueues ; qid++ )
|
|
{
|
|
if( (c_est + queue_cost[ qid ]) <= avg_cost_of_q )
|
|
break ;
|
|
|
|
if( min_cost > queue_cost[ qid ] )
|
|
{
|
|
min_cost_q = qid ;
|
|
min_cost = queue_cost[ qid ] ;
|
|
}
|
|
}
|
|
|
|
if( qid >= n_taskqueues )
|
|
{
|
|
/* All queues are nearly full. Put to min-cost queue */
|
|
qid = min_cost_q ;
|
|
}
|
|
|
|
/* Update queue cost */
|
|
queue_cost[ qid ] += c_est ;
|
|
|
|
|
|
/* Clear incoming energy variable */
|
|
p->el_root->rad_in.r = 0.0 ;
|
|
p->el_root->rad_in.g = 0.0 ;
|
|
p->el_root->rad_in.b = 0.0 ;
|
|
|
|
/* Clear cost value */
|
|
pc->cost_estimate = -1 ;
|
|
pc->n_bsp_node = 0 ;
|
|
|
|
/* Enqueue */
|
|
enqueue_ray_task( qid, p->el_root, TASK_APPEND, process_id ) ;
|
|
|
|
}
|
|
#endif
|
|
|
|
|
|
|
|
/***************************************************************************
|
|
*
|
|
* init_radavg_tasks()
|
|
*
|
|
* Create initial tasks to perform radiosity averaging.
|
|
*
|
|
****************************************************************************/
|
|
|
|
void init_radavg_tasks(long mode, long process_id)
|
|
{
|
|
|
|
/* If this is not the first process to initialize, then return */
|
|
if( ! check_task_counter() )
|
|
return ;
|
|
|
|
/* Create RadAvg tasks */
|
|
foreach_patch_in_bsp( _init_radavg_tasks, mode, process_id ) ;
|
|
}
|
|
|
|
|
|
static void _init_radavg_tasks(Patch *p, long mode, long process_id)
|
|
{
|
|
enqueue_radavg_task( p->seq_no % n_taskqueues, p->el_root, mode, process_id ) ;
|
|
}
|
|
|
|
|
|
|
|
/***************************************
|
|
*
|
|
* init_global()
|
|
*
|
|
****************************************/
|
|
|
|
|
|
void init_global(long process_id)
|
|
{
|
|
/* Clear BSP root pointer */
|
|
global->index = 1; /* ****** */
|
|
global->bsp_root = 0 ;
|
|
LOCKINIT(global->index_lock);
|
|
LOCKINIT(global->bsp_tree_lock);
|
|
|
|
/* Initialize radiosity statistics variables */
|
|
LOCKINIT(global->avg_radiosity_lock);
|
|
global->converged = 0 ;
|
|
global->prev_total_energy.r = 0.0 ;
|
|
global->prev_total_energy.g = 0.0 ;
|
|
global->prev_total_energy.b = 0.0 ;
|
|
global->total_energy.r = 1.0 ;
|
|
global->total_energy.g = 1.0 ;
|
|
global->total_energy.b = 1.0 ;
|
|
global->total_patch_area = 1.0 ;
|
|
global->iteration_count = -1 ; /* init_ray_task() increments to 0 */
|
|
|
|
/* Initialize the cost sum */
|
|
LOCKINIT(global->cost_sum_lock);
|
|
global->cost_sum = 0 ;
|
|
global->cost_estimate_sum = 0 ;
|
|
|
|
/* Initialize the barrier */
|
|
BARINIT(global->barrier, n_processors);
|
|
LOCKINIT(global->pbar_lock);
|
|
global->pbar_count = 0 ;
|
|
|
|
/* Initialize task counter */
|
|
global->task_counter = 0 ;
|
|
LOCKINIT(global->task_counter_lock);
|
|
|
|
/* Initialize task queue */
|
|
init_taskq(process_id) ;
|
|
|
|
/* Initialize Patch, Element, Interaction free lists */
|
|
init_patchlist(process_id) ;
|
|
init_elemlist(process_id) ;
|
|
init_interactionlist(process_id) ;
|
|
init_elemvertex(process_id) ;
|
|
init_edge(process_id) ;
|
|
|
|
/* Initialize statistical info */
|
|
init_stat_info(process_id) ;
|
|
|
|
}
|
|
|
|
|
|
/*************************************************************
|
|
*
|
|
* parse_args() Parse arguments
|
|
*
|
|
**************************************************************/
|
|
|
|
static void parse_args(int argc, char *argv[])
|
|
{
|
|
long cnt ;
|
|
|
|
/* Parse arguments */
|
|
for( cnt = 1 ; cnt < argc ; cnt++ )
|
|
{
|
|
if( strcmp( argv[cnt], "-p" ) == 0 ) {
|
|
sscanf( argv[++cnt], "%ld", &n_processors ) ;
|
|
n_taskqueues = n_processors;
|
|
}
|
|
else if( strcmp( argv[cnt], "-tq" ) == 0 )
|
|
sscanf( argv[++cnt], "%ld", &n_tasks_per_queue ) ;
|
|
else if( strcmp( argv[cnt], "-ae" ) == 0 )
|
|
sscanf( argv[++cnt], "%f", &Area_epsilon ) ;
|
|
else if( strcmp( argv[cnt], "-pr" ) == 0 )
|
|
sscanf( argv[++cnt], "%ld", &N_inter_parallel_bf_refine ) ;
|
|
else if( strcmp( argv[cnt], "-pv" ) == 0 )
|
|
sscanf( argv[++cnt], "%ld", &N_visibility_per_task ) ;
|
|
else if( strcmp( argv[cnt], "-bf" ) == 0 )
|
|
sscanf( argv[++cnt], "%f", &BFepsilon ) ;
|
|
else if( strcmp( argv[cnt], "-en" ) == 0 )
|
|
sscanf( argv[++cnt], "%f", &Energy_epsilon ) ;
|
|
|
|
else if( strcmp( argv[cnt], "-batch" ) == 0 )
|
|
batch_mode = 1 ;
|
|
else if( strcmp( argv[cnt], "-verbose" ) == 0 )
|
|
verbose_mode = 1 ;
|
|
else if( strcmp( argv[cnt], "-s" ) == 0 )
|
|
dostats = 1 ;
|
|
else if( strcmp( argv[cnt], "-room" ) == 0 )
|
|
model_selector = MODEL_ROOM_DATA ;
|
|
else if( strcmp( argv[cnt], "-largeroom" ) == 0 )
|
|
model_selector = MODEL_LARGEROOM_DATA ;
|
|
else if(( strcmp( argv[cnt], "-help" ) == 0 ) || ( strcmp( argv[cnt], "-h" ) == 0 ) || ( strcmp( argv[cnt], "-H" ) == 0 )) {
|
|
print_usage() ;
|
|
exit(0) ;
|
|
}
|
|
}
|
|
|
|
|
|
/* Then check the arguments */
|
|
if( (n_processors < 1) || (MAX_PROCESSORS < n_processors) )
|
|
{
|
|
fprintf( stderr, "Bad number of processors: %ld\n",
|
|
n_processors ) ;
|
|
exit(1) ;
|
|
}
|
|
if( (n_taskqueues < 1) || (MAX_TASKQUEUES < n_taskqueues) )
|
|
{
|
|
fprintf( stderr, "Bad number of task queues: %ld\n",
|
|
n_taskqueues ) ;
|
|
exit(1) ;
|
|
}
|
|
/* Check epsilon values */
|
|
if( Area_epsilon < 0.0 )
|
|
{
|
|
fprintf( stderr, "Area epsilon must be positive\n" ) ;
|
|
exit(1) ;
|
|
}
|
|
if( BFepsilon < 0.0 )
|
|
{
|
|
fprintf( stderr, "BFepsilon must be within [0,1]\n" ) ;
|
|
exit(1) ;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
/*************************************************************
|
|
*
|
|
* print_usage()
|
|
*
|
|
**************************************************************/
|
|
|
|
void print_usage()
|
|
{
|
|
fprintf( stderr, "Usage: RADIOSITY [options..]\n\n" ) ;
|
|
fprintf( stderr, "\tNote: Must have a space between option label and numeric value, if any\n\n");
|
|
fprintf( stderr, " -p (d) # of processes\n" ) ;
|
|
fprintf( stderr, " -tq (d) # of tasks per queue: default (200) in code for SPLASH\n" ) ;
|
|
fprintf( stderr, " -ae (f) Area epsilon: default (2000.0) in code for SPLASH\n" ) ;
|
|
fprintf( stderr, " -pr (d) # of inter for parallel refinement: default (5) in code for SPLASH\n") ;
|
|
fprintf( stderr, " -pv (d) # of visibility comp in a task: default (4) in code for SPLASH\n") ;
|
|
fprintf( stderr, " -bf (f) BFepsilon (BF refinement): default (0.015) in code for SPLASH\n" ) ;
|
|
fprintf( stderr, " -en (f) Energy epsilon (convergence): default (0.005) in code for SPLASH\n" ) ;
|
|
fprintf( stderr, " -room Use room model (default=test)\n" ) ;
|
|
fprintf( stderr, " -largeroom Use large room model\n" ) ;
|
|
fprintf( stderr, " -batch Batch mode (use for SPLASH)\n" ) ;
|
|
fprintf( stderr, " -verbose Verbose mode (don't use for SPLASH)\n" ) ;
|
|
fprintf( stderr, " -s Measure per-process timing (don't use for SPLASH)\n" ) ;
|
|
}
|
|
|