Ejemplo n.º 1
0
void
render_camera_render(render_camera_t *camera, struct tie_s *tie, camera_tile_t *tile, tienet_buffer_t *result)
{
    render_camera_thread_data_t td;
    unsigned int scanline;
    uint32_t ind;

    ind = result->ind;

    /* Allocate storage for results */
    if (tile->format == RENDER_CAMERA_BIT_DEPTH_24) {
	ind += 3 * (unsigned int)tile->size_x * (unsigned int)tile->size_y + sizeof(camera_tile_t);
    } else if (tile->format == RENDER_CAMERA_BIT_DEPTH_128) {
	ind += 4 * sizeof(tfloat) * (unsigned int)tile->size_x * (unsigned int)tile->size_y + sizeof(camera_tile_t);
    }

    TIENET_BUFFER_SIZE((*result), ind);

    TCOPY(camera_tile_t, tile, 0, result->data, result->ind);
    result->ind += sizeof(camera_tile_t);

    td.tie = tie;
    td.camera = camera;
    td.tile = tile;
    td.res_buf = &((char *)result->data)[result->ind];
    scanline = 0;
    td.scanline = &scanline;

    bu_parallel(render_camera_render_thread, camera->thread_num, &td);

    result->ind = ind;

    return;
}
/* 0 = no difference within tolerance, 1 = difference >= tolerance */
int
analyze_raydiff(/* TODO - decide what to return.  Probably some sort of left, common, right segment sets.  See what rtcheck does... */
	struct db_i *dbip, const char *obj1, const char *obj2, struct bn_tol *tol)
{
    int ret;
    int count = 0;
    struct rt_i *rtip;
    int ncpus = bu_avail_cpus();
    point_t min, mid, max;
    struct rt_pattern_data *xdata, *ydata, *zdata;
    fastf_t *rays;
    struct raydiff_container *state;

    if (!dbip || !obj1 || !obj2 || !tol) return 0;

    rtip = rt_new_rti(dbip);
    if (rt_gettree(rtip, obj1) < 0) return -1;
    if (rt_gettree(rtip, obj2) < 0) return -1;
    rt_prep_parallel(rtip, 1);


    /* Now we've got the bounding box - set up the grids */
    VMOVE(min, rtip->mdl_min);
    VMOVE(max, rtip->mdl_max);
    VSET(mid, (max[0] - min[0])/2, (max[1] - min[1])/2, (max[2] - min[2])/2);

    BU_GET(xdata, struct rt_pattern_data);
    VSET(xdata->center_pt, min[0] - 0.1 * min[0], mid[1], mid[2]);
    VSET(xdata->center_dir, 1, 0, 0);
    xdata->vn = 2;
    xdata->pn = 2;
    xdata->n_vec = (vect_t *)bu_calloc(xdata->vn + 1, sizeof(vect_t), "vects array");
    xdata->n_p = (fastf_t *)bu_calloc(xdata->pn + 1, sizeof(fastf_t), "params array");
    xdata->n_p[0] = 50; /* TODO - get tolerances from caller */
    xdata->n_p[1] = 50;
    VSET(xdata->n_vec[0], 0, max[1], 0);
    VSET(xdata->n_vec[1], 0, 0, max[2]);
    ret = rt_pattern(xdata, RT_PATTERN_RECT_ORTHOGRID);
    bu_free(xdata->n_vec, "x vec inputs");
    bu_free(xdata->n_p, "x p inputs");
    if (ret < 0) return -1;


    BU_GET(ydata, struct rt_pattern_data);
    VSET(ydata->center_pt, mid[0], min[1] - 0.1 * min[1], mid[2]);
    VSET(ydata->center_dir, 0, 1, 0);
    ydata->vn = 2;
    ydata->pn = 2;
    ydata->n_vec = (vect_t *)bu_calloc(ydata->vn + 1, sizeof(vect_t), "vects array");
    ydata->n_p = (fastf_t *)bu_calloc(ydata->pn + 1, sizeof(fastf_t), "params array");
    ydata->n_p[0] = 50; /* TODO - get tolerances from caller */
    ydata->n_p[1] = 50;
    VSET(ydata->n_vec[0], max[0], 0, 0);
    VSET(ydata->n_vec[1], 0, 0, max[2]);
    ret = rt_pattern(ydata, RT_PATTERN_RECT_ORTHOGRID);
    bu_free(ydata->n_vec, "y vec inputs");
    bu_free(ydata->n_p, "y p inputs");
    if (ret < 0) return -1;

    BU_GET(zdata, struct rt_pattern_data);
    VSET(zdata->center_pt, mid[0], mid[1], min[2] - 0.1 * min[2]);
    VSET(zdata->center_dir, 0, 0, 1);
    zdata->vn = 2;
    zdata->pn = 2;
    zdata->n_vec = (vect_t *)bu_calloc(zdata->vn + 1, sizeof(vect_t), "vects array");
    zdata->n_p = (fastf_t *)bu_calloc(zdata->pn + 1, sizeof(fastf_t), "params array");
    zdata->n_p[0] = 50; /* TODO - get tolerances from caller */
    zdata->n_p[1] = 50;
    VSET(zdata->n_vec[0], max[0], 0, 0);
    VSET(zdata->n_vec[1], 0, max[1], 0);
    ret = rt_pattern(zdata, RT_PATTERN_RECT_ORTHOGRID);
    bu_free(zdata->n_vec, "x vec inputs");
    bu_free(zdata->n_p, "x p inputs");
    if (ret < 0) return -1;

    /* Consolidate the grids into a single ray array */
    {
	size_t i, j;
	rays = (fastf_t *)bu_calloc((xdata->ray_cnt + ydata->ray_cnt + zdata->ray_cnt + 1) * 6, sizeof(fastf_t), "rays");
	count = 0;
	for (i = 0; i < xdata->ray_cnt; i++) {
	    for (j = 0; j < 6; j++) {
		rays[6*count+j] = xdata->rays[6*i + j];
	    }
	    count++;
	}
	for (i = 0; i < ydata->ray_cnt; i++) {
	    for (j = 0; j < 6; j++) {
		rays[6*count+j] = ydata->rays[6*i + j];
	    }
	    count++;
	}
	for (i = 0; i < zdata->ray_cnt; i++) {
	    for (j = 0; j < 6; j++) {
		rays[6*count+j] = zdata->rays[6*i+j];
	    }
	    count++;
	}

    }
    bu_free(xdata->rays, "x rays");
    bu_free(ydata->rays, "y rays");
    bu_free(zdata->rays, "z rays");
    BU_PUT(xdata, struct rt_pattern_data);
    BU_PUT(ydata, struct rt_pattern_data);
    BU_PUT(zdata, struct rt_pattern_data);

    bu_log("ray cnt: %d\n", count);

    {
	int i, j;
	ncpus = 2;
	state = (struct raydiff_container *)bu_calloc(ncpus+1, sizeof(struct raydiff_container), "resources");
	for (i = 0; i < ncpus+1; i++) {
	    state[i].rtip = rtip;
	    state[i].tol = 0.5;
	    state[i].ncpus = ncpus;
	    state[i].left_name = bu_strdup(obj1);
	    state[i].right_name = bu_strdup(obj2);
	    BU_GET(state[i].resp, struct resource);
	    rt_init_resource(state[i].resp, i, state->rtip);
	    BU_GET(state[i].left, struct bu_ptbl);
	    bu_ptbl_init(state[i].left, 64, "left solid hits");
	    BU_GET(state[i].both, struct bu_ptbl);
	    bu_ptbl_init(state[i].both, 64, "hits on both solids");
	    BU_GET(state[i].right, struct bu_ptbl);
	    bu_ptbl_init(state[i].right, 64, "right solid hits");
	    state[i].rays_cnt = count;
	    state[i].rays = rays;
	}
	bu_parallel(raydiff_gen_worker, ncpus, (void *)state);

	/* Collect and print all of the results */
	for (i = 0; i < ncpus+1; i++) {
	    for (j = 0; j < (int)BU_PTBL_LEN(state[i].left); j++) {
		struct diff_seg *dseg = (struct diff_seg *)BU_PTBL_GET(state[i].left, j);
		bu_log("Result: LEFT diff vol (%s): %g %g %g -> %g %g %g\n", obj1, V3ARGS(dseg->in_pt), V3ARGS(dseg->out_pt));
	    }
	    for (j = 0; j < (int)BU_PTBL_LEN(state[i].both); j++) {
		struct diff_seg *dseg = (struct diff_seg *)BU_PTBL_GET(state[i].both, j);
		bu_log("Result: BOTH): %g %g %g -> %g %g %g\n", V3ARGS(dseg->in_pt), V3ARGS(dseg->out_pt));
	    }
	    for (j = 0; j < (int)BU_PTBL_LEN(state[i].right); j++) {
		struct diff_seg *dseg = (struct diff_seg *)BU_PTBL_GET(state[i].right, j);
		bu_log("Result: RIGHT diff vol (%s): %g %g %g -> %g %g %g\n", obj2, V3ARGS(dseg->in_pt), V3ARGS(dseg->out_pt));
	    }
	}

	/* Free results */
	for (i = 0; i < ncpus+1; i++) {
	    for (j = 0; j < (int)BU_PTBL_LEN(state[i].left); j++) {
		struct diff_seg *dseg = (struct diff_seg *)BU_PTBL_GET(state[i].left, j);
		BU_PUT(dseg, struct diff_seg);
	    }
	    bu_ptbl_free(state[i].left);
	    BU_PUT(state[i].left, struct diff_seg);
	    for (j = 0; j < (int)BU_PTBL_LEN(state[i].both); j++) {
		struct diff_seg *dseg = (struct diff_seg *)BU_PTBL_GET(state[i].both, j);
		BU_PUT(dseg, struct diff_seg);
	    }
	    bu_ptbl_free(state[i].both);
	    BU_PUT(state[i].both, struct diff_seg);
	    for (j = 0; j < (int)BU_PTBL_LEN(state[i].right); j++) {
		struct diff_seg *dseg = (struct diff_seg *)BU_PTBL_GET(state[i].right, j);
		BU_PUT(dseg, struct diff_seg);
	    }
	    bu_ptbl_free(state[i].right);
	    BU_PUT(state[i].right, struct diff_seg);

	    bu_free((void *)state[i].left_name, "left name");
	    bu_free((void *)state[i].right_name, "right name");
	    BU_PUT(state[i].resp, struct resource);
	}
	bu_free(state, "free state containers");
    }
    return 0;
}
Ejemplo n.º 3
0
/**
 * Compute a run of pixels, in parallel if the hardware permits it.
 *
 * For a general-purpose version, see LIBRT rt_shoot_many_rays().
 */
void
do_run(int a, int b)
{
    int cpu;

#ifdef USE_FORKED_THREADS
    int pid, wpid;
    int waitret;
    void *buffer = (void*)0;
    int p[2] = {0, 0};
    struct resource *tmp_res;

    if (RTG.rtg_parallel) {
	buffer = bu_calloc(npsw, sizeof(resource[0]), "buffer");
	if (pipe(p) == -1) {
	    perror("pipe failed");
	}
    }
#endif

    cur_pixel = a;
    last_pixel = b;

    if (!RTG.rtg_parallel) {
	/*
	 * SERIAL case -- one CPU does all the work.
	 */
	npsw = 1;
	worker(0, NULL);
    } else {
	/*
	 * Parallel case.
	 */

	/* hack to bypass a bug in the Linux 2.4 kernel pthreads
	 * implementation. cpu statistics are only traceable on a
	 * process level and the timers will report effectively no
	 * elapsed cpu time.  this allows the stats of all threads to
	 * be gathered up by an encompassing process that may be
	 * timed.
	 *
	 * XXX this should somehow only apply to a build on a 2.4
	 * linux kernel.
	 */
#ifdef USE_FORKED_THREADS
	pid = fork();
	if (pid < 0) {
	    perror("fork failed");
	    bu_exit(1, NULL);
	} else if (pid == 0) {
#endif

	    bu_parallel(worker, npsw, NULL);

#ifdef USE_FORKED_THREADS
	    /* send raytrace instance data back to the parent */
	    if (write(p[1], resource, sizeof(resource[0]) * npsw) == -1) {
		perror("Unable to write to the communication pipe");
		bu_exit(1, NULL);
	    }
	    /* flush the pipe */
	    if (close(p[1]) == -1) {
		perror("Unable to close the communication pipe");
		sleep(1); /* give the parent time to read */
	    }
	    bu_exit(0, NULL);
	} else {
	    if (read(p[0], buffer, sizeof(resource[0]) * npsw) == -1) {
		perror("Unable to read from the communication pipe");
	    }

	    /* do not use the just read info to overwrite the resource
	     * structures.  doing so will hose the resources
	     * completely
	     */

	    /* parent ends up waiting on his child (and his child's
	     * threads) to terminate.  we can get valid usage
	     * statistics on a child process.
	     */
	    while ((wpid = wait(&waitret)) != pid && wpid != -1)
		; /* do nothing */
	} /* end fork() */
#endif

    } /* end parallel case */

#ifdef USE_FORKED_THREADS
    if (RTG.rtg_parallel) {
	tmp_res = (struct resource *)buffer;
    } else {
	tmp_res = resource;
    }
    for (cpu=0; cpu < npsw; cpu++) {
	if (tmp_res[cpu].re_magic != RESOURCE_MAGIC) {
	    bu_log("ERROR: CPU %d resources corrupted, statistics bad\n", cpu);
	    continue;
	}
	rt_add_res_stats(APP.a_rt_i, &tmp_res[cpu]);
	rt_zero_res_stats(&resource[cpu]);
    }
#else
    /* Tally up the statistics */
    for (cpu=0; cpu < npsw; cpu++) {
	if (resource[cpu].re_magic != RESOURCE_MAGIC) {
	    bu_log("ERROR: CPU %d resources corrupted, statistics bad\n", cpu);
	    continue;
	}
	rt_add_res_stats(APP.a_rt_i, &resource[cpu]);
    }
#endif
    return;
}
HIDDEN int
_rt_generate_points(int **faces, int *num_faces, point_t **points, int *num_pnts, struct bu_ptbl *hit_pnts, struct db_i *dbip, const char *obj, fastf_t delta)
{
    int i, dir1, j;
    point_t min, max;
    int ncpus = bu_avail_cpus();
    struct rt_parallel_container *state;
    struct bu_vls vlsstr;
    bu_vls_init(&vlsstr);

    if (!hit_pnts || !dbip || !obj) return -1;

    BU_GET(state, struct rt_parallel_container);

    state->rtip = rt_new_rti(dbip);
    state->delta = delta;

    if (rt_gettree(state->rtip, obj) < 0) return -1;
    rt_prep_parallel(state->rtip, 1);

    state->resp = (struct resource *)bu_calloc(ncpus+1, sizeof(struct resource), "resources");
    for (i = 0; i < ncpus+1; i++) {
	rt_init_resource(&(state->resp[i]), i, state->rtip);
    }

    state->npts = (struct rt_point_container *)bu_calloc(ncpus+1, sizeof(struct rt_point_container), "point container arrays");
    int n[3];
    VMOVE(min, state->rtip->mdl_min);
    VMOVE(max, state->rtip->mdl_max);
    for (i = 0; i < 3; i++) {
	n[i] = (int)((max[i] - min[i])/state->delta) + 2;
	if(n[i] < 12) n[i] = 12;
    }
    int total = 0;
    for (i = 0; i < 3; i++) total += n[i]*n[(i+1)%3];
    if (total > 1e6) total = 1e6;
    for (i = 0; i < ncpus+1; i++) {
	state->npts[i].pts = (struct npoints *)bu_calloc(total, sizeof(struct npoints), "npoints arrays");
	state->npts[i].pnt_cnt = 0;
	state->npts[i].capacity = total;
    }

    for (dir1 = 0; dir1 < 3; dir1++) {
	state->ray_dir = dir1;
	state->ncpus = ncpus;
	state->delta = delta;
	bu_parallel(_rt_gen_worker, ncpus, (void *)state);
    }

    int out_cnt = 0;
    for (i = 0; i < ncpus+1; i++) {
	bu_log("%d, pnt_cnt: %d\n", i, state->npts[i].pnt_cnt);
	for (j = 0; j < state->npts[i].pnt_cnt; j++) {
	    struct npoints *npt = &(state->npts[i].pts[j]);
	    if (npt->in.is_set) out_cnt++;
	    if (npt->out.is_set) out_cnt++;
	}
    }

    struct rt_vert **rt_verts = (struct rt_vert **)bu_calloc(out_cnt, sizeof(struct rt_vert *), "output array");
    int curr_ind = 0;
    for (i = 0; i < ncpus+1; i++) {
	for (j = 0; j < state->npts[i].pnt_cnt; j++) {
	    struct npoints *npt = &(state->npts[i].pts[j]);
	    if (npt->in.is_set) {
		rt_verts[curr_ind] = &(npt->in);
		curr_ind++;
	    }
	    if (npt->out.is_set) {
		rt_verts[curr_ind] = &(npt->out);
		curr_ind++;
	    }
	}
    }

    struct spr_options opts = SPR_OPTIONS_DEFAULT_INIT;
    (void)spr_surface_build(faces, num_faces, (double **)points, num_pnts, (const struct cvertex **)rt_verts, out_cnt, &opts);

    return 0;
}