rnatm

Load and structure data describing an atmosphere
git clone git://git.meso-star.fr/rnatm.git
Log | Files | Refs | README | LICENSE

commit 2022a9e83e5ae483d286bd2711fc566a8c311dc1
parent e0c41bfab79971106eb4112763b0a8facdbdb92a
Author: Vincent Forest <vincent.forest@meso-star.com>
Date:   Mon, 29 Aug 2022 18:19:06 +0200

Finalise the unloading of built octrees

Diffstat:
Msrc/rnatm.c | 44++++++++++++++++++++++++++++++++++++++++++++
Msrc/rnatm.h | 6++++--
Msrc/rnatm_c.h | 13+++++++++++++
Msrc/rnatm_octree.c | 68+++++++++++++++++++++++++-------------------------------------------
Msrc/rnatm_write_vtk_octree.c | 18++++++++++++++----
5 files changed, 100 insertions(+), 49 deletions(-)

diff --git a/src/rnatm.c b/src/rnatm.c @@ -134,6 +134,7 @@ create_rnatm ref_init(&atm->ref); atm->allocator = allocator; atm->verbose = args->verbose; + atm->octrees_storage = args->octrees_storage; str_init(atm->allocator, &atm->name); gas_init(atm->allocator, &atm->gas); darray_aerosol_init(atm->allocator, &atm->aerosols); @@ -193,6 +194,7 @@ release_rnatm(ref_T* ref) struct rnatm* atm = CONTAINER_OF(ref, struct rnatm, ref); ASSERT(ref); if(atm->logger == &atm->logger__) logger_release(&atm->logger__); + if(atm->svx) SVX(device_ref_put(atm->svx)); darray_aerosol_release(&atm->aerosols); darray_accel_struct_release(&atm->accel_structs); if(atm->svx_allocator_is_init) { @@ -486,3 +488,45 @@ accel_struct_copy_and_release(struct accel_struct* dst, struct accel_struct* src src->octree = NULL; return RES_OK; } + +res_T +make_sure_octree_is_loaded(struct rnatm* atm, const size_t istruct) +{ + struct accel_struct* accel_struct = NULL; + int err = 0; + res_T res = RES_OK; + ASSERT(atm && istruct < darray_accel_struct_size_get(&atm->accel_structs)); + + accel_struct = darray_accel_struct_data_get(&atm->accel_structs) + istruct; + if(accel_struct->octree) goto exit; /* The octree is already loaded */ + + /* Prepare to read the octree's data */ + err = fsetpos(atm->octrees_storage, &accel_struct->fpos); + if(err != 0) { res = RES_IO_ERR; goto error; } + + /* Deserialize the octree */ + res = svx_tree_create_from_stream + (atm->svx, atm->octrees_storage, &accel_struct->octree); + if(res != RES_OK) goto error; + +exit: + return res; +error: + log_err(atm, "error loading octree %lu -- %s", + (unsigned long)istruct, res_to_cstr(res)); + goto exit; +} + +void +unload_octree(struct rnatm* atm, const size_t istruct) +{ + struct accel_struct* accel_struct = NULL; + ASSERT(atm); + ASSERT(istruct < darray_accel_struct_size_get(&atm->accel_structs)); + + accel_struct = darray_accel_struct_data_get(&atm->accel_structs) + istruct; + if(accel_struct->octree) { + SVX(tree_ref_put(accel_struct->octree)); + accel_struct->octree = NULL; + } +} diff --git a/src/rnatm.h b/src/rnatm.h @@ -85,7 +85,9 @@ struct rnatm_create_args { size_t naerosols; char* name; /* Name of the atmosphere */ - FILE* octrees_storage; /* File where octrees are serialized. May be NULL */ + /* Read/write file where octrees are offloaded. May be NULL => octrees are + * kept in memory */ + FILE* octrees_storage; /* Spectral range to consider (in wavenumbers). Limits are inclusive */ double spectral_range[2]; @@ -165,7 +167,7 @@ rnatm_get_octrees_count RNATM_API res_T rnatm_write_vtk_octrees - (const struct rnatm* atm, + (struct rnatm* atm, const size_t octrees[2], /* Range of consider. Limits are inclusive */ FILE* stream); diff --git a/src/rnatm_c.h b/src/rnatm_c.h @@ -186,6 +186,8 @@ struct rnatm { struct darray_accel_struct accel_structs; struct str name; + FILE* octrees_storage; + unsigned grid_definition[3]; unsigned nthreads; @@ -196,6 +198,7 @@ struct rnatm { struct mem_allocator* allocator; struct mem_allocator svx_allocator; + struct svx_device* svx; int svx_allocator_is_init; ref_T ref; }; @@ -215,4 +218,14 @@ setup_octrees (struct rnatm* atm, const struct rnatm_create_args* args); +extern LOCAL_SYM res_T +make_sure_octree_is_loaded + (struct rnatm* atm, + const size_t iaccel_struct); + +extern LOCAL_SYM void +unload_octree + (struct rnatm* atm, + const size_t iaccel_struct); + #endif /* RNATM_C_H */ diff --git a/src/rnatm_octree.c b/src/rnatm_octree.c @@ -55,13 +55,6 @@ struct build_sync { #define BUILD_SYNC_NULL__ {NULL, NULL, 0} static const struct build_sync BUILD_SYNC_NULL = BUILD_SYNC_NULL__; -struct storage { - FILE* fp; /* File pointer */ - fpos_t header; /* Position of the header */ -}; -#define STORAGE_NULL__ {NULL} -static const struct storage STORAGE_NULL = STORAGE_NULL__; - struct build_octree_context { struct pool* pool; struct partition* part; /* Current partition */ @@ -1177,28 +1170,20 @@ vx_challenge_merge } static res_T -storage_init - (struct rnatm* atm, - const struct rnatm_create_args* args, - struct storage* storage) +reserve_storage_header(struct rnatm* atm, fpos_t* header) { size_t noctrees = 0; size_t header_size = 0; int err = 0; res_T res = RES_OK; - ASSERT(atm && args && storage); + ASSERT(atm && header); - if(!args->octrees_storage) { /* No octrees storage */ - *storage = STORAGE_NULL; - goto exit; - } + if(!atm->octrees_storage) goto exit; noctrees = darray_accel_struct_size_get(&atm->accel_structs); - storage->fp = args->octrees_storage; - - err = fgetpos(storage->fp, &storage->header); + err = fgetpos(atm->octrees_storage, header); if(err != 0) { res = RES_IO_ERR; goto error; } /* Compute the header size */ @@ -1208,38 +1193,37 @@ storage_init ASSERT(header_size < LONG_MAX); /* Reserve the space for the header */ - err = fseek(storage->fp, (long)header_size, SEEK_CUR); + err = fseek(atm->octrees_storage, (long)header_size, SEEK_CUR); if(err != 0) { res = RES_IO_ERR; goto error; } exit: return res; error: - log_err(atm, "error initializing disk storage of octrees -- %s\n", + log_err(atm, "error reserving octree storage header -- %s\n", strerror(errno)); goto exit; } static res_T -storage_write_octrees +store_octrees (struct rnatm* atm, - const struct storage* storage, const size_t ioctrees[2]) /* Octrees to write. Limits are inclusive */ { size_t ioctree = 0; int err = 0; res_T res = RES_OK; - ASSERT(atm && storage && ioctrees && ioctrees[0] <= ioctrees[1]); + ASSERT(atm && ioctrees && ioctrees[0] <= ioctrees[1]); ASSERT(ioctrees[1] < darray_accel_struct_size_get(&atm->accel_structs)); /* No storage: nothing to do */ - if(!storage->fp) goto exit; + if(!atm->octrees_storage) goto exit; FOR_EACH(ioctree, ioctrees[0], ioctrees[1]+1) { struct accel_struct* accel_struct = NULL; accel_struct = darray_accel_struct_data_get(&atm->accel_structs) + ioctree; /* Save the current file offset */ - err = fgetpos(storage->fp, &accel_struct->fpos); + err = fgetpos(atm->octrees_storage, &accel_struct->fpos); if(err != 0) { log_err(atm, "error retrieving octree storage position -- %s\n", strerror(errno)); @@ -1248,7 +1232,7 @@ storage_write_octrees } /* Serialize the octree */ - res = svx_tree_write(accel_struct->octree, storage->fp); + res = svx_tree_write(accel_struct->octree, atm->octrees_storage); if(res != RES_OK) { log_err(atm, "error serializing octree %lu -- %s\n", (unsigned long)ioctree, res_to_cstr(res)); @@ -1256,8 +1240,7 @@ storage_write_octrees } /* Free the octree memory */ - SVX(tree_ref_put(accel_struct->octree)); - accel_struct->octree = NULL; + unload_octree(atm, ioctree); } exit: @@ -1267,18 +1250,18 @@ error: } static res_T -storage_finalize(struct rnatm* atm, struct storage* storage) +finalize_storage(struct rnatm* atm, const fpos_t* header) { size_t naccel_structs = 0; size_t iaccel_struct = 0; int err = 0; res_T res = RES_OK; - ASSERT(atm && storage); + ASSERT(atm && header); /* No storage: nothing to do */ - if(storage->fp) goto exit; + if(!atm->octrees_storage) goto exit; - err = fsetpos(storage->fp, &storage->header); + err = fsetpos(atm->octrees_storage, header); if(err != 0) { log_err(atm, "error positioning on octree storage header -- %s\n", strerror(errno)); @@ -1290,8 +1273,8 @@ storage_finalize(struct rnatm* atm, struct storage* storage) /* Write the number of voxelized octrees and their corresponding offset */ #define WRITE(Var) { \ - if(fwrite((Var), sizeof(*(Var)), 1, storage->fp) != 1) { \ - log_err(atm, "error serializing octree storage header\n"); \ + if(fwrite((Var), sizeof(*(Var)), 1, atm->octrees_storage) != 1) { \ + log_err(atm, "error serializing octree storage header\n"); \ res = RES_IO_ERR; \ goto error; \ } \ @@ -1318,8 +1301,7 @@ build_octrees struct pool* pool, struct build_sync* sync) { - struct storage storage = STORAGE_NULL; - struct svx_device* svx = NULL; + fpos_t octrees_header; struct accel_struct* accel_structs = NULL; double low[3], upp[3]; size_t def[3]; @@ -1329,7 +1311,8 @@ build_octrees ATOMIC res = RES_OK; ASSERT(atm && args && pool); - res = svx_device_create(atm->logger, &atm->svx_allocator, atm->verbose, &svx); + res = svx_device_create + (atm->logger, &atm->svx_allocator, atm->verbose, &atm->svx); if(res != RES_OK) goto error; /* Recover the AABB from the atmosphere. Note that we have already made sure @@ -1348,7 +1331,7 @@ build_octrees voxel_width = pool_get_voxel_width(pool); /* Setup the disk storage of the octrees */ - res = storage_init(atm, args, &storage); + res = reserve_storage_header(atm, &octrees_header); if(res != RES_OK) goto error; /* Build the octrees. Each thread consumes an element of the voxels generated @@ -1387,7 +1370,7 @@ build_octrees vx_desc.context = &ctx; vx_desc.size = NFLOATS_PER_VOXEL * sizeof(float); - res_local = svx_octree_create(svx, low, upp, def, &vx_desc, &octree); + res_local = svx_octree_create(atm->svx, low, upp, def, &vx_desc, &octree); if(ctx.part) partition_free(ctx.part); if(res_local != RES_OK) { ATOMIC_SET(&res, res_local); @@ -1406,16 +1389,15 @@ build_octrees /* Offload builded octrees */ ioctrees[0] = istruct; ioctrees[1] = istruct + batch_size - 1; - res = storage_write_octrees(atm, &storage, ioctrees); + res = store_octrees(atm, ioctrees); if(res != RES_OK) goto error; } /* Finalize the file where octrees are offloaded */ - res = storage_finalize(atm, &storage); + res = finalize_storage(atm, &octrees_header); if(res != RES_OK) goto error; exit: - if(svx) SVX(device_ref_put(svx)); return (res_T)res; error: /* Signal to the voxelization thread that there is no need to wait for the diff --git a/src/rnatm_write_vtk_octree.c b/src/rnatm_write_vtk_octree.c @@ -143,9 +143,9 @@ register_leaf CHK(RES_OK == darray_double_push_back(&ctx->data, &kext_max)); } -static void +static res_T write_vtk_octree - (const struct rnatm* atm, + (struct rnatm* atm, const size_t iaccel_struct, struct octree_data* data, FILE* stream) @@ -155,10 +155,14 @@ write_vtk_octree size_t nvertices; size_t ncells; size_t i; + res_T res = RES_OK; ASSERT(atm && stream); ASSERT(iaccel_struct < darray_accel_struct_size_get(&atm->accel_structs)); + res = make_sure_octree_is_loaded(atm, iaccel_struct); + if(res != RES_OK) goto error; + accel_struct = darray_accel_struct_cdata_get(&atm->accel_structs)+iaccel_struct; octree_data_clear(data); @@ -219,6 +223,11 @@ write_vtk_octree FOR_EACH(i, 0, ncells) { fprintf(stream, "%g %g\n", leaf_data[i*2+0], leaf_data[i*2+1]); } + +exit: + return res; +error: + goto exit; } /******************************************************************************* @@ -226,7 +235,7 @@ write_vtk_octree ******************************************************************************/ res_T rnatm_write_vtk_octrees - (const struct rnatm* atm, + (struct rnatm* atm, const size_t structs[2], /* Range of acceleration structures to write */ FILE* stream) { @@ -251,7 +260,8 @@ rnatm_write_vtk_octrees octree_data_init(atm, &data); FOR_EACH(i, structs[0], structs[1]+1) { - write_vtk_octree(atm, structs[0]+i, &data, stream); + res = write_vtk_octree(atm, structs[0]+i, &data, stream); + if(res != RES_OK) goto error; } octree_data_release(&data);