commit 89ee753dce248d7343357d8274bd491272b7345d
parent 7dd027bdfd4639cf36f07b80e9aba1ae7edb3f01
Author: Christophe Coustet <christophe.coustet@meso-star.com>
Date: Fri, 16 Mar 2018 14:39:44 +0100
Additional openmp stuff; mostly about many enclosure scenario
Diffstat:
1 file changed, 169 insertions(+), 141 deletions(-)
diff --git a/src/senc_scene_analyze.c b/src/senc_scene_analyze.c
@@ -137,19 +137,68 @@ get_side_from_stack
return id;
}
+static void
+get_scn_indices(const unsigned itri, unsigned ids[3], void* ctx) {
+ int i;
+ const struct senc_scene* scene = ctx;
+ const struct triangle_in* trg =
+ darray_triangle_in_cdata_get(&scene->triangles_in) + itri;
+ FOR_EACH(i, 0, 3) {
+ ASSERT(trg->vertice_id[i] < scene->nverts);
+ ids[i] = (unsigned) trg->vertice_id[i]; /* Back to API type */
+ }
+}
+
+static void
+get_scn_position(const unsigned ivert, float pos[3], void* ctx) {
+ const struct senc_scene* scene = ctx;
+ const union double3* pt =
+ darray_position_cdata_get(&scene->vertices) + ivert;
+ f3_set_d3(pos, pt->vec);
+}
+
+static int
+self_hit_filter
+(const struct s3d_hit* hit,
+ const float ray_org[3],
+ const float ray_dir[3],
+ void* ray_data,
+ void* filter_data)
+{
+ const struct darray_triangle_comp* triangles_comp = filter_data;
+ const component_id_t* origin_component = ray_data;
+ const struct triangle_comp* hit_trg_comp;
+ enum side_id hit_side;
+ component_id_t hit_component;
+
+ (void) ray_org; (void) ray_dir;
+ ASSERT(hit && triangles_comp && origin_component);
+ ASSERT(hit->prim.prim_id < darray_triangle_comp_size_get(triangles_comp));
+ hit_trg_comp = darray_triangle_comp_cdata_get(triangles_comp)
+ + hit->prim.prim_id;
+ hit_side = (hit->normal[2] > 0) ? SIDE_FRONT : SIDE_BACK;
+ hit_component = hit_trg_comp->component[hit_side];
+
+ /* Not self hit or distance should be small */
+ ASSERT(hit_component != *origin_component || hit->distance < 1e-6);
+ return (hit_component == *origin_component);
+}
+
static res_T
extract_connex_components
(struct senc_descriptor* desc,
struct trgside* trgsides,
struct darray_ptr_component_descriptor* connex_components,
const struct darray_triangle_tmp* triangles_tmp_array,
- struct darray_triangle_comp* triangles_comp)
+ struct darray_triangle_comp* triangles_comp,
+ struct s3d_scene_view** s3d_view)
{
res_T res = RES_OK;
const struct senc_scene* scn;
struct mem_allocator* alloc;
ATOMIC component_count = 0;
- int mm;
+ volatile int exit_for = 0;
+ int64_t mm;
#ifndef NDEBUG
trg_id_t t;
component_id_t c;
@@ -162,7 +211,7 @@ extract_connex_components
/* Just a hint; to avoid contention on first loop */
OK2(darray_ptr_component_descriptor_reserve(connex_components, 2 * scn->nmeds),
- error_); /* Cannot jump into openmp block */
+ error_); /* Cannot goto into openmp block */
#ifndef NDEBUG
FOR_EACH(t, 0, scn->nutris) {
@@ -183,13 +232,14 @@ extract_connex_components
struct darray_side_id stack;
darray_side_id_init(alloc, &stack);
- #pragma omp for schedule(dynamic)
- for(mm = 0; mm < (int)scn->nmeds; mm++) { /* Process all media */
+ #pragma omp for schedule(dynamic) nowait
+ for(mm = 0; mm < (int64_t)scn->nmeds; mm++) { /* Process all media */
const medium_id_t m = (medium_id_t)mm;
struct cc_descriptor* cc;
/* Any not-already-used side is used as a starting point */
side_id_t first_side_not_in_component;
- if(res != RES_OK) continue;
+
+ if(exit_for) continue;
first_side_not_in_component
= darray_side_range_cdata_get(&scn->media_use)[m].first;
if(first_side_not_in_component == SIDE_NULL__)
@@ -202,8 +252,8 @@ extract_connex_components
side_id_t crt_side_id = start_side_id;
side_id_t last_side_id = start_side_id;
ASSERT(start_side_id == SIDE_NULL__ || start_side_id < 2 * scn->nutris);
- if(start_side_id == SIDE_NULL__) /* start_side_id=SIDE_NULL__ => done! */
- break;
+ if(start_side_id == SIDE_NULL__)
+ break; /* start_side_id=SIDE_NULL__ => done! */
ASSERT(trgsides[start_side_id].list_id == FLAG_LIST_SIDE_LIST);
#ifndef NDEBUG
@@ -219,7 +269,7 @@ extract_connex_components
cc = MEM_ALLOC(alloc, sizeof(struct cc_descriptor));
if(!cc) {
res = RES_MEM_ERR;
- goto error;
+ goto error1;
}
cc_descriptor_init(alloc, cc);
ASSERT(m == trgsides[start_side_id].medium);
@@ -321,7 +371,7 @@ extract_connex_components
side_id_t neighbour_id = crt_side->facing_side_id[i];
trg_id_t nbour_trg_id = TRGSIDE_2_TRG(neighbour_id);
const struct trgside* neighbour = trgsides + neighbour_id;
- CHK(m == crt_side->medium);
+ ASSERT(m == crt_side->medium);
if(neighbour->medium != crt_side->medium) {
/* Found medium discontinuity! Model topology is broken. */
const struct triangle_in* triangles_in
@@ -350,7 +400,7 @@ extract_connex_components
log_err(desc->scene->dev, "Media: %lu VS %lu\n",
(unsigned long)neighbour->medium, (unsigned long)crt_side->medium);
res = RES_BAD_ARG;
- goto error;
+ goto error1;
}
if(neighbour->list_id == FLAG_LIST_COMPONENT) {
/* Already processed */
@@ -373,7 +423,7 @@ extract_connex_components
cc->side_range.last = last_side_id;
/* Need to synchronize connex_components growth as this global structure
* is accessed by multipe threads */
-#pragma omp critical
+ #pragma omp critical
{
struct cc_descriptor** components;
size_t sz = darray_ptr_component_descriptor_size_get(connex_components);
@@ -390,11 +440,46 @@ extract_connex_components
components[cc->cc_id] = cc;
}
}
+ OK2(res, error1);
}
- error:
- continue; /* Cannot exit openmp block */
+ continue;
+ error1:
+ /* Cannot goto out of openmp block */
+ exit_for = 1;
+ continue;
}
+ /* No barrier here (nowait clause).
+ * The first thread executes the single block */
darray_side_id_release(&stack);
+ #pragma omp single nowait
+ {
+ struct s3d_device* s3d = NULL;
+ struct s3d_scene* s3d_scn = NULL;
+ struct s3d_shape* s3d_shp = NULL;
+ struct s3d_vertex_data attribs;
+
+ attribs.type = S3D_FLOAT3;
+ attribs.usage = S3D_POSITION;
+ attribs.get = get_scn_position;
+
+ /* Put geometry in a 3D view */
+ OK(s3d_device_create(desc->scene->dev->logger, alloc, 0, &s3d));
+ OK(s3d_scene_create(s3d, &s3d_scn));
+ OK(s3d_shape_create_mesh(s3d, &s3d_shp));
+
+ /* Back to API type for ntris and nverts */
+ ASSERT(desc->scene->nutris < UINT_MAX);
+ ASSERT(desc->scene->nuverts < UINT_MAX);
+ OK(s3d_mesh_setup_indexed_vertices(s3d_shp, (unsigned) desc->scene->nutris,
+ get_scn_indices, (unsigned) desc->scene->nuverts, &attribs, 1, desc->scene));
+ s3d_mesh_set_hit_filter_function(s3d_shp, self_hit_filter, triangles_comp);
+ OK(s3d_scene_attach_shape(s3d_scn, s3d_shp));
+ OK(s3d_scene_view_create(s3d_scn, S3D_TRACE, s3d_view));
+ error:
+ if(s3d) S3D(device_ref_put(s3d));
+ if(s3d_scn) S3D(scene_ref_put(s3d_scn));
+ if(s3d_shp) S3D(shape_ref_put(s3d_shp));
+ }
}
OK2(res, error_);
@@ -424,73 +509,23 @@ error_:
goto exit;
}
-static void
-get_scn_indices(const unsigned itri, unsigned ids[3], void* ctx) {
- int i;
- const struct senc_scene* scene = ctx;
- const struct triangle_in* trg =
- darray_triangle_in_cdata_get(&scene->triangles_in) + itri;
- FOR_EACH(i, 0, 3) {
- ASSERT(trg->vertice_id[i] < scene->nverts);
- ids[i] = (unsigned)trg->vertice_id[i]; /* Back to API type */
- }
-}
-
-static void
-get_scn_position(const unsigned ivert, float pos[3], void* ctx) {
- const struct senc_scene* scene = ctx;
- const union double3* pt =
- darray_position_cdata_get(&scene->vertices) + ivert;
- f3_set_d3(pos, pt->vec);
-}
-
-static int
-self_hit_filter
-(const struct s3d_hit* hit,
- const float ray_org[3],
- const float ray_dir[3],
- void* ray_data,
- void* filter_data)
-{
- const struct darray_triangle_comp* triangles_comp = filter_data;
- const component_id_t* origin_component = ray_data;
- const struct triangle_comp* hit_trg_comp;
- enum side_id hit_side;
- component_id_t hit_component;
-
- (void)ray_org; (void)ray_dir;
- ASSERT(hit && triangles_comp && origin_component);
- ASSERT(hit->prim.prim_id < darray_triangle_comp_size_get(triangles_comp));
- hit_trg_comp = darray_triangle_comp_cdata_get(triangles_comp)
- + hit->prim.prim_id;
- hit_side = (hit->normal[2] > 0) ? SIDE_FRONT : SIDE_BACK;
- hit_component = hit_trg_comp->component[hit_side];
-
- /* Not self hit or distance should be small */
- ASSERT(hit_component != *origin_component || hit->distance < 1e-6);
- return (hit_component == *origin_component);
-}
-
static res_T
group_connex_components
(struct senc_descriptor* desc,
struct trgside* trgsides,
struct darray_triangle_comp* triangles_comp,
- struct darray_ptr_component_descriptor* connex_components)
+ struct darray_ptr_component_descriptor* connex_components,
+ struct s3d_scene_view* s3d_view)
{
res_T res = RES_OK;
struct mem_allocator* alloc;
struct cc_descriptor** descriptors;
- struct s3d_device* s3d = NULL;
- struct s3d_scene* s3d_scn = NULL;
- struct s3d_shape* s3d_shp = NULL;
- struct s3d_scene_view* s3d_view = NULL;
- struct s3d_vertex_data attribs;
size_t tmp;
- component_id_t cc_count, c;
- medium_id_t infinite_medium = MEDIUM_NULL__;
- side_id_t infinite_medium_first_side = SIDE_MAX__;
- unsigned char infinite_medium_is_known = 0;
+ component_id_t cc_count;
+ int64_t ccc;
+ volatile int exit_for = 0;
+ ATOMIC next_enclosure_id = desc->enclosures_count;
+ struct cc_descriptor* infinity_first_cc = NULL;
(void)trgsides;
ASSERT(desc && trgsides && triangles_comp && connex_components);
@@ -500,28 +535,10 @@ group_connex_components
ASSERT(tmp <= COMPONENT_MAX__);
cc_count = (component_id_t)tmp;
- if(!cc_count) return RES_OK; /* No component to group */
-
- attribs.type = S3D_FLOAT3;
- attribs.usage = S3D_POSITION;
- attribs.get = get_scn_position;
-
- /* Put geometry in a 3D view */
- OK(s3d_device_create(desc->scene->dev->logger, alloc, 0, &s3d));
- OK(s3d_scene_create(s3d, &s3d_scn));
- OK(s3d_shape_create_mesh(s3d, &s3d_shp));
-
- /* Back to API type for ntris and nverts */
- ASSERT(desc->scene->nutris < UINT_MAX);
- ASSERT(desc->scene->nuverts < UINT_MAX);
- OK(s3d_mesh_setup_indexed_vertices(s3d_shp, (unsigned)desc->scene->nutris,
- get_scn_indices, (unsigned)desc->scene->nuverts, &attribs, 1, desc->scene));
- s3d_mesh_set_hit_filter_function(s3d_shp, self_hit_filter, triangles_comp);
- OK(s3d_scene_attach_shape(s3d_scn, s3d_shp));
- OK(s3d_scene_view_create(s3d_scn, S3D_TRACE, &s3d_view));
-
/* Cast rays to find links between connex components */
- FOR_EACH(c, 0, cc_count) {
+ #pragma omp parallel for
+ for(ccc = 0; ccc < (int64_t)cc_count; ccc++) {
+ component_id_t c = (component_id_t)ccc;
struct s3d_hit hit = S3D_HIT_NULL;
float origin[3];
const float dir[3] = { 0, 0, 1 };
@@ -532,14 +549,17 @@ group_connex_components
component_id_t self_hit_component
= origin_trg->component[1 - TRGSIDE_2_SIDE(cc->max_z_side_id)];
+ if(exit_for) continue;
ASSERT(cc->cc_id == c);
ASSERT(cc->cc_group_root == CC_GROUP_ID_NONE);
if(cc->max_z_nz < 0) {
+ size_t id;
/* Don't need to cast a ray */
cc->cc_group_root = cc->cc_id; /* New group with self as root */
- ASSERT(desc->enclosures_count < ENCLOSURE_MAX__);
- cc->enclosure_id = desc->enclosures_count++;
+ id = ATOMIC_INCR(&next_enclosure_id) - 1;
+ ASSERT(id < ENCLOSURE_MAX__);
+ cc->enclosure_id = (enclosure_id_t)id;
continue;
}
@@ -555,21 +575,19 @@ group_connex_components
== TRGSIDE_OPPOSITE(cc->max_z_side_id))));
f3_set_d3(origin, cc->max_vrtx);
/* Self-hit data: self hit if hit this component "on the other side" */
- OK(s3d_scene_view_trace_ray(s3d_view, origin, dir, range,
- &self_hit_component, &hit));
+ OK2(s3d_scene_view_trace_ray(s3d_view, origin, dir, range,
+ &self_hit_component, &hit), error_);
/* If no hit, the component is facing an infinite medium */
if(S3D_HIT_NONE(&hit)) {
cc->cc_group_root = CC_GROUP_ROOT_INFINITE;
cc->enclosure_id = 0;
- if(!infinite_medium_is_known) {
- infinite_medium_is_known = 1;
- infinite_medium = cc->medium;
- infinite_medium_first_side = cc->max_z_side_id;
- continue;
- }
- if(infinite_medium != cc->medium) {
+ /* Keep the first component facing infinity */
+ ATOMIC_CAS(&(intptr_t)infinity_first_cc, (intptr_t)cc, (intptr_t)NULL);
+ if(infinity_first_cc->medium != cc->medium) {
+ const side_id_t infinity_first_side = infinity_first_cc->max_z_side_id;
+ const medium_id_t infinity_medium = infinity_first_cc->medium;
/* Medium mismatch! Model topology is broken. */
- const trg_id_t t1 = TRGSIDE_2_TRG(infinite_medium_first_side);
+ const trg_id_t t1 = TRGSIDE_2_TRG(infinity_first_side);
const trg_id_t t2 = TRGSIDE_2_TRG(cc->max_z_side_id);
const struct triangle_in* triangles_in
= darray_triangle_in_cdata_get(&desc->scene->triangles_in);
@@ -579,7 +597,7 @@ group_connex_components
"Medium mismatch found between triangle %lu %s side and triangle"
" %lu %s side, both facing infinity.\n",
(unsigned long)triangles_in[t1].global_id,
- TRGSIDE_IS_FRONT(infinite_medium_first_side) ? "front" : "back",
+ TRGSIDE_IS_FRONT(infinity_first_side) ? "front" : "back",
(unsigned long)triangles_in[t2].global_id,
TRGSIDE_IS_FRONT(cc->max_z_side_id) ? "front" : "back");
log_err(desc->scene->dev,
@@ -595,9 +613,9 @@ group_connex_components
SPLIT3(positions[triangles_in[t2].vertice_id[1]].vec),
SPLIT3(positions[triangles_in[t2].vertice_id[2]].vec));
log_err(desc->scene->dev, "Media: %lu VS %lu\n",
- (unsigned long)infinite_medium, (unsigned long)cc->medium);
+ (unsigned long)infinity_medium, (unsigned long)cc->medium);
res = RES_BAD_ARG;
- goto error;
+ goto error_;
}
/* Same medium as previous members of the group: OK */
continue;
@@ -657,14 +675,22 @@ group_connex_components
(unsigned long)cc->medium);
res = RES_BAD_ARG;
- goto error;
+ goto error_;
}
}
+ continue;
+ error_:
+ exit_for = 1;
+ continue;
}
+ ASSERT(next_enclosure_id < ENCLOSURE_MAX__);
+ desc->enclosures_count = (enclosure_id_t)next_enclosure_id;
+ OK(res);
/* Post-process links to group connex components */
OK(darray_enclosure_resize(&desc->enclosures, desc->enclosures_count));
- FOR_EACH(c, 0, cc_count) {
+ FOR_EACH(ccc, 0, cc_count) {
+ component_id_t c = (component_id_t)ccc;
struct cc_descriptor* const cc = descriptors[c];
const struct cc_descriptor* other_desc = cc;
struct enclosure_data* enclosures
@@ -693,11 +719,6 @@ group_connex_components
}
exit:
- /* Local Star3D stuff is no longer useful */
- if(s3d) S3D(device_ref_put(s3d));
- if(s3d_scn) S3D(scene_ref_put(s3d_scn));
- if(s3d_shp) S3D(shape_ref_put(s3d_shp));
- if(s3d_view) S3D(scene_view_ref_put(s3d_view));
return res;
error:
goto exit;
@@ -931,8 +952,9 @@ build_result
const struct triangle_in* triangles_in;
struct triangle_enc* triangles_enc;
const struct triangle_comp* triangles_comp;
- int tt;
- int ee;
+ volatile int exit_for = 0;
+ int64_t tt;
+ int64_t ee;
ASSERT(desc && connex_components && triangles_comp_array);
@@ -946,31 +968,34 @@ build_result
error_);
triangles_enc = darray_triangle_enc_data_get(&desc->triangles_enc);
- /* Build global enclosure information */
- #pragma omp parallel for
- for(tt = 0; tt < (int)desc->scene->nutris; tt++) {
- trg_id_t t = (trg_id_t)tt;
- const component_id_t cf_id = triangles_comp[t].component[SIDE_FRONT];
- const component_id_t cb_id = triangles_comp[t].component[SIDE_BACK];
- const struct cc_descriptor* cf = cc_descriptors[cf_id];
- const struct cc_descriptor* cb = cc_descriptors[cb_id];
- const enclosure_id_t ef_id = cf->enclosure_id;
- const enclosure_id_t eb_id = cb->enclosure_id;
- ASSERT(triangles_enc[t].enclosure[SIDE_FRONT] == ENCLOSURE_NULL__);
- triangles_enc[t].enclosure[SIDE_FRONT] = ef_id;
- ASSERT(triangles_enc[t].enclosure[SIDE_BACK] == ENCLOSURE_NULL__);
- triangles_enc[t].enclosure[SIDE_BACK] = eb_id;
- }
-
- /* Resize/push operations on enclosure's fields are valid in the
- * openmp block as a given enclosure is processed by a single thread */
#pragma omp parallel
{
struct htable_vrtx_id vtable;
+
+ /* Build global enclosure information */
+ #pragma omp for
+ for(tt = 0; tt < (int64_t) desc->scene->nutris; tt++) {
+ trg_id_t t = (trg_id_t)tt;
+ const component_id_t cf_id = triangles_comp[t].component[SIDE_FRONT];
+ const component_id_t cb_id = triangles_comp[t].component[SIDE_BACK];
+ const struct cc_descriptor* cf = cc_descriptors[cf_id];
+ const struct cc_descriptor* cb = cc_descriptors[cb_id];
+ const enclosure_id_t ef_id = cf->enclosure_id;
+ const enclosure_id_t eb_id = cb->enclosure_id;
+ ASSERT(triangles_enc[t].enclosure[SIDE_FRONT] == ENCLOSURE_NULL__);
+ triangles_enc[t].enclosure[SIDE_FRONT] = ef_id;
+ ASSERT(triangles_enc[t].enclosure[SIDE_BACK] == ENCLOSURE_NULL__);
+ triangles_enc[t].enclosure[SIDE_BACK] = eb_id;
+ }
+ /* Implicit barrier here */
+
+ /* Resize/push operations on enclosure's fields are valid in the
+ * openmp block as a given enclosure is processed by a single thread */
htable_vrtx_id_init(alloc, &vtable);
- #pragma omp for schedule(dynamic)
- for(ee = 0; ee < (int)desc->enclosures_count; ee++) {
+ ASSERT(desc->enclosures_count <= ENCLOSURE_MAX__);
+ #pragma omp for schedule(dynamic) nowait
+ for(ee = 0; ee < (int64_t)desc->enclosures_count; ee++) {
const enclosure_id_t e = (enclosure_id_t)ee;
struct enclosure_data* enc = enclosures + e;
const struct cc_descriptor* current = cc_descriptors[enc->first_component];
@@ -979,10 +1004,9 @@ build_result
trg_id_t t;
ASSERT(enc->first_component
< darray_ptr_component_descriptor_size_get(connex_components));
- ASSERT(ee <= ENCLOSURE_MAX__);
ASSERT(current->cc_id == enc->first_component);
- if(res != RES_OK) continue;
+ if(exit_for) continue;
ASSERT(e <= UINT_MAX);
enc->header.enclosure_id = (unsigned)e; /* Back to API type */
ASSERT(current->enclosure_id == enc->header.enclosure_id);
@@ -1052,8 +1076,10 @@ build_result
}
if(fst_idx == sgd_idx) break;
}
+ continue;
error:
- /* Cannot exit openmp block */
+ /* Cannot goto out of openmp block */
+ exit_for = 1;
continue;
}
htable_vrtx_id_release(&vtable);
@@ -1089,6 +1115,7 @@ senc_scene_analyze(struct senc_scene* scn, struct senc_descriptor** out_desc)
char triangles_comp_initialized = 0;
/* Array of triangle sides. */
struct trgside* trgsides = NULL;
+ struct s3d_scene_view* s3d_view = NULL;
if(!scn || !out_desc) return RES_BAD_ARG;
@@ -1128,7 +1155,7 @@ senc_scene_analyze(struct senc_scene* scn, struct senc_descriptor** out_desc)
/* Step 2: extract triangle connex components */
res = extract_connex_components(desc, trgsides, &connex_components,
- &triangles_tmp, &triangles_comp);
+ &triangles_tmp, &triangles_comp, &s3d_view);
if(res != RES_OK) {
log_err(scn->dev,
"%s: could not extract connex components from scene.\n", FUNC_NAME);
@@ -1140,7 +1167,8 @@ senc_scene_analyze(struct senc_scene* scn, struct senc_descriptor** out_desc)
/* Step 3: group components */
res = group_connex_components(desc, trgsides, &triangles_comp,
- &connex_components);
+ &connex_components, s3d_view);
+ if (s3d_view) S3D(scene_view_ref_put(s3d_view));
if(res != RES_OK) {
log_err(scn->dev,
"%s: could not group connex components from scene.\n", FUNC_NAME);