2017-04-26 17:20:15 +02:00
/*************************************************************************/
/* */
/* 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. */
/* */
/*************************************************************************/
/*
* NAME
* prt - parallel ray tracer
*
* SYNOPSIS
* prt [ options ] envfile
*
* - h Print this usage message .
* - a < n > Enable antialiasing with n subpixels ( default = 1 ) .
* - m < n > Request n megabytes of global memory ( default = 32 ) .
* - p < n > Run on n processors ( default = 1 ) .
*
* DESCRIPTION
*
* RETURNS
* PRT returns an exit code of 0 to the OS for successful operation ; it
* returns a non - zero exit code ( usually 1 ) if any type of error occurs .
*
* EXAMPLES
* To ray trace cube . env on 1 processor and default global memory size :
*
* prt cube . env
*
* To ray trace car . env on 4 processors and 72 MB of global memory :
*
* prt - p4 - m72 car . env
*
* FILES
*
* SEE ALSO
*
* DIAGNOSTICS
* All error messages take the form :
*
* prt : Text of the error message .
*
* All possible error messages are listed below , including the potential
* cause of the error , and the corrective action , if any .
*
* FATAL ERRORS
* Invalid option ' % c ' .
* The command line included an option which was not
* recognized . Check your command line syntax , remove
* the offending option , and try again .
*
* Cannot open file " filename " .
* The specified file could not be found , or some other
* OS error prevented it from being opened . Check your
* typing and try again .
*
* Cannot allocate local memory .
* malloc ( ) failed for some reason .
*
* Cannot allocate global memory .
* G_MALLOC ( ) failed for some reason .
*
* Valid range for # processors is [ 1 , % ld ] .
* Do not exceed the ranges shown by the message .
*
*/
# define MAIN /* indicate to rt.H that we need main_env for this file*/
# define VERSION "1.00"
2017-04-26 18:03:02 +02:00
# include <stdio.h>
# include <math.h>
2017-04-26 17:20:15 +02:00
# include "rt.h"
2017-04-26 18:03:02 +02:00
2017-04-26 17:20:15 +02:00
CHAR * ProgName = " RAYTRACE " ; /* The program name. */
INT nprocs = 1 ; /* The number of processors to use. */
INT MaxGlobMem = 32 ; /* Maximum global memory needed (MB).*/
INT NumSubRays = 1 ; /* Number of subpixel samples to calc*/
INT dostats = 0 ;
/*
* NAME
* Usage - print proper usage message
*
* SYNOPSIS
* VOID Usage ( )
*
* RETURNS
* Nothing .
*/
VOID Usage ( )
2017-04-26 18:03:02 +02:00
{
fprintf ( stdout , " %s - parallel ray tracer \n " , ProgName ) ;
fprintf ( stdout , " Version %s \n \n " , VERSION ) ;
2017-04-26 17:20:15 +02:00
2017-04-26 18:03:02 +02:00
fprintf ( stdout , " Usage: \t %s [options] envfile \n \n " , ProgName ) ;
2017-04-26 17:20:15 +02:00
2017-04-26 18:03:02 +02:00
fprintf ( stdout , " \t -h \t Print this usage message. \n " ) ;
fprintf ( stdout , " \t -a<n> \t Enable antialiasing with n subpixels (default = 1). \n \t When using with SPLASH suite for evaluation, use default (no antialiasing) \n " ) ;
fprintf ( stdout , " \t -m<n> \t Request n megabytes of global memory (default = 32). \n " ) ;
fprintf ( stdout , " \t -p<n> \t Run on n processors (default = 1). \n " ) ;
2017-04-26 17:20:15 +02:00
fprintf ( stdout , " \t -s \t Measure and print per-process timing information. \n " ) ;
2017-04-26 18:03:02 +02:00
fprintf ( stdout , " \n " ) ;
}
2017-04-26 17:20:15 +02:00
/*
* NAME
* PrintStatistics - print out various ray tracer statistics
*
* SYNOPSIS
* VOID PrintStatistics ( )
*
* RETURNS
* Nothing .
*/
VOID PrintStatistics ( )
2017-04-26 18:03:02 +02:00
{
/*
printf ( " \n ****** Ray trace Stats ****** \n " ) ;
printf ( " \t Resolution: \t \t %ld by %ld \n " , Display . xres + 1 , Display . yres + 1 ) ;
printf ( " \t Number Lights: \t \t %ld \n " , nlights ) ;
printf ( " \t Anti level: \t \t %ld \n " , Display . maxAAsubdiv ) ;
printf ( " \t Total Rays: \t \t %ld \n " , Stats . total_rays ) ;
printf ( " \t Primary Rays: \t \t %ld \n " , Stats . prim_rays ) ;
printf ( " \t Shadow Rays: \t \t %ld \n " , Stats . shad_rays ) ;
printf ( " \t Shadow Rays Hit: \t %ld \n " , Stats . shad_rays_hit ) ;
printf ( " \t Shadow Rays Not Hit: \t %ld \n " , Stats . shad_rays_not_hit ) ;
printf ( " \t Shadow Coherence Rays: \t %ld \n " , Stats . shad_coherence_rays ) ;
printf ( " \t Reflective Rays: \t %ld \n " , Stats . refl_rays ) ;
printf ( " \t TransmissiveRays: \t %ld \n " , Stats . trans_rays ) ;
printf ( " \t Anti-Aliasing Rays: \t %ld \n " , Stats . aa_rays ) ;
printf ( " \t Background Pixels: \t %ld \n " , Stats . coverage ) ;
printf ( " \t Max Tree depth reached: \t %ld \n " , Stats . max_tree_depth ) ;
printf ( " \t Max # prims tested for a ray: \t %ld \n " , Stats . max_objs_ray ) ;
printf ( " \t Max Rays shot for a pixel: \t %ld \n " , Stats . max_rays_pixel ) ;
printf ( " \t Max # prims tested for a pixel: \t %ld \n " , Stats . max_objs_pixel ) ;
printf ( " \n " ) ;
*/
if ( TraversalType = = TT_HUG )
{
/* prn_ds_stats();
prn_tv_stats ( ) ; */
ma_print ( ) ;
}
}
2017-04-26 17:20:15 +02:00
/*
* NAME
* StartRayTrace - starting point for all ray tracing proceses
*
* SYNOPSIS
* VOID StartRayTrace ( )
*
* RETURNS
* Nothing .
*/
VOID StartRayTrace ( )
2017-04-26 18:03:02 +02:00
{
INT pid ; /* Our internal process id number. */
UINT begin ;
UINT end ;
2017-04-26 17:20:15 +02:00
2017-04-26 18:03:02 +02:00
LOCK ( gm - > pidlock )
pid = gm - > pid + + ;
UNLOCK ( gm - > pidlock )
2017-04-26 17:20:15 +02:00
2017-04-26 18:03:02 +02:00
BARINCLUDE ( gm - > start ) ;
2017-04-26 17:20:15 +02:00
2017-04-26 18:03:02 +02:00
if ( ( pid = = 0 ) | | ( dostats ) )
2017-04-26 17:20:15 +02:00
CLOCK ( begin ) ;
2017-04-26 18:03:02 +02:00
/* POSSIBLE ENHANCEMENT: Here's where one might lock processes down
to processors if need be */
2017-04-26 17:20:15 +02:00
2017-04-26 18:03:02 +02:00
InitWorkPool ( pid ) ;
InitRayTreeStack ( Display . maxlevel , pid ) ;
2017-04-26 17:20:15 +02:00
2017-04-26 18:03:02 +02:00
/*
* Wait for all processes to be created , initialize their work
* pools , and arrive at this point ; then proceed . This BARRIER
* is absolutely required . Read comments in PutJob before
* moving this barrier .
*/
2017-04-26 17:20:15 +02:00
2017-04-26 18:03:02 +02:00
BARRIER ( gm - > start , gm - > nprocs )
2017-04-26 17:20:15 +02:00
2017-04-26 18:03:02 +02:00
/* POSSIBLE ENHANCEMENT: Here's where one would RESET STATISTICS
and TIMING if one wanted to measure only the parallel part */
2017-04-26 17:20:15 +02:00
2017-04-26 18:03:02 +02:00
RayTrace ( pid ) ;
2017-04-26 17:20:15 +02:00
2017-04-26 18:03:02 +02:00
if ( ( pid = = 0 ) | | ( dostats ) ) {
2017-04-26 17:20:15 +02:00
CLOCK ( end ) ;
gm - > partime [ pid ] = ( end - begin ) & 0x7FFFFFFF ;
if ( pid = = 0 ) gm - > par_start_time = begin ;
}
2017-04-26 18:03:02 +02:00
}
2017-04-26 17:20:15 +02:00
/*
* NAME
* main - mainline for the program
*
* SYNOPSIS
* INT main ( argc , argv )
* INT argc ;
* CHAR * argv [ ] ;
*
* DESCRIPTION
* Main parses command line arguments , opens / closes the files involved ,
* performs initializations , reads in the model database , partitions it
* as needed , and calls StartTraceRay ( ) to do the work .
*
* RETURNS
* 0 if successful .
* 1 for any type of failure .
*/
int main ( int argc , CHAR * argv [ ] )
2017-04-26 18:03:02 +02:00
{
INT i ;
UINT begin ;
UINT end ;
UINT lapsed ;
MATRIX vtrans , Vinv ; /* View transformation and inverse. */
/*
* First , process command line arguments .
*/
i = 1 ;
while ( ( i < argc ) & & ( argv [ i ] [ 0 ] = = ' - ' ) ) {
switch ( argv [ i ] [ 1 ] ) {
case ' ? ' :
case ' h ' :
case ' H ' :
Usage ( ) ;
exit ( 1 ) ;
case ' a ' :
case ' A ' :
AntiAlias = TRUE ;
if ( argv [ i ] [ 2 ] ! = ' \0 ' ) {
NumSubRays = atoi ( & argv [ i ] [ 2 ] ) ;
} else {
NumSubRays = atoi ( & argv [ + + i ] [ 0 ] ) ;
}
break ;
case ' m ' :
if ( argv [ i ] [ 2 ] ! = ' \0 ' ) {
MaxGlobMem = atoi ( & argv [ i ] [ 2 ] ) ;
} else {
MaxGlobMem = atoi ( & argv [ + + i ] [ 0 ] ) ;
}
break ;
case ' p ' :
if ( argv [ i ] [ 2 ] ! = ' \0 ' ) {
nprocs = atoi ( & argv [ i ] [ 2 ] ) ;
} else {
nprocs = atoi ( & argv [ + + i ] [ 0 ] ) ;
}
break ;
case ' s ' :
case ' S ' :
dostats = TRUE ;
break ;
default :
fprintf ( stderr , " %s: Invalid option \' %c \' . \n " , ProgName , argv [ i ] [ 0 ] ) ;
exit ( 1 ) ;
}
i + + ;
}
if ( i = = argc ) {
Usage ( ) ;
exit ( 1 ) ;
}
/*
* Make sure nprocs is within valid range .
*/
if ( nprocs < 1 | | nprocs > MAX_PROCS )
{
fprintf ( stderr , " %s: Valid range for #processors is [1, %d]. \n " , ProgName , MAX_PROCS ) ;
exit ( 1 ) ;
}
/*
* Print command line parameters .
*/
printf ( " \n " ) ;
printf ( " Number of processors: \t %ld \n " , nprocs ) ;
printf ( " Global shared memory size: \t %ld MB \n " , MaxGlobMem ) ;
printf ( " Samples per pixel: \t %ld \n " , NumSubRays ) ;
printf ( " \n " ) ;
/*
* Initialize the shared memory environment and request the total
* amount of amount of shared memory we might need . This
* includes memory for the database , grid , and framebuffer .
*/
MaxGlobMem < < = 20 ; /* Convert MB to bytes. */
MAIN_INITENV ( , MaxGlobMem + 512 * 1024 )
gm = ( GMEM * ) G_MALLOC ( sizeof ( GMEM ) ) ;
/*
* Perform shared environment initializations .
*/
gm - > nprocs = nprocs ;
gm - > pid = 0 ;
gm - > rid = 1 ;
BARINIT ( gm - > start , nprocs )
LOCKINIT ( gm - > pidlock )
LOCKINIT ( gm - > ridlock )
LOCKINIT ( gm - > memlock )
ALOCKINIT ( gm - > wplock , nprocs )
2017-04-26 17:20:15 +02:00
/* POSSIBLE ENHANCEMENT: Here is where one might distribute the
raystruct data structure across physically distributed memories as
desired . */
2017-04-26 18:03:02 +02:00
if ( ! GlobalHeapInit ( MaxGlobMem ) )
{
fprintf ( stderr , " %s: Cannot initialize global heap. \n " , ProgName ) ;
exit ( 1 ) ;
}
2017-04-26 17:20:15 +02:00
2017-04-26 18:03:02 +02:00
/*
* Initialize HUG parameters , read environment and geometry files .
*/
2017-04-26 17:20:15 +02:00
2017-04-26 18:03:02 +02:00
Huniform_defaults ( ) ;
ReadEnvFile ( /* *argv*/ argv [ i ] ) ;
ReadGeoFile ( GeoFileName ) ;
OpenFrameBuffer ( ) ;
2017-04-26 17:20:15 +02:00
2017-04-26 18:03:02 +02:00
/*
* Compute view transform and its inverse .
*/
2017-04-26 17:20:15 +02:00
2017-04-26 18:03:02 +02:00
CreateViewMatrix ( ) ;
MatrixCopy ( vtrans , View . vtrans ) ;
MatrixInverse ( Vinv , vtrans ) ;
MatrixCopy ( View . vtransInv , Vinv ) ;
2017-04-26 17:20:15 +02:00
2017-04-26 18:03:02 +02:00
/*
* Print out what we have so far .
*/
2017-04-26 17:20:15 +02:00
2017-04-26 18:03:02 +02:00
printf ( " Number of primitive objects: \t %ld \n " , prim_obj_cnt ) ;
printf ( " Number of primitive elements: \t %ld \n " , prim_elem_cnt ) ;
2017-04-26 17:20:15 +02:00
2017-04-26 18:03:02 +02:00
/*
* Preprocess database into hierarchical uniform grid .
*/
2017-04-26 17:20:15 +02:00
2017-04-26 18:03:02 +02:00
if ( TraversalType = = TT_HUG )
BuildHierarchy_Uniform ( ) ;
2017-04-26 17:20:15 +02:00
2017-04-26 18:03:02 +02:00
/*
* Now create slave processes .
*/
2017-04-26 17:20:15 +02:00
2017-04-26 18:03:02 +02:00
CLOCK ( begin )
CREATE ( StartRayTrace , gm - > nprocs ) ;
WAIT_FOR_END ( gm - > nprocs ) ;
CLOCK ( end )
2017-04-26 17:20:15 +02:00
2017-04-26 18:03:02 +02:00
/*
* We are finished . Clean up , print statistics and run time .
*/
2017-04-26 17:20:15 +02:00
2017-04-26 18:03:02 +02:00
CloseFrameBuffer ( PicFileName ) ;
PrintStatistics ( ) ;
2017-04-26 17:20:15 +02:00
2017-04-26 18:03:02 +02:00
lapsed = ( end - begin ) & 0x7FFFFFFF ;
2017-04-26 17:20:15 +02:00
2017-04-26 18:03:02 +02:00
printf ( " TIMING STATISTICS MEASURED BY MAIN PROCESS: \n " ) ;
printf ( " Overall start time %20lu \n " , begin ) ;
printf ( " Overall end time %20lu \n " , end ) ;
printf ( " Total time with initialization %20lu \n " , lapsed ) ;
printf ( " Total time without initialization %20lu \n " , end - gm - > par_start_time ) ;
2017-04-26 17:20:15 +02:00
if ( dostats ) {
unsigned totalproctime , maxproctime , minproctime ;
printf ( " \n \n \n PER-PROCESS STATISTICS: \n " ) ;
printf ( " %20s%20s \n " , " Proc " , " Time " ) ;
printf ( " %20s%20s \n \n " , " " , " Tracing Rays " ) ;
for ( i = 0 ; i < gm - > nprocs ; i + + )
printf ( " %20ld%20ld \n " , i , gm - > partime [ i ] ) ;
totalproctime = gm - > partime [ 0 ] ;
minproctime = gm - > partime [ 0 ] ;
maxproctime = gm - > partime [ 0 ] ;
for ( i = 1 ; i < gm - > nprocs ; i + + ) {
totalproctime + = gm - > partime [ i ] ;
if ( gm - > partime [ i ] > maxproctime )
maxproctime = gm - > partime [ i ] ;
if ( gm - > partime [ i ] < minproctime )
minproctime = gm - > partime [ i ] ;
}
printf ( " \n \n %20s%20d \n " , " Max = " , maxproctime ) ;
printf ( " %20s%20d \n " , " Min = " , minproctime ) ;
printf ( " %20s%20d \n " , " Avg = " , ( int ) ( ( ( double ) totalproctime ) / ( ( double ) ( 1.0 * gm - > nprocs ) ) ) ) ;
}
2017-04-26 18:03:02 +02:00
MAIN_END
}
2017-04-26 17:20:15 +02:00