Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Rename bvh #1382

Merged
merged 9 commits into from
Aug 7, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
197 changes: 105 additions & 92 deletions libs/yocto/yocto_bvh.cpp

Large diffs are not rendered by default.

110 changes: 72 additions & 38 deletions libs/yocto/yocto_bvh.h
Original file line number Diff line number Diff line change
Expand Up @@ -66,36 +66,16 @@ using std::vector;
// -----------------------------------------------------------------------------
namespace yocto {

// BVH tree node containing its bounds, indices to the BVH arrays of either
// primitives or internal nodes, the node element type,
// and the split axis. Leaf and internal nodes are identical, except that
// indices refer to primitives for leaf nodes or other nodes for internal nodes.
struct bvh_node {
bbox3f bbox = invalidb3f;
int32_t start = 0;
int16_t num = 0;
int8_t axis = 0;
bool internal = false;
};

// BVH tree stored as a node array with the tree structure is encoded using
// array indices. BVH nodes indices refer to either the node array,
// for internal nodes, or the primitive arrays, for leaf nodes.
// Application data is not stored explicitly.
// Shape BVHs are just the bvh for the shape.
struct shape_bvh {
vector<bvh_node> nodes = {};
vector<int> primitives = {};
bvh_tree bvh = {};
};

// BVH tree stored as a node array with the tree structure is encoded using
// array indices. BVH nodes indices refer to either the node array,
// for internal nodes, or the primitive arrays, for leaf nodes.
// We also store the BVH of the contained shapes.
// Scene BVHs store the bvh for instances and shapes.
// Application data is not stored explicitly.
struct scene_bvh {
vector<bvh_node> nodes = {};
vector<int> primitives = {};
vector<shape_bvh> shapes = {}; // shapes
bvh_tree bvh = {};
vector<shape_bvh> shapes = {};
};

// Build the bvh acceleration structure.
Expand Down Expand Up @@ -150,39 +130,41 @@ scene_intersection overlap_scene_bvh(const scene_bvh& bvh,
// -----------------------------------------------------------------------------
namespace yocto {

// Wrapper for Intel's Embree
using ebvh_tree = unique_ptr<void, void (*)(void*)>;

// Wrapper for Intel Embree.
struct shape_embree_bvh {
unique_ptr<void, void (*)(void*)> embree_bvh = {nullptr, nullptr}; // embree
struct shape_ebvh {
ebvh_tree ebvh = {nullptr, nullptr};
};

// Wrapper for Intel Embree.
struct scene_embree_bvh {
vector<shape_embree_bvh> shapes = {}; // shapes
unique_ptr<void, void (*)(void*)> embree_bvh = {nullptr, nullptr}; // embree
struct scene_ebvh {
ebvh_tree ebvh = {nullptr, nullptr}; // instances
vector<shape_ebvh> shapes = {}; // shapes
};

// Check if embree is supported
bool embree_supported();

// Build the bvh acceleration structure.
shape_embree_bvh make_shape_embree_bvh(
const shape_data& shape, bool highquality = false);
scene_embree_bvh make_scene_embree_bvh(
shape_ebvh make_shape_ebvh(const shape_data& shape, bool highquality = false);
scene_ebvh make_scene_ebvh(
const scene_data& scene, bool highquality = false, bool noparallel = false);

// Refit bvh data
void update_shape_embree_bvh(shape_embree_bvh& bvh, const shape_data& shape);
void update_scene_embree_bvh(scene_embree_bvh& bvh, const scene_data& scene,
void update_shape_ebvh(shape_ebvh& bvh, const shape_data& shape);
void update_scene_ebvh(scene_ebvh& bvh, const scene_data& scene,
const vector<int>& updated_instances, const vector<int>& updated_shapes);

// Intersect ray with a bvh returning either the first or any intersection
// depending on `find_any`. Returns the ray distance , the instance id,
// the shape element index and the element barycentric coordinates.
shape_intersection intersect_shape_embree_bvh(const shape_embree_bvh& bvh,
shape_intersection intersect_shape_ebvh(const shape_ebvh& bvh,
const shape_data& shape, const ray3f& ray, bool find_any = false);
scene_intersection intersect_scene_embree_bvh(const scene_embree_bvh& bvh,
scene_intersection intersect_scene_ebvh(const scene_ebvh& bvh,
const scene_data& scene, const ray3f& ray, bool find_any = false);
scene_intersection intersect_instance_embree_bvh(const scene_embree_bvh& bvh,
scene_intersection intersect_instance_ebvh(const scene_ebvh& bvh,
const scene_data& scene, int instance, const ray3f& ray,
bool find_any = false);

Expand Down Expand Up @@ -272,4 +254,56 @@ using bvh_scene [[deprecated]] = scene_bvh;

} // namespace yocto

// -----------------------------------------------------------------------------
// EMBREE BACKWARD COMPATIBILITY
// -----------------------------------------------------------------------------
namespace yocto {

// backward compatibility
using shape_embree_bvh = shape_ebvh;
using scene_embree_bvh = scene_ebvh;

// Build the bvh acceleration structure.
[[deprecated]] inline shape_embree_bvh make_shape_embree_bvh(
const shape_data& shape, bool highquality = false) {
return make_shape_ebvh(shape, highquality);
}
[[deprecated]] inline scene_embree_bvh make_scene_embree_bvh(
const scene_data& scene, bool highquality = false,
bool noparallel = false) {
return make_scene_ebvh(scene, highquality, noparallel);
}

// Refit bvh data
[[deprecated]] inline void update_shape_embree_bvh(
shape_embree_bvh& bvh, const shape_data& shape) {
return update_shape_ebvh(bvh, shape);
}
[[deprecated]] inline void update_scene_embree_bvh(scene_ebvh& bvh,
const scene_data& scene, const vector<int>& updated_instances,
const vector<int>& updated_shapes) {
return update_scene_ebvh(bvh, scene, updated_instances, updated_shapes);
}

// Intersect ray with a bvh returning either the first or any intersection
// depending on `find_any`. Returns the ray distance , the instance id,
// the shape element index and the element barycentric coordinates.
[[deprecated]] inline shape_intersection intersect_shape_embree_bvh(
const shape_ebvh& bvh, const shape_data& shape, const ray3f& ray,
bool find_any = false) {
return intersect_shape_ebvh(bvh, shape, ray, find_any);
}
[[deprecated]] inline scene_intersection intersect_scene_embree_bvh(
const scene_ebvh& bvh, const scene_data& scene, const ray3f& ray,
bool find_any = false) {
return intersect_scene_ebvh(bvh, scene, ray, find_any);
}
[[deprecated]] inline scene_intersection intersect_instance_embree_bvh(
const scene_ebvh& bvh, const scene_data& scene, int instance,
const ray3f& ray, bool find_any = false) {
return intersect_instance_ebvh(bvh, scene, instance, ray, find_any);
}

} // namespace yocto

#endif
68 changes: 42 additions & 26 deletions libs/yocto/yocto_cutrace.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -223,26 +223,42 @@ cuscene_data::~cuscene_data() {
clear_buffer(environments);
};

cubvh_data::cubvh_data(cubvh_data&& other) {
cubvh_tree::cubvh_tree(cubvh_tree&& other) {
buffer.swap(other.buffer);
std::swap(handle, other.handle);
}
cubvh_tree& cubvh_tree::operator=(cubvh_tree&& other) {
buffer.swap(other.buffer);
std::swap(handle, other.handle);
return *this;
}
cubvh_tree::~cubvh_tree() { clear_buffer(buffer); }

cushape_bvh::cushape_bvh(cushape_bvh&& other) {
bvh.buffer.swap(other.bvh.buffer);
std::swap(bvh.handle, other.bvh.handle);
}
cushape_bvh& cushape_bvh::operator=(cushape_bvh&& other) {
bvh.buffer.swap(other.bvh.buffer);
std::swap(bvh.handle, other.bvh.handle);
return *this;
}
cushape_bvh::~cushape_bvh() {}

cuscene_bvh::cuscene_bvh(cuscene_bvh&& other) {
instances.swap(other.instances);
shapes_bvhs.swap(other.shapes_bvhs);
instances_bvh.buffer.swap(other.instances_bvh.buffer);
std::swap(instances_bvh.handle, other.instances_bvh.handle);
shapes.swap(other.shapes);
bvh.buffer.swap(other.bvh.buffer);
std::swap(bvh.handle, other.bvh.handle);
}
cubvh_data& cubvh_data::operator=(cubvh_data&& other) {
cuscene_bvh& cuscene_bvh::operator=(cuscene_bvh&& other) {
instances.swap(other.instances);
shapes_bvhs.swap(other.shapes_bvhs);
instances_bvh.buffer.swap(other.instances_bvh.buffer);
std::swap(instances_bvh.handle, other.instances_bvh.handle);
shapes.swap(other.shapes);
bvh.buffer.swap(other.bvh.buffer);
std::swap(bvh.handle, other.bvh.handle);
return *this;
}
cubvh_data::~cubvh_data() {
for (auto& shape_bvh : shapes_bvhs) {
clear_buffer(shape_bvh.buffer);
// TODO: bvh
}
clear_buffer(instances);
}
cuscene_bvh::~cuscene_bvh() { clear_buffer(instances); }

cutrace_context::cutrace_context(cutrace_context&& other) {
std::swap(denoiser, other.denoiser);
Expand Down Expand Up @@ -505,7 +521,7 @@ cutrace_context make_cutrace_context(const trace_params& params) {

// start a new render
void trace_start(cutrace_context& context, cutrace_state& state,
const cuscene_data& cuscene, const cubvh_data& bvh,
const cuscene_data& cuscene, const cuscene_bvh& bvh,
const cutrace_lights& lights, const scene_data& scene,
const trace_params& params) {
auto globals = cutrace_globals{};
Expand All @@ -514,7 +530,7 @@ void trace_start(cutrace_context& context, cutrace_state& state,
update_buffer_value(context.cuda_stream, context.globals_buffer,
offsetof(cutrace_globals, scene), cuscene);
update_buffer_value(context.cuda_stream, context.globals_buffer,
offsetof(cutrace_globals, bvh), bvh.instances_bvh.handle);
offsetof(cutrace_globals, bvh), bvh.bvh.handle);
update_buffer_value(context.cuda_stream, context.globals_buffer,
offsetof(cutrace_globals, lights), lights);
update_buffer_value(context.cuda_stream, context.globals_buffer,
Expand All @@ -525,7 +541,7 @@ void trace_start(cutrace_context& context, cutrace_state& state,

// render a batch of samples
void trace_samples(cutrace_context& context, cutrace_state& state,
const cuscene_data& cuscene, const cubvh_data& bvh,
const cuscene_data& cuscene, const cuscene_bvh& bvh,
const cutrace_lights& lights, const scene_data& scene,
const trace_params& params) {
if (state.samples >= params.samples) return;
Expand Down Expand Up @@ -700,9 +716,9 @@ void update_cutrace_cameras(cutrace_context& context, cuscene_data& cuscene,
sync_gpu(context.cuda_stream);
}

cubvh_data make_cutrace_bvh(cutrace_context& context, const cuscene_data& scene,
const trace_params& params) {
auto bvh = cubvh_data{};
cutrace_bvh make_cutrace_bvh(cutrace_context& context,
const cuscene_data& scene, const trace_params& params) {
auto bvh = cutrace_bvh{};

// download shapes and instances
// this is not efficient, but keeps the API very clean
Expand All @@ -711,7 +727,7 @@ cubvh_data make_cutrace_bvh(cutrace_context& context, const cuscene_data& scene,
auto instances_data = download_buffer_vector(scene.instances);

// shapes
bvh.shapes_bvhs.resize(scene.shapes.size());
bvh.shapes.resize(scene.shapes.size());
for (auto shape_id = (size_t)0; shape_id < scene.shapes.size(); shape_id++) {
auto& shape = shapes_data[shape_id];

Expand Down Expand Up @@ -757,7 +773,7 @@ cubvh_data make_cutrace_bvh(cutrace_context& context, const cuscene_data& scene,
context.cuda_stream, accelerator_sizes.tempSizeInBytes, (byte*)nullptr);
auto bvh_buffer = make_buffer(context.cuda_stream,
accelerator_sizes.outputSizeInBytes, (byte*)nullptr);
auto& sbvh = bvh.shapes_bvhs[shape_id];
auto& sbvh = bvh.shapes[shape_id].bvh;
check_result(optixAccelBuild(context.optix_context,
/* cuda_stream */ 0, &accelerator_options, &built_input, (int)1,
temporary_buffer.device_ptr(), temporary_buffer.size_in_bytes(),
Expand Down Expand Up @@ -796,7 +812,7 @@ cubvh_data make_cutrace_bvh(cutrace_context& context, const cuscene_data& scene,
memcpy(opinstance.transform, &transform, sizeof(float) * 12);
opinstance.sbtOffset = 0;
opinstance.instanceId = instance_id;
opinstance.traversableHandle = bvh.shapes_bvhs[instance.shape].handle;
opinstance.traversableHandle = bvh.shapes[instance.shape].bvh.handle;
opinstance.flags = OPTIX_INSTANCE_FLAG_NONE;
opinstance.visibilityMask = 0xff;
}
Expand Down Expand Up @@ -830,7 +846,7 @@ cubvh_data make_cutrace_bvh(cutrace_context& context, const cuscene_data& scene,
auto bvh_buffer = make_buffer(context.cuda_stream,
accelerator_sizes.outputSizeInBytes, (byte*)nullptr);

auto& ibvh = bvh.instances_bvh;
auto& ibvh = bvh.bvh;
check_result(optixAccelBuild(context.optix_context,
/* cuda_stream */ 0, &accelerator_options, &build_input, (int)1,
temporary_buffer.device_ptr(), temporary_buffer.size_in_bytes(),
Expand Down Expand Up @@ -979,7 +995,7 @@ image_data cutrace_image(const scene_data& scene, const trace_params& params) {

// render preview
void trace_preview(image_data& image, cutrace_context& context,
cutrace_state& pstate, const cuscene_data& cuscene, const cubvh_data& bvh,
cutrace_state& pstate, const cuscene_data& cuscene, const cutrace_bvh& bvh,
const cutrace_lights& lights, const scene_data& scene,
const trace_params& params) {
auto pparams = params;
Expand Down
45 changes: 30 additions & 15 deletions libs/yocto/yocto_cutrace.h
Original file line number Diff line number Diff line change
Expand Up @@ -79,10 +79,11 @@ namespace yocto {

// forward declarations
struct cuscene_data;
struct cubvh_data;
struct cuscene_bvh;
struct cutrace_state;
struct cutrace_lights;
struct cutrace_context;
using cutrace_bvh = cuscene_bvh;

// Initialize GPU context.
cutrace_context make_cutrace_context(const trace_params& params);
Expand All @@ -94,7 +95,7 @@ void update_cutrace_cameras(cutrace_context& context, cuscene_data& cuscene,
const scene_data& scene, const trace_params& params);

// Build the bvh acceleration structure.
cubvh_data make_cutrace_bvh(cutrace_context& context,
cutrace_bvh make_cutrace_bvh(cutrace_context& context,
const cuscene_data& cuscene, const trace_params& params);

// Initialize state.
Expand All @@ -109,18 +110,18 @@ cutrace_lights make_cutrace_lights(cutrace_context& context,

// Start rendering an image.
void trace_start(cutrace_context& context, cutrace_state& state,
const cuscene_data& cuscene, const cubvh_data& bvh,
const cuscene_data& cuscene, const cutrace_bvh& bvh,
const cutrace_lights& lights, const scene_data& scene,
const trace_params& params);

// Progressively computes an image.
void trace_samples(cutrace_context& context, cutrace_state& state,
const cuscene_data& cuscene, const cubvh_data& bvh,
const cuscene_data& cuscene, const cutrace_bvh& bvh,
const cutrace_lights& lights, const scene_data& scene,
const trace_params& params);

void trace_preview(image_data& image, cutrace_context& context,
cutrace_state& pstate, const cuscene_data& cuscene, const cubvh_data& bvh,
cutrace_state& pstate, const cuscene_data& cuscene, const cutrace_bvh& bvh,
const cutrace_lights& lights, const scene_data& scene,
const trace_params& params);

Expand Down Expand Up @@ -191,8 +192,8 @@ struct cuspan {
CUdeviceptr device_ptr() const { return _data; }
size_t size_in_bytes() const { return _size * sizeof(T); }
void swap(cuspan& other) {
std::swap(_data, other._data);
std::swap(_size, other._size);
std::swap(_data, other._data);
std::swap(_size, other._size);
}

CUdeviceptr _data = 0;
Expand Down Expand Up @@ -281,17 +282,31 @@ struct cuscene_data {
struct cubvh_tree {
cuspan<byte> buffer = {};
OptixTraversableHandle handle = 0;

cubvh_tree() {}
cubvh_tree(cubvh_tree&&);
cubvh_tree& operator=(cubvh_tree&&);
~cubvh_tree();
};

struct cushape_bvh {
cubvh_tree bvh = {};

cushape_bvh() {}
cushape_bvh(cushape_bvh&&);
cushape_bvh& operator=(cushape_bvh&&);
~cushape_bvh();
};

struct cubvh_data {
cuspan<OptixInstance> instances = {};
cubvh_tree instances_bvh = {};
vector<cubvh_tree> shapes_bvhs = {};
struct cuscene_bvh {
cubvh_tree bvh = {};
vector<cushape_bvh> shapes = {};
cuspan<OptixInstance> instances = {};

cubvh_data() {}
cubvh_data(cubvh_data&&);
cubvh_data& operator=(cubvh_data&&);
~cubvh_data();
cuscene_bvh() {}
cuscene_bvh(cuscene_bvh&&);
cuscene_bvh& operator=(cuscene_bvh&&);
~cuscene_bvh();
};

// state
Expand Down
Loading