diff --git a/source/blender/gpencil_modifiers/intern/lineart/lineart_cpu.c b/source/blender/gpencil_modifiers/intern/lineart/lineart_cpu.c index e0baf35546a..5c3f588df7d 100644 --- a/source/blender/gpencil_modifiers/intern/lineart/lineart_cpu.c +++ b/source/blender/gpencil_modifiers/intern/lineart/lineart_cpu.c @@ -52,8 +52,6 @@ #include "lineart_intern.h" -#include "atomic_ops.h" - typedef struct LineartIsecSingle { float v1[3], v2[3]; LineartTriangle *tri1, *tri2; @@ -351,13 +349,6 @@ BLI_INLINE bool lineart_occlusion_is_adjacent_intersection(LineartEdge *e, Linea static void lineart_bounding_area_triangle_reallocate(LineartBoundingArea *ba) { - for (int i = 0; i < ba->max_triangle_count; i++) { - LineartTriangle *tri; - do { - tri = (LineartTriangle *)atomic_load_ptr(&ba->linked_triangles[i]); - /* Need to wait for worker threads to fill in the last few triangles. */ - } while (UNLIKELY(tri == NULL)); - } ba->max_triangle_count *= 2; ba->linked_triangles = MEM_recallocN(ba->linked_triangles, sizeof(LineartTriangle *) * ba->max_triangle_count); @@ -3252,20 +3243,14 @@ static void lineart_triangle_intersect_in_bounding_area(LineartTriangle *tri, return; } - /* Testing_triangle->testing[0] is used to store pairing triangle reference. - * See definition of LineartTriangleThread for more info. */ - LineartTriangle *testing_triangle; - LineartTriangleThread *tt; - double *G0 = tri->v[0]->gloc, *G1 = tri->v[1]->gloc, *G2 = tri->v[2]->gloc; /* If this _is_ the smallest subdiv bounding area, then do the intersections there. */ for (int i = 0; i < up_to; i++) { - do { - testing_triangle = (LineartTriangle *)atomic_load_ptr(&ba->linked_triangles[i]); - } while (UNLIKELY(testing_triangle == NULL)); - - tt = (LineartTriangleThread *)testing_triangle; + /* Testing_triangle->testing[0] is used to store pairing triangle reference. + * See definition of LineartTriangleThread for more info. */ + LineartTriangle *testing_triangle = ba->linked_triangles[i]; + LineartTriangleThread *tt = (LineartTriangleThread *)testing_triangle; if (testing_triangle == tri || tt->testing_e[th->thread_id] == (LineartEdge *)tri) { continue; @@ -3758,8 +3743,6 @@ static void lineart_bounding_area_split(LineartRenderBuffer *rb, LineartBoundingArea *ba = lineart_mem_acquire_thread(&rb->render_data_pool, sizeof(LineartBoundingArea) * 4); - LineartTriangle *tri; - ba[0].l = root->cx; ba[0].r = root->r; ba[0].u = root->u; @@ -3800,10 +3783,8 @@ static void lineart_bounding_area_split(LineartRenderBuffer *rb, } for (int i = 0; i < root->triangle_count; i++) { - do { - tri = (LineartTriangle *)atomic_load_ptr(&root->linked_triangles[i]); - /* Need to wait for worker threads to fill in the last few triangles. */ - } while (UNLIKELY(tri == NULL)); + LineartTriangle *tri = root->linked_triangles[i]; + double b[4]; b[0] = MIN3(tri->v[0]->fbcoord[0], tri->v[1]->fbcoord[0], tri->v[2]->fbcoord[0]); b[1] = MAX3(tri->v[0]->fbcoord[0], tri->v[1]->fbcoord[0], tri->v[2]->fbcoord[0]); @@ -3964,62 +3945,40 @@ static void lineart_bounding_area_link_triangle_cas(LineartRenderBuffer *rb, return; } - while (1) { - uint32_t old_tri_index = old_ba->triangle_count; - uint32_t new_tri_index = old_tri_index + 1; - uint32_t max_triangles = old_ba->max_triangle_count; + BLI_spin_lock(&old_ba->lock); - /* If there are still space left in this tile for insertion. */ - if (old_tri_index < max_triangles) { + /* If there are still space left in this tile for insertion. */ + if (old_ba->triangle_count < old_ba->max_triangle_count) { + const uint32_t old_tri_count = old_ba->triangle_count; - /* Use atomic compare and swap to get a index, we can't use atomic increment here because it - * could overflow the index when multiple threads are incrementing. */ - uint32_t success_old_index = atomic_cas_uint32( - &old_ba->triangle_count, old_tri_index, new_tri_index); + old_ba->linked_triangles[old_ba->triangle_count++] = tri; - if (success_old_index != old_tri_index) { - /* Too bad, other threads grabbed this index, we retry. */ - continue; - } - - /* Successfully grabbed a viable index to insert the triangle into. - * Insert into [old_tri_index] for correct array offset starting from [0]. */ - atomic_store_ptr(&old_ba->linked_triangles[old_tri_index], tri); - - /* Do intersections in place. */ - if (do_intersection && rb->use_intersections) { - lineart_triangle_intersect_in_bounding_area(tri, old_ba, th, old_tri_index); - } - break; + /* Do intersections in place. */ + if (do_intersection && rb->use_intersections) { + lineart_triangle_intersect_in_bounding_area(tri, old_ba, th, old_tri_count); } - else { /* We need to wait for either splitting or array extension to be done. */ - - /* Splitting/extending can only be operated by one thread. */ - BLI_spin_lock(&old_ba->lock); - - if (recursive_level < rb->tile_recursive_level) { - if (!old_ba->child) { - /* old_ba->child==NULL, means we are the thread that's doing the splitting. */ - lineart_bounding_area_split(rb, old_ba, recursive_level); - } /* Otherwise other thread has completed the splitting process. */ - } - else { - if (max_triangles == old_ba->max_triangle_count) { - /* Means we are the thread that's doing the extension. */ - lineart_bounding_area_triangle_reallocate(old_ba); - } /* Otherwise other thread has completed the extending the array. */ - } - - /* Job done, allow other threads to add into new tile. */ - BLI_spin_unlock(&old_ba->lock); - - /* Of course we still have our own triangle needs to be added. */ - lineart_bounding_area_link_triangle_cas( - rb, root_ba, tri, LRUB, recursive, recursive_level, do_intersection, th); + } + else { /* We need to wait for either splitting or array extension to be done. */ - break; + if (recursive_level < rb->tile_recursive_level) { + if (!old_ba->child) { + /* old_ba->child==NULL, means we are the thread that's doing the splitting. */ + lineart_bounding_area_split(rb, old_ba, recursive_level); + } /* Otherwise other thread has completed the splitting process. */ + } + else { + if (old_ba->max_triangle_count == old_ba->max_triangle_count) { + /* Means we are the thread that's doing the extension. */ + lineart_bounding_area_triangle_reallocate(old_ba); + } /* Otherwise other thread has completed the extending the array. */ } + + /* Of course we still have our own triangle needs to be added. */ + lineart_bounding_area_link_triangle_cas( + rb, root_ba, tri, LRUB, recursive, recursive_level, do_intersection, th); } + + BLI_spin_unlock(&old_ba->lock); } static void lineart_free_bounding_area_memory(LineartBoundingArea *ba, bool recursive)