| /*************************************************************************/ |
| /* */ |
| /* 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 |
| * workpool.c |
| * |
| * DESCRIPTION |
| * This file contains the private data definitions and code for the ray |
| * job work pool. Each processor has its own workpool. |
| * |
| * The workpool consists of a stack of pixel bundles. Each bundle |
| * contains jobs for primary rays for a contiguous 2D pixel screen |
| * region. |
| * |
| */ |
| |
| |
| #include <stdio.h> |
| #include <math.h> |
| #include "rt.h" |
| |
| |
| |
| /* |
| * NAME |
| * PutJob - put another job into pid's work pool |
| * |
| * SYNOPSIS |
| * VOID PutJob(xs, ys, xe, ye, xbe, ybe, pid) |
| * INT xs, ys; // Start of block. |
| * INT xe, ye; // Extent of block. |
| * INT xbe, ybe; // Extent of bundle. |
| * INT pid; // Process id. |
| * |
| * DESCRIPTION |
| * Given a block of image screen pixels, this routine generates pixel |
| * bundle entries that are inserted into pid's work pool stack. |
| * |
| * A block includes the starting pixel address, the block size in x and y |
| * dimensions and the bundle size for making pixel jobs. |
| * |
| * Pixel addresses are 0 relative. |
| * |
| * Locking of workpools for job insertion is not required since a given |
| * process only inserts into its own pool and since we use a barrier |
| * before jobs can be removed from workpools. |
| * |
| * RETURNS |
| * Nothing. |
| */ |
| |
| VOID PutJob(xs, ys, xe, ye, xbe, ybe, pid) |
| INT xs, ys; |
| INT xe, ye; |
| INT xbe, ybe; |
| INT pid; |
| { |
| INT i, j; |
| INT xb_addr, yb_addr; /* Bundle pixel address. */ |
| INT xb_end, yb_end; /* End bundle pixels. */ |
| INT xb_size, yb_size; /* Bundle size. */ |
| WPJOB *wpentry; /* New work pool entry. */ |
| |
| /* Starting block pixel address (upper left pixel). */ |
| |
| xb_addr = xs; |
| yb_addr = ys; |
| |
| /* Ending block pixel address (lower right pixel). */ |
| |
| xb_end = xb_addr + xe - 1; |
| yb_end = yb_addr + ye - 1; |
| |
| for (i = 0; i < ye; i += ybe) |
| { |
| for (j = 0; j < xe; j += xbe) |
| { |
| /* Determine bundle size. */ |
| |
| if ((xb_addr + xbe - 1) <= xb_end) |
| xb_size = xbe; |
| else |
| xb_size = xb_end - xb_addr + 1; |
| |
| if ((yb_addr + ybe - 1) <= yb_end) |
| yb_size = ybe; |
| else |
| yb_size = yb_end - yb_addr + 1; |
| |
| |
| /* Initialize work pool entry. */ |
| |
| wpentry = GlobalMalloc(sizeof(WPJOB), "workpool.c"); |
| |
| wpentry->xpix = xb_addr; |
| wpentry->ypix = yb_addr; |
| wpentry->xdim = xb_size; |
| wpentry->ydim = yb_size; |
| |
| |
| /* Add to top of work pool stack. */ |
| |
| if (!gm->workpool[pid][0]) |
| wpentry->next = NULL; |
| else |
| wpentry->next = gm->workpool[pid][0]; |
| |
| gm->workpool[pid][0] = wpentry; |
| xb_addr += xbe; |
| } |
| |
| xb_addr = xs; |
| yb_addr += ybe; |
| } |
| } |
| |
| |
| |
| /* |
| * NAME |
| * GetJob - get next job from pid's work pool |
| * |
| * SYNOPSIS |
| * INT GetJob(job, pid) |
| * RAYJOB *job; // Ray job description. |
| * INT pid; // Process id. |
| * |
| * DESCRIPTION |
| * Return a primary ray job bundle from the top of the stack. A ray job |
| * bundle consists of the starting primary ray pixel address and the size |
| * of the pixel bundle. |
| * |
| * RETURNS |
| * Work pool status code. |
| */ |
| |
| INT GetJob(job, pid) |
| RAYJOB *job; |
| INT pid; |
| { |
| WPJOB *wpentry; /* Work pool entry. */ |
| |
| ALOCK(gm->wplock, pid) |
| wpentry = gm->workpool[pid][0]; |
| |
| if (!wpentry) |
| { |
| gm->wpstat[pid][0] = WPS_EMPTY; |
| AULOCK(gm->wplock, pid) |
| return (WPS_EMPTY); |
| } |
| |
| gm->workpool[pid][0] = wpentry->next; |
| AULOCK(gm->wplock, pid) |
| |
| /* Set up ray job information. */ |
| |
| job->x = wpentry->xpix; |
| job->y = wpentry->ypix; |
| job->xcurr = wpentry->xpix; |
| job->ycurr = wpentry->ypix; |
| job->xlen = wpentry->xdim; |
| job->ylen = wpentry->ydim; |
| |
| GlobalFree(wpentry); |
| return (WPS_VALID); |
| } |
| |
| |
| |
| /* |
| * NAME |
| * GetJobs - get next job for pid (with job stealing) |
| * |
| * SYNOPSIS |
| * INT GetJobs(job, pid) |
| * RAYJOB *job; // Ray job pointer from work pool. |
| * INT pid; // Process id. |
| * |
| * DESCRIPTION |
| * |
| * RETURNS |
| * Workpool status. |
| */ |
| |
| INT GetJobs(job, pid) |
| RAYJOB *job; |
| INT pid; |
| { |
| INT i; |
| |
| i = pid; |
| |
| /* First, try to get job from pid's own pool (or pool 0). */ |
| |
| if (gm->wpstat[i][0] == WPS_VALID) |
| if (GetJob(job, i) == WPS_VALID) |
| { |
| return (WPS_VALID); |
| } |
| |
| |
| /* |
| * If that failed, try to get job from another pid's work |
| * pool. |
| */ |
| |
| i = (pid + 1) % gm->nprocs; |
| |
| while (i != pid) |
| { |
| if (gm->wpstat[i][0] == WPS_VALID) |
| if (GetJob(job, i) == WPS_VALID) |
| { |
| return (WPS_VALID); |
| } |
| |
| i = (i + 1) % gm->nprocs; |
| } |
| |
| return (WPS_EMPTY); |
| } |
| |
| |
| |
| /* |
| * NAME |
| * PrintWorkPool - print out the work pool entries for a given process |
| * |
| * SYNOPSIS |
| * VOID PrintWorkPool(pid) |
| * INT pid; // Process id. |
| * |
| * RETURNS |
| * Nothing. |
| */ |
| |
| VOID PrintWorkPool(pid) |
| INT pid; |
| { |
| WPJOB *j; |
| |
| j = gm->workpool[pid][0]; |
| |
| while (j) |
| { |
| printf("Workpool entry: pid=%3ld xs=%3ld ys=%3ld xe=%3ld ye=%3ld\n", pid, j->xpix, j->ypix, j->xdim, j->ydim); |
| j = j->next; |
| } |
| } |
| |
| |
| |
| /* |
| * NAME |
| * InitWorkPool - fill pid's work pool with jobs |
| * |
| * SYNOPSIS |
| * VOID InitWorkPool(pid) |
| * INT pid; // Process id to initialize. |
| * |
| * RETURNS |
| * Nothing. |
| */ |
| |
| VOID InitWorkPool(pid) |
| INT pid; |
| { |
| INT i; |
| INT x, y; |
| INT xe, ye; |
| INT xsize, ysize; |
| |
| gm->wpstat[pid][0] = WPS_VALID; |
| gm->workpool[pid][0] = NULL; |
| |
| i = 0; |
| xsize = Display.xres/blockx; |
| ysize = Display.yres/blocky; |
| |
| for (y = 0; y < Display.yres; y += ysize) |
| { |
| if (y + ysize > Display.yres) |
| ye = Display.yres - y; |
| else |
| ye = ysize; |
| |
| for (x = 0; x < Display.xres; x += xsize) |
| { |
| if (x + xsize > Display.xres) |
| xe = Display.xres - x; |
| else |
| xe = xsize; |
| |
| if (i == pid) |
| PutJob(x, y, xe, ye, bundlex, bundley, pid); |
| |
| i = (i + 1)%gm->nprocs; |
| } |
| } |
| |
| } |
| |