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:
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);