Revision: 69981
          http://sourceforge.net/p/brlcad/code/69981
Author:   vasco_costa
Date:     2017-07-21 19:46:08 +0000 (Fri, 21 Jul 2017)
Log Message:
-----------
patch #472 by Marco Domingues: faster iteration over sparse bitarrays. fix 
memory pointer address bugs. fix render with 'e *' command. use one regiontable 
per ray instead of one per partition.

Modified Paths:
--------------
    brlcad/branches/opencl/include/rt/region.h
    brlcad/branches/opencl/src/librt/prep.c
    brlcad/branches/opencl/src/librt/primitives/bool.cl
    brlcad/branches/opencl/src/librt/primitives/common.cl
    brlcad/branches/opencl/src/librt/primitives/primitive_util.c

Modified: brlcad/branches/opencl/include/rt/region.h
===================================================================
--- brlcad/branches/opencl/include/rt/region.h  2017-07-21 19:08:00 UTC (rev 
69980)
+++ brlcad/branches/opencl/include/rt/region.h  2017-07-21 19:46:08 UTC (rev 
69981)
@@ -77,6 +77,7 @@
     cl_uint rtree_offset;           /**< @brief index to the start of the rpn 
tree */
     cl_uint reg_nrtree;             /**< @brief number of elements in rtree */
     cl_int reg_aircode;             /**< @brief Region ID AIR code */
+    cl_int reg_bit;                 /**< @brief constant index into Regions[] 
*/
     cl_short reg_all_unions;        /**< @brief 1=boolean tree is all unions */
 };
 

Modified: brlcad/branches/opencl/src/librt/prep.c
===================================================================
--- brlcad/branches/opencl/src/librt/prep.c     2017-07-21 19:08:00 UTC (rev 
69980)
+++ brlcad/branches/opencl/src/librt/prep.c     2017-07-21 19:46:08 UTC (rev 
69981)
@@ -596,6 +596,7 @@
 
                regions[i].reg_nrtree = regp->reg_nrtree;
                regions[i].reg_aircode = regp->reg_aircode;
+               regions[i].reg_bit = regp->reg_bit;
                regions[i].reg_all_unions = regp->reg_all_unions;
 
                rt_tree_rpn(rtree, regp->reg_treetop, &len);

Modified: brlcad/branches/opencl/src/librt/primitives/bool.cl
===================================================================
--- brlcad/branches/opencl/src/librt/primitives/bool.cl 2017-07-21 19:08:00 UTC 
(rev 69980)
+++ brlcad/branches/opencl/src/librt/primitives/bool.cl 2017-07-21 19:46:08 UTC 
(rev 69981)
@@ -135,7 +135,7 @@
        newpp->outseg = k;
        newpp->outhit = segp->seg_out;
        newpp->evaluated = 0;
-       set(segs_bv, start_index + ipartition[id] + (bv_index - 1), k-h[id]);
+       set(segs_bv, (start_index + ipartition[id]) * bv_index, k-h[id]);
        insert_partition_pp(partitions, ipartition, id, head, start_index + 
ipartition[id], *head);
        ipartition[id]++;
        return;
@@ -172,7 +172,7 @@
            newpp->outseg = k;
            newpp->outhit = segp->seg_out;
            newpp->evaluated = 0;
-           set(segs_bv, start_index + ipartition[id] + (bv_index - 1), 
k-h[id]);
+           set(segs_bv, (start_index + ipartition[id]) * bv_index, k-h[id]);
            insert_partition_pp(partitions, ipartition, id, head, start_index + 
ipartition[id], pp->forw_pp);
            ipartition[id]++;
            return;
@@ -240,7 +240,8 @@
            pp->outseg = k;
            pp->outhit = segp->seg_out;
            pp->evaluated = 0;
-           set(segs_bv, start_index + ipartition[id] + (bv_index - 1), 
k-h[id]);
+           pp->region_id = UINT_MAX;
+               set(segs_bv, (start_index + ipartition[id]) * bv_index, 
k-h[id]);
            append_partition_pp(partitions, ipartition, id, start_index + 
ipartition[id], &tail_pp);
            ipartition[id]++;
        } else if (NEAR_ZERO(diff, rti_tol_dist)) {
@@ -257,7 +258,8 @@
            pp->outseg = k;
            pp->outhit = segp->seg_out;
            pp->evaluated = 0;
-           set(segs_bv, start_index + ipartition[id] + (bv_index - 1), 
k-h[id]);
+               pp->region_id = UINT_MAX;
+               set(segs_bv, (start_index + ipartition[id]) * bv_index, 
k-h[id]);
            append_partition_pp(partitions, ipartition, id, start_index + 
ipartition[id], &tail_pp);
            ipartition[id]++;
        } else {
@@ -319,7 +321,7 @@
                    /* new partition is the span before seg joins partition */
                    newpp = &partitions[start_index + ipartition[id]];
                    *newpp = *pp;
-                   copy_bv(segs_bv, bv_index, start_index + ipartition[id] + 
(bv_index - 1), j + (bv_index - 1));
+                   copy_bv(segs_bv, bv_index, (start_index + ipartition[id]) * 
bv_index, j * bv_index);
 
                    pp->inseg = k;
                    pp->inhit = segp->seg_in;
@@ -326,6 +328,7 @@
                    newpp->outseg = k;
                    newpp->outhit = segp->seg_in;
                    newpp->evaluated = 0;
+                       newpp->region_id = UINT_MAX;
                    insert_partition_pp(partitions, ipartition, id, &head_pp, 
start_index + ipartition[id], j);
                    ipartition[id]++;
                } else if (diff > -(rti_tol_dist)) {
@@ -363,10 +366,11 @@
                     */
                    newpp = &partitions[start_index + ipartition[id]];
 
-                   set(segs_bv, start_index + ipartition[id] + (bv_index - 1), 
k-h[id]);
+                   set(segs_bv, (start_index + ipartition[id]) * bv_index, 
k-h[id]);
                    newpp->inseg = lastseg;
                    newpp->inhit = *lasthit;
                    newpp->evaluated = 0;
+                       newpp->region_id = UINT_MAX;
                    diff = segp->seg_out.hit_dist - pp->inhit.hit_dist;
                    if (diff < -(rti_tol_dist)) {
                        /*
@@ -436,7 +440,7 @@
                     *  SSSSSSSS
                     *  pp  |  newpp
                     */
-                   set(segs_bv, j + (bv_index - 1), k-h[id]);
+                   set(segs_bv, j * bv_index, k-h[id]);
 
                    lasthit = &pp->outhit;
                    lastseg = pp->outseg;
@@ -450,7 +454,7 @@
                     *   PPPP
                     *   SSSS
                     */
-                   set(segs_bv, j + (bv_index - 1), k-h[id]);
+                   set(segs_bv, j * bv_index, k-h[id]);
                    break;
                } else {
                    /*
@@ -464,12 +468,13 @@
                     */
                    newpp = &partitions[start_index + ipartition[id]];
                    *newpp = *pp;
-                   copy_bv(segs_bv, bv_index, start_index + ipartition[id] + 
(bv_index - 1), j + (bv_index - 1));
+                   copy_bv(segs_bv, bv_index, (start_index + ipartition[id]) * 
bv_index, j * bv_index);
 
-                   set(segs_bv, start_index + ipartition[id] + (bv_index - 1), 
k-h[id]);
+                   set(segs_bv, (start_index + ipartition[id]) * bv_index, 
k-h[id]);
                    newpp->outseg = k;
                    newpp->outhit = segp->seg_out;
                    newpp->evaluated = 0;
+                       newpp->region_id = UINT_MAX;
                    pp->inseg = k;
                    pp->inhit = segp->seg_out;
                    insert_partition_pp(partitions, ipartition, id, &head_pp, 
start_index + ipartition[id], j);
@@ -486,12 +491,13 @@
             */
            if (ipartition[id] > 0 && j == UINT_MAX) {
                newpp = &partitions[start_index + ipartition[id]];
-               set(segs_bv, start_index + ipartition[id] + (bv_index - 1), 
k-h[id]);
+               set(segs_bv, (start_index + ipartition[id]) * bv_index, 
k-h[id]);
                newpp->inseg = lastseg;
                newpp->inhit = *lasthit;
                newpp->outseg = k;
                newpp->outhit = segp->seg_out;
                newpp->evaluated = 0;
+               newpp->region_id = UINT_MAX;
                append_partition_pp(partitions, ipartition, id, start_index + 
ipartition[id], &tail_pp);
                ipartition[id]++;
            }
@@ -612,10 +618,11 @@
                pp = &partitions[offset];
                //iterate over segments of partition
                for (uint i = 0; i < bv_index; i++) {
-                   uint lz = clz(segs_bv[offset + (bv_index - 1) + i]);
-                   while ( lz != 32) {
+                   uint mask = segs_bv[offset * bv_index + i];
+                   while (mask != 0) {
+                       uint lz = clz(mask);
                        uint k = h[id] + (31 - lz);
-                       if (isset(segs_bv, offset + (bv_index - 1), k - h[id]) 
!= 0) {
+                       if (isset(segs_bv, offset * bv_index, k - h[id]) != 0) {
                            RESULT_TYPE segp = segs+k;
 
                            if (segp->seg_sti == st_bit) {
@@ -623,9 +630,10 @@
                                break;
                            }
                        }
+                       // clear bit in mask
+                       mask &= ~(1 << (31 - lz));
+                   }
                        if (ret) break;
-                       lz++;
-                   }
                }
                stack[stackend++] = ret;
                break;
@@ -643,16 +651,17 @@
  */
 void build_regiontable(global struct bool_region *bregions, global union 
tree_rpn *rtree, RESULT_TYPE segs,
         global uint *segs_bv, global uint *regiontable, const uint pp_idx, 
const uint seg_idx,
-        const uint bv_index, const uint rt_index, const uint total_regions)
+        const uint bv_index, const uint rt_index, const uint total_regions, 
const size_t id)
 {
     RESULT_TYPE segp;
 
     /* Iterate over segments of partition */
     for (uint i = 0; i < bv_index; i++) {
-       uint lz = clz(segs_bv[pp_idx + (bv_index - 1) + i]);
-       while (lz != 32) {
+       uint mask = segs_bv[pp_idx * bv_index + i];
+       while (mask != 0) {
+               uint lz = clz(mask);
            uint k = seg_idx + (31 - lz);
-           if (isset(segs_bv, pp_idx + (bv_index - 1), k - seg_idx) != 0) {
+           if (isset(segs_bv, pp_idx * bv_index, k - seg_idx) != 0) {
                segp = segs+k;
 
                /* Search for all regions involved in this partition */
@@ -659,80 +668,145 @@
                for (uint m = 0; m < total_regions; m++) {
                    if (region_involved(bregions, rtree, m, segp->seg_sti)) {
                        /* Region involved */
-                       if (isset(regiontable, pp_idx + (rt_index - 1), m) != 
0) {
+                       if (isset(regiontable, id * rt_index, m) != 0) {
                            continue;
                        } else {
-                           set(regiontable, pp_idx + (rt_index - 1), m);
+                           set(regiontable, id * rt_index, m);
                        }
                    }
                }
            }
-           lz++;
+           // clear bit in mask
+               mask &= ~(1 << (31 - lz));
        }
     }
 }
 
 void
-rt_default_multioverlap(global struct bool_region *bregions, global uint 
*regiontable, const uint pp_idx, const uint total_regions)
+reset_regiontable(global uint *regiontable, const size_t id, const uint 
rt_index)
 {
+    for (uint k = 0; k < rt_index; k++) {
+        regiontable[id * rt_index + k] = 0;
+    }
+}
+
+int
+rt_defoverlap(global struct partition *partitions, const uint pp_idx, global 
struct bool_region *reg1,
+             const uint reg1_id, global struct bool_region *reg2, const uint 
reg2_id, const uint headpp_idx)
+{
+
+    global struct partition *pp;
+
+    /*
+     * Apply heuristics as to which region should claim partition.
+     */
+    if (reg1->reg_aircode != 0) {
+       /* reg1 was air, replace with reg2 */
+       return 2;
+    }
+
+    pp = &partitions[pp_idx];
+    if (pp->back_pp != headpp_idx) {
+       if (partitions[pp->back_pp].region_id == reg1_id)
+           return 1;
+       if (partitions[pp->back_pp].region_id == reg2_id)
+           return 2;
+    }
+
+    /* To provide some consistency from ray to ray, use lowest bit # */
+    if (reg1->reg_bit < reg2->reg_bit)
+       return 1;
+    return 2;
+}
+
+void
+rt_default_multioverlap(global struct partition *partitions, global struct 
bool_region *bregions, global uint *regiontable,
+                       const uint pp_idx, const uint total_regions, const uint 
headpp_idx, const size_t id)
+{
     global struct bool_region *lastregion;
-    int code;
-    uint i;
+    int code, ret;
 
     uint rt_index = total_regions/32 +1;
+       uint lastregion_id;
 
     // Get first region of the regiontable
-    for (i = 0; i < total_regions; i++) {
-       if (isset(regiontable, pp_idx + (rt_index - 1), i) != 0) {
-           lastregion = &bregions[i];
-           break;
+    for (uint i = 0; i < rt_index; i++) {
+       uint mask = regiontable[id * rt_index + i];
+       ret = 0;
+       while (mask != 0) {
+           uint lz = clz(mask);
+           uint k = (i * 32) + (31 - lz);
+           if (isset(regiontable, id * rt_index, k) != 0) {
+               lastregion = &bregions[k];
+               lastregion_id = k;
+               ret = 1;
+               break;
+           }
+           // clear bit in mask
+           mask &= ~(1 << (31 - lz));
        }
+       if (ret) break;
     }
 
     /* Examine the overlapping regions, pairwise */
-    for (uint j = i + 1; j < total_regions; j++) {
+    for (uint i = 0; i < rt_index; i++) {
+       uint mask = regiontable[id * rt_index + i];
+       while (mask != 0) {
+           uint lz = clz(mask);
+           uint k = (i * 32) + (31 - lz);
+           if (k != lastregion_id && isset(regiontable, id * rt_index, k) != 
0) {
+               global struct bool_region *regp;
+               regp = &bregions[k];
 
-       if (isset(regiontable, pp_idx + (rt_index - 1), j) != 0) {
-           global struct bool_region *regp;
-           regp = &bregions[j];
-
-           /*
-            * Two or more regions claim this partition
-            */
-           if (lastregion->reg_aircode != 0 && regp->reg_aircode == 0) {
-               /* last region is air, replace with solid regp */
-               code = 2;
-           } else if (lastregion->reg_aircode == 0 && regp->reg_aircode != 0) {
-               /* last region solid, regp is air, keep last */
-               code = 1;
-           } else if (lastregion->reg_aircode != 0 &&
-                   regp->reg_aircode != 0 &&
-                   regp->reg_aircode == lastregion->reg_aircode) {
-               /* both are same air, keep last */
-               code = 1;
-           }
-
-           /* Implement the policy in "code" */
-           switch (code) {
-               case 0:
+               code = -1;
+               /*
+                * Two or more regions claim this partition
+                */
+               if (lastregion->reg_aircode != 0 && regp->reg_aircode == 0) {
+                   /* last region is air, replace with solid regp */
+                   code = 2;
+               } else if (lastregion->reg_aircode == 0 && regp->reg_aircode != 
0) {
+                   /* last region solid, regp is air, keep last */
+                   code = 1;
+               } else if (lastregion->reg_aircode != 0 &&
+                          regp->reg_aircode != 0 &&
+                          regp->reg_aircode == lastregion->reg_aircode) {
+                   /* both are same air, keep last */
+                   code = 1;
+               } else {
                    /*
-                    * Destroy the whole partition.
-                    * Reset regiontable
+                    * Hand overlap to old-style application-specific
+                    * overlap handler, or default.
+                    * 0 = destroy partition,
+                    * 1 = keep part, claiming region=lastregion
+                    * 2 = keep part, claiming region=regp
                     */
-                   for (uint k = 0; k < rt_index; k++) {
-                       regiontable[k] = 0;
-                   }
-                   return;
-               case 1:
-                   /* Keep partition, claiming region = lastregion */
-                   clr(regiontable, pp_idx + (rt_index - 1), j);
-                   break;
-               case 2:
-                   /* Keep partition, claiming region = regp */
-                   lastregion = regp;
-                   clr(regiontable, pp_idx + (rt_index - 1), i);
-                   break;
+                   code = rt_defoverlap(partitions, pp_idx, lastregion, 
lastregion_id, regp, k, headpp_idx);
+               }
+
+               /* Implement the policy in "code" */
+               switch (code) {
+                   case 0:
+                       /*
+                        * Destroy the whole partition.
+                        * Reset regiontable
+                        */
+                       reset_regiontable(regiontable, id, rt_index);
+                       return;
+                   case 1:
+                       /* Keep partition, claiming region = lastregion */
+                       clr(regiontable, id * rt_index, k);
+                       break;
+                   case 2:
+                       /* Keep partition, claiming region = regp */
+                       clr(regiontable, id * rt_index, lastregion_id);
+                       lastregion = regp;
+                       lastregion_id = k;
+                       break;
+               }
            }
+           // clear bit in mask
+           mask &= ~(1 << (31 - lz));
        }
     }
 }
@@ -801,29 +875,37 @@
            }
        }
 
+       /* Start with a clean state when evaluating this partition */
+       reset_regiontable(regiontable, id, rt_index);
+
        /*
         * Build regiontable bitarray of all the regions involved in this
         * partitions to later evaluate the partitions against the involved
         * regions and to resolve any overlap that may occur
         */
-       build_regiontable(bregions, rtree, segs, segs_bv, regiontable, 
current_index, h[id], bv_index, rt_index, total_regions);
+       build_regiontable(bregions, rtree, segs, segs_bv, regiontable, 
current_index, h[id], bv_index, rt_index, total_regions, id);
 
        /* Evaluate the boolean trees of any regions involved */
-       for (uint i = 0; i < total_regions; i++) {
+       for (uint i = 0; i < rt_index; i++) {
+           uint mask = regiontable[id * rt_index + i];
+           while (mask != 0) {
+               uint lz = clz(mask);
+               uint k = (i * 32) + (31 - lz);
+               if (isset(regiontable, id * rt_index, k) != 0) {
 
-           if (isset(regiontable, current_index + (rt_index - 1), i) != 0) {
+                   if (bregions[k].reg_all_unions) {
+                       claiming_regions++;
+                       lastregion_idx = k;
+                   }
 
-               if (bregions[i].reg_all_unions) {
-                   claiming_regions++;
-                   lastregion_idx = i;
-                   continue;
+                   else if (bool_eval(partitions, ipartition, segs, h, 
segs_bv, bv_index, current_index, id, bregions, rtree, k) == BOOL_TRUE) {
+                       /* This region claims partition */
+                       claiming_regions++;
+                       lastregion_idx = k;
+                   }
                }
-
-               if (bool_eval(partitions, ipartition, segs, h, segs_bv, 
bv_index, current_index, id, bregions, rtree, i) == BOOL_TRUE) {
-                   /* This region claims partition */
-                   claiming_regions++;
-                   lastregion_idx = i;
-               }
+               // clear bit in mask
+               mask &= ~(1 << (31 - lz));
            }
        }
 
@@ -832,15 +914,22 @@
 
        if (claiming_regions > 1) {
            /* There is an overlap between two or more regions */
-           rt_default_multioverlap(bregions, regiontable, current_index, 
total_regions);
+           rt_default_multioverlap(partitions, bregions, regiontable, 
current_index, total_regions, head, id);
 
            /* Count number of remaining regions, s/b 0 or 1 */
            claiming_regions = 0;
-           for (uint i = 0; i < total_regions; i++) {
+           for (uint i = 0; i < rt_index; i++) {
+               uint mask = regiontable[id * rt_index + i];
+               while (mask != 0) {
+                   uint lz = clz(mask);
+                   uint k = (i * 32) + (31 - lz);
 
-               if (isset(regiontable, current_index + (rt_index - 1), i) != 0) 
{
-                   claiming_regions++;
-                   lastregion_idx = i;
+                   if (isset(regiontable, id * rt_index, k) != 0) {
+                       claiming_regions++;
+                       lastregion_idx = k;
+                   }
+                   // clear bit in mask
+                   mask &= ~(1 << (31 - lz));
                }
            }
 

Modified: brlcad/branches/opencl/src/librt/primitives/common.cl
===================================================================
--- brlcad/branches/opencl/src/librt/primitives/common.cl       2017-07-21 
19:08:00 UTC (rev 69980)
+++ brlcad/branches/opencl/src/librt/primitives/common.cl       2017-07-21 
19:46:08 UTC (rev 69981)
@@ -77,6 +77,7 @@
     uint rtree_offset;          /* index to the start of the rpn tree */
     uint reg_nrtree;            /* number of elements in rtree */
     int reg_aircode;            /* Region ID AIR code */
+    int reg_bit;                /* constant index into Regions[] */
     short reg_all_unions;       /* 1=boolean tree is all unions */
 };
 

Modified: brlcad/branches/opencl/src/librt/primitives/primitive_util.c
===================================================================
--- brlcad/branches/opencl/src/librt/primitives/primitive_util.c        
2017-07-21 19:08:00 UTC (rev 69980)
+++ brlcad/branches/opencl/src/librt/primitives/primitive_util.c        
2017-07-21 19:46:08 UTC (rev 69981)
@@ -1002,7 +1002,7 @@
                sz_bv = sizeof(cl_uint) * (h[npix]*2) * (max_depth/32 + 1); /* 
bitarray to represent the segs in each partition */
                bv = (cl_uint*)bu_calloc(1, sz_bv, "bv");
 
-               sz_regiontable = sizeof(cl_uint) * (h[npix]*2) * 
(clt_db_nregions/32 +1); /* bitarray to represent the regions involved in each 
partition */
+               sz_regiontable = sizeof(cl_uint) * npix * (clt_db_nregions/32 
+1); /* bitarray to represent the regions involved in each partition */
                regiontable = (cl_uint*)bu_calloc(1, sz_regiontable, 
"regiontable");
 
            bu_free(h, "h");

This was sent by the SourceForge.net collaborative development platform, the 
world's largest Open Source development site.


------------------------------------------------------------------------------
Check out the vibrant tech community on one of the world's most
engaging tech sites, Slashdot.org! http://sdm.link/slashdot
_______________________________________________
BRL-CAD Source Commits mailing list
brlcad-commits@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/brlcad-commits

Reply via email to