Added some test_break during the build process.
authorAndre Susano Pinto <andresusanopinto@gmail.com>
Sun, 4 Oct 2009 16:56:00 +0000 (16:56 +0000)
committerAndre Susano Pinto <andresusanopinto@gmail.com>
Sun, 4 Oct 2009 16:56:00 +0000 (16:56 +0000)
(Maybe later this should be done with some thread_cancel function instead of doing variable/callbacks tests)

source/blender/render/intern/include/rayobject.h
source/blender/render/intern/raytrace/rayobject.cpp
source/blender/render/intern/raytrace/rayobject_qbvh.cpp
source/blender/render/intern/raytrace/rayobject_rtbuild.cpp
source/blender/render/intern/raytrace/rayobject_rtbuild.h
source/blender/render/intern/raytrace/rayobject_svbvh.cpp
source/blender/render/intern/raytrace/rayobject_vbvh.cpp
source/blender/render/intern/raytrace/vbvh.h
source/blender/render/intern/source/rayshade.c

index 337f9ca3fddb0bc6a084faa0189625ea5f844412..9e35c0feac5c77859f66b09f73de2c4d0fc7f5a4 100644 (file)
@@ -93,6 +93,21 @@ extern "C" {
 #define RE_rayobject_isVlakPrimitive(o)        ((((intptr_t)o)&3) == 3)
 
 
+
+/*
+ * This class is intended as a place holder for control, configuration of the rayobject like:
+ *     - stop building (TODO maybe when porting build to threads this could be implemented with some thread_cancel function)
+ *  - max number of threads and threads callback to use during build
+ *     ...
+ */    
+typedef int  (*RE_rayobjectcontrol_test_break_callback)(void *data);
+typedef struct RayObjectControl RayObjectControl;
+struct RayObjectControl
+{
+       void *data;
+       RE_rayobjectcontrol_test_break_callback test_break;     
+};
+
 /*
  * This rayobject represents a generic object. With it's own callbacks for raytrace operations.
  * It's suitable to implement things like LOD.
@@ -100,9 +115,13 @@ extern "C" {
 struct RayObject
 {
        struct RayObjectAPI *api;
+
+       struct RayObjectControl control;
 };
 
 
+
+
 typedef int  (*RE_rayobject_raycast_callback)(RayObject *, Isect *);
 typedef void (*RE_rayobject_add_callback)(RayObject *raytree, RayObject *rayobject);
 typedef void (*RE_rayobject_done_callback)(RayObject *);
@@ -144,6 +163,11 @@ int RE_rayobject_bb_intersect_test(const Isect *i, const float *bb); /* same as
 float RE_rayobject_cost(RayObject *r);
 
 
+/*
+ * Returns true if for some reason a heavy processing function should stop
+ * (eg.: user asked to stop during a tree a build)
+ */
+int RE_rayobjectcontrol_test_break(RayObjectControl *c);
 
 
 #define ISECT_EPSILON ((float)FLT_EPSILON)
index 34faa2951ceff995da481d033ccf952d0f2cec5f..95387cf1ee442e8fab3022bcad5cfba78094b0d2 100644 (file)
@@ -528,3 +528,10 @@ void RE_rayobject_hint_bb(RayObject *r, RayHint *hint, float *min, float *max)
        else assert(0);
 }
 
+int RE_rayobjectcontrol_test_break(RayObjectControl *control)
+{
+       if(control->test_break)
+               return control->test_break( control->data );
+
+       return 0;
+}
index 59daf9dc9624d50134a4bbbf3f46df2e8e29ebbb..b18ee0824cfe9d30b893c4993477a655ef58de07 100644 (file)
@@ -47,7 +47,7 @@ struct QBVHTree
 template<>
 void bvh_done<QBVHTree>(QBVHTree *obj)
 {
-       rtbuild_done(obj->builder);
+       rtbuild_done(obj->builder, &obj->rayobj.control);
        
        //TODO find a away to exactly calculate the needed memory
        MemArena *arena1 = BLI_memarena_new(BLI_MEMARENA_STD_BUFSIZE);
@@ -59,7 +59,15 @@ void bvh_done<QBVHTree>(QBVHTree *obj)
 
        //Build and optimize the tree   
        //TODO do this in 1 pass (half memory usage during building)    
-       VBVHNode *root = BuildBinaryVBVH<VBVHNode>(arena1).transform(obj->builder);     
+       VBVHNode *root = BuildBinaryVBVH<VBVHNode>(arena1, &obj->rayobj.control).transform(obj->builder);       
+       
+       if(RE_rayobjectcontrol_test_break(&obj->rayobj.control))
+       {
+               BLI_memarena_free(arena1);
+               BLI_memarena_free(arena2);
+               return;
+       }
+       
        pushup_simd<VBVHNode,4>(root);                                     
        obj->root = Reorganize_SVBVH<VBVHNode>(arena2).transform(root);
        
index 430045b56b66a47f0a13beec2bbcda4d2695793a..9523e72589396fd4b9acfc6199b6f47985239b81 100644 (file)
@@ -130,11 +130,14 @@ static void object_sort(Item *begin, Item *end, int axis)
        assert(false);
 }
 
-void rtbuild_done(RTBuilder *b)
+void rtbuild_done(RTBuilder *b, RayObjectControl* ctrl)
 {
        for(int i=0; i<3; i++)
        if(b->sorted_begin[i])
+       {
+               if(RE_rayobjectcontrol_test_break(ctrl)) break;
                object_sort( b->sorted_begin[i], b->sorted_end[i], i );
+       }
 }
 
 RayObject* rtbuild_get_primitive(RTBuilder *b, int index)
index 8f471f095e22c0b468e534ef77d40d749c75afae..71665681586d08965906fa9f3333e61c503487fe 100644 (file)
@@ -85,7 +85,7 @@ typedef struct RTBuilder
 RTBuilder* rtbuild_create(int size);
 void rtbuild_free(RTBuilder *b);
 void rtbuild_add(RTBuilder *b, RayObject *o);
-void rtbuild_done(RTBuilder *b);
+void rtbuild_done(RTBuilder *b, RayObjectControl *c);
 void rtbuild_merge_bb(RTBuilder *b, float *min, float *max);
 int rtbuild_size(RTBuilder *b);
 
index f806fcf93ef791949e50d69dc7b28a292d752a5d..229e82dfa68511b8cbfabb69667ad6fff0338c00 100644 (file)
@@ -58,7 +58,7 @@ struct PackCost
 template<>
 void bvh_done<SVBVHTree>(SVBVHTree *obj)
 {
-       rtbuild_done(obj->builder);
+       rtbuild_done(obj->builder, &obj->rayobj.control);
        
        //TODO find a away to exactly calculate the needed memory
        MemArena *arena1 = BLI_memarena_new(BLI_MEMARENA_STD_BUFSIZE);
@@ -71,7 +71,14 @@ void bvh_done<SVBVHTree>(SVBVHTree *obj)
        //Build and optimize the tree
        if(0)
        {
-               VBVHNode *root = BuildBinaryVBVH<VBVHNode>(arena1).transform(obj->builder);
+               VBVHNode *root = BuildBinaryVBVH<VBVHNode>(arena1,&obj->rayobj.control).transform(obj->builder);
+               if(RE_rayobjectcontrol_test_break(&obj->rayobj.control))
+               {
+                       BLI_memarena_free(arena1);
+                       BLI_memarena_free(arena2);
+                       return;
+               }
+               
                reorganize(root);
                remove_useless(root, &root);
                bvh_refit(root);
@@ -86,7 +93,14 @@ void bvh_done<SVBVHTree>(SVBVHTree *obj)
        {
                //Finds the optimal packing of this tree using a given cost model
                //TODO this uses quite a lot of memory, find ways to reduce memory usage during building
-               OVBVHNode *root = BuildBinaryVBVH<OVBVHNode>(arena1).transform(obj->builder);                   
+               OVBVHNode *root = BuildBinaryVBVH<OVBVHNode>(arena1,&obj->rayobj.control).transform(obj->builder);                      
+               if(RE_rayobjectcontrol_test_break(&obj->rayobj.control))
+               {
+                       BLI_memarena_free(arena1);
+                       BLI_memarena_free(arena2);
+                       return;
+               }
+
                VBVH_optimalPackSIMD<OVBVHNode,PackCost>(PackCost()).transform(root);
                obj->root = Reorganize_SVBVH<OVBVHNode>(arena2).transform(root);
        }
index 5260abf67aed3c347a110283b7e610cc416ee062..11f04c04141bfbfc9289f536ab1313f234e41d42 100644 (file)
@@ -72,7 +72,7 @@ struct PackCost
 template<>
 void bvh_done<VBVHTree>(VBVHTree *obj)
 {
-       rtbuild_done(obj->builder);
+       rtbuild_done(obj->builder, &obj->rayobj.control);
        
        //TODO find a away to exactly calculate the needed memory
        MemArena *arena1 = BLI_memarena_new(BLI_MEMARENA_STD_BUFSIZE);
@@ -81,7 +81,12 @@ void bvh_done<VBVHTree>(VBVHTree *obj)
        //Build and optimize the tree
        if(1)
        {
-               VBVHNode *root = BuildBinaryVBVH<VBVHNode>(arena1).transform(obj->builder);
+               VBVHNode *root = BuildBinaryVBVH<VBVHNode>(arena1,&obj->rayobj.control).transform(obj->builder);
+               if(RE_rayobjectcontrol_test_break(&obj->rayobj.control))
+               {
+                       BLI_memarena_free(arena1);
+                       return;
+               }
 
                reorganize(root);
                remove_useless(root, &root);
index db1df43f6650dfd2ffb4b7c99afba8eb755e9083..1ff51786e52f160871ffe045c8c42e50e9351ae1 100644 (file)
@@ -107,10 +107,18 @@ template<class Node>
 struct BuildBinaryVBVH
 {
        MemArena *arena;
+       RayObjectControl *control;
 
-       BuildBinaryVBVH(MemArena *a)
+       void test_break()
+       {
+               if(RE_rayobjectcontrol_test_break(control))
+                       throw "Stop";
+       }
+
+       BuildBinaryVBVH(MemArena *a, RayObjectControl *c)
        {
                arena = a;
+               control = c;
        }
 
        Node *create_node()
@@ -130,6 +138,18 @@ struct BuildBinaryVBVH
        }
        
        Node *transform(RTBuilder *builder)
+       {
+               try
+               {
+                       return _transform(builder);
+                       
+               } catch(...)
+               {
+               }
+               return NULL;
+       }
+       
+       Node *_transform(RTBuilder *builder)
        {
                
                int size = rtbuild_size(builder);
@@ -143,6 +163,8 @@ struct BuildBinaryVBVH
                }
                else
                {
+                       test_break();
+                       
                        Node *node = create_node();
 
                        INIT_MINMAX(node->bb, node->bb+3);
@@ -157,7 +179,7 @@ struct BuildBinaryVBVH
                                RTBuilder tmp;
                                rtbuild_get_child(builder, i, &tmp);
                                
-                               *child = transform(&tmp);
+                               *child = _transform(&tmp);
                                child = &((*child)->sibling);
                        }
 
index 641085d8cd6c2bc5c4b26c0b2b02918407b3ffd7..9ef8aa3aba29e18301e29375bf2772c210408efc 100644 (file)
 /* only to be used here in this file, it's for speed */
 extern struct Render R;
 /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
-RayObject *  RE_rayobject_create(int type, int size)
+static int test_break(void *data)
 {
+       Render *re = (Render*)data;
+       return re->test_break(re->tbh);
+}
+
+static RE_rayobject_config_control(RayObject *r, Render *re)
+{
+       if(RE_rayobject_isRayAPI(r))
+       {
+               r = RE_rayobject_align( r );
+               r->control.data = re;
+               r->control.test_break = test_break;
+       }
+}
+
+RayObject*  RE_rayobject_create(Render *re, int type, int size)
+{
+       RayObject * res = NULL;
+
        if(type == R_RAYSTRUCTURE_AUTO)
        {
                //TODO
@@ -83,30 +101,21 @@ RayObject *  RE_rayobject_create(int type, int size)
                //      type = R_RAYSTRUCTURE_VBVH;
        }
                
-       if(type == R_RAYSTRUCTURE_OCTREE)
-       {
-               //TODO dynamic ocres
-               return RE_rayobject_octree_create(R.r.ocres, size);
-       }
-       if(type == R_RAYSTRUCTURE_BLIBVH)
-       {
-               return RE_rayobject_blibvh_create(size);
-       }
-       if(type == R_RAYSTRUCTURE_VBVH)
-       {
-               return RE_rayobject_vbvh_create(size);
-       }
-       if(type == R_RAYSTRUCTURE_SIMD_SVBVH)
-       {
-               return RE_rayobject_svbvh_create(size);
-       }
-       if(type == R_RAYSTRUCTURE_SIMD_QBVH)
-       {
-               return RE_rayobject_qbvh_create(size);
-       }
-       assert( NULL );
+       if(type == R_RAYSTRUCTURE_OCTREE) //TODO dynamic ocres
+               res = RE_rayobject_octree_create(re->r.ocres, size);
+       else if(type == R_RAYSTRUCTURE_BLIBVH)
+               res = RE_rayobject_blibvh_create(size);
+       else if(type == R_RAYSTRUCTURE_VBVH)
+               res = RE_rayobject_vbvh_create(size);
+       else if(type == R_RAYSTRUCTURE_SIMD_SVBVH)
+               res = RE_rayobject_svbvh_create(size);
+       else if(type == R_RAYSTRUCTURE_SIMD_QBVH)
+               res = RE_rayobject_qbvh_create(size);
+       
+       if(res)
+               RE_rayobject_config_control( res, re );
        
-       return NULL;
+       return res;
 }
 
 #ifdef RE_RAYCOUNTER
@@ -217,7 +226,7 @@ RayObject* makeraytree_object(Render *re, ObjectInstanceRen *obi)
                assert( faces > 0 );
 
                //Create Ray cast accelaration structure                
-               raytree = obr->raytree = RE_rayobject_create( re->r.raytrace_structure, faces );
+               raytree = obr->raytree = RE_rayobject_create( re,  re->r.raytrace_structure, faces );
                if(  (re->r.raytrace_options & R_RAYTRACE_USE_LOCAL_COORDS) )
                        vlakprimitive = obr->rayprimitives = (VlakPrimitive*)MEM_callocN(faces*sizeof(VlakPrimitive), "ObjectRen primitives");
                else
@@ -311,7 +320,7 @@ static void makeraytree_single(Render *re)
        }
        
        //Create raytree
-       raytree = re->raytree = RE_rayobject_create( re->r.raytrace_structure, faces+special );
+       raytree = re->raytree = RE_rayobject_create( re, re->r.raytrace_structure, faces+special );
 
        if( (re->r.raytrace_options & R_RAYTRACE_USE_LOCAL_COORDS) )
        {
@@ -325,6 +334,9 @@ static void makeraytree_single(Render *re)
        for(obi=re->instancetable.first; obi; obi=obi->next)
        if(is_raytraceable(re, obi))
        {
+               if(test_break(re))
+                       break;
+
                if(has_special_rayobject(re, obi))
                {
                        RayObject *obj = makeraytree_object(re, obi);
@@ -371,10 +383,13 @@ static void makeraytree_single(Render *re)
                }
        }
        
-       re->i.infostr= "Raytree.. building";
-       re->stats_draw(re->sdh, &re->i);
+       if(!test_break(re))
+       {       
+               re->i.infostr= "Raytree.. building";
+               re->stats_draw(re->sdh, &re->i);
 
-       RE_rayobject_done( raytree );   
+               RE_rayobject_done( raytree );   
+       }
 }
 
 void makeraytree(Render *re)
@@ -391,20 +406,29 @@ void makeraytree(Render *re)
                re->r.raytrace_options &= ~( R_RAYTRACE_USE_INSTANCES | R_RAYTRACE_USE_LOCAL_COORDS);
 
        BENCH(makeraytree_single(re), tree_build);
-               
-       //Calculate raytree max_size
-       //This is ONLY needed to kept a bogus behaviour of SUN and HEMI lights
-       RE_rayobject_merge_bb( re->raytree, min, max );
-       for(i=0; i<3; i++)
+       if(test_break(re))
        {
-               min[i] += 0.01f;
-               max[i] += 0.01f;
-               sub[i] = max[i]-min[i];
+               freeraytree(re);
+
+               re->i.infostr= "Raytree building canceled";
+               re->stats_draw(re->sdh, &re->i);
        }
-       re->maxdist = sqrt( sub[0]*sub[0] + sub[1]*sub[1] + sub[2]*sub[2] );
+       else
+       {
+               //Calculate raytree max_size
+               //This is ONLY needed to kept a bogus behaviour of SUN and HEMI lights
+               RE_rayobject_merge_bb( re->raytree, min, max );
+               for(i=0; i<3; i++)
+               {
+                       min[i] += 0.01f;
+                       max[i] += 0.01f;
+                       sub[i] = max[i]-min[i];
+               }
+               re->maxdist = sqrt( sub[0]*sub[0] + sub[1]*sub[1] + sub[2]*sub[2] );
 
-       re->i.infostr= "Raytree finished";
-       re->stats_draw(re->sdh, &re->i);
+               re->i.infostr= "Raytree finished";
+               re->stats_draw(re->sdh, &re->i);
+       }
 }
 
 void shade_ray(Isect *is, ShadeInput *shi, ShadeResult *shr)