Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPatrick Mours <pmours@nvidia.com>2020-12-10 16:18:25 +0300
committerPatrick Mours <pmours@nvidia.com>2020-12-11 15:24:29 +0300
commitbfb6fce6594e9cf133bd18aee311c1e5e32dc799 (patch)
tree7c813e17ea87e9aae64221b3ac7a8d42ab894c85 /intern/cycles/bvh
parentd72ec16e70721408c875040325c984941687b4a2 (diff)
Cycles: Add CPU+GPU rendering support with OptiX
Adds support for building multiple BVH types in order to support using both CPU and OptiX devices for rendering simultaneously. Primitive packing for Embree and OptiX is now standalone, so it only needs to be run once and can be shared between the two. Additionally, BVH building was made a device call, so that each device backend can decide how to perform the building. The multi-device for instance creates a special multi-BVH that holds references to several sub-BVHs, one for each sub-device. Reviewed By: brecht, kevindietrich Differential Revision: https://developer.blender.org/D9718
Diffstat (limited to 'intern/cycles/bvh')
-rw-r--r--intern/cycles/bvh/CMakeLists.txt2
-rw-r--r--intern/cycles/bvh/bvh.cpp432
-rw-r--r--intern/cycles/bvh/bvh.h48
-rw-r--r--intern/cycles/bvh/bvh2.cpp409
-rw-r--r--intern/cycles/bvh/bvh2.h39
-rw-r--r--intern/cycles/bvh/bvh_embree.cpp329
-rw-r--r--intern/cycles/bvh/bvh_embree.h32
-rw-r--r--intern/cycles/bvh/bvh_multi.cpp37
-rw-r--r--intern/cycles/bvh/bvh_multi.h39
-rw-r--r--intern/cycles/bvh/bvh_optix.cpp204
-rw-r--r--intern/cycles/bvh/bvh_optix.h28
11 files changed, 580 insertions, 1019 deletions
diff --git a/intern/cycles/bvh/CMakeLists.txt b/intern/cycles/bvh/CMakeLists.txt
index 703c69b1797..8cc72359757 100644
--- a/intern/cycles/bvh/CMakeLists.txt
+++ b/intern/cycles/bvh/CMakeLists.txt
@@ -25,6 +25,7 @@ set(SRC
bvh_binning.cpp
bvh_build.cpp
bvh_embree.cpp
+ bvh_multi.cpp
bvh_node.cpp
bvh_optix.cpp
bvh_sort.cpp
@@ -38,6 +39,7 @@ set(SRC_HEADERS
bvh_binning.h
bvh_build.h
bvh_embree.h
+ bvh_multi.h
bvh_node.h
bvh_optix.h
bvh_params.h
diff --git a/intern/cycles/bvh/bvh.cpp b/intern/cycles/bvh/bvh.cpp
index a51ac4cf4a9..256382e63ba 100644
--- a/intern/cycles/bvh/bvh.cpp
+++ b/intern/cycles/bvh/bvh.cpp
@@ -17,17 +17,11 @@
#include "bvh/bvh.h"
-#include "render/hair.h"
-#include "render/mesh.h"
-#include "render/object.h"
-
#include "bvh/bvh2.h"
-#include "bvh/bvh_build.h"
#include "bvh/bvh_embree.h"
-#include "bvh/bvh_node.h"
+#include "bvh/bvh_multi.h"
#include "bvh/bvh_optix.h"
-#include "util/util_foreach.h"
#include "util/util_logging.h"
#include "util/util_progress.h"
@@ -38,14 +32,17 @@ CCL_NAMESPACE_BEGIN
const char *bvh_layout_name(BVHLayout layout)
{
switch (layout) {
- case BVH_LAYOUT_BVH2:
- return "BVH2";
case BVH_LAYOUT_NONE:
return "NONE";
+ case BVH_LAYOUT_BVH2:
+ return "BVH2";
case BVH_LAYOUT_EMBREE:
return "EMBREE";
case BVH_LAYOUT_OPTIX:
return "OPTIX";
+ case BVH_LAYOUT_MULTI_OPTIX:
+ case BVH_LAYOUT_MULTI_OPTIX_EMBREE:
+ return "MULTI";
case BVH_LAYOUT_ALL:
return "ALL";
}
@@ -76,17 +73,6 @@ BVHLayout BVHParams::best_bvh_layout(BVHLayout requested_layout, BVHLayoutMask s
return (BVHLayout)(1 << widest_allowed_layout_mask);
}
-/* Pack Utility */
-
-BVHStackEntry::BVHStackEntry(const BVHNode *n, int i) : node(n), idx(i)
-{
-}
-
-int BVHStackEntry::encodeIdx() const
-{
- return (node->is_leaf()) ? ~idx : idx;
-}
-
/* BVH */
BVH::BVH(const BVHParams &params_,
@@ -99,24 +85,27 @@ BVH::BVH(const BVHParams &params_,
BVH *BVH::create(const BVHParams &params,
const vector<Geometry *> &geometry,
const vector<Object *> &objects,
- const Device *device)
+ Device *device)
{
switch (params.bvh_layout) {
case BVH_LAYOUT_BVH2:
return new BVH2(params, geometry, objects);
case BVH_LAYOUT_EMBREE:
#ifdef WITH_EMBREE
- return new BVHEmbree(params, geometry, objects, device);
+ return new BVHEmbree(params, geometry, objects);
#else
- (void)device;
break;
#endif
case BVH_LAYOUT_OPTIX:
#ifdef WITH_OPTIX
- return new BVHOptiX(params, geometry, objects);
+ return new BVHOptiX(params, geometry, objects, device);
#else
+ (void)device;
break;
#endif
+ case BVH_LAYOUT_MULTI_OPTIX:
+ case BVH_LAYOUT_MULTI_OPTIX_EMBREE:
+ return new BVHMulti(params, geometry, objects);
case BVH_LAYOUT_NONE:
case BVH_LAYOUT_ALL:
break;
@@ -125,399 +114,4 @@ BVH *BVH::create(const BVHParams &params,
return NULL;
}
-/* Building */
-
-void BVH::build(Progress &progress, Stats *)
-{
- progress.set_substatus("Building BVH");
-
- /* build nodes */
- BVHBuild bvh_build(objects,
- pack.prim_type,
- pack.prim_index,
- pack.prim_object,
- pack.prim_time,
- params,
- progress);
- BVHNode *bvh2_root = bvh_build.run();
-
- if (progress.get_cancel()) {
- if (bvh2_root != NULL) {
- bvh2_root->deleteSubtree();
- }
- return;
- }
-
- /* BVH builder returns tree in a binary mode (with two children per inner
- * node. Need to adopt that for a wider BVH implementations. */
- BVHNode *root = widen_children_nodes(bvh2_root);
- if (root != bvh2_root) {
- bvh2_root->deleteSubtree();
- }
-
- if (progress.get_cancel()) {
- if (root != NULL) {
- root->deleteSubtree();
- }
- return;
- }
-
- /* pack triangles */
- progress.set_substatus("Packing BVH triangles and strands");
- pack_primitives();
-
- if (progress.get_cancel()) {
- root->deleteSubtree();
- return;
- }
-
- /* pack nodes */
- progress.set_substatus("Packing BVH nodes");
- pack_nodes(root);
-
- /* free build nodes */
- root->deleteSubtree();
-}
-
-/* Refitting */
-
-void BVH::refit(Progress &progress)
-{
- progress.set_substatus("Packing BVH primitives");
- pack_primitives();
-
- if (progress.get_cancel())
- return;
-
- progress.set_substatus("Refitting BVH nodes");
- refit_nodes();
-}
-
-void BVH::refit_primitives(int start, int end, BoundBox &bbox, uint &visibility)
-{
- /* Refit range of primitives. */
- for (int prim = start; prim < end; prim++) {
- int pidx = pack.prim_index[prim];
- int tob = pack.prim_object[prim];
- Object *ob = objects[tob];
-
- if (pidx == -1) {
- /* Object instance. */
- bbox.grow(ob->bounds);
- }
- else {
- /* Primitives. */
- if (pack.prim_type[prim] & PRIMITIVE_ALL_CURVE) {
- /* Curves. */
- const Hair *hair = static_cast<const Hair *>(ob->get_geometry());
- int prim_offset = (params.top_level) ? hair->prim_offset : 0;
- Hair::Curve curve = hair->get_curve(pidx - prim_offset);
- int k = PRIMITIVE_UNPACK_SEGMENT(pack.prim_type[prim]);
-
- curve.bounds_grow(k, &hair->get_curve_keys()[0], &hair->get_curve_radius()[0], bbox);
-
- /* Motion curves. */
- if (hair->get_use_motion_blur()) {
- Attribute *attr = hair->attributes.find(ATTR_STD_MOTION_VERTEX_POSITION);
-
- if (attr) {
- size_t hair_size = hair->get_curve_keys().size();
- size_t steps = hair->get_motion_steps() - 1;
- float3 *key_steps = attr->data_float3();
-
- for (size_t i = 0; i < steps; i++)
- curve.bounds_grow(k, key_steps + i * hair_size, &hair->get_curve_radius()[0], bbox);
- }
- }
- }
- else {
- /* Triangles. */
- const Mesh *mesh = static_cast<const Mesh *>(ob->get_geometry());
- int prim_offset = (params.top_level) ? mesh->prim_offset : 0;
- Mesh::Triangle triangle = mesh->get_triangle(pidx - prim_offset);
- const float3 *vpos = &mesh->verts[0];
-
- triangle.bounds_grow(vpos, bbox);
-
- /* Motion triangles. */
- if (mesh->use_motion_blur) {
- Attribute *attr = mesh->attributes.find(ATTR_STD_MOTION_VERTEX_POSITION);
-
- if (attr) {
- size_t mesh_size = mesh->verts.size();
- size_t steps = mesh->motion_steps - 1;
- float3 *vert_steps = attr->data_float3();
-
- for (size_t i = 0; i < steps; i++)
- triangle.bounds_grow(vert_steps + i * mesh_size, bbox);
- }
- }
- }
- }
- visibility |= ob->visibility_for_tracing();
- }
-}
-
-/* Triangles */
-
-void BVH::pack_triangle(int idx, float4 tri_verts[3])
-{
- int tob = pack.prim_object[idx];
- assert(tob >= 0 && tob < objects.size());
- const Mesh *mesh = static_cast<const Mesh *>(objects[tob]->get_geometry());
-
- int tidx = pack.prim_index[idx];
- Mesh::Triangle t = mesh->get_triangle(tidx);
- const float3 *vpos = &mesh->verts[0];
- float3 v0 = vpos[t.v[0]];
- float3 v1 = vpos[t.v[1]];
- float3 v2 = vpos[t.v[2]];
-
- tri_verts[0] = float3_to_float4(v0);
- tri_verts[1] = float3_to_float4(v1);
- tri_verts[2] = float3_to_float4(v2);
-}
-
-void BVH::pack_primitives()
-{
- const size_t tidx_size = pack.prim_index.size();
- size_t num_prim_triangles = 0;
- /* Count number of triangles primitives in BVH. */
- for (unsigned int i = 0; i < tidx_size; i++) {
- if ((pack.prim_index[i] != -1)) {
- if ((pack.prim_type[i] & PRIMITIVE_ALL_TRIANGLE) != 0) {
- ++num_prim_triangles;
- }
- }
- }
- /* Reserve size for arrays. */
- pack.prim_tri_index.clear();
- pack.prim_tri_index.resize(tidx_size);
- pack.prim_tri_verts.clear();
- pack.prim_tri_verts.resize(num_prim_triangles * 3);
- pack.prim_visibility.clear();
- pack.prim_visibility.resize(tidx_size);
- /* Fill in all the arrays. */
- size_t prim_triangle_index = 0;
- for (unsigned int i = 0; i < tidx_size; i++) {
- if (pack.prim_index[i] != -1) {
- int tob = pack.prim_object[i];
- Object *ob = objects[tob];
- if ((pack.prim_type[i] & PRIMITIVE_ALL_TRIANGLE) != 0) {
- pack_triangle(i, (float4 *)&pack.prim_tri_verts[3 * prim_triangle_index]);
- pack.prim_tri_index[i] = 3 * prim_triangle_index;
- ++prim_triangle_index;
- }
- else {
- pack.prim_tri_index[i] = -1;
- }
- pack.prim_visibility[i] = ob->visibility_for_tracing();
- }
- else {
- pack.prim_tri_index[i] = -1;
- pack.prim_visibility[i] = 0;
- }
- }
-}
-
-/* Pack Instances */
-
-void BVH::pack_instances(size_t nodes_size, size_t leaf_nodes_size)
-{
- /* Adjust primitive index to point to the triangle in the global array, for
- * geometry with transform applied and already in the top level BVH.
- */
- for (size_t i = 0; i < pack.prim_index.size(); i++) {
- if (pack.prim_index[i] != -1) {
- pack.prim_index[i] += objects[pack.prim_object[i]]->get_geometry()->prim_offset;
- }
- }
-
- /* track offsets of instanced BVH data in global array */
- size_t prim_offset = pack.prim_index.size();
- size_t nodes_offset = nodes_size;
- size_t nodes_leaf_offset = leaf_nodes_size;
-
- /* clear array that gives the node indexes for instanced objects */
- pack.object_node.clear();
-
- /* reserve */
- size_t prim_index_size = pack.prim_index.size();
- size_t prim_tri_verts_size = pack.prim_tri_verts.size();
-
- size_t pack_prim_index_offset = prim_index_size;
- size_t pack_prim_tri_verts_offset = prim_tri_verts_size;
- size_t pack_nodes_offset = nodes_size;
- size_t pack_leaf_nodes_offset = leaf_nodes_size;
- size_t object_offset = 0;
-
- foreach (Geometry *geom, geometry) {
- BVH *bvh = geom->bvh;
-
- if (geom->need_build_bvh(params.bvh_layout)) {
- prim_index_size += bvh->pack.prim_index.size();
- prim_tri_verts_size += bvh->pack.prim_tri_verts.size();
- nodes_size += bvh->pack.nodes.size();
- leaf_nodes_size += bvh->pack.leaf_nodes.size();
- }
- }
-
- pack.prim_index.resize(prim_index_size);
- pack.prim_type.resize(prim_index_size);
- pack.prim_object.resize(prim_index_size);
- pack.prim_visibility.resize(prim_index_size);
- pack.prim_tri_verts.resize(prim_tri_verts_size);
- pack.prim_tri_index.resize(prim_index_size);
- pack.nodes.resize(nodes_size);
- pack.leaf_nodes.resize(leaf_nodes_size);
- pack.object_node.resize(objects.size());
-
- if (params.num_motion_curve_steps > 0 || params.num_motion_triangle_steps > 0) {
- pack.prim_time.resize(prim_index_size);
- }
-
- int *pack_prim_index = (pack.prim_index.size()) ? &pack.prim_index[0] : NULL;
- int *pack_prim_type = (pack.prim_type.size()) ? &pack.prim_type[0] : NULL;
- int *pack_prim_object = (pack.prim_object.size()) ? &pack.prim_object[0] : NULL;
- uint *pack_prim_visibility = (pack.prim_visibility.size()) ? &pack.prim_visibility[0] : NULL;
- float4 *pack_prim_tri_verts = (pack.prim_tri_verts.size()) ? &pack.prim_tri_verts[0] : NULL;
- uint *pack_prim_tri_index = (pack.prim_tri_index.size()) ? &pack.prim_tri_index[0] : NULL;
- int4 *pack_nodes = (pack.nodes.size()) ? &pack.nodes[0] : NULL;
- int4 *pack_leaf_nodes = (pack.leaf_nodes.size()) ? &pack.leaf_nodes[0] : NULL;
- float2 *pack_prim_time = (pack.prim_time.size()) ? &pack.prim_time[0] : NULL;
-
- map<Geometry *, int> geometry_map;
-
- /* merge */
- foreach (Object *ob, objects) {
- Geometry *geom = ob->get_geometry();
-
- /* We assume that if mesh doesn't need own BVH it was already included
- * into a top-level BVH and no packing here is needed.
- */
- if (!geom->need_build_bvh(params.bvh_layout)) {
- pack.object_node[object_offset++] = 0;
- continue;
- }
-
- /* if mesh already added once, don't add it again, but used set
- * node offset for this object */
- map<Geometry *, int>::iterator it = geometry_map.find(geom);
-
- if (geometry_map.find(geom) != geometry_map.end()) {
- int noffset = it->second;
- pack.object_node[object_offset++] = noffset;
- continue;
- }
-
- BVH *bvh = geom->bvh;
-
- int noffset = nodes_offset;
- int noffset_leaf = nodes_leaf_offset;
- int geom_prim_offset = geom->prim_offset;
-
- /* fill in node indexes for instances */
- if (bvh->pack.root_index == -1)
- pack.object_node[object_offset++] = -noffset_leaf - 1;
- else
- pack.object_node[object_offset++] = noffset;
-
- geometry_map[geom] = pack.object_node[object_offset - 1];
-
- /* merge primitive, object and triangle indexes */
- if (bvh->pack.prim_index.size()) {
- size_t bvh_prim_index_size = bvh->pack.prim_index.size();
- int *bvh_prim_index = &bvh->pack.prim_index[0];
- int *bvh_prim_type = &bvh->pack.prim_type[0];
- uint *bvh_prim_visibility = &bvh->pack.prim_visibility[0];
- uint *bvh_prim_tri_index = &bvh->pack.prim_tri_index[0];
- float2 *bvh_prim_time = bvh->pack.prim_time.size() ? &bvh->pack.prim_time[0] : NULL;
-
- for (size_t i = 0; i < bvh_prim_index_size; i++) {
- if (bvh->pack.prim_type[i] & PRIMITIVE_ALL_CURVE) {
- pack_prim_index[pack_prim_index_offset] = bvh_prim_index[i] + geom_prim_offset;
- pack_prim_tri_index[pack_prim_index_offset] = -1;
- }
- else {
- pack_prim_index[pack_prim_index_offset] = bvh_prim_index[i] + geom_prim_offset;
- pack_prim_tri_index[pack_prim_index_offset] = bvh_prim_tri_index[i] +
- pack_prim_tri_verts_offset;
- }
-
- pack_prim_type[pack_prim_index_offset] = bvh_prim_type[i];
- pack_prim_visibility[pack_prim_index_offset] = bvh_prim_visibility[i];
- pack_prim_object[pack_prim_index_offset] = 0; // unused for instances
- if (bvh_prim_time != NULL) {
- pack_prim_time[pack_prim_index_offset] = bvh_prim_time[i];
- }
- pack_prim_index_offset++;
- }
- }
-
- /* Merge triangle vertices data. */
- if (bvh->pack.prim_tri_verts.size()) {
- const size_t prim_tri_size = bvh->pack.prim_tri_verts.size();
- memcpy(pack_prim_tri_verts + pack_prim_tri_verts_offset,
- &bvh->pack.prim_tri_verts[0],
- prim_tri_size * sizeof(float4));
- pack_prim_tri_verts_offset += prim_tri_size;
- }
-
- /* merge nodes */
- if (bvh->pack.leaf_nodes.size()) {
- int4 *leaf_nodes_offset = &bvh->pack.leaf_nodes[0];
- size_t leaf_nodes_offset_size = bvh->pack.leaf_nodes.size();
- for (size_t i = 0, j = 0; i < leaf_nodes_offset_size; i += BVH_NODE_LEAF_SIZE, j++) {
- int4 data = leaf_nodes_offset[i];
- data.x += prim_offset;
- data.y += prim_offset;
- pack_leaf_nodes[pack_leaf_nodes_offset] = data;
- for (int j = 1; j < BVH_NODE_LEAF_SIZE; ++j) {
- pack_leaf_nodes[pack_leaf_nodes_offset + j] = leaf_nodes_offset[i + j];
- }
- pack_leaf_nodes_offset += BVH_NODE_LEAF_SIZE;
- }
- }
-
- if (bvh->pack.nodes.size()) {
- int4 *bvh_nodes = &bvh->pack.nodes[0];
- size_t bvh_nodes_size = bvh->pack.nodes.size();
-
- for (size_t i = 0, j = 0; i < bvh_nodes_size; j++) {
- size_t nsize, nsize_bbox;
- if (bvh_nodes[i].x & PATH_RAY_NODE_UNALIGNED) {
- nsize = BVH_UNALIGNED_NODE_SIZE;
- nsize_bbox = 0;
- }
- else {
- nsize = BVH_NODE_SIZE;
- nsize_bbox = 0;
- }
-
- memcpy(pack_nodes + pack_nodes_offset, bvh_nodes + i, nsize_bbox * sizeof(int4));
-
- /* Modify offsets into arrays */
- int4 data = bvh_nodes[i + nsize_bbox];
- data.z += (data.z < 0) ? -noffset_leaf : noffset;
- data.w += (data.w < 0) ? -noffset_leaf : noffset;
- pack_nodes[pack_nodes_offset + nsize_bbox] = data;
-
- /* Usually this copies nothing, but we better
- * be prepared for possible node size extension.
- */
- memcpy(&pack_nodes[pack_nodes_offset + nsize_bbox + 1],
- &bvh_nodes[i + nsize_bbox + 1],
- sizeof(int4) * (nsize - (nsize_bbox + 1)));
-
- pack_nodes_offset += nsize;
- i += nsize;
- }
- }
-
- nodes_offset += bvh->pack.nodes.size();
- nodes_leaf_offset += bvh->pack.leaf_nodes.size();
- prim_offset += bvh->pack.prim_index.size();
- }
-}
-
CCL_NAMESPACE_END
diff --git a/intern/cycles/bvh/bvh.h b/intern/cycles/bvh/bvh.h
index 033b1fd8e04..94935c26f10 100644
--- a/intern/cycles/bvh/bvh.h
+++ b/intern/cycles/bvh/bvh.h
@@ -25,17 +25,16 @@
CCL_NAMESPACE_BEGIN
-class Stats;
-class Device;
-class DeviceScene;
+class BoundBox;
class BVHNode;
-struct BVHStackEntry;
class BVHParams;
-class BoundBox;
-class LeafNode;
+class Device;
+class DeviceScene;
class Geometry;
+class LeafNode;
class Object;
class Progress;
+class Stats;
#define BVH_ALIGN 4096
#define TRI_NODE_SIZE 3
@@ -76,13 +75,10 @@ struct PackedBVH {
}
};
-enum BVH_TYPE { bvh2 };
-
/* BVH */
class BVH {
public:
- PackedBVH pack;
BVHParams params;
vector<Geometry *> geometry;
vector<Object *> objects;
@@ -90,47 +86,15 @@ class BVH {
static BVH *create(const BVHParams &params,
const vector<Geometry *> &geometry,
const vector<Object *> &objects,
- const Device *device);
+ Device *device);
virtual ~BVH()
{
}
- virtual void build(Progress &progress, Stats *stats = NULL);
- virtual void copy_to_device(Progress & /*progress*/, DeviceScene * /*dscene*/)
- {
- }
-
- void refit(Progress &progress);
-
protected:
BVH(const BVHParams &params,
const vector<Geometry *> &geometry,
const vector<Object *> &objects);
-
- /* Refit range of primitives. */
- void refit_primitives(int start, int end, BoundBox &bbox, uint &visibility);
-
- /* triangles and strands */
- void pack_primitives();
- void pack_triangle(int idx, float4 storage[3]);
-
- /* merge instance BVH's */
- void pack_instances(size_t nodes_size, size_t leaf_nodes_size);
-
- /* for subclasses to implement */
- virtual void pack_nodes(const BVHNode *root) = 0;
- virtual void refit_nodes() = 0;
-
- virtual BVHNode *widen_children_nodes(const BVHNode *root) = 0;
-};
-
-/* Pack Utility */
-struct BVHStackEntry {
- const BVHNode *node;
- int idx;
-
- BVHStackEntry(const BVHNode *n = 0, int i = 0);
- int encodeIdx() const;
};
CCL_NAMESPACE_END
diff --git a/intern/cycles/bvh/bvh2.cpp b/intern/cycles/bvh/bvh2.cpp
index c903070429e..379ae9b25ff 100644
--- a/intern/cycles/bvh/bvh2.cpp
+++ b/intern/cycles/bvh/bvh2.cpp
@@ -17,14 +17,28 @@
#include "bvh/bvh2.h"
+#include "render/hair.h"
#include "render/mesh.h"
#include "render/object.h"
+#include "bvh/bvh_build.h"
#include "bvh/bvh_node.h"
#include "bvh/bvh_unaligned.h"
+#include "util/util_foreach.h"
+#include "util/util_progress.h"
+
CCL_NAMESPACE_BEGIN
+BVHStackEntry::BVHStackEntry(const BVHNode *n, int i) : node(n), idx(i)
+{
+}
+
+int BVHStackEntry::encodeIdx() const
+{
+ return (node->is_leaf()) ? ~idx : idx;
+}
+
BVH2::BVH2(const BVHParams &params_,
const vector<Geometry *> &geometry_,
const vector<Object *> &objects_)
@@ -32,6 +46,70 @@ BVH2::BVH2(const BVHParams &params_,
{
}
+void BVH2::build(Progress &progress, Stats *)
+{
+ progress.set_substatus("Building BVH");
+
+ /* build nodes */
+ BVHBuild bvh_build(objects,
+ pack.prim_type,
+ pack.prim_index,
+ pack.prim_object,
+ pack.prim_time,
+ params,
+ progress);
+ BVHNode *bvh2_root = bvh_build.run();
+
+ if (progress.get_cancel()) {
+ if (bvh2_root != NULL) {
+ bvh2_root->deleteSubtree();
+ }
+ return;
+ }
+
+ /* BVH builder returns tree in a binary mode (with two children per inner
+ * node. Need to adopt that for a wider BVH implementations. */
+ BVHNode *root = widen_children_nodes(bvh2_root);
+ if (root != bvh2_root) {
+ bvh2_root->deleteSubtree();
+ }
+
+ if (progress.get_cancel()) {
+ if (root != NULL) {
+ root->deleteSubtree();
+ }
+ return;
+ }
+
+ /* pack triangles */
+ progress.set_substatus("Packing BVH triangles and strands");
+ pack_primitives();
+
+ if (progress.get_cancel()) {
+ root->deleteSubtree();
+ return;
+ }
+
+ /* pack nodes */
+ progress.set_substatus("Packing BVH nodes");
+ pack_nodes(root);
+
+ /* free build nodes */
+ root->deleteSubtree();
+}
+
+void BVH2::refit(Progress &progress)
+{
+ progress.set_substatus("Packing BVH primitives");
+ pack_primitives();
+
+ if (progress.get_cancel())
+ return;
+
+ progress.set_substatus("Refitting BVH nodes");
+ refit_nodes();
+}
+
BVHNode *BVH2::widen_children_nodes(const BVHNode *root)
{
return const_cast<BVHNode *>(root);
@@ -253,7 +331,7 @@ void BVH2::refit_node(int idx, bool leaf, BoundBox &bbox, uint &visibility)
const int c0 = data[0].x;
const int c1 = data[0].y;
- BVH::refit_primitives(c0, c1, bbox, visibility);
+ refit_primitives(c0, c1, bbox, visibility);
/* TODO(sergey): De-duplicate with pack_leaf(). */
float4 leaf_data[BVH_NODE_LEAF_SIZE];
@@ -292,4 +370,333 @@ void BVH2::refit_node(int idx, bool leaf, BoundBox &bbox, uint &visibility)
}
}
+/* Refitting */
+
+void BVH2::refit_primitives(int start, int end, BoundBox &bbox, uint &visibility)
+{
+ /* Refit range of primitives. */
+ for (int prim = start; prim < end; prim++) {
+ int pidx = pack.prim_index[prim];
+ int tob = pack.prim_object[prim];
+ Object *ob = objects[tob];
+
+ if (pidx == -1) {
+ /* Object instance. */
+ bbox.grow(ob->bounds);
+ }
+ else {
+ /* Primitives. */
+ if (pack.prim_type[prim] & PRIMITIVE_ALL_CURVE) {
+ /* Curves. */
+ const Hair *hair = static_cast<const Hair *>(ob->get_geometry());
+ int prim_offset = (params.top_level) ? hair->prim_offset : 0;
+ Hair::Curve curve = hair->get_curve(pidx - prim_offset);
+ int k = PRIMITIVE_UNPACK_SEGMENT(pack.prim_type[prim]);
+
+ curve.bounds_grow(k, &hair->get_curve_keys()[0], &hair->get_curve_radius()[0], bbox);
+
+ /* Motion curves. */
+ if (hair->get_use_motion_blur()) {
+ Attribute *attr = hair->attributes.find(ATTR_STD_MOTION_VERTEX_POSITION);
+
+ if (attr) {
+ size_t hair_size = hair->get_curve_keys().size();
+ size_t steps = hair->get_motion_steps() - 1;
+ float3 *key_steps = attr->data_float3();
+
+ for (size_t i = 0; i < steps; i++)
+ curve.bounds_grow(k, key_steps + i * hair_size, &hair->get_curve_radius()[0], bbox);
+ }
+ }
+ }
+ else {
+ /* Triangles. */
+ const Mesh *mesh = static_cast<const Mesh *>(ob->get_geometry());
+ int prim_offset = (params.top_level) ? mesh->prim_offset : 0;
+ Mesh::Triangle triangle = mesh->get_triangle(pidx - prim_offset);
+ const float3 *vpos = &mesh->verts[0];
+
+ triangle.bounds_grow(vpos, bbox);
+
+ /* Motion triangles. */
+ if (mesh->use_motion_blur) {
+ Attribute *attr = mesh->attributes.find(ATTR_STD_MOTION_VERTEX_POSITION);
+
+ if (attr) {
+ size_t mesh_size = mesh->verts.size();
+ size_t steps = mesh->motion_steps - 1;
+ float3 *vert_steps = attr->data_float3();
+
+ for (size_t i = 0; i < steps; i++)
+ triangle.bounds_grow(vert_steps + i * mesh_size, bbox);
+ }
+ }
+ }
+ }
+ visibility |= ob->visibility_for_tracing();
+ }
+}
+
+/* Triangles */
+
+void BVH2::pack_triangle(int idx, float4 tri_verts[3])
+{
+ int tob = pack.prim_object[idx];
+ assert(tob >= 0 && tob < objects.size());
+ const Mesh *mesh = static_cast<const Mesh *>(objects[tob]->get_geometry());
+
+ int tidx = pack.prim_index[idx];
+ Mesh::Triangle t = mesh->get_triangle(tidx);
+ const float3 *vpos = &mesh->verts[0];
+ float3 v0 = vpos[t.v[0]];
+ float3 v1 = vpos[t.v[1]];
+ float3 v2 = vpos[t.v[2]];
+
+ tri_verts[0] = float3_to_float4(v0);
+ tri_verts[1] = float3_to_float4(v1);
+ tri_verts[2] = float3_to_float4(v2);
+}
+
+void BVH2::pack_primitives()
+{
+ const size_t tidx_size = pack.prim_index.size();
+ size_t num_prim_triangles = 0;
+ /* Count number of triangles primitives in BVH. */
+ for (unsigned int i = 0; i < tidx_size; i++) {
+ if ((pack.prim_index[i] != -1)) {
+ if ((pack.prim_type[i] & PRIMITIVE_ALL_TRIANGLE) != 0) {
+ ++num_prim_triangles;
+ }
+ }
+ }
+ /* Reserve size for arrays. */
+ pack.prim_tri_index.clear();
+ pack.prim_tri_index.resize(tidx_size);
+ pack.prim_tri_verts.clear();
+ pack.prim_tri_verts.resize(num_prim_triangles * 3);
+ pack.prim_visibility.clear();
+ pack.prim_visibility.resize(tidx_size);
+ /* Fill in all the arrays. */
+ size_t prim_triangle_index = 0;
+ for (unsigned int i = 0; i < tidx_size; i++) {
+ if (pack.prim_index[i] != -1) {
+ int tob = pack.prim_object[i];
+ Object *ob = objects[tob];
+ if ((pack.prim_type[i] & PRIMITIVE_ALL_TRIANGLE) != 0) {
+ pack_triangle(i, (float4 *)&pack.prim_tri_verts[3 * prim_triangle_index]);
+ pack.prim_tri_index[i] = 3 * prim_triangle_index;
+ ++prim_triangle_index;
+ }
+ else {
+ pack.prim_tri_index[i] = -1;
+ }
+ pack.prim_visibility[i] = ob->visibility_for_tracing();
+ }
+ else {
+ pack.prim_tri_index[i] = -1;
+ pack.prim_visibility[i] = 0;
+ }
+ }
+}
+
+/* Pack Instances */
+
+void BVH2::pack_instances(size_t nodes_size, size_t leaf_nodes_size)
+{
+ /* Adjust primitive index to point to the triangle in the global array, for
+ * geometry with transform applied and already in the top level BVH.
+ */
+ for (size_t i = 0; i < pack.prim_index.size(); i++) {
+ if (pack.prim_index[i] != -1) {
+ pack.prim_index[i] += objects[pack.prim_object[i]]->get_geometry()->prim_offset;
+ }
+ }
+
+ /* track offsets of instanced BVH data in global array */
+ size_t prim_offset = pack.prim_index.size();
+ size_t nodes_offset = nodes_size;
+ size_t nodes_leaf_offset = leaf_nodes_size;
+
+ /* clear array that gives the node indexes for instanced objects */
+ pack.object_node.clear();
+
+ /* reserve */
+ size_t prim_index_size = pack.prim_index.size();
+ size_t prim_tri_verts_size = pack.prim_tri_verts.size();
+
+ size_t pack_prim_index_offset = prim_index_size;
+ size_t pack_prim_tri_verts_offset = prim_tri_verts_size;
+ size_t pack_nodes_offset = nodes_size;
+ size_t pack_leaf_nodes_offset = leaf_nodes_size;
+ size_t object_offset = 0;
+
+ foreach (Geometry *geom, geometry) {
+ BVH2 *bvh = static_cast<BVH2 *>(geom->bvh);
+
+ if (geom->need_build_bvh(params.bvh_layout)) {
+ prim_index_size += bvh->pack.prim_index.size();
+ prim_tri_verts_size += bvh->pack.prim_tri_verts.size();
+ nodes_size += bvh->pack.nodes.size();
+ leaf_nodes_size += bvh->pack.leaf_nodes.size();
+ }
+ }
+
+ pack.prim_index.resize(prim_index_size);
+ pack.prim_type.resize(prim_index_size);
+ pack.prim_object.resize(prim_index_size);
+ pack.prim_visibility.resize(prim_index_size);
+ pack.prim_tri_verts.resize(prim_tri_verts_size);
+ pack.prim_tri_index.resize(prim_index_size);
+ pack.nodes.resize(nodes_size);
+ pack.leaf_nodes.resize(leaf_nodes_size);
+ pack.object_node.resize(objects.size());
+
+ if (params.num_motion_curve_steps > 0 || params.num_motion_triangle_steps > 0) {
+ pack.prim_time.resize(prim_index_size);
+ }
+
+ int *pack_prim_index = (pack.prim_index.size()) ? &pack.prim_index[0] : NULL;
+ int *pack_prim_type = (pack.prim_type.size()) ? &pack.prim_type[0] : NULL;
+ int *pack_prim_object = (pack.prim_object.size()) ? &pack.prim_object[0] : NULL;
+ uint *pack_prim_visibility = (pack.prim_visibility.size()) ? &pack.prim_visibility[0] : NULL;
+ float4 *pack_prim_tri_verts = (pack.prim_tri_verts.size()) ? &pack.prim_tri_verts[0] : NULL;
+ uint *pack_prim_tri_index = (pack.prim_tri_index.size()) ? &pack.prim_tri_index[0] : NULL;
+ int4 *pack_nodes = (pack.nodes.size()) ? &pack.nodes[0] : NULL;
+ int4 *pack_leaf_nodes = (pack.leaf_nodes.size()) ? &pack.leaf_nodes[0] : NULL;
+ float2 *pack_prim_time = (pack.prim_time.size()) ? &pack.prim_time[0] : NULL;
+
+ unordered_map<Geometry *, int> geometry_map;
+
+ /* merge */
+ foreach (Object *ob, objects) {
+ Geometry *geom = ob->get_geometry();
+
+ /* We assume that if mesh doesn't need own BVH it was already included
+ * into a top-level BVH and no packing here is needed.
+ */
+ if (!geom->need_build_bvh(params.bvh_layout)) {
+ pack.object_node[object_offset++] = 0;
+ continue;
+ }
+
+ /* if mesh already added once, don't add it again, but used set
+ * node offset for this object */
+ unordered_map<Geometry *, int>::iterator it = geometry_map.find(geom);
+
+ if (geometry_map.find(geom) != geometry_map.end()) {
+ int noffset = it->second;
+ pack.object_node[object_offset++] = noffset;
+ continue;
+ }
+
+ BVH2 *bvh = static_cast<BVH2 *>(geom->bvh);
+
+ int noffset = nodes_offset;
+ int noffset_leaf = nodes_leaf_offset;
+ int geom_prim_offset = geom->prim_offset;
+
+ /* fill in node indexes for instances */
+ if (bvh->pack.root_index == -1)
+ pack.object_node[object_offset++] = -noffset_leaf - 1;
+ else
+ pack.object_node[object_offset++] = noffset;
+
+ geometry_map[geom] = pack.object_node[object_offset - 1];
+
+ /* merge primitive, object and triangle indexes */
+ if (bvh->pack.prim_index.size()) {
+ size_t bvh_prim_index_size = bvh->pack.prim_index.size();
+ int *bvh_prim_index = &bvh->pack.prim_index[0];
+ int *bvh_prim_type = &bvh->pack.prim_type[0];
+ uint *bvh_prim_visibility = &bvh->pack.prim_visibility[0];
+ uint *bvh_prim_tri_index = &bvh->pack.prim_tri_index[0];
+ float2 *bvh_prim_time = bvh->pack.prim_time.size() ? &bvh->pack.prim_time[0] : NULL;
+
+ for (size_t i = 0; i < bvh_prim_index_size; i++) {
+ if (bvh->pack.prim_type[i] & PRIMITIVE_ALL_CURVE) {
+ pack_prim_index[pack_prim_index_offset] = bvh_prim_index[i] + geom_prim_offset;
+ pack_prim_tri_index[pack_prim_index_offset] = -1;
+ }
+ else {
+ pack_prim_index[pack_prim_index_offset] = bvh_prim_index[i] + geom_prim_offset;
+ pack_prim_tri_index[pack_prim_index_offset] = bvh_prim_tri_index[i] +
+ pack_prim_tri_verts_offset;
+ }
+
+ pack_prim_type[pack_prim_index_offset] = bvh_prim_type[i];
+ pack_prim_visibility[pack_prim_index_offset] = bvh_prim_visibility[i];
+ pack_prim_object[pack_prim_index_offset] = 0; // unused for instances
+ if (bvh_prim_time != NULL) {
+ pack_prim_time[pack_prim_index_offset] = bvh_prim_time[i];
+ }
+ pack_prim_index_offset++;
+ }
+ }
+
+ /* Merge triangle vertices data. */
+ if (bvh->pack.prim_tri_verts.size()) {
+ const size_t prim_tri_size = bvh->pack.prim_tri_verts.size();
+ memcpy(pack_prim_tri_verts + pack_prim_tri_verts_offset,
+ &bvh->pack.prim_tri_verts[0],
+ prim_tri_size * sizeof(float4));
+ pack_prim_tri_verts_offset += prim_tri_size;
+ }
+
+ /* merge nodes */
+ if (bvh->pack.leaf_nodes.size()) {
+ int4 *leaf_nodes_offset = &bvh->pack.leaf_nodes[0];
+ size_t leaf_nodes_offset_size = bvh->pack.leaf_nodes.size();
+ for (size_t i = 0, j = 0; i < leaf_nodes_offset_size; i += BVH_NODE_LEAF_SIZE, j++) {
+ int4 data = leaf_nodes_offset[i];
+ data.x += prim_offset;
+ data.y += prim_offset;
+ pack_leaf_nodes[pack_leaf_nodes_offset] = data;
+ for (int j = 1; j < BVH_NODE_LEAF_SIZE; ++j) {
+ pack_leaf_nodes[pack_leaf_nodes_offset + j] = leaf_nodes_offset[i + j];
+ }
+ pack_leaf_nodes_offset += BVH_NODE_LEAF_SIZE;
+ }
+ }
+
+ if (bvh->pack.nodes.size()) {
+ int4 *bvh_nodes = &bvh->pack.nodes[0];
+ size_t bvh_nodes_size = bvh->pack.nodes.size();
+
+ for (size_t i = 0, j = 0; i < bvh_nodes_size; j++) {
+ size_t nsize, nsize_bbox;
+ if (bvh_nodes[i].x & PATH_RAY_NODE_UNALIGNED) {
+ nsize = BVH_UNALIGNED_NODE_SIZE;
+ nsize_bbox = 0;
+ }
+ else {
+ nsize = BVH_NODE_SIZE;
+ nsize_bbox = 0;
+ }
+
+ memcpy(pack_nodes + pack_nodes_offset, bvh_nodes + i, nsize_bbox * sizeof(int4));
+
+ /* Modify offsets into arrays */
+ int4 data = bvh_nodes[i + nsize_bbox];
+ data.z += (data.z < 0) ? -noffset_leaf : noffset;
+ data.w += (data.w < 0) ? -noffset_leaf : noffset;
+ pack_nodes[pack_nodes_offset + nsize_bbox] = data;
+
+ /* Usually this copies nothing, but we better
+ * be prepared for possible node size extension.
+ */
+ memcpy(&pack_nodes[pack_nodes_offset + nsize_bbox + 1],
+ &bvh_nodes[i + nsize_bbox + 1],
+ sizeof(int4) * (nsize - (nsize_bbox + 1)));
+
+ pack_nodes_offset += nsize;
+ i += nsize;
+ }
+ }
+
+ nodes_offset += bvh->pack.nodes.size();
+ nodes_leaf_offset += bvh->pack.leaf_nodes.size();
+ prim_offset += bvh->pack.prim_index.size();
+ }
+}
+
CCL_NAMESPACE_END
diff --git a/intern/cycles/bvh/bvh2.h b/intern/cycles/bvh/bvh2.h
index fa3e45b72d2..1030a0f76c7 100644
--- a/intern/cycles/bvh/bvh2.h
+++ b/intern/cycles/bvh/bvh2.h
@@ -26,23 +26,30 @@
CCL_NAMESPACE_BEGIN
-class BVHNode;
-struct BVHStackEntry;
-class BVHParams;
-class BoundBox;
-class LeafNode;
-class Object;
-class Progress;
-
#define BVH_NODE_SIZE 4
#define BVH_NODE_LEAF_SIZE 1
#define BVH_UNALIGNED_NODE_SIZE 7
+/* Pack Utility */
+struct BVHStackEntry {
+ const BVHNode *node;
+ int idx;
+
+ BVHStackEntry(const BVHNode *n = 0, int i = 0);
+ int encodeIdx() const;
+};
+
/* BVH2
*
* Typical BVH with each node having two children.
*/
class BVH2 : public BVH {
+ public:
+ void build(Progress &progress, Stats *stats);
+ void refit(Progress &progress);
+
+ PackedBVH pack;
+
protected:
/* constructor */
friend class BVH;
@@ -51,10 +58,10 @@ class BVH2 : public BVH {
const vector<Object *> &objects);
/* Building process. */
- virtual BVHNode *widen_children_nodes(const BVHNode *root) override;
+ virtual BVHNode *widen_children_nodes(const BVHNode *root);
/* pack */
- void pack_nodes(const BVHNode *root) override;
+ void pack_nodes(const BVHNode *root);
void pack_leaf(const BVHStackEntry &e, const LeafNode *leaf);
void pack_inner(const BVHStackEntry &e, const BVHStackEntry &e0, const BVHStackEntry &e1);
@@ -84,8 +91,18 @@ class BVH2 : public BVH {
uint visibility1);
/* refit */
- void refit_nodes() override;
+ void refit_nodes();
void refit_node(int idx, bool leaf, BoundBox &bbox, uint &visibility);
+
+ /* Refit range of primitives. */
+ void refit_primitives(int start, int end, BoundBox &bbox, uint &visibility);
+
+ /* triangles and strands */
+ void pack_primitives();
+ void pack_triangle(int idx, float4 storage[3]);
+
+ /* merge instance BVH's */
+ void pack_instances(size_t nodes_size, size_t leaf_nodes_size);
};
CCL_NAMESPACE_END
diff --git a/intern/cycles/bvh/bvh_embree.cpp b/intern/cycles/bvh/bvh_embree.cpp
index 910e3780b2e..b874bda7186 100644
--- a/intern/cycles/bvh/bvh_embree.cpp
+++ b/intern/cycles/bvh/bvh_embree.cpp
@@ -298,82 +298,31 @@ static bool rtc_progress_func(void *user_ptr, const double n)
return !progress->get_cancel();
}
-static size_t count_primitives(Geometry *geom)
-{
- if (geom->geometry_type == Geometry::MESH || geom->geometry_type == Geometry::VOLUME) {
- Mesh *mesh = static_cast<Mesh *>(geom);
- return mesh->num_triangles();
- }
- else if (geom->geometry_type == Geometry::HAIR) {
- Hair *hair = static_cast<Hair *>(geom);
- return hair->num_segments();
- }
-
- return 0;
-}
-
BVHEmbree::BVHEmbree(const BVHParams &params_,
const vector<Geometry *> &geometry_,
- const vector<Object *> &objects_,
- const Device *device)
+ const vector<Object *> &objects_)
: BVH(params_, geometry_, objects_),
scene(NULL),
- mem_used(0),
- top_level(NULL),
- rtc_device((RTCDevice)device->bvh_device()),
- stats(NULL),
- curve_subdivisions(params.curve_subdivisions),
- build_quality(RTC_BUILD_QUALITY_REFIT),
- dynamic_scene(true)
+ rtc_device(NULL),
+ build_quality(RTC_BUILD_QUALITY_REFIT)
{
_MM_SET_FLUSH_ZERO_MODE(_MM_FLUSH_ZERO_ON);
_MM_SET_DENORMALS_ZERO_MODE(_MM_DENORMALS_ZERO_ON);
-
- rtcSetDeviceErrorFunction(rtc_device, rtc_error_func, NULL);
-
- pack.root_index = -1;
}
BVHEmbree::~BVHEmbree()
{
- if (!params.top_level) {
- destroy(scene);
- }
-}
-
-void BVHEmbree::destroy(RTCScene scene)
-{
if (scene) {
rtcReleaseScene(scene);
- scene = NULL;
- }
-}
-
-void BVHEmbree::delete_rtcScene()
-{
- if (scene) {
- /* When this BVH is used as an instance in a top level BVH, don't delete now
- * Let the top_level BVH know that it should delete it later. */
- if (top_level) {
- top_level->add_delayed_delete_scene(scene);
- }
- else {
- rtcReleaseScene(scene);
- if (delayed_delete_scenes.size()) {
- foreach (RTCScene s, delayed_delete_scenes) {
- rtcReleaseScene(s);
- }
- }
- delayed_delete_scenes.clear();
- }
- scene = NULL;
}
}
-void BVHEmbree::build(Progress &progress, Stats *stats_)
+void BVHEmbree::build(Progress &progress, Stats *stats, RTCDevice rtc_device_)
{
+ rtc_device = rtc_device_;
assert(rtc_device);
- stats = stats_;
+
+ rtcSetDeviceErrorFunction(rtc_device, rtc_error_func, NULL);
rtcSetDeviceMemoryMonitorFunction(rtc_device, rtc_memory_monitor_func, stats);
progress.set_substatus("Building BVH");
@@ -394,35 +343,7 @@ void BVHEmbree::build(Progress &progress, Stats *stats_)
RTC_BUILD_QUALITY_MEDIUM);
rtcSetSceneBuildQuality(scene, build_quality);
- /* Count triangles and curves first, reserve arrays once. */
- size_t prim_count = 0;
-
- foreach (Object *ob, objects) {
- if (params.top_level) {
- if (!ob->is_traceable()) {
- continue;
- }
- if (!ob->get_geometry()->is_instanced()) {
- prim_count += count_primitives(ob->get_geometry());
- }
- else {
- ++prim_count;
- }
- }
- else {
- prim_count += count_primitives(ob->get_geometry());
- }
- }
-
- pack.prim_object.reserve(prim_count);
- pack.prim_type.reserve(prim_count);
- pack.prim_index.reserve(prim_count);
- pack.prim_tri_index.reserve(prim_count);
-
int i = 0;
-
- pack.object_node.clear();
-
foreach (Object *ob, objects) {
if (params.top_level) {
if (!ob->is_traceable()) {
@@ -445,37 +366,11 @@ void BVHEmbree::build(Progress &progress, Stats *stats_)
}
if (progress.get_cancel()) {
- delete_rtcScene();
- stats = NULL;
return;
}
rtcSetSceneProgressMonitorFunction(scene, rtc_progress_func, &progress);
rtcCommitScene(scene);
-
- pack_primitives();
-
- if (progress.get_cancel()) {
- delete_rtcScene();
- stats = NULL;
- return;
- }
-
- progress.set_substatus("Packing geometry");
- pack_nodes(NULL);
-
- stats = NULL;
-}
-
-void BVHEmbree::copy_to_device(Progress & /*progress*/, DeviceScene *dscene)
-{
- dscene->data.bvh.scene = scene;
-}
-
-BVHNode *BVHEmbree::widen_children_nodes(const BVHNode * /*root*/)
-{
- assert(!"Must not be called.");
- return NULL;
}
void BVHEmbree::add_object(Object *ob, int i)
@@ -498,15 +393,8 @@ void BVHEmbree::add_object(Object *ob, int i)
void BVHEmbree::add_instance(Object *ob, int i)
{
- if (!ob || !ob->get_geometry()) {
- assert(0);
- return;
- }
BVHEmbree *instance_bvh = (BVHEmbree *)(ob->get_geometry()->bvh);
-
- if (instance_bvh->top_level != this) {
- instance_bvh->top_level = this;
- }
+ assert(instance_bvh != NULL);
const size_t num_object_motion_steps = ob->use_motion() ? ob->get_motion().size() : 1;
const size_t num_motion_steps = min(num_object_motion_steps, RTC_MAX_TIME_STEP_COUNT);
@@ -538,11 +426,6 @@ void BVHEmbree::add_instance(Object *ob, int i)
geom_id, 0, RTC_FORMAT_FLOAT3X4_ROW_MAJOR, (const float *)&ob->get_tfm());
}
- pack.prim_index.push_back_slow(-1);
- pack.prim_object.push_back_slow(i);
- pack.prim_type.push_back_slow(PRIMITIVE_NONE);
- pack.prim_tri_index.push_back_slow(-1);
-
rtcSetGeometryUserData(geom_id, (void *)instance_bvh->scene);
rtcSetGeometryMask(geom_id, ob->visibility_for_tracing());
@@ -553,20 +436,22 @@ void BVHEmbree::add_instance(Object *ob, int i)
void BVHEmbree::add_triangles(const Object *ob, const Mesh *mesh, int i)
{
- size_t prim_offset = pack.prim_index.size();
+ size_t prim_offset = mesh->optix_prim_offset;
+
const Attribute *attr_mP = NULL;
- size_t num_geometry_motion_steps = 1;
+ size_t num_motion_steps = 1;
if (mesh->has_motion_blur()) {
attr_mP = mesh->attributes.find(ATTR_STD_MOTION_VERTEX_POSITION);
if (attr_mP) {
- num_geometry_motion_steps = mesh->get_motion_steps();
+ num_motion_steps = mesh->get_motion_steps();
}
}
- const size_t num_motion_steps = min(num_geometry_motion_steps, RTC_MAX_TIME_STEP_COUNT);
- assert(num_geometry_motion_steps <= RTC_MAX_TIME_STEP_COUNT);
+ assert(num_motion_steps <= RTC_MAX_TIME_STEP_COUNT);
+ num_motion_steps = min(num_motion_steps, RTC_MAX_TIME_STEP_COUNT);
const size_t num_triangles = mesh->num_triangles();
+
RTCGeometry geom_id = rtcNewGeometry(rtc_device, RTC_GEOMETRY_TYPE_TRIANGLE);
rtcSetGeometryBuildQuality(geom_id, build_quality);
rtcSetGeometryTimeStepCount(geom_id, num_motion_steps);
@@ -588,22 +473,6 @@ void BVHEmbree::add_triangles(const Object *ob, const Mesh *mesh, int i)
set_tri_vertex_buffer(geom_id, mesh, false);
- size_t prim_object_size = pack.prim_object.size();
- pack.prim_object.resize(prim_object_size + num_triangles);
- size_t prim_type_size = pack.prim_type.size();
- pack.prim_type.resize(prim_type_size + num_triangles);
- size_t prim_index_size = pack.prim_index.size();
- pack.prim_index.resize(prim_index_size + num_triangles);
- pack.prim_tri_index.resize(prim_index_size + num_triangles);
- int prim_type = (num_motion_steps > 1 ? PRIMITIVE_MOTION_TRIANGLE : PRIMITIVE_TRIANGLE);
-
- for (size_t j = 0; j < num_triangles; ++j) {
- pack.prim_object[prim_object_size + j] = i;
- pack.prim_type[prim_type_size + j] = prim_type;
- pack.prim_index[prim_index_size + j] = j;
- pack.prim_tri_index[prim_index_size + j] = j;
- }
-
rtcSetGeometryUserData(geom_id, (void *)prim_offset);
rtcSetGeometryOccludedFilterFunction(geom_id, rtc_filter_occluded_func);
rtcSetGeometryMask(geom_id, ob->visibility_for_tracing());
@@ -629,12 +498,12 @@ void BVHEmbree::set_tri_vertex_buffer(RTCGeometry geom_id, const Mesh *mesh, con
}
}
}
- const size_t num_verts = mesh->verts.size();
+ const size_t num_verts = mesh->get_verts().size();
for (int t = 0; t < num_motion_steps; ++t) {
const float3 *verts;
if (t == t_mid) {
- verts = &mesh->verts[0];
+ verts = mesh->get_verts().data();
}
else {
int t_ = (t > t_mid) ? (t - 1) : t;
@@ -736,24 +605,19 @@ void BVHEmbree::set_curve_vertex_buffer(RTCGeometry geom_id, const Hair *hair, c
void BVHEmbree::add_curves(const Object *ob, const Hair *hair, int i)
{
- size_t prim_offset = pack.prim_index.size();
+ size_t prim_offset = hair->optix_prim_offset;
+
const Attribute *attr_mP = NULL;
- size_t num_geometry_motion_steps = 1;
+ size_t num_motion_steps = 1;
if (hair->has_motion_blur()) {
attr_mP = hair->attributes.find(ATTR_STD_MOTION_VERTEX_POSITION);
if (attr_mP) {
- num_geometry_motion_steps = hair->get_motion_steps();
+ num_motion_steps = hair->get_motion_steps();
}
}
- const size_t num_motion_steps = min(num_geometry_motion_steps, RTC_MAX_TIME_STEP_COUNT);
- const PrimitiveType primitive_type =
- (num_motion_steps > 1) ?
- ((hair->curve_shape == CURVE_RIBBON) ? PRIMITIVE_MOTION_CURVE_RIBBON :
- PRIMITIVE_MOTION_CURVE_THICK) :
- ((hair->curve_shape == CURVE_RIBBON) ? PRIMITIVE_CURVE_RIBBON : PRIMITIVE_CURVE_THICK);
-
- assert(num_geometry_motion_steps <= RTC_MAX_TIME_STEP_COUNT);
+ assert(num_motion_steps <= RTC_MAX_TIME_STEP_COUNT);
+ num_motion_steps = min(num_motion_steps, RTC_MAX_TIME_STEP_COUNT);
const size_t num_curves = hair->num_curves();
size_t num_segments = 0;
@@ -763,22 +627,12 @@ void BVHEmbree::add_curves(const Object *ob, const Hair *hair, int i)
num_segments += c.num_segments();
}
- /* Make room for Cycles specific data. */
- size_t prim_object_size = pack.prim_object.size();
- pack.prim_object.resize(prim_object_size + num_segments);
- size_t prim_type_size = pack.prim_type.size();
- pack.prim_type.resize(prim_type_size + num_segments);
- size_t prim_index_size = pack.prim_index.size();
- pack.prim_index.resize(prim_index_size + num_segments);
- size_t prim_tri_index_size = pack.prim_index.size();
- pack.prim_tri_index.resize(prim_tri_index_size + num_segments);
-
enum RTCGeometryType type = (hair->curve_shape == CURVE_RIBBON ?
RTC_GEOMETRY_TYPE_FLAT_CATMULL_ROM_CURVE :
RTC_GEOMETRY_TYPE_ROUND_CATMULL_ROM_CURVE);
RTCGeometry geom_id = rtcNewGeometry(rtc_device, type);
- rtcSetGeometryTessellationRate(geom_id, curve_subdivisions + 1);
+ rtcSetGeometryTessellationRate(geom_id, params.curve_subdivisions + 1);
unsigned *rtc_indices = (unsigned *)rtcSetNewGeometryBuffer(
geom_id, RTC_BUFFER_TYPE_INDEX, 0, RTC_FORMAT_UINT, sizeof(int), num_segments);
size_t rtc_index = 0;
@@ -788,11 +642,6 @@ void BVHEmbree::add_curves(const Object *ob, const Hair *hair, int i)
rtc_indices[rtc_index] = c.first_key + k;
/* Room for extra CVs at Catmull-Rom splines. */
rtc_indices[rtc_index] += j * 2;
- /* Cycles specific data. */
- pack.prim_object[prim_object_size + rtc_index] = i;
- pack.prim_type[prim_type_size + rtc_index] = (PRIMITIVE_PACK_SEGMENT(primitive_type, k));
- pack.prim_index[prim_index_size + rtc_index] = j;
- pack.prim_tri_index[prim_tri_index_size + rtc_index] = rtc_index;
++rtc_index;
}
@@ -818,134 +667,10 @@ void BVHEmbree::add_curves(const Object *ob, const Hair *hair, int i)
rtcReleaseGeometry(geom_id);
}
-void BVHEmbree::pack_nodes(const BVHNode *)
+void BVHEmbree::refit(Progress &progress)
{
- /* Quite a bit of this code is for compatibility with Cycles' native BVH. */
- if (!params.top_level) {
- return;
- }
-
- for (size_t i = 0; i < pack.prim_index.size(); ++i) {
- if (pack.prim_index[i] != -1) {
- pack.prim_index[i] += objects[pack.prim_object[i]]->get_geometry()->prim_offset;
- }
- }
-
- size_t prim_offset = pack.prim_index.size();
-
- /* reserve */
- size_t prim_index_size = pack.prim_index.size();
- size_t prim_tri_verts_size = pack.prim_tri_verts.size();
-
- size_t pack_prim_index_offset = prim_index_size;
- size_t pack_prim_tri_verts_offset = prim_tri_verts_size;
- size_t object_offset = 0;
-
- map<Geometry *, int> geometry_map;
-
- foreach (Object *ob, objects) {
- Geometry *geom = ob->get_geometry();
- BVH *bvh = geom->bvh;
-
- if (geom->need_build_bvh(BVH_LAYOUT_EMBREE)) {
- if (geometry_map.find(geom) == geometry_map.end()) {
- prim_index_size += bvh->pack.prim_index.size();
- prim_tri_verts_size += bvh->pack.prim_tri_verts.size();
- geometry_map[geom] = 1;
- }
- }
- }
+ progress.set_substatus("Refitting BVH nodes");
- geometry_map.clear();
-
- pack.prim_index.resize(prim_index_size);
- pack.prim_type.resize(prim_index_size);
- pack.prim_object.resize(prim_index_size);
- pack.prim_visibility.clear();
- pack.prim_tri_verts.resize(prim_tri_verts_size);
- pack.prim_tri_index.resize(prim_index_size);
- pack.object_node.resize(objects.size());
-
- int *pack_prim_index = (pack.prim_index.size()) ? &pack.prim_index[0] : NULL;
- int *pack_prim_type = (pack.prim_type.size()) ? &pack.prim_type[0] : NULL;
- int *pack_prim_object = (pack.prim_object.size()) ? &pack.prim_object[0] : NULL;
- float4 *pack_prim_tri_verts = (pack.prim_tri_verts.size()) ? &pack.prim_tri_verts[0] : NULL;
- uint *pack_prim_tri_index = (pack.prim_tri_index.size()) ? &pack.prim_tri_index[0] : NULL;
-
- /* merge */
- foreach (Object *ob, objects) {
- Geometry *geom = ob->get_geometry();
-
- /* We assume that if mesh doesn't need own BVH it was already included
- * into a top-level BVH and no packing here is needed.
- */
- if (!geom->need_build_bvh(BVH_LAYOUT_EMBREE)) {
- pack.object_node[object_offset++] = prim_offset;
- continue;
- }
-
- /* if geom already added once, don't add it again, but used set
- * node offset for this object */
- map<Geometry *, int>::iterator it = geometry_map.find(geom);
-
- if (geometry_map.find(geom) != geometry_map.end()) {
- int noffset = it->second;
- pack.object_node[object_offset++] = noffset;
- continue;
- }
-
- BVHEmbree *bvh = (BVHEmbree *)geom->bvh;
-
- rtc_memory_monitor_func(stats, unaccounted_mem, true);
- unaccounted_mem = 0;
-
- int geom_prim_offset = geom->prim_offset;
-
- /* fill in node indexes for instances */
- pack.object_node[object_offset++] = prim_offset;
-
- geometry_map[geom] = pack.object_node[object_offset - 1];
-
- /* merge primitive, object and triangle indexes */
- if (bvh->pack.prim_index.size()) {
- size_t bvh_prim_index_size = bvh->pack.prim_index.size();
- int *bvh_prim_index = &bvh->pack.prim_index[0];
- int *bvh_prim_type = &bvh->pack.prim_type[0];
- uint *bvh_prim_tri_index = &bvh->pack.prim_tri_index[0];
-
- for (size_t i = 0; i < bvh_prim_index_size; ++i) {
- if (bvh->pack.prim_type[i] & PRIMITIVE_ALL_CURVE) {
- pack_prim_index[pack_prim_index_offset] = bvh_prim_index[i] + geom_prim_offset;
- pack_prim_tri_index[pack_prim_index_offset] = -1;
- }
- else {
- pack_prim_index[pack_prim_index_offset] = bvh_prim_index[i] + geom_prim_offset;
- pack_prim_tri_index[pack_prim_index_offset] = bvh_prim_tri_index[i] +
- pack_prim_tri_verts_offset;
- }
-
- pack_prim_type[pack_prim_index_offset] = bvh_prim_type[i];
- pack_prim_object[pack_prim_index_offset] = 0;
-
- ++pack_prim_index_offset;
- }
- }
-
- /* Merge triangle vertices data. */
- if (bvh->pack.prim_tri_verts.size()) {
- const size_t prim_tri_size = bvh->pack.prim_tri_verts.size();
- memcpy(pack_prim_tri_verts + pack_prim_tri_verts_offset,
- &bvh->pack.prim_tri_verts[0],
- prim_tri_size * sizeof(float4));
- pack_prim_tri_verts_offset += prim_tri_size;
- }
-
- prim_offset += bvh->pack.prim_index.size();
- }
-}
-
-void BVHEmbree::refit_nodes()
-{
/* Update all vertex buffers, then tell Embree to rebuild/-fit the BVHs. */
unsigned geom_id = 0;
foreach (Object *ob, objects) {
@@ -971,8 +696,10 @@ void BVHEmbree::refit_nodes()
}
geom_id += 2;
}
+
rtcCommitScene(scene);
}
+
CCL_NAMESPACE_END
#endif /* WITH_EMBREE */
diff --git a/intern/cycles/bvh/bvh_embree.h b/intern/cycles/bvh/bvh_embree.h
index 3e895e7b588..01636fbd1dc 100644
--- a/intern/cycles/bvh/bvh_embree.h
+++ b/intern/cycles/bvh/bvh_embree.h
@@ -31,56 +31,34 @@
CCL_NAMESPACE_BEGIN
-class Geometry;
class Hair;
class Mesh;
class BVHEmbree : public BVH {
public:
- virtual void build(Progress &progress, Stats *stats) override;
- virtual void copy_to_device(Progress &progress, DeviceScene *dscene) override;
- virtual ~BVHEmbree();
- RTCScene scene;
- static void destroy(RTCScene);
+ void build(Progress &progress, Stats *stats, RTCDevice rtc_device);
+ void refit(Progress &progress);
- /* Building process. */
- virtual BVHNode *widen_children_nodes(const BVHNode *root) override;
+ RTCScene scene;
protected:
friend class BVH;
BVHEmbree(const BVHParams &params,
const vector<Geometry *> &geometry,
- const vector<Object *> &objects,
- const Device *device);
-
- virtual void pack_nodes(const BVHNode *) override;
- virtual void refit_nodes() override;
+ const vector<Object *> &objects);
+ virtual ~BVHEmbree();
void add_object(Object *ob, int i);
void add_instance(Object *ob, int i);
void add_curves(const Object *ob, const Hair *hair, int i);
void add_triangles(const Object *ob, const Mesh *mesh, int i);
- ssize_t mem_used;
-
- void add_delayed_delete_scene(RTCScene scene)
- {
- delayed_delete_scenes.push_back(scene);
- }
- BVHEmbree *top_level;
-
private:
- void delete_rtcScene();
void set_tri_vertex_buffer(RTCGeometry geom_id, const Mesh *mesh, const bool update);
void set_curve_vertex_buffer(RTCGeometry geom_id, const Hair *hair, const bool update);
RTCDevice rtc_device;
-
- Stats *stats;
- vector<RTCScene> delayed_delete_scenes;
- int curve_subdivisions;
enum RTCBuildQuality build_quality;
- bool dynamic_scene;
};
CCL_NAMESPACE_END
diff --git a/intern/cycles/bvh/bvh_multi.cpp b/intern/cycles/bvh/bvh_multi.cpp
new file mode 100644
index 00000000000..a9e771f20f1
--- /dev/null
+++ b/intern/cycles/bvh/bvh_multi.cpp
@@ -0,0 +1,37 @@
+/*
+ * Copyright 2020, Blender Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "bvh/bvh_multi.h"
+
+#include "util/util_foreach.h"
+
+CCL_NAMESPACE_BEGIN
+
+BVHMulti::BVHMulti(const BVHParams &params_,
+ const vector<Geometry *> &geometry_,
+ const vector<Object *> &objects_)
+ : BVH(params_, geometry_, objects_)
+{
+}
+
+BVHMulti::~BVHMulti()
+{
+ foreach (BVH *bvh, sub_bvhs) {
+ delete bvh;
+ }
+}
+
+CCL_NAMESPACE_END
diff --git a/intern/cycles/bvh/bvh_multi.h b/intern/cycles/bvh/bvh_multi.h
new file mode 100644
index 00000000000..840438c5d0c
--- /dev/null
+++ b/intern/cycles/bvh/bvh_multi.h
@@ -0,0 +1,39 @@
+/*
+ * Copyright 2020, Blender Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __BVH_MULTI_H__
+#define __BVH_MULTI_H__
+
+#include "bvh/bvh.h"
+#include "bvh/bvh_params.h"
+
+CCL_NAMESPACE_BEGIN
+
+class BVHMulti : public BVH {
+ public:
+ vector<BVH *> sub_bvhs;
+
+ protected:
+ friend class BVH;
+ BVHMulti(const BVHParams &params,
+ const vector<Geometry *> &geometry,
+ const vector<Object *> &objects);
+ virtual ~BVHMulti();
+};
+
+CCL_NAMESPACE_END
+
+#endif /* __BVH_MULTI_H__ */
diff --git a/intern/cycles/bvh/bvh_optix.cpp b/intern/cycles/bvh/bvh_optix.cpp
index 52fc9c0a50d..e094f339ede 100644
--- a/intern/cycles/bvh/bvh_optix.cpp
+++ b/intern/cycles/bvh/bvh_optix.cpp
@@ -19,212 +19,22 @@
# include "bvh/bvh_optix.h"
-# include "device/device.h"
-
-# include "render/geometry.h"
-# include "render/hair.h"
-# include "render/mesh.h"
-# include "render/object.h"
-
-# include "util/util_foreach.h"
-# include "util/util_logging.h"
-# include "util/util_progress.h"
-
CCL_NAMESPACE_BEGIN
BVHOptiX::BVHOptiX(const BVHParams &params_,
const vector<Geometry *> &geometry_,
- const vector<Object *> &objects_)
- : BVH(params_, geometry_, objects_)
+ const vector<Object *> &objects_,
+ Device *device)
+ : BVH(params_, geometry_, objects_),
+ traversable_handle(0),
+ as_data(device, params_.top_level ? "optix tlas" : "optix blas"),
+ motion_transform_data(device, "optix motion transform")
{
- optix_handle = 0;
- optix_data_handle = 0;
- do_refit = false;
}
BVHOptiX::~BVHOptiX()
{
-}
-
-void BVHOptiX::build(Progress &, Stats *)
-{
- if (params.top_level)
- pack_tlas();
- else
- pack_blas();
-}
-
-void BVHOptiX::copy_to_device(Progress &progress, DeviceScene *dscene)
-{
- progress.set_status("Updating Scene BVH", "Building OptiX acceleration structure");
-
- Device *const device = dscene->bvh_nodes.device;
- if (!device->build_optix_bvh(this))
- progress.set_error("Failed to build OptiX acceleration structure");
-}
-
-void BVHOptiX::pack_blas()
-{
- // Bottom-level BVH can contain multiple primitive types, so merge them:
- assert(geometry.size() == 1 && objects.size() == 1); // These are built per-mesh
- Geometry *const geom = geometry[0];
-
- if (geom->geometry_type == Geometry::HAIR) {
- Hair *const hair = static_cast<Hair *const>(geom);
- if (hair->num_curves() > 0) {
- const size_t num_curves = hair->num_curves();
- const size_t num_segments = hair->num_segments();
- pack.prim_type.reserve(pack.prim_type.size() + num_segments);
- pack.prim_index.reserve(pack.prim_index.size() + num_segments);
- pack.prim_object.reserve(pack.prim_object.size() + num_segments);
- // 'pack.prim_time' is only used in geom_curve_intersect.h
- // It is not needed because of OPTIX_MOTION_FLAG_[START|END]_VANISH
-
- uint type = (hair->get_use_motion_blur() &&
- hair->attributes.find(ATTR_STD_MOTION_VERTEX_POSITION)) ?
- ((hair->curve_shape == CURVE_RIBBON) ? PRIMITIVE_MOTION_CURVE_RIBBON :
- PRIMITIVE_MOTION_CURVE_THICK) :
- ((hair->curve_shape == CURVE_RIBBON) ? PRIMITIVE_CURVE_RIBBON :
- PRIMITIVE_CURVE_THICK);
-
- for (size_t j = 0; j < num_curves; ++j) {
- const Hair::Curve curve = hair->get_curve(j);
- for (size_t k = 0; k < curve.num_segments(); ++k) {
- pack.prim_type.push_back_reserved(PRIMITIVE_PACK_SEGMENT(type, k));
- // Each curve segment points back to its curve index
- pack.prim_index.push_back_reserved(j);
- pack.prim_object.push_back_reserved(0);
- }
- }
- }
- }
- else if (geom->geometry_type == Geometry::MESH || geom->geometry_type == Geometry::VOLUME) {
- Mesh *const mesh = static_cast<Mesh *const>(geom);
- if (mesh->num_triangles() > 0) {
- const size_t num_triangles = mesh->num_triangles();
- pack.prim_type.reserve(pack.prim_type.size() + num_triangles);
- pack.prim_index.reserve(pack.prim_index.size() + num_triangles);
- pack.prim_object.reserve(pack.prim_object.size() + num_triangles);
-
- uint type = PRIMITIVE_TRIANGLE;
- if (mesh->get_use_motion_blur() && mesh->attributes.find(ATTR_STD_MOTION_VERTEX_POSITION))
- type = PRIMITIVE_MOTION_TRIANGLE;
-
- for (size_t k = 0; k < num_triangles; ++k) {
- pack.prim_type.push_back_reserved(type);
- pack.prim_index.push_back_reserved(k);
- pack.prim_object.push_back_reserved(0);
- }
- }
- }
-
- // Initialize visibility to zero and later update it during top-level build
- uint prev_visibility = objects[0]->get_visibility();
- objects[0]->set_visibility(0);
-
- // Update 'pack.prim_tri_index', 'pack.prim_tri_verts' and 'pack.prim_visibility'
- pack_primitives();
-
- // Reset visibility after packing
- objects[0]->set_visibility(prev_visibility);
-}
-
-void BVHOptiX::pack_tlas()
-{
- // Calculate total packed size
- size_t prim_index_size = 0;
- size_t prim_tri_verts_size = 0;
- foreach (Geometry *geom, geometry) {
- BVH *const bvh = geom->bvh;
- prim_index_size += bvh->pack.prim_index.size();
- prim_tri_verts_size += bvh->pack.prim_tri_verts.size();
- }
-
- if (prim_index_size == 0)
- return; // Abort right away if this is an empty BVH
-
- size_t pack_offset = 0;
- size_t pack_verts_offset = 0;
-
- pack.prim_type.resize(prim_index_size);
- int *pack_prim_type = pack.prim_type.data();
- pack.prim_index.resize(prim_index_size);
- int *pack_prim_index = pack.prim_index.data();
- pack.prim_object.resize(prim_index_size);
- int *pack_prim_object = pack.prim_object.data();
- pack.prim_visibility.resize(prim_index_size);
- uint *pack_prim_visibility = pack.prim_visibility.data();
- pack.prim_tri_index.resize(prim_index_size);
- uint *pack_prim_tri_index = pack.prim_tri_index.data();
- pack.prim_tri_verts.resize(prim_tri_verts_size);
- float4 *pack_prim_tri_verts = pack.prim_tri_verts.data();
-
- // Top-level BVH should only contain instances, see 'Geometry::need_build_bvh'
- // Iterate over scene mesh list instead of objects, since the 'prim_offset' is calculated based
- // on that list, which may be ordered differently from the object list.
- foreach (Geometry *geom, geometry) {
- PackedBVH &bvh_pack = geom->bvh->pack;
- int geom_prim_offset = geom->prim_offset;
-
- // Merge visibility flags of all objects and fix object indices for non-instanced geometry
- int object_index = 0; // Unused for instanced geometry
- int object_visibility = 0;
- foreach (Object *ob, objects) {
- if (ob->get_geometry() == geom) {
- object_visibility |= ob->visibility_for_tracing();
- if (!geom->is_instanced()) {
- object_index = ob->get_device_index();
- break;
- }
- }
- }
-
- // Merge primitive, object and triangle indexes
- if (!bvh_pack.prim_index.empty()) {
- int *bvh_prim_type = &bvh_pack.prim_type[0];
- int *bvh_prim_index = &bvh_pack.prim_index[0];
- uint *bvh_prim_tri_index = &bvh_pack.prim_tri_index[0];
- uint *bvh_prim_visibility = &bvh_pack.prim_visibility[0];
-
- for (size_t i = 0; i < bvh_pack.prim_index.size(); i++, pack_offset++) {
- if (bvh_pack.prim_type[i] & PRIMITIVE_ALL_CURVE) {
- pack_prim_index[pack_offset] = bvh_prim_index[i] + geom_prim_offset;
- pack_prim_tri_index[pack_offset] = -1;
- }
- else {
- pack_prim_index[pack_offset] = bvh_prim_index[i] + geom_prim_offset;
- pack_prim_tri_index[pack_offset] = bvh_prim_tri_index[i] + pack_verts_offset;
- }
-
- pack_prim_type[pack_offset] = bvh_prim_type[i];
- pack_prim_object[pack_offset] = object_index;
- pack_prim_visibility[pack_offset] = bvh_prim_visibility[i] | object_visibility;
- }
- }
-
- // Merge triangle vertex data
- if (!bvh_pack.prim_tri_verts.empty()) {
- const size_t prim_tri_size = bvh_pack.prim_tri_verts.size();
- memcpy(pack_prim_tri_verts + pack_verts_offset,
- bvh_pack.prim_tri_verts.data(),
- prim_tri_size * sizeof(float4));
- pack_verts_offset += prim_tri_size;
- }
- }
-}
-
-void BVHOptiX::pack_nodes(const BVHNode *)
-{
-}
-
-void BVHOptiX::refit_nodes()
-{
- do_refit = true;
-}
-
-BVHNode *BVHOptiX::widen_children_nodes(const BVHNode *)
-{
- return NULL;
+ // Acceleration structure memory is freed via the 'as_data' destructor
}
CCL_NAMESPACE_END
diff --git a/intern/cycles/bvh/bvh_optix.h b/intern/cycles/bvh/bvh_optix.h
index 663cba67260..aa514beae0d 100644
--- a/intern/cycles/bvh/bvh_optix.h
+++ b/intern/cycles/bvh/bvh_optix.h
@@ -26,33 +26,19 @@
CCL_NAMESPACE_BEGIN
-class Geometry;
-class Optix;
-
class BVHOptiX : public BVH {
- friend class BVH;
-
public:
- uint64_t optix_handle;
- uint64_t optix_data_handle;
- bool do_refit;
+ uint64_t traversable_handle;
+ device_only_memory<char> as_data;
+ device_only_memory<char> motion_transform_data;
+ protected:
+ friend class BVH;
BVHOptiX(const BVHParams &params,
const vector<Geometry *> &geometry,
- const vector<Object *> &objects);
+ const vector<Object *> &objects,
+ Device *device);
virtual ~BVHOptiX();
-
- virtual void build(Progress &progress, Stats *) override;
- virtual void copy_to_device(Progress &progress, DeviceScene *dscene) override;
-
- private:
- void pack_blas();
- void pack_tlas();
-
- virtual void pack_nodes(const BVHNode *) override;
- virtual void refit_nodes() override;
-
- virtual BVHNode *widen_children_nodes(const BVHNode *) override;
};
CCL_NAMESPACE_END