From 55541d8a8143b97ce0d452caf4ececa8903c31a0 Mon Sep 17 00:00:00 2001 From: Andre Susano Pinto Date: Sun, 4 Oct 2009 16:56:00 +0000 Subject: Added some test_break during the build process. (Maybe later this should be done with some thread_cancel function instead of doing variable/callbacks tests) --- source/blender/render/intern/include/rayobject.h | 24 +++++ .../blender/render/intern/raytrace/rayobject.cpp | 7 ++ .../render/intern/raytrace/rayobject_qbvh.cpp | 12 ++- .../render/intern/raytrace/rayobject_rtbuild.cpp | 5 +- .../render/intern/raytrace/rayobject_rtbuild.h | 2 +- .../render/intern/raytrace/rayobject_svbvh.cpp | 20 +++- .../render/intern/raytrace/rayobject_vbvh.cpp | 9 +- source/blender/render/intern/raytrace/vbvh.h | 26 +++++- source/blender/render/intern/source/rayshade.c | 104 +++++++++++++-------- 9 files changed, 158 insertions(+), 51 deletions(-) (limited to 'source/blender/render/intern') diff --git a/source/blender/render/intern/include/rayobject.h b/source/blender/render/intern/include/rayobject.h index 337f9ca3fdd..9e35c0feac5 100644 --- a/source/blender/render/intern/include/rayobject.h +++ b/source/blender/render/intern/include/rayobject.h @@ -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) diff --git a/source/blender/render/intern/raytrace/rayobject.cpp b/source/blender/render/intern/raytrace/rayobject.cpp index 34faa2951ce..95387cf1ee4 100644 --- a/source/blender/render/intern/raytrace/rayobject.cpp +++ b/source/blender/render/intern/raytrace/rayobject.cpp @@ -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; +} diff --git a/source/blender/render/intern/raytrace/rayobject_qbvh.cpp b/source/blender/render/intern/raytrace/rayobject_qbvh.cpp index 59daf9dc962..b18ee0824cf 100644 --- a/source/blender/render/intern/raytrace/rayobject_qbvh.cpp +++ b/source/blender/render/intern/raytrace/rayobject_qbvh.cpp @@ -47,7 +47,7 @@ struct QBVHTree template<> void bvh_done(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 *obj) //Build and optimize the tree //TODO do this in 1 pass (half memory usage during building) - VBVHNode *root = BuildBinaryVBVH(arena1).transform(obj->builder); + VBVHNode *root = BuildBinaryVBVH(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(root); obj->root = Reorganize_SVBVH(arena2).transform(root); diff --git a/source/blender/render/intern/raytrace/rayobject_rtbuild.cpp b/source/blender/render/intern/raytrace/rayobject_rtbuild.cpp index 430045b56b6..9523e725893 100644 --- a/source/blender/render/intern/raytrace/rayobject_rtbuild.cpp +++ b/source/blender/render/intern/raytrace/rayobject_rtbuild.cpp @@ -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) diff --git a/source/blender/render/intern/raytrace/rayobject_rtbuild.h b/source/blender/render/intern/raytrace/rayobject_rtbuild.h index 8f471f095e2..71665681586 100644 --- a/source/blender/render/intern/raytrace/rayobject_rtbuild.h +++ b/source/blender/render/intern/raytrace/rayobject_rtbuild.h @@ -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); diff --git a/source/blender/render/intern/raytrace/rayobject_svbvh.cpp b/source/blender/render/intern/raytrace/rayobject_svbvh.cpp index f806fcf93ef..229e82dfa68 100644 --- a/source/blender/render/intern/raytrace/rayobject_svbvh.cpp +++ b/source/blender/render/intern/raytrace/rayobject_svbvh.cpp @@ -58,7 +58,7 @@ struct PackCost template<> void bvh_done(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 *obj) //Build and optimize the tree if(0) { - VBVHNode *root = BuildBinaryVBVH(arena1).transform(obj->builder); + VBVHNode *root = BuildBinaryVBVH(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 *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(arena1).transform(obj->builder); + OVBVHNode *root = BuildBinaryVBVH(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(PackCost()).transform(root); obj->root = Reorganize_SVBVH(arena2).transform(root); } diff --git a/source/blender/render/intern/raytrace/rayobject_vbvh.cpp b/source/blender/render/intern/raytrace/rayobject_vbvh.cpp index 5260abf67ae..11f04c04141 100644 --- a/source/blender/render/intern/raytrace/rayobject_vbvh.cpp +++ b/source/blender/render/intern/raytrace/rayobject_vbvh.cpp @@ -72,7 +72,7 @@ struct PackCost template<> void bvh_done(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 *obj) //Build and optimize the tree if(1) { - VBVHNode *root = BuildBinaryVBVH(arena1).transform(obj->builder); + VBVHNode *root = BuildBinaryVBVH(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); diff --git a/source/blender/render/intern/raytrace/vbvh.h b/source/blender/render/intern/raytrace/vbvh.h index db1df43f665..1ff51786e52 100644 --- a/source/blender/render/intern/raytrace/vbvh.h +++ b/source/blender/render/intern/raytrace/vbvh.h @@ -107,10 +107,18 @@ template 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); } diff --git a/source/blender/render/intern/source/rayshade.c b/source/blender/render/intern/source/rayshade.c index 641085d8cd6..9ef8aa3aba2 100644 --- a/source/blender/render/intern/source/rayshade.c +++ b/source/blender/render/intern/source/rayshade.c @@ -72,8 +72,26 @@ /* 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) -- cgit v1.2.3