gem5/splash2/codes/apps/raytrace/trace.C
Sanchayan Maity 0f4b39775c Fix splash2 benchmark
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.
2017-04-26 21:33:02 +05:30

313 lines
7.5 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. */
/* */
/*************************************************************************/
/*
* NAME
* trace.c
*
* DESCRIPTION
* This file contains the routines to process ray jobs from the work pool
* containing primary ray jobs.
*/
#include <stdio.h>
#include <math.h>
#include "rt.h"
/*
* NAME
* frand - generate random floating point number
*
* SYNOPSIS
* REAL frand()
* Used instead of standard srand for portability to other systems than Unix.
*
* RETURNS
* A random floating point number in the range 0 <= x < 1.
*/
REAL frand()
{
REAL r;
static LONG lLastRand = 0;
lLastRand = lLastRand*214013L + 2531011L;
r = (REAL)((lLastRand >> 16) & 0x7FFF)/32768.0;
return (r);
}
/*
* NAME
* GetRayJobFromBundle -
*
* SYNOPSIS
* BOOL GetRayJobFromBundle(job, x, y)
* RAYJOB *job; // Ray job from work pool.
* INT *x, *y; // Pixel address.
*
* DESCRIPTION
* This routine determines if there are any more primary rays left to
* process in the ray bundle job.
*
* The routine returns FALSE if the bundle processing is complete. If
* there are more jobs, the current x and y pixel position are returned
* through procedure parameters. Then, x and y are bundle is updated for
* the next inquiry and TRUE is returned.
*
* RETURNS
* See above.
*/
BOOL GetRayJobFromBundle(RAYJOB *job, INT *x, INT *y)
{
*x = job->xcurr; /* Set pixel address first. */
*y = job->ycurr;
if ((job->y + job->ylen) == job->ycurr) /* All done? */
return (FALSE);
job->xcurr++; /* Update to next pixel. */
if ((job->x +job->xlen) == job->xcurr )
{
job->xcurr = job->x; /* Go to new scanline. */
job->ycurr++;
}
return (TRUE);
}
/*
* NAME
* ConvertPrimRayJobToRayMsg - convert primary ray job to the ray message format
*
* SYNOPSIS
* VOID ConvertPrimRayJobToRayMsg(ray, x, y)
* RAY *ray; // Ray message.
* REAL x, y; // Pixel.
*
* DESCRIPTION
* This routine converts the primary ray job to the ray message format.
* The ray origin and direction are computed and the other ray message
* variables are initialized.
*
* Perspective Projection:
*
* Calculate ray direction thru pixel and transform it back to
* the world coordinate system. Origin of ray is eye position.
*
* Orthographic Projection:
*
* Calculate ray direction thru pixel and transform it back to
* the world coordinate system. Origin of ray must also be
* calculated.
* RETURNS
* Nothing.
*/
VOID ConvertPrimRayJobToRayMsg(RAY *ray, REAL x, REAL y)
{
VEC4 dir;
VEC4 origin;
if (View.projection == PT_PERSP)
{
dir[0] = -Display.scrHalfWidth + (x*Display.vWscale);
dir[1] = Display.scrHalfHeight - (y*Display.vHscale);
dir[2] = Display.scrDist;
dir[3] = 0.0;
/* Transform ray back to world. */
TransformViewRay(dir);
VecNorm(dir);
VecCopy(ray->D, dir);
VecCopy(ray->P, View.eye);
}
else
{
/* Orthographic projection. */
dir[0] = 0.0;
dir[1] = 0.0;
dir[2] = 1.0;
dir[3] = 0.0;
/* Transform ray back to world. */
TransformViewRay(dir);
VecNorm(dir);
VecCopy(ray->D, dir);
/* Calculate origin. */
origin[0] = -Display.scrHalfWidth + (x*Display.vWscale);
origin[1] = Display.scrHalfHeight - (y*Display.vHscale);
origin[2] = 0.0;
origin[3] = 1.0;
/* Transform origin back to world. */
TransformViewRay(origin);
VecCopy(ray->P, origin);
}
/* Initialize other fields of ray message. */
ray->level = 0;
ray->weight = 1.0/(REAL)NumSubRays;
LOCK(gm->ridlock);
ray->id = gm->rid++;
UNLOCK(gm->ridlock);
ray->x = (INT)x;
ray->y = (INT)y;
}
/*
* NAME
* RayTrace - process primary ray bundle jobs from the workpool
*
* SYNOPSIS
* VOID RayTrace(pid)
* INT pid; // Process id.
*
* DESCRIPTION
* Process primary ray bundle jobs from the workpool. Each ray job from
* the ray bundle list performs the following tasks.
*
* A ray bundle job is converted to a ray message and pushed
* on the raytree stack. A ray job consists of a pixel address
* while the ray message also contains the ray origin, direction,
* level in tree, ray weight, ray id, and grid parameters.
* Processing begins with the primary ray and secondary rays being
* pushed onto the stack as the raytree is built and processed.
* The raytree stack is used to avoid recursion.
*
* Processes all jobs on raytree stack.
*
* Calls routines for intersecting a ray with the environment and
* for shading the ray.
*
* RETURNS
* Nothing.
*/
VOID RayTrace(INT pid)
{
INT j;
INT x, y; /* Pixel address. */
REAL xx, yy;
VEC3 N; /* Normal at intersection. */
VEC3 Ipoint; /* Intersection point. */
COLOR c; /* Color for storing background. */
RAY *ray; /* Ray pointer. */
RAY rmsg; /* Ray message. */
RAYJOB job; /* Ray job from work pool. */
OBJECT *po; /* Ptr to object. */
BOOL hit; /* An object hit? */
IRECORD hitrecord; /* Intersection record. */
ray = &rmsg;
while (GetJobs(&job, pid) != WPS_EMPTY)
{
while (GetRayJobFromBundle(&job, &x, &y))
{
/* Convert the ray job to the ray message format. */
xx = (REAL)x;
yy = (REAL)y;
if (AntiAlias)
for (j = 0; j < NumSubRays; j++)
{
ConvertPrimRayJobToRayMsg(ray, xx + frand(), yy + frand());
PushRayTreeStack(ray, pid);
}
else
{
ConvertPrimRayJobToRayMsg(ray, xx, yy);
PushRayTreeStack(ray, pid);
}
while (PopRayTreeStack(ray, pid) != RTS_EMPTY)
{
/* Find which object is closest along the ray. */
switch (TraversalType)
{
case TT_LIST:
hit = Intersect(ray, &hitrecord);
break;
case TT_HUG:
hit = TraverseHierarchyUniform(ray, &hitrecord, pid);
break;
}
/* Process the object ray hit. */
if (hit)
{
/*
* Get parent object to be able to access
* object operations.
*/
po = hitrecord.pelem->parent;
/* Calculate intersection point. */
RayPoint(Ipoint, ray, hitrecord.t);
/* Calculate normal at this point. */
(*po->procs->normal)(&hitrecord, Ipoint, N);
/* Make sure normal is pointing toward ray origin. */
if ((VecDot(ray->D, N)) > 0.0)
VecNegate(N, N);
/*
* Compute shade at this point - will process
* shadow rays and add secondary reflection
* and refraction rays to ray tree stack
*/
Shade(Ipoint, N, ray, &hitrecord, pid);
}
else
{
/* Add background as pixel contribution. */
VecCopy(c, View.bkg);
VecScale(c, ray->weight, c);
AddPixelColor(c, ray->x, ray->y);
}
}
}
}
}