diff options
author | Julian Eisel <eiseljulian@gmail.com> | 2015-10-21 18:30:35 +0300 |
---|---|---|
committer | Julian Eisel <eiseljulian@gmail.com> | 2015-10-21 18:30:35 +0300 |
commit | 0775680e4d05eda3c495a56dc0b6eafbe96dc586 (patch) | |
tree | 4f3286eef96dec6ababe43467ed2a4f50388b988 /intern/cycles/bvh | |
parent | 4ade467fc6adfc13ce9e21d7e50b366fce70ea5f (diff) | |
parent | 6bc007610263c879f6bb30b844ba9d9a0fb9433c (diff) |
Merge branch 'master' into UI-graphical-redesignUI-graphical-redesign
Conflicts:
source/blender/blenkernel/BKE_blender.h
source/blender/blenloader/intern/versioning_270.c
source/blender/editors/interface/interface.c
source/blender/editors/interface/interface_handlers.c
source/blender/editors/interface/interface_intern.h
source/blender/editors/interface/resources.c
Diffstat (limited to 'intern/cycles/bvh')
-rw-r--r-- | intern/cycles/bvh/bvh.cpp | 126 | ||||
-rw-r--r-- | intern/cycles/bvh/bvh.h | 9 | ||||
-rw-r--r-- | intern/cycles/bvh/bvh_binning.cpp | 6 | ||||
-rw-r--r-- | intern/cycles/bvh/bvh_build.cpp | 18 | ||||
-rw-r--r-- | intern/cycles/bvh/bvh_params.h | 4 | ||||
-rw-r--r-- | intern/cycles/bvh/bvh_split.cpp | 237 | ||||
-rw-r--r-- | intern/cycles/bvh/bvh_split.h | 53 |
7 files changed, 249 insertions, 204 deletions
diff --git a/intern/cycles/bvh/bvh.cpp b/intern/cycles/bvh/bvh.cpp index 350ca16f6e2..4a5f8b1bda6 100644 --- a/intern/cycles/bvh/bvh.cpp +++ b/intern/cycles/bvh/bvh.cpp @@ -25,7 +25,6 @@ #include "bvh_node.h" #include "bvh_params.h" -#include "util_cache.h" #include "util_debug.h" #include "util_foreach.h" #include "util_logging.h" @@ -70,125 +69,12 @@ BVH *BVH::create(const BVHParams& params, const vector<Object*>& objects) return new RegularBVH(params, objects); } -/* Cache */ - -bool BVH::cache_read(CacheData& key) -{ - key.add(system_cpu_bits()); - key.add(¶ms, sizeof(params)); - - foreach(Object *ob, objects) { - Mesh *mesh = ob->mesh; - - key.add(mesh->verts); - key.add(mesh->triangles); - key.add(mesh->curve_keys); - key.add(mesh->curves); - key.add(&ob->bounds, sizeof(ob->bounds)); - key.add(&ob->visibility, sizeof(ob->visibility)); - key.add(&mesh->transform_applied, sizeof(bool)); - - if(mesh->use_motion_blur) { - Attribute *attr = mesh->attributes.find(ATTR_STD_MOTION_VERTEX_POSITION); - if(attr) - key.add(attr->buffer); - - attr = mesh->curve_attributes.find(ATTR_STD_MOTION_VERTEX_POSITION); - if(attr) - key.add(attr->buffer); - } - } - - CacheData value; - - if(Cache::global.lookup(key, value)) { - cache_filename = key.get_filename(); - - if(!(value.read(pack.root_index) && - value.read(pack.SAH) && - value.read(pack.nodes) && - value.read(pack.leaf_nodes) && - value.read(pack.object_node) && - value.read(pack.tri_woop) && - value.read(pack.prim_type) && - value.read(pack.prim_visibility) && - value.read(pack.prim_index) && - value.read(pack.prim_object))) - { - /* Clear the pack if load failed. */ - pack.root_index = 0; - pack.SAH = 0.0f; - pack.nodes.clear(); - pack.leaf_nodes.clear(); - pack.object_node.clear(); - pack.tri_woop.clear(); - pack.prim_type.clear(); - pack.prim_visibility.clear(); - pack.prim_index.clear(); - pack.prim_object.clear(); - return false; - } - return true; - } - - return false; -} - -void BVH::cache_write(CacheData& key) -{ - CacheData value; - - value.add(pack.root_index); - value.add(pack.SAH); - - value.add(pack.nodes); - value.add(pack.leaf_nodes); - value.add(pack.object_node); - value.add(pack.tri_woop); - value.add(pack.prim_type); - value.add(pack.prim_visibility); - value.add(pack.prim_index); - value.add(pack.prim_object); - - Cache::global.insert(key, value); - - cache_filename = key.get_filename(); -} - -void BVH::clear_cache_except() -{ - set<string> except; - - if(!cache_filename.empty()) - except.insert(cache_filename); - - foreach(Object *ob, objects) { - Mesh *mesh = ob->mesh; - BVH *bvh = mesh->bvh; - - if(bvh && !bvh->cache_filename.empty()) - except.insert(bvh->cache_filename); - } - - Cache::global.clear_except("bvh", except); -} - /* Building */ void BVH::build(Progress& progress) { progress.set_substatus("Building BVH"); - /* cache read */ - CacheData key("bvh"); - - if(params.use_cache) { - progress.set_substatus("Looking in BVH cache"); - - if(cache_read(key)) - return; - } - /* build nodes */ BVHBuild bvh_build(objects, pack.prim_type, @@ -227,18 +113,6 @@ void BVH::build(Progress& progress) /* free build nodes */ root->deleteSubtree(); - - if(progress.get_cancel()) return; - - /* cache write */ - if(params.use_cache) { - progress.set_substatus("Writing BVH cache"); - cache_write(key); - - /* clear other bvh files from cache */ - if(params.top_level) - clear_cache_except(); - } } /* Refitting */ diff --git a/intern/cycles/bvh/bvh.h b/intern/cycles/bvh/bvh.h index 669d2ccdcd5..272a3fa1514 100644 --- a/intern/cycles/bvh/bvh.h +++ b/intern/cycles/bvh/bvh.h @@ -20,7 +20,6 @@ #include "bvh_params.h" -#include "util_string.h" #include "util_types.h" #include "util_vector.h" @@ -30,7 +29,6 @@ class BVHNode; struct BVHStackEntry; class BVHParams; class BoundBox; -class CacheData; class LeafNode; class Object; class Progress; @@ -87,7 +85,6 @@ public: PackedBVH pack; BVHParams params; vector<Object*> objects; - string cache_filename; static BVH *create(const BVHParams& params, const vector<Object*>& objects); virtual ~BVH() {} @@ -95,15 +92,9 @@ public: void build(Progress& progress); void refit(Progress& progress); - void clear_cache_except(); - protected: BVH(const BVHParams& params, const vector<Object*>& objects); - /* cache */ - bool cache_read(CacheData& key); - void cache_write(CacheData& key); - /* triangles and strands*/ void pack_primitives(); void pack_triangle(int idx, float4 woop[3]); diff --git a/intern/cycles/bvh/bvh_binning.cpp b/intern/cycles/bvh/bvh_binning.cpp index db96490a36f..8745e39c21e 100644 --- a/intern/cycles/bvh/bvh_binning.cpp +++ b/intern/cycles/bvh/bvh_binning.cpp @@ -76,8 +76,8 @@ BVHObjectBinning::BVHObjectBinning(const BVHRange& job, BVHReference *prims) prefetch_L2(&prims[start() + i + 8]); /* map even and odd primitive to bin */ - BVHReference prim0 = prims[start() + i + 0]; - BVHReference prim1 = prims[start() + i + 1]; + const BVHReference& prim0 = prims[start() + i + 0]; + const BVHReference& prim1 = prims[start() + i + 1]; int4 bin0 = get_bin(prim0.bounds()); int4 bin1 = get_bin(prim1.bounds()); @@ -96,7 +96,7 @@ BVHObjectBinning::BVHObjectBinning(const BVHRange& job, BVHReference *prims) /* for uneven number of primitives */ if(i < ssize_t(size())) { /* map primitive to bin */ - BVHReference prim0 = prims[start() + i]; + const BVHReference& prim0 = prims[start() + i]; int4 bin0 = get_bin(prim0.bounds()); /* increase bounds of bins */ diff --git a/intern/cycles/bvh/bvh_build.cpp b/intern/cycles/bvh/bvh_build.cpp index a44ad656316..45b0aaa2d63 100644 --- a/intern/cycles/bvh/bvh_build.cpp +++ b/intern/cycles/bvh/bvh_build.cpp @@ -234,8 +234,14 @@ BVHNode* BVHBuild::run() return NULL; /* init spatial splits */ - if(params.top_level) /* todo: get rid of this */ + if(params.top_level) { + /* NOTE: Technically it is supported by the builder but it's not really + * optimized for speed yet and not really clear yet if it has measurable + * improvement on render time. Needs some extra investigation before + * enabling spatial split for top level BVH. + */ params.use_spatial_split = false; + } spatial_min_overlap = root.bounds().safe_area() * params.spatial_split_alpha; spatial_right_bounds.clear(); @@ -276,6 +282,8 @@ BVHNode* BVHBuild::run() else if(!params.use_spatial_split) { /*rotate(rootnode, 4, 5);*/ rootnode->update_visibility(); + } + if(rootnode != NULL) { VLOG(1) << "BVH build statistics:\n" << " Build time: " << time_dt() - build_start_time << "\n" << " Total number of nodes: " @@ -525,11 +533,9 @@ BVHNode* BVHBuild::create_leaf_node(const BVHRange& range) /* Extend an array when needed. */ if(prim_type.size() < range.end()) { assert(params.use_spatial_split); - /* TODO(sergey): We might want to look into different policies of - * re-allocation here, so on the one hand we would not do as much - * re-allocations and on the other hand will have small memory - * overhead. - */ + prim_type.reserve(references.size()); + prim_index.reserve(references.size()); + prim_object.reserve(references.size()); prim_type.resize(range.end()); prim_index.resize(range.end()); prim_object.resize(range.end()); diff --git a/intern/cycles/bvh/bvh_params.h b/intern/cycles/bvh/bvh_params.h index af8d8eeb3ee..faa995c3f29 100644 --- a/intern/cycles/bvh/bvh_params.h +++ b/intern/cycles/bvh/bvh_params.h @@ -43,9 +43,6 @@ public: /* object or mesh level bvh */ bool top_level; - /* disk cache */ - bool use_cache; - /* QBVH */ bool use_qbvh; @@ -71,7 +68,6 @@ public: max_curve_leaf_size = 2; top_level = false; - use_cache = false; use_qbvh = false; } diff --git a/intern/cycles/bvh/bvh_split.cpp b/intern/cycles/bvh/bvh_split.cpp index 2290c4143ad..534c1aa73b5 100644 --- a/intern/cycles/bvh/bvh_split.cpp +++ b/intern/cycles/bvh/bvh_split.cpp @@ -191,11 +191,16 @@ void BVHSpatialSplit::split(BVHBuild *builder, BVHRange& left, BVHRange& right, } } - /* duplicate or unsplit references intersecting both sides. */ + /* Duplicate or unsplit references intersecting both sides. + * + * Duplication happens into a temporary pre-allocated vector in order to + * reduce number of memmove() calls happening in vector.insert(). + */ + vector<BVHReference> new_refs; + new_refs.reserve(right_start - left_end); while(left_end < right_start) { /* split reference. */ BVHReference lref, rref; - split_reference(builder, lref, rref, refs[left_end], this->dim, this->pos); /* compute SAH for duplicate/unsplit candidates. */ @@ -234,61 +239,36 @@ void BVHSpatialSplit::split(BVHBuild *builder, BVHRange& left, BVHRange& right, left_bounds = ldb; right_bounds = rdb; refs[left_end++] = lref; - refs.insert(refs.begin() + right_end, rref); + new_refs.push_back(rref); right_end++; } } - + /* Insert duplicated references into actual array in one go. */ + if(new_refs.size() != 0) { + refs.insert(refs.begin() + right_end - new_refs.size(), + new_refs.begin(), + new_refs.end()); + } left = BVHRange(left_bounds, left_start, left_end - left_start); right = BVHRange(right_bounds, right_start, right_end - right_start); } -void BVHSpatialSplit::split_reference(BVHBuild *builder, BVHReference& left, BVHReference& right, const BVHReference& ref, int dim, float pos) +void BVHSpatialSplit::split_triangle_primitive(const Mesh *mesh, + const Transform *tfm, + int prim_index, + int dim, + float pos, + BoundBox& left_bounds, + BoundBox& right_bounds) { - /* initialize boundboxes */ - BoundBox left_bounds = BoundBox::empty; - BoundBox right_bounds = BoundBox::empty; - - /* loop over vertices/edges. */ - Object *ob = builder->objects[ref.prim_object()]; - const Mesh *mesh = ob->mesh; - - if(ref.prim_type() & PRIMITIVE_ALL_TRIANGLE) { - const int *inds = mesh->triangles[ref.prim_index()].v; - const float3 *verts = &mesh->verts[0]; - const float3* v1 = &verts[inds[2]]; - - for(int i = 0; i < 3; i++) { - const float3* v0 = v1; - int vindex = inds[i]; - v1 = &verts[vindex]; - float v0p = (*v0)[dim]; - float v1p = (*v1)[dim]; - - /* insert vertex to the boxes it belongs to. */ - if(v0p <= pos) - left_bounds.grow(*v0); - - if(v0p >= pos) - right_bounds.grow(*v0); - - /* edge intersects the plane => insert intersection to both boxes. */ - if((v0p < pos && v1p > pos) || (v0p > pos && v1p < pos)) { - float3 t = lerp(*v0, *v1, clamp((pos - v0p) / (v1p - v0p), 0.0f, 1.0f)); - left_bounds.grow(t); - right_bounds.grow(t); - } - } - } - else { - /* curve split: NOTE - Currently ignores curve width and needs to be fixed.*/ - const int k0 = mesh->curves[ref.prim_index()].first_key + PRIMITIVE_UNPACK_SEGMENT(ref.prim_type()); - const int k1 = k0 + 1; - const float4 key0 = mesh->curve_keys[k0]; - const float4 key1 = mesh->curve_keys[k1]; - const float3 v0 = float4_to_float3(key0); - const float3 v1 = float4_to_float3(key1); - + const int *inds = mesh->triangles[prim_index].v; + const float3 *verts = &mesh->verts[0]; + float3 v1 = tfm ? transform_point(tfm, verts[inds[2]]) : verts[inds[2]]; + + for(int i = 0; i < 3; i++) { + float3 v0 = v1; + int vindex = inds[i]; + v1 = tfm ? transform_point(tfm, verts[vindex]) : verts[vindex]; float v0p = v0[dim]; float v1p = v1[dim]; @@ -299,12 +279,6 @@ void BVHSpatialSplit::split_reference(BVHBuild *builder, BVHReference& left, BVH if(v0p >= pos) right_bounds.grow(v0); - if(v1p <= pos) - left_bounds.grow(v1); - - if(v1p >= pos) - right_bounds.grow(v1); - /* edge intersects the plane => insert intersection to both boxes. */ if((v0p < pos && v1p > pos) || (v0p > pos && v1p < pos)) { float3 t = lerp(v0, v1, clamp((pos - v0p) / (v1p - v0p), 0.0f, 1.0f)); @@ -312,6 +286,159 @@ void BVHSpatialSplit::split_reference(BVHBuild *builder, BVHReference& left, BVH right_bounds.grow(t); } } +} + +void BVHSpatialSplit::split_curve_primitive(const Mesh *mesh, + const Transform *tfm, + int prim_index, + int segment_index, + int dim, + float pos, + BoundBox& left_bounds, + BoundBox& right_bounds) +{ + /* curve split: NOTE - Currently ignores curve width and needs to be fixed.*/ + const int k0 = mesh->curves[prim_index].first_key + segment_index; + const int k1 = k0 + 1; + const float4& key0 = mesh->curve_keys[k0]; + const float4& key1 = mesh->curve_keys[k1]; + float3 v0 = float4_to_float3(key0); + float3 v1 = float4_to_float3(key1); + + if(tfm != NULL) { + v0 = transform_point(tfm, v0); + v1 = transform_point(tfm, v1); + } + + float v0p = v0[dim]; + float v1p = v1[dim]; + + /* insert vertex to the boxes it belongs to. */ + if(v0p <= pos) + left_bounds.grow(v0); + + if(v0p >= pos) + right_bounds.grow(v0); + + if(v1p <= pos) + left_bounds.grow(v1); + + if(v1p >= pos) + right_bounds.grow(v1); + + /* edge intersects the plane => insert intersection to both boxes. */ + if((v0p < pos && v1p > pos) || (v0p > pos && v1p < pos)) { + float3 t = lerp(v0, v1, clamp((pos - v0p) / (v1p - v0p), 0.0f, 1.0f)); + left_bounds.grow(t); + right_bounds.grow(t); + } +} + +void BVHSpatialSplit::split_triangle_reference(const BVHReference& ref, + const Mesh *mesh, + int dim, + float pos, + BoundBox& left_bounds, + BoundBox& right_bounds) +{ + split_triangle_primitive(mesh, + NULL, + ref.prim_index(), + dim, + pos, + left_bounds, + right_bounds); +} + +void BVHSpatialSplit::split_curve_reference(const BVHReference& ref, + const Mesh *mesh, + int dim, + float pos, + BoundBox& left_bounds, + BoundBox& right_bounds) +{ + split_curve_primitive(mesh, + NULL, + ref.prim_index(), + PRIMITIVE_UNPACK_SEGMENT(ref.prim_type()), + dim, + pos, + left_bounds, + right_bounds); +} + +void BVHSpatialSplit::split_object_reference(const Object *object, + int dim, + float pos, + BoundBox& left_bounds, + BoundBox& right_bounds) +{ + Mesh *mesh = object->mesh; + for(int tri_idx = 0; tri_idx < mesh->triangles.size(); ++tri_idx) { + split_triangle_primitive(mesh, + &object->tfm, + tri_idx, + dim, + pos, + left_bounds, + right_bounds); + } + for(int curve_idx = 0; curve_idx < mesh->curves.size(); ++curve_idx) { + Mesh::Curve &curve = mesh->curves[curve_idx]; + for(int segment_idx = 0; + segment_idx < curve.num_keys - 1; + ++segment_idx) + { + split_curve_primitive(mesh, + &object->tfm, + curve_idx, + segment_idx, + dim, + pos, + left_bounds, + right_bounds); + } + } +} + +void BVHSpatialSplit::split_reference(BVHBuild *builder, + BVHReference& left, + BVHReference& right, + const BVHReference& ref, + int dim, + float pos) +{ + /* initialize boundboxes */ + BoundBox left_bounds = BoundBox::empty; + BoundBox right_bounds = BoundBox::empty; + + /* loop over vertices/edges. */ + Object *ob = builder->objects[ref.prim_object()]; + const Mesh *mesh = ob->mesh; + + if(ref.prim_type() & PRIMITIVE_ALL_TRIANGLE) { + split_triangle_reference(ref, + mesh, + dim, + pos, + left_bounds, + right_bounds); + } + else if(ref.prim_type() & PRIMITIVE_ALL_CURVE) { + split_curve_reference(ref, + mesh, + dim, + pos, + left_bounds, + right_bounds); + } + else { + split_object_reference(ob, + dim, + pos, + left_bounds, + right_bounds); + } /* intersect with original bounds. */ left_bounds.max[dim] = pos; diff --git a/intern/cycles/bvh/bvh_split.h b/intern/cycles/bvh/bvh_split.h index 5b739311e5f..1e46bb66203 100644 --- a/intern/cycles/bvh/bvh_split.h +++ b/intern/cycles/bvh/bvh_split.h @@ -55,7 +55,58 @@ public: BVHSpatialSplit(BVHBuild *builder, const BVHRange& range, float nodeSAH); void split(BVHBuild *builder, BVHRange& left, BVHRange& right, const BVHRange& range); - void split_reference(BVHBuild *builder, BVHReference& left, BVHReference& right, const BVHReference& ref, int dim, float pos); + void split_reference(BVHBuild *builder, + BVHReference& left, + BVHReference& right, + const BVHReference& ref, + int dim, + float pos); + +protected: + /* Lower-level functions which calculates boundaries of left and right nodes + * needed for spatial split. + * + * Operates directly with primitive specified by it's index, reused by higher + * level splitting functions. + */ + void split_triangle_primitive(const Mesh *mesh, + const Transform *tfm, + int prim_index, + int dim, + float pos, + BoundBox& left_bounds, + BoundBox& right_bounds); + void split_curve_primitive(const Mesh *mesh, + const Transform *tfm, + int prim_index, + int segment_index, + int dim, + float pos, + BoundBox& left_bounds, + BoundBox& right_bounds); + + /* Lower-level functions which calculates boundaries of left and right nodes + * needed for spatial split. + * + * Operates with BVHReference, internally uses lower level API functions. + */ + void split_triangle_reference(const BVHReference& ref, + const Mesh *mesh, + int dim, + float pos, + BoundBox& left_bounds, + BoundBox& right_bounds); + void split_curve_reference(const BVHReference& ref, + const Mesh *mesh, + int dim, + float pos, + BoundBox& left_bounds, + BoundBox& right_bounds); + void split_object_reference(const Object *object, + int dim, + float pos, + BoundBox& left_bounds, + BoundBox& right_bounds); }; /* Mixed Object-Spatial Split */ |