htrdr

Solving radiative transfer in heterogeneous media
git clone git://git.meso-star.fr/htrdr.git
Log | Files | Refs | README | LICENSE

commit a9551f9de1a1cbd49306738e13a10bf768548eb9
parent 476b6100867ab3e4124cbd8ebd9c40d068950d24
Author: Vincent Forest <vincent.forest@meso-star.com>
Date:   Thu, 19 Mar 2020 18:01:51 +0100

Update of the buffer memory layout

Diffstat:
Msrc/htrdr.c | 98++++++++++++++++++++++++++++++++++++++++++++++++++-----------------------------
Msrc/htrdr_c.h | 9---------
Msrc/htrdr_draw_radiance.c | 164++++++++++++++++++++++++++++++++++++++++++++++++++-----------------------------
Msrc/htrdr_solve.h | 40++++++++++++++++++++++++++++++----------
4 files changed, 196 insertions(+), 115 deletions(-)

diff --git a/src/htrdr.c b/src/htrdr.c @@ -109,18 +109,23 @@ dump_accum_buffer FILE* stream) { struct htrdr_buffer_layout layout; + size_t pixsz, pixal; size_t x, y; res_T res = RES_OK; ASSERT(htrdr && buf && stream_name && stream); (void)stream_name; + if(htsky_is_long_wave(htrdr->sky)) { + pixsz = sizeof(struct htrdr_pixel_lw); + pixal = ALIGNOF(struct htrdr_pixel_lw); + } else { + pixsz = sizeof(struct htrdr_pixel_sw); + pixal = ALIGNOF(struct htrdr_pixel_sw); + } + htrdr_buffer_get_layout(buf, &layout); - if(layout.elmt_size != sizeof(struct htrdr_accum[HTRDR_ESTIMATES_COUNT__]) - || layout.alignment < ALIGNOF(struct htrdr_accum[HTRDR_ESTIMATES_COUNT__])) { - htrdr_log_err(htrdr, - "%s: invalid buffer layout. " - "The pixel size must be the size of %lu accumulators.\n", - FUNC_NAME, (unsigned long)HTRDR_ESTIMATES_COUNT__); + if(layout.elmt_size != pixsz || layout.alignment != pixal) { + htrdr_log_err(htrdr, "%s: invalid buffer layout. ", FUNC_NAME); res = RES_BAD_ARG; goto error; } @@ -130,20 +135,32 @@ dump_accum_buffer if(time_acc) *time_acc = HTRDR_ACCUM_NULL; FOR_EACH(y, 0, layout.height) { FOR_EACH(x, 0, layout.width) { - const struct htrdr_accum* accums = htrdr_buffer_at(buf, x, y); - int i; - FOR_EACH(i, 0, HTRDR_ESTIMATES_COUNT__) { - double E, SE; - - htrdr_accum_get_estimation(&accums[i], &E, &SE); - fprintf(stream, "%g %g ", E, SE); + struct htrdr_estimate pix_time = HTRDR_ESTIMATE_NULL; + const struct htrdr_accum* pix_time_acc = NULL; + + if(htsky_is_long_wave(htrdr->sky)) { + const struct htrdr_pixel_lw* pix = htrdr_buffer_at(buf, x, y); + fprintf(stream, "%g %g ", pix->radiance.E, pix->radiance.SE); + fprintf(stream, "%g %g ", pix->radiance.E, pix->radiance.SE); + fprintf(stream, "%g %g ", pix->radiance.E, pix->radiance.SE); + pix_time_acc = &pix->time; + + } else { + const struct htrdr_pixel_sw* pix = htrdr_buffer_at(buf, x, y); + fprintf(stream, "%g %g ", pix->X.E, pix->X.SE); + fprintf(stream, "%g %g ", pix->Y.E, pix->Y.SE); + fprintf(stream, "%g %g ", pix->Z.E, pix->Z.SE); + pix_time_acc = &pix->time; } + + htrdr_accum_get_estimation(pix_time_acc, &pix_time); + fprintf(stream, "%g %g\n", pix_time.E, pix_time.SE); + if(time_acc) { - time_acc->sum_weights += accums[HTRDR_ESTIMATE_TIME].sum_weights; - time_acc->sum_weights_sqr += accums[HTRDR_ESTIMATE_TIME].sum_weights_sqr; - time_acc->nweights += accums[HTRDR_ESTIMATE_TIME].nweights; + time_acc->sum_weights += pix_time_acc->sum_weights; + time_acc->sum_weights_sqr += pix_time_acc->sum_weights_sqr; + time_acc->nweights += pix_time_acc->nweights; } - fprintf(stream, "\n"); } fprintf(stream, "\n"); } @@ -518,22 +535,6 @@ htrdr_init args->camera.up, proj_ratio, MDEG2RAD(args->camera.fov_y), &htrdr->cam); if(res != RES_OK) goto error; - /* Create the image buffer only on the master process; the image parts - * rendered by the processes are gathered onto the master process. */ - if(!htrdr->dump_vtk && htrdr->mpi_rank == 0) { - /* 4 accums: X, Y, Z components and one more for the per realisation time */ - const size_t pixsz = sizeof(struct htrdr_accum[HTRDR_ESTIMATES_COUNT__]); - const size_t pixal = ALIGNOF(struct htrdr_accum[HTRDR_ESTIMATES_COUNT__]); - res = htrdr_buffer_create(htrdr, - args->image.definition[0], /* Width */ - args->image.definition[1], /* Height */ - args->image.definition[0] * pixsz, /* Pitch */ - pixsz, /* Size of a pixel */ - pixal, /* Alignment of a pixel */ - &htrdr->buf); - if(res != RES_OK) goto error; - } - res = htrdr_sun_create(htrdr, &htrdr->sun); if(res != RES_OK) goto error; spherical_to_cartesian_dir @@ -592,6 +593,29 @@ htrdr_init } } + /* Create the image buffer only on the master process; the image parts + * rendered by the processes are gathered onto the master process. */ + if(!htrdr->dump_vtk && htrdr->mpi_rank == 0) { + size_t pixsz = 0; /* sizeof(pixel) */ + size_t pixal = 0; /* alignof(pixel) */ + + if(htsky_is_long_wave(htrdr->sky)) { + pixsz = sizeof(struct htrdr_pixel_lw); + pixal = ALIGNOF(struct htrdr_pixel_lw); + } else { + pixsz = sizeof(struct htrdr_pixel_sw); + pixal = ALIGNOF(struct htrdr_pixel_sw); + } + res = htrdr_buffer_create(htrdr, + args->image.definition[0], /* Width */ + args->image.definition[1], /* Height */ + args->image.definition[0] * pixsz, /* Pitch */ + pixsz, /* Size of a pixel */ + pixal, /* Alignment of a pixel */ + &htrdr->buf); + if(res != RES_OK) goto error; + } + exit: return res; error: @@ -651,15 +675,17 @@ htrdr_run(struct htrdr* htrdr) if(res != RES_OK) goto error; if(htrdr->mpi_rank == 0) { struct htrdr_accum path_time_acc = HTRDR_ACCUM_NULL; - double E, SE; + struct htrdr_estimate path_time; res = dump_accum_buffer(htrdr, htrdr->buf, &path_time_acc, str_cget(&htrdr->output_name), htrdr->output); if(res != RES_OK) goto error; - htrdr_accum_get_estimation(&path_time_acc, &E, &SE); + htrdr_accum_get_estimation(&path_time_acc, &path_time); htrdr_log(htrdr, - "Time per radiative path (in micro seconds): %g +/- %g\n", E, SE); + "Time per radiative path (in micro seconds): %g +/- %g\n", + path_time.E, + path_time.SE); } } exit: diff --git a/src/htrdr_c.h b/src/htrdr_c.h @@ -33,15 +33,6 @@ enum htrdr_mpi_message { HTRDR_MPI_TILE_DATA }; -enum htrdr_estimate { - HTRDR_ESTIMATE_X, - HTRDR_ESTIMATE_RADIANCE = HTRDR_ESTIMATE_X, - HTRDR_ESTIMATE_Y, - HTRDR_ESTIMATE_Z, - HTRDR_ESTIMATE_TIME, /* Time per realisation */ - HTRDR_ESTIMATES_COUNT__ -}; - struct htrdr; #define SW_WAVELENGTH_MIN 380 /* In nanometer */ diff --git a/src/htrdr_draw_radiance.c b/src/htrdr_draw_radiance.c @@ -43,6 +43,16 @@ #define TILE_SIZE 32 /* Definition in X & Y of a tile */ STATIC_ASSERT(IS_POW2(TILE_SIZE), TILE_SIZE_must_be_a_power_of_2); +enum pixel_format { + PIXEL_LW, + PIXEL_SW +}; + +union pixel { + struct htrdr_pixel_lw lw; + struct htrdr_pixel_sw sw; +}; + /* Tile of row ordered image pixels */ struct tile { struct list_node node; @@ -51,8 +61,9 @@ struct tile { struct tile_data { uint16_t x, y; /* 2D coordinates of the tile in tile space */ + enum pixel_format format; /* Simulate the flexible array member of the C99 standard. */ - struct htrdr_accum accums[1/*dummy element*/]; + union pixel pixels[1/*Dummy element*/]; } data; }; @@ -89,22 +100,24 @@ morton2D_encode(const uint16_t u16) } static FINLINE struct tile* -tile_create(struct mem_allocator* allocator) +tile_create(struct mem_allocator* allocator, const enum pixel_format fmt) { struct tile* tile; const size_t tile_sz = - sizeof(struct tile) - sizeof(struct htrdr_accum)/*rm dummy accum*/; + sizeof(struct tile) - sizeof(union pixel)/*rm dummy pixel*/; const size_t buf_sz = /* Flexiblbe array element */ - TILE_SIZE*TILE_SIZE*sizeof(struct htrdr_accum[HTRDR_ESTIMATES_COUNT__]); + TILE_SIZE*TILE_SIZE*sizeof(union pixel); ASSERT(allocator); tile = MEM_ALLOC(allocator, tile_sz+buf_sz); if(!tile) return NULL; + tile->data.format = fmt; + ref_init(&tile->ref); list_init(&tile->node); tile->allocator = allocator; - ASSERT(IS_ALIGNED(&tile->data.accums, ALIGNOF(struct htrdr_accum))); + ASSERT(IS_ALIGNED(&tile->data.pixels, ALIGNOF(union pixel))); return tile; } @@ -131,18 +144,19 @@ tile_ref_put(struct tile* tile) ref_put(&tile->ref, release_tile); } -static FINLINE struct htrdr_accum* +static FINLINE union pixel* tile_at (struct tile* tile, const size_t x, /* In tile space */ const size_t y) /* In tile space */ { ASSERT(tile && x < TILE_SIZE && y < TILE_SIZE); - return tile->data.accums + (y*TILE_SIZE + x) * HTRDR_ESTIMATES_COUNT__; + return tile->data.pixels + (y*TILE_SIZE + x); } - static void -write_tile_data(struct htrdr_buffer* buf, const struct tile_data* tile_data) +write_tile_data + (struct htrdr_buffer* buf, + const struct tile_data* tile_data) { struct htrdr_buffer_layout layout = HTRDR_BUFFER_LAYOUT_NULL; size_t icol, irow; @@ -153,7 +167,9 @@ write_tile_data(struct htrdr_buffer* buf, const struct tile_data* tile_data) htrdr_buffer_get_layout(buf, &layout); buf_mem = htrdr_buffer_get_data(buf); - ASSERT(layout.elmt_size == sizeof(struct htrdr_accum[HTRDR_ESTIMATES_COUNT__])); + ASSERT(layout.elmt_size == (tile_data->format == PIXEL_LW + ? sizeof(struct htrdr_pixel_lw) + : sizeof(struct htrdr_pixel_sw))); /* Compute the row/column of the tile origin into the buffer */ icol = tile_data->x * (size_t)TILE_SIZE; @@ -163,13 +179,24 @@ write_tile_data(struct htrdr_buffer* buf, const struct tile_data* tile_data) ncols_tile = MMIN(icol + TILE_SIZE, layout.width) - icol; nrows_tile = MMIN(irow + TILE_SIZE, layout.height) - irow; - /* Copy the tile data, row by row */ + /* Copy the row ordered tile data */ FOR_EACH(irow_tile, 0, nrows_tile) { char* buf_row = buf_mem + (irow + irow_tile) * layout.pitch; - const struct htrdr_accum* tile_row = - tile_data->accums + irow_tile*TILE_SIZE*HTRDR_ESTIMATES_COUNT__; - memcpy(buf_row + icol*sizeof(struct htrdr_accum[HTRDR_ESTIMATES_COUNT__]), - tile_row, ncols_tile*sizeof(struct htrdr_accum[HTRDR_ESTIMATES_COUNT__])); + char* buf_col = buf_row + icol * layout.elmt_size; + const union pixel* tile_row = tile_data->pixels + irow_tile*TILE_SIZE; + size_t x; + + FOR_EACH(x, 0, ncols_tile) { + switch(tile_data->format) { + case PIXEL_LW: + ((struct htrdr_pixel_lw*)buf_col)[x] = tile_row[x].lw; + break; + case PIXEL_SW: + ((struct htrdr_pixel_sw*)buf_col)[x] = tile_row[x].sw; + break; + default: FATAL("Unreachable code.\n"); break; + } + } } } @@ -394,8 +421,8 @@ mpi_gather_tiles { /* Compute the size of the tile_data */ const size_t msg_sz = - sizeof(struct tile_data) - sizeof(struct htrdr_accum)/*dummy*/ - + TILE_SIZE*TILE_SIZE*sizeof(struct htrdr_accum[HTRDR_ESTIMATES_COUNT__]); + sizeof(struct tile_data) - sizeof(union pixel)/*dummy*/ + + TILE_SIZE*TILE_SIZE*sizeof(union pixel); struct list_node* node = NULL; struct tile* tile = NULL; @@ -425,7 +452,8 @@ mpi_gather_tiles /* Create a temporary tile to receive the tile data computed by the * concurrent MPI processes */ - tile = tile_create(htrdr->allocator); + tile = tile_create + (htrdr->allocator, htsky_is_long_wave(htrdr->sky) ? PIXEL_LW : PIXEL_SW); if(!tile) { res = RES_MEM_ERR; htrdr_log_err(htrdr, @@ -434,7 +462,7 @@ mpi_gather_tiles goto error; } - /* Receive the tile data of the concurret MPI processes */ + /* Receive the tile data of the concurrent MPI processes */ FOR_EACH(itile, itile, ntiles) { MPI(Recv(&tile->data, (int)msg_sz, MPI_CHAR, MPI_ANY_SOURCE, HTRDR_MPI_TILE_DATA, MPI_COMM_WORLD, MPI_STATUS_IGNORE)); @@ -482,26 +510,21 @@ draw_pixel_sw const struct htrdr_camera* cam, const size_t spp, struct ssp_rng* rng, - struct htrdr_accum* pix_accums) + struct htrdr_pixel_sw* pixel) { + struct htrdr_accum XYZ[3]; /* X, Y, and Z */ + struct htrdr_accum time; size_t ichannel; - ASSERT(ipix && ipix && pix_sz && cam && rng && pix_accums); + ASSERT(ipix && ipix && pix_sz && cam && rng && pixel); ASSERT(!htsky_is_long_wave(htrdr->sky)); - /* Reset the pixel accumulators */ - pix_accums[HTRDR_ESTIMATE_X] = HTRDR_ACCUM_NULL; - pix_accums[HTRDR_ESTIMATE_Y] = HTRDR_ACCUM_NULL; - pix_accums[HTRDR_ESTIMATE_Z] = HTRDR_ACCUM_NULL; - pix_accums[HTRDR_ESTIMATE_TIME] = HTRDR_ACCUM_NULL; + /* Reset accumulators */ + XYZ[0] = HTRDR_ACCUM_NULL; + XYZ[1] = HTRDR_ACCUM_NULL; + XYZ[2] = HTRDR_ACCUM_NULL; + time = HTRDR_ACCUM_NULL; FOR_EACH(ichannel, 0, 3) { - /* Check that the X, Y and Z estimates are stored in accumulators 0, 1 et - * 2, respectively */ - STATIC_ASSERT - ( HTRDR_ESTIMATE_X == 0 - && HTRDR_ESTIMATE_Y == 1 - && HTRDR_ESTIMATE_Z == 2, - Unexpected_htrdr_estimate_enumerate); size_t isamp; FOR_EACH(isamp, 0, spp) { @@ -556,16 +579,22 @@ draw_pixel_sw usec = (double)time_val(&t0, TIME_NSEC) * 0.001; /* Update the pixel accumulator of the current channel */ - pix_accums[ichannel].sum_weights += weight; - pix_accums[ichannel].sum_weights_sqr += weight*weight; - pix_accums[ichannel].nweights += 1; + XYZ[ichannel].sum_weights += weight; + XYZ[ichannel].sum_weights_sqr += weight*weight; + XYZ[ichannel].nweights += 1; /* Update the pixel accumulator of per realisation time */ - pix_accums[HTRDR_ESTIMATE_TIME].sum_weights += usec; - pix_accums[HTRDR_ESTIMATE_TIME].sum_weights_sqr += usec*usec; - pix_accums[HTRDR_ESTIMATE_TIME].nweights += 1; + time.sum_weights += usec; + time.sum_weights_sqr += usec*usec; + time.nweights += 1; } } + + /* Flush pixel data */ + htrdr_accum_get_estimation(XYZ+0, &pixel->X); + htrdr_accum_get_estimation(XYZ+1, &pixel->Y); + htrdr_accum_get_estimation(XYZ+2, &pixel->Z); + pixel->time = time; } static void @@ -577,15 +606,17 @@ draw_pixel_lw const struct htrdr_camera* cam, const size_t spp, struct ssp_rng* rng, - struct htrdr_accum* pix_accums) + struct htrdr_pixel_lw* pixel) { + struct htrdr_accum radiance; + struct htrdr_accum time; size_t isamp; - ASSERT(ipix && ipix && pix_sz && cam && rng && pix_accums); + ASSERT(ipix && ipix && pix_sz && cam && rng && pixel); ASSERT(htsky_is_long_wave(htrdr->sky)); /* Reset the pixel accumulators */ - pix_accums[HTRDR_ESTIMATE_RADIANCE] = HTRDR_ACCUM_NULL; - pix_accums[HTRDR_ESTIMATE_TIME] = HTRDR_ACCUM_NULL; + radiance = HTRDR_ACCUM_NULL; + time = HTRDR_ACCUM_NULL; FOR_EACH(isamp, 0, spp) { struct time t0, t1; @@ -626,15 +657,20 @@ draw_pixel_lw usec = (double)time_val(&t0, TIME_NSEC) * 0.001; /* Update the pixel accumulator of the current channel */ - pix_accums[HTRDR_ESTIMATE_RADIANCE].sum_weights += weight; - pix_accums[HTRDR_ESTIMATE_RADIANCE].sum_weights_sqr += weight*weight; - pix_accums[HTRDR_ESTIMATE_RADIANCE].nweights += 1; + radiance.sum_weights += weight; + radiance.sum_weights_sqr += weight*weight; + radiance.nweights += 1; /* Update the pixel accumulator of per realisation time */ - pix_accums[HTRDR_ESTIMATE_TIME].sum_weights += usec; - pix_accums[HTRDR_ESTIMATE_TIME].sum_weights_sqr += usec*usec; - pix_accums[HTRDR_ESTIMATE_TIME].nweights += 1; + time.sum_weights += usec; + time.sum_weights_sqr += usec*usec; + time.nweights += 1; } + + /* Flush pixel data */ + htrdr_accum_get_estimation(&radiance, &pixel->radiance); + pixel->radiance_temperature = HTRDR_ESTIMATE_NULL; /* TODO */ + pixel->time = time; } static res_T @@ -659,7 +695,7 @@ draw_tile npixels *= npixels; FOR_EACH(mcode, 0, npixels) { - struct htrdr_accum* pix_accums; + union pixel* pixel; size_t ipix_tile[2]; /* Pixel coord in the tile */ size_t ipix[2]; /* Pixel coord in the buffer */ @@ -669,7 +705,7 @@ draw_tile if(ipix_tile[1] >= tile_sz[1]) continue; /* Pixel is out of tile */ /* Fetch and reset the pixel accumulator */ - pix_accums = tile_at(tile, ipix_tile[0], ipix_tile[1]); + pixel = tile_at(tile, ipix_tile[0], ipix_tile[1]); /* Compute the pixel coordinate */ ipix[0] = tile_org[0] + ipix_tile[0]; @@ -677,9 +713,9 @@ draw_tile /* Draw the pixel */ if(htsky_is_long_wave(htrdr->sky)) { - draw_pixel_lw(htrdr, ithread, ipix, pix_sz, cam, spp, rng, pix_accums); + draw_pixel_lw(htrdr, ithread, ipix, pix_sz, cam, spp, rng, &pixel->lw); } else { - draw_pixel_sw(htrdr, ithread, ipix, pix_sz, cam, spp, rng, pix_accums); + draw_pixel_sw(htrdr, ithread, ipix, pix_sz, cam, spp, rng, &pixel->sw); } } return RES_OK; @@ -703,6 +739,7 @@ draw_image size_t nthreads = 0; size_t nthieves = 0; size_t proc_ntiles = 0; + enum pixel_format pixfmt; ATOMIC nsolved_tiles = 0; ATOMIC res = RES_OK; ASSERT(htrdr && cam && spp && ntiles_adjusted && work && tiles); @@ -724,6 +761,8 @@ draw_image htrdr->mpi_working_procs[htrdr->mpi_rank] = 0; --htrdr->mpi_nworking_procs; + pixfmt = htsky_is_long_wave(htrdr->sky) ? PIXEL_LW : PIXEL_SW; + omp_set_num_threads((int)nthreads); #pragma omp parallel for(;;) { @@ -759,7 +798,7 @@ draw_image ASSERT(tile_org[0] < ntiles_x && tile_org[1] < ntiles_y); /* Create the tile */ - tile = tile_create(htrdr->allocator); + tile = tile_create(htrdr->allocator, pixfmt); if(!tile) { ATOMIC_SET(&res, RES_MEM_ERR); htrdr_log_err(htrdr, @@ -868,16 +907,21 @@ htrdr_draw_radiance proc_work_init(htrdr->allocator, &work); if(htrdr->mpi_rank == 0) { + size_t pixsz, pixal; htrdr_buffer_get_layout(buf, &layout); ASSERT(layout.width || layout.height || layout.elmt_size); ASSERT(layout.width == width && layout.height == height); - if(layout.elmt_size != sizeof(struct htrdr_accum[HTRDR_ESTIMATES_COUNT__]) - || layout.alignment < ALIGNOF(struct htrdr_accum[HTRDR_ESTIMATES_COUNT__])) { - htrdr_log_err(htrdr, - "%s: invalid buffer layout. " - "The pixel size must be the size of %lu accumulators.\n", - FUNC_NAME, (unsigned long)HTRDR_ESTIMATES_COUNT__); + if(htsky_is_long_wave(htrdr->sky)) { + pixsz = sizeof(struct htrdr_pixel_lw); + pixal = ALIGNOF(struct htrdr_pixel_lw); + } else { + pixsz = sizeof(struct htrdr_pixel_sw); + pixal = ALIGNOF(struct htrdr_pixel_sw); + } + + if(layout.elmt_size != pixsz || layout.alignment < pixal) { + htrdr_log_err(htrdr, "%s: invalid buffer layout.\n", FUNC_NAME); res = RES_BAD_ARG; goto error; } diff --git a/src/htrdr_solve.h b/src/htrdr_solve.h @@ -26,8 +26,29 @@ struct htrdr_accum { size_t nweights; /* #accumlated weights */ size_t nfailures; /* #failures */ }; -#define HTRDR_ACCUM_NULL__ {0,0,0,0} -static const struct htrdr_accum HTRDR_ACCUM_NULL = HTRDR_ACCUM_NULL__; +static const struct htrdr_accum HTRDR_ACCUM_NULL; + +/* Monte carlo estimate */ +struct htrdr_estimate { + double E; /* Expected value */ + double SE; /* Standard error */ +}; +static const struct htrdr_estimate HTRDR_ESTIMATE_NULL; + +struct htrdr_pixel_sw { + struct htrdr_estimate X; /* In W/m^2/sr */ + struct htrdr_estimate Y; /* In W/m^2/sr */ + struct htrdr_estimate Z; /* In W/m^2/sr */ + struct htrdr_accum time; /* In microseconds */ +}; +static const struct htrdr_pixel_sw HTRDR_PIXEL_SW_NULL; + +struct htrdr_pixel_lw { + struct htrdr_estimate radiance; /* In W/m^2/sr */ + struct htrdr_estimate radiance_temperature; /* In K */ + struct htrdr_accum time; /* In microseconds */ +}; +static const struct htrdr_pixel_lw HTRDR_PIXEL_LW_NULL; /* Forward declarations */ struct htrdr; @@ -63,7 +84,7 @@ htrdr_draw_radiance const size_t height, /* Image height */ const size_t spp, /* #samples per pixel, i.e. #realisations */ /* Buffer of struct htrdr_accum[4]. May be NULL on non master processes */ - struct htrdr_buffer* buf); + struct htrdr_buffer* buf); extern LOCAL_SYM int htrdr_ground_filter @@ -76,14 +97,13 @@ htrdr_ground_filter static FINLINE void htrdr_accum_get_estimation (const struct htrdr_accum* acc, - double* expected_value, - double* std_err) + struct htrdr_estimate* estimate) { - ASSERT(acc && expected_value && std_err); + ASSERT(acc && estimate); if(!acc->nweights) { - *expected_value = 0; - *std_err = 0; + estimate->E = 0; + estimate->SE = 0; } else { const double N = (double)acc->nweights; double E, V, SE; @@ -91,8 +111,8 @@ htrdr_accum_get_estimation V = MMAX(acc->sum_weights_sqr / N - E*E, 0); SE = sqrt(V/N); - *expected_value = E; - *std_err = SE; + estimate->E = E; + estimate->SE = SE; } }