/*************************************************************************/ /* */ /* 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. */ /* */ /*************************************************************************/ /************************************************************************* * * * main.c: Starting point for rendering system. * * * Usage: VOLREND num_processes input_file [-a] where input_file is head for the head data set. i.e. the filename without a suffix. and the -a option enables adaptive sampling of pixels. *************************************************************************/ #include "incl.h" #include #include #include #include #include "tiffio.h" #define SH_MEM_AMT 60000000 MAIN_ENV #include "anl.h" struct GlobalMemory *Global; long image_section[NI]; long voxel_section[NM]; long num_nodes,frame; long num_blocks,num_xblocks,num_yblocks; PIXEL *image_address; MPIXEL *mask_image_address; PIXEL *image_block,*mask_image_block; PIXEL *shd_address; BOOLEAN *sbit_address; long shd_length; long image_len[NI], mask_image_len[NI]; int image_length; long mask_image_length; char filename[FILENAME_STRING_SIZE]; void mclock(long stoptime, long starttime, long *exectime) { if (stoptime < starttime) *exectime = ((ULONG_MAX - starttime) + stoptime)/1000; else *exectime = (stoptime - starttime)/1000; } int main(int argc, char *argv[]) { if ((argc < 3) || (strncmp(argv[1],"-h",strlen("-h")) == 0) || (strncmp(argv[1],"-h",strlen("-H")) == 0)){ printf("usage: VOLREND num_processes input_file\n"); exit(-1); } MAIN_INITENV(, SH_MEM_AMT); num_nodes = atol(argv[1]); strcpy(filename,argv[2]); if (argc == 4) { if (strncmp(argv[3],"-a",strlen("-a")) == 0) adaptive = YES; else { printf("usage: VOLREND num_processes input_file [-a] \n"); exit(-1); } } Frame(); /* if (num_nodes > 1) WAIT_FOR_END(num_nodes-1);*/ if (num_nodes > 1) WAIT_FOR_END(num_nodes); MAIN_END; } void Frame() { long starttime,stoptime,exectime,i; Init_Options(); printf("*****Entering init_decomposition with num_nodes = %ld\n",num_nodes); fflush(stdout); Init_Decomposition(); printf("*****Exited init_decomposition with num_nodes = %ld\n",num_nodes); fflush(stdout); Global = (struct GlobalMemory *)NU_MALLOC(sizeof(struct GlobalMemory),0); BARINIT(Global->SlaveBarrier, num_nodes); BARINIT(Global->TimeBarrier, num_nodes); LOCKINIT(Global->IndexLock); LOCKINIT(Global->CountLock); ALOCKINIT(Global->QLock,MAX_NUMPROC+1); /* load dataset from file to each node */ #ifndef RENDER_ONLY CLOCK(starttime); Load_Map(filename); CLOCK(stoptime); mclock(stoptime,starttime,&exectime); printf("wall clock execution time to load map: %lu ms\n", exectime); #endif CLOCK(starttime); #ifndef RENDER_ONLY Compute_Normal(); #ifdef PREPROCESS Store_Normal(filename); #endif #else Load_Normal(filename); #endif CLOCK(stoptime); mclock(stoptime,starttime,&exectime); printf("wall clock execution time to compute normal: %lu ms\n", exectime); CLOCK(starttime); #ifndef RENDER_ONLY Compute_Opacity(); #ifdef PREPROCESS Store_Opacity(filename); #endif #else Load_Opacity(filename); #endif CLOCK(stoptime); mclock(stoptime,starttime,&exectime); printf("wall clock execution time to compute opacity: %lu ms\n", exectime); Compute_Pre_View(); shd_length = LOOKUP_SIZE; Allocate_Shading_Table(&shd_address,shd_length); /* allocate space for image */ image_len[X] = frust_len; image_len[Y] = frust_len; image_length = image_len[X] * image_len[Y]; Allocate_Image(&image_address,image_length); if (num_nodes == 1) { block_xlen = image_len[X]; block_ylen = image_len[Y]; num_blocks = 1; num_xblocks = 1; num_yblocks = 1; image_block = image_address; } else { num_xblocks = ROUNDUP((float)image_len[X]/(float)block_xlen); num_yblocks = ROUNDUP((float)image_len[Y]/(float)block_ylen); num_blocks = num_xblocks * num_yblocks; Lallocate_Image(&image_block,block_xlen*block_ylen); } CLOCK(starttime); #ifndef RENDER_ONLY Compute_Octree(); #ifdef PREPROCESS Store_Octree(filename); #endif #else Load_Octree(filename); #endif CLOCK(stoptime); mclock(stoptime,starttime,&exectime); printf("wall clock execution time to compute octree: %lu ms\n", exectime); #ifdef PREPROCESS return; #endif if (adaptive) { printf("1.\n"); for (i=0; iIndex = NODE0; printf("\nRendering...\n"); printf("node\tframe\ttime\titime\trays\thrays\tsamples trilirped\n"); CREATE(Render_Loop, num_nodes); } void Render_Loop() { long step,i; PIXEL *local_image_address; MPIXEL *local_mask_image_address; char outfile[FILENAME_STRING_SIZE]; long image_partition,mask_image_partition; float inv_num_nodes; long my_node; LOCK(Global->IndexLock); my_node = Global->Index++; UNLOCK(Global->IndexLock); my_node = my_node%num_nodes; BARINCLUDE(Global->TimeBarrier); BARINCLUDE(Global->SlaveBarrier); /* POSSIBLE ENHANCEMENT: Here's where one might bind the process to a processor, if one wanted to. */ inv_num_nodes = 1.0/(float)num_nodes; image_partition = ROUNDUP(image_length*inv_num_nodes); mask_image_partition = ROUNDUP(mask_image_length*inv_num_nodes); #ifdef DIM for (dim=0; dimSlaveBarrier,num_nodes); if (my_node == num_nodes-1) { for (i=image_partition*my_node; iSlaveBarrier,num_nodes); Global->Counter = num_nodes; Global->Queue[num_nodes][0] = num_nodes; Global->Queue[my_node][0] = 0; Render(my_node); if (my_node == ROOT) { if (ROTATE_STEPS > 1) { #ifdef DIM sprintf(outfile, "%s_%ld",filename, 1000+dim*ROTATE_STEPS+step); #else sprintf(outfile, "%s_%ld.tiff",filename, 1000+step); #endif /* Store_Image(outfile); p = image_address; for (zz = 0;zz < image_length;zz++) { tiff_image[zz] = (long) ((*p)*256*256*256 + (*p)*256*256 + (*p)*256 + (*p)); p++; } tiff_save_rgba(outfile,tiff_image,image_len[X],image_len[Y]); */ WriteGrayscaleTIFF(outfile, image_len[X],image_len[Y],image_len[X], image_address); } else { /* Store_Image(filename); p = image_address; for (zz = 0;zz < image_length;zz++) { tiff_image[zz] = (long) ((*p)*256*256*256 + (*p)*256*256 + (*p)*256 + (*p)); p++; } tiff_save_rgba(filename,tiff_image,image_len[X],image_len[Y]); */ strcat(filename,".tiff"); WriteGrayscaleTIFF(filename, image_len[X],image_len[Y],image_len[X], image_address); } } } #ifdef DIM } #endif } #if 0 void Error(char string[], char *arg1, char *arg2, char *arg3, char *arg4, char *arg5, char *arg6, char *arg7, char *arg8) { fprintf(stderr,string,arg1,arg2,arg3,arg4,arg5,arg6,arg7,arg8); exit(1); } #else void Error(char string[], ...) { va_list ap; char *arg1 = NULL, *arg2 = NULL, *arg3 = NULL, *arg4 = NULL, *arg5 = NULL, *arg6 = NULL, *arg7 = NULL, *arg8 = NULL; va_start(ap, string); arg1 = va_arg(ap, char *); arg1 = va_arg(ap, char *); arg1 = va_arg(ap, char *); arg1 = va_arg(ap, char *); arg1 = va_arg(ap, char *); arg1 = va_arg(ap, char *); arg1 = va_arg(ap, char *); arg1 = va_arg(ap, char *); va_end(ap); fprintf(stderr,string,arg1,arg2,arg3,arg4,arg5,arg6,arg7,arg8); exit(1); } #endif void Allocate_Image(PIXEL **address, long length) { long i; printf(" Allocating image of %ld bytes...\n", length*sizeof(PIXEL)); *address = (PIXEL *)NU_MALLOC(length*sizeof(PIXEL),0); if (*address == NULL) Error(" No space available for image.\n", NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); for (i=0; i