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)
This commit is contained in:
@@ -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)
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
return NULL;
|
||||
if(res)
|
||||
RE_rayobject_config_control( res, re );
|
||||
|
||||
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];
|
||||
}
|
||||
re->maxdist = sqrt( sub[0]*sub[0] + sub[1]*sub[1] + sub[2]*sub[2] );
|
||||
freeraytree(re);
|
||||
|
||||
re->i.infostr= "Raytree finished";
|
||||
re->stats_draw(re->sdh, &re->i);
|
||||
re->i.infostr= "Raytree building canceled";
|
||||
re->stats_draw(re->sdh, &re->i);
|
||||
}
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
void shade_ray(Isect *is, ShadeInput *shi, ShadeResult *shr)
|
||||
|
||||
Reference in New Issue
Block a user