commit 53552af739157da351f96a3a8eb1b4d2688cc90e
parent 069779bdcec8d9f59b8225db3e7a26ca20c6b0e4
Author: Vincent Forest <vincent.forest@meso-star.com>
Date: Fri, 8 Jan 2021 15:20:07 +0100
Implement partition and pool internal data structures
These data structures are going to be used in the parallel construction
of the octree partitionning volumetric optical properties.
Diffstat:
5 files changed, 368 insertions(+), 3 deletions(-)
diff --git a/cmake/CMakeLists.txt b/cmake/CMakeLists.txt
@@ -51,10 +51,12 @@ set(VERSION ${VERSION_MAJOR}.${VERSION_MINOR}.${VERSION_PATCH})
set(ATRSTM_FILES_SRC
atrstm.c
atrstm_log.c
+ atrstm_partition.c
atrstm_setup_uvm.c)
set(ATRSTM_FILES_INC
atrstm_c.h
- atrstm_log.h)
+ atrstm_log.h
+ atrstm_partition.h)
set(ATRSTM_FILES_INC_API
atrstm.h)
diff --git a/src/atrstm.h b/src/atrstm.h
@@ -38,6 +38,26 @@
#define ATRSTM(Func) atrstm_ ## Func
#endif
+enum atrstm_property {
+ ATRSTM_Ks, /* Scattering coefficient */
+ ATRSTM_Ka, /* Absorption coefficient */
+ ATRSTM_Kext, /* Extinction coefficient = Ks + Ka */
+ ATRSTM_PROPS_COUNT__
+};
+
+/* List of medium components */
+enum atrstm_component {
+ ATRSTM_CPNT_GAS,
+ ATRSTM_CPNT_SOOT,
+ ATRSTM_CPNTS_COUNT__
+};
+
+enum atrstm_svx_op {
+ ATRSTM_SVX_MIN,
+ ATRSTM_SVX_MAX,
+ ATRSTM_SVX_OPS_COUNT__
+};
+
enum atrstm_spectral_type {
ATRSTM_SPECTRAL_LW, /* Longwave */
ATRSTM_SPECTRAL_SW, /* Shortwave */
@@ -54,7 +74,7 @@ struct atrstm_args {
double wlen_range[2]; /* Spectral range to handle In nm */
unsigned grid_max_definition[3]; /* Maximum definition of the grid */
double optical_thickness; /* Threshold used during octree building */
- int precompute_normals; /* Pre-compute the Tetrahedron normals */
+ int precompute_normals; /* Pre-compute the tetrahedra normals */
unsigned nthreads; /* Hint on the number of threads to use */
int verbose; /* Verbosity level */
};
@@ -69,7 +89,7 @@ struct atrstm_args {
{DBL_MAX,-DBL_MAX}, /* Spectral integration range */ \
{UINT_MAX, UINT_MAX, UINT_MAX}, /* Acceleration grid max definition */ \
1, /* Optical thickness */ \
- 1, /* Precompute tetrahedron normals */ \
+ 1, /* Precompute tetrahedra normals */ \
(unsigned)~0, /* #threads */ \
0 /* Verbosity level */ \
}
diff --git a/src/atrstm_partition.c b/src/atrstm_partition.c
@@ -0,0 +1,175 @@
+/* Copyright (C) 2020 CNRS
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>. */
+
+#include "atrstm_partition.h"
+
+#include <rsys/condition.h>
+#include <rsys/mem_allocator.h>
+#include <rsys/mutex.h>
+
+#include <string.h>
+
+/******************************************************************************
+ * Local functions
+ ******************************************************************************/
+res_T
+pool_init(struct mem_allocator* mem_allocator, struct pool* pool)
+{
+ STATIC_ASSERT(POOL_MAX_NPARTITIONS > 0,
+ Unexpected_value_of_POOL_MAX_NPARTITIONS);
+ size_t ipart;
+ res_T res = RES_OK;
+ ASSERT(pool);
+
+ memset(pool, 0, sizeof(*pool));
+
+ list_init(&pool->parts_free);
+ list_init(&pool->parts_full);
+ pool->allocator = mem_allocator ? mem_allocator : &mem_default_allocator;
+
+ pool->mutex = mutex_create();
+ if(!pool->mutex) { res = RES_UNKNOWN_ERR; goto error; }
+ pool->cond_new = cond_create();
+ if(pool->cond_new) { res = RES_UNKNOWN_ERR; goto error; }
+ pool->cond_fetch = cond_create();
+ if(pool->cond_fetch) { res = RES_UNKNOWN_ERR; goto error; }
+
+ FOR_EACH(ipart, 0, POOL_MAX_NPARTITIONS) {
+ struct part* part = MEM_ALLOC_ALIGNED(pool->allocator, sizeof(*part), 64);
+ if(!part) {
+ res = RES_MEM_ERR;
+ goto error;
+ }
+ list_add(&pool->parts_free, &part->node);
+ }
+
+exit:
+ pool_release(pool);
+ return res;
+error:
+ goto exit;
+}
+
+void
+pool_release(struct pool* pool)
+{
+ struct list_node* node;
+ struct list_node* tmp_node;
+ ASSERT(pool);
+
+ if(pool->mutex) mutex_destroy(pool->mutex);
+ if(pool->cond_new) cond_destroy(pool->cond_new);
+ if(pool->cond_fetch) cond_destroy(pool->cond_fetch);
+
+ LIST_FOR_EACH_SAFE(node, tmp_node, &pool->parts_free) {
+ struct part* part = CONTAINER_OF(node, struct part, node);
+ list_del(node);
+ MEM_RM(pool->allocator, part);
+ }
+
+ LIST_FOR_EACH_SAFE(node, tmp_node, &pool->parts_full) {
+ struct part* part = CONTAINER_OF(node, struct part, node);
+ list_del(node);
+ MEM_RM(pool->allocator, part);
+ }
+
+ ASSERT(is_list_empty(&pool->parts_free));
+ ASSERT(is_list_empty(&pool->parts_full));
+
+ memset(pool, 0, sizeof(*pool));
+}
+
+struct part*
+pool_new_partition(struct pool* pool)
+{
+ struct list_node* node = NULL;
+ struct part* part = NULL;
+ ASSERT(pool);
+
+ mutex_lock(pool->mutex);
+ if(is_list_empty(&pool->parts_free)) {
+ cond_wait(pool->cond_new, pool->mutex);
+ }
+ node = list_head(&pool->parts_free);
+ list_del(node);
+ mutex_unlock(pool->mutex);
+
+ part = CONTAINER_OF(node, struct part, node);
+ return part;
+}
+
+void
+pool_free_partition(struct pool* pool, struct part* part)
+{
+ ASSERT(pool && part && is_list_empty(&part->node));
+
+ mutex_lock(pool->mutex);
+ list_add_tail(&pool->parts_free, &part->node);
+ mutex_unlock(pool->mutex);
+
+ cond_signal(pool->cond_new);
+}
+
+void
+pool_commit_partition(struct pool* pool, struct part* part)
+{
+ struct list_node* node = NULL;
+ ASSERT(pool && part);
+
+ mutex_lock(pool->mutex);
+ LIST_FOR_EACH_REVERSE(node, &pool->parts_full) {
+ struct part* part2 = CONTAINER_OF(node, struct part, node);
+ if(part2->id <= part->id) break;
+ }
+ list_add(node, &part->node);
+ mutex_unlock(pool->mutex);
+
+ cond_signal(pool->cond_fetch);
+}
+
+struct part*
+pool_fetch_partition(struct pool* pool, size_t part_id)
+{
+ struct part* found_part = NULL;
+ struct list_node* node = NULL;
+ ASSERT(pool);
+
+ mutex_lock(pool->mutex);
+ for(;;) {
+ /* Search for a partition that match the submitted id */
+ LIST_FOR_EACH(node, &pool->parts_full) {
+ struct part* part = CONTAINER_OF(node, struct part, node);
+
+ if(part->id == part_id) {
+ found_part = part;
+ break;
+ }
+
+ /* Partitions are sorted in ascending order. Stop the linear search if the
+ * current id is greater than the submitted one */
+ if(part->id > part_id) break;
+ }
+ if(!found_part) {
+ cond_wait(pool->cond_fetch, pool->mutex);
+ } else {
+ list_del(&found_part->node);
+ break;
+ }
+ }
+ mutex_unlock(pool->mutex);
+
+ return found_part;
+}
+
diff --git a/src/atrstm_partition.h b/src/atrstm_partition.h
@@ -0,0 +1,91 @@
+/* Copyright (C) 2020 CNRS
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>. */
+
+#ifndef ATRSTM_PARTITION_H
+#define ATRSTM_PARTITION_H
+
+#include "atrstm_svx.h"
+#include <rsys/list.h>
+
+/* Definition of a partition along the 4 axis */
+#define PARTITION_DEFINITION 32
+
+/* Max #partitions stored into the partition pool */
+#define POOL_MAX_NPARTITIONS 16
+
+/* Forward declarations */
+struct cond;
+struct mem_allocator;
+struct mutex;
+
+struct part {
+ /* Morton ordered list of voxels */
+ float voxels
+ [ PARTITION_DEFINITION
+ * PARTITION_DEFINITION
+ * PARTITION_DEFINITION
+ * NFLOATS_PER_VOXEL];
+ struct list_node node;
+ size_t id; /* Unique identifier of the partition */
+};
+
+struct pool {
+ /* Linked list of pre-allocated partitions */
+ struct list_node parts_free;
+
+ /* List of available partition sorted in ascending order wrt partition id */
+ struct list_node parts_full;
+
+ struct mutex* mutex;
+ struct cond* cond_new;
+ struct cond* cond_fetch;
+
+ struct mem_allocator* allocator;
+};
+
+extern LOCAL_SYM res_T
+pool_init
+ (struct mem_allocator* allocator, /* May be NULL <=> default allocator */
+ struct pool* pool);
+
+extern LOCAL_SYM void
+pool_release
+ (struct pool* pool);
+
+/* Return a free partition. Wait until a free partition is available */
+extern LOCAL_SYM struct part*
+pool_new_partition
+ (struct pool* pool);
+
+/* Register the partition as a free partition against the pool */
+extern LOCAL_SYM void
+pool_free_partition
+ (struct pool* pool,
+ struct part* part);
+
+/* Register the partition as a valid partition that can be fetched */
+extern LOCAL_SYM void
+pool_commit_partition
+ (struct pool* pool,
+ struct part* part);
+
+/* Return the partition whose id is `part_id`. Wait until the expected
+ * partition is available */
+extern LOCAL_SYM struct part*
+pool_fetch_partition
+ (struct pool* pool,
+ const size_t part_id);
+
+#endif /* ATRSTM_PARTITION_H */
diff --git a/src/atrstm_svx.h b/src/atrstm_svx.h
@@ -0,0 +1,77 @@
+/* Copyright (C) 2020 CNRS
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>. */
+
+#ifndef ATRSTM_SVX_H
+#define ATRSTM_SVX_H
+
+#include "atrstm.h"
+
+/* SVX Memory layout
+ * -----------------
+ *
+ * For each SVX voxel, the data of the optical property are stored
+ * linearly as N single precision floating point data, with N computed as
+ * bellow:
+ *
+ * N = ATRSTM_PROPS_COUNT__ #optical properties per voxel
+ * * ATRSTM_SVX_OPS_COUNT__ #supported operations on each properties
+ * * ATRSTM_CPNTS_COUNT__; #components on which properties are defined
+ *
+ * In a given voxel, the index `id' in [0, N-1] corresponding to the optical
+ * property `enum atrstm_property P' of the component `enum atrstm_component
+ * C' according to the operation `enum atrstm_svx_op O' is
+ * then computed as bellow:
+ *
+ * id = C * NFLOATS_PER_CPNT + P * HTSKY_SVX_OPS_COUNT__ + O;
+ * NFLOATS_PER_CPNT = ATRSTM_SVX_OPS_COUNT__ * ATRSTM_PROPS_COUNT__;
+ */
+
+/* Constant defining the number of floating point data per component */
+#define NFLOATS_PER_CPNT (ATRSTM_SVX_OPS_COUNT__ * ATRSTM_PROPS_COUNT__)
+
+/* Constant defining the overall number of floating point data of a voxel */
+#define NFLOATS_PER_VOXEL (NFLOATS_PER_CPNT * ATRSTM_CPNTS_COUNT__)
+
+static FINLINE float
+vox_get
+ (const float* data,
+ const enum atrstm_component cpnt,
+ const enum atrstm_property prop,
+ const enum atrstm_svx_op op)
+{
+ ASSERT(data);
+ ASSERT((unsigned)cpnt < ATRSTM_CPNTS_COUNT__);
+ ASSERT((unsigned)prop < ATRSTM_PROPS_COUNT__);
+ ASSERT((unsigned)op < ATRSTM_SVX_OPS_COUNT__);
+ return data[cpnt*NFLOATS_PER_CPNT + prop*ATRSTM_SVX_OPS_COUNT__ + op];
+}
+
+static FINLINE void
+vox_set
+ (float* data,
+ const enum atrstm_component cpnt,
+ const enum atrstm_property prop,
+ const enum atrstm_svx_op op,
+ const float val)
+{
+ ASSERT(data);
+ ASSERT((unsigned)cpnt < ATRSTM_CPNTS_COUNT__);
+ ASSERT((unsigned)prop < ATRSTM_PROPS_COUNT__);
+ ASSERT((unsigned)op < ATRSTM_SVX_OPS_COUNT__);
+ data[cpnt*NFLOATS_PER_CPNT + prop*ATRSTM_SVX_OPS_COUNT__ + op] = val;
+}
+
+#endif /* ATRSTM_SVX_H */
+