-
Notifications
You must be signed in to change notification settings - Fork 255
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
[✨ feature] Scene: allow bypassing ray intersection acceleration data structures #297
base: master
Are you sure you want to change the base?
Changes from 3 commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -61,10 +61,22 @@ MI_VARIANT Scene<Float, Spectrum>::Scene(const Properties &props) { | |
for (Sensor *sensor: m_sensors) | ||
sensor->set_scene(this); | ||
|
||
if constexpr (dr::is_cuda_v<Float>) | ||
accel_init_gpu(props); | ||
else | ||
accel_init_cpu(props); | ||
// Decide whether to use acceleration data structures for ray intersections | ||
// TODO: do we even want a heuristic? Could lead to surprising changes in performance for the user. | ||
bool naive_intersection_desirable = m_shapes.size() <= 5; | ||
m_use_naive_intersection = | ||
props.get<bool>("use_naive_intersection", naive_intersection_desirable); | ||
if (m_use_naive_intersection) | ||
Log(Info, "The scene will not use acceleration data structures " | ||
"for ray intersections."); | ||
|
||
// Build acceleration data structures if needed | ||
if (!m_use_naive_intersection) { | ||
if constexpr (dr::is_cuda_v<Float>) | ||
accel_init_gpu(props); | ||
else | ||
accel_init_cpu(props); | ||
} | ||
|
||
if (!m_emitters.empty()) { | ||
// Inform environment emitters etc. about the scene bounds | ||
|
@@ -84,10 +96,12 @@ MI_VARIANT Scene<Float, Spectrum>::Scene(const Properties &props) { | |
} | ||
|
||
MI_VARIANT Scene<Float, Spectrum>::~Scene() { | ||
if constexpr (dr::is_cuda_v<Float>) | ||
accel_release_gpu(); | ||
else | ||
accel_release_cpu(); | ||
if (!m_use_naive_intersection) { | ||
if constexpr (dr::is_cuda_v<Float>) | ||
accel_release_gpu(); | ||
else | ||
accel_release_cpu(); | ||
} | ||
|
||
// Trigger deallocation of all instances | ||
m_emitters.clear(); | ||
|
@@ -111,6 +125,27 @@ Scene<Float, Spectrum>::ray_intersect(const Ray3f &ray, uint32_t ray_flags, Mask | |
MI_MASKED_FUNCTION(ProfilerPhase::RayIntersect, active); | ||
DRJIT_MARK_USED(coherent); | ||
|
||
if (m_use_naive_intersection) { | ||
// Naive intersection mode: bypass all acceleration data structures, | ||
// test for intersections explicitly against each shape. | ||
PreliminaryIntersection3f pi = dr::zeros<PreliminaryIntersection3f>(); | ||
|
||
for (size_t shape_index = 0; shape_index < m_shapes.size(); ++shape_index) { | ||
PreliminaryIntersection3f prim_pi = | ||
m_shapes[shape_index]->ray_intersect_preliminary(ray, active); | ||
// TODO: fix masked struct assignment | ||
Mask valid = prim_pi.is_valid() && prim_pi.t < pi.t; | ||
dr::masked(pi.t, valid) = prim_pi.t; | ||
dr::masked(pi.prim_uv, valid) = prim_pi.prim_uv; | ||
dr::masked(pi.prim_index, valid) = prim_pi.prim_index; | ||
dr::masked(pi.shape, valid) = prim_pi.shape; | ||
dr::masked(pi.instance, valid) = prim_pi.instance; | ||
dr::masked(pi.shape_index, valid) = shape_index; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Need to fix this. Currently encountering a compilation error if trying to do a masked assignment to In file included from /home/merlin/Code/mitsuba3-master/src/render/scene.cpp:3:
In file included from /home/merlin/Code/mitsuba3-master/include/mitsuba/render/bsdf.h:4:
/home/merlin/Code/mitsuba3-master/include/mitsuba/render/interaction.h:560:36: error: no type named 'Ray3f' in 'drjit::detail::MaskedArray<mitsuba::Shape<dr::DiffArray<dr::CUDAArray<float>>, Color<dr::DiffArray<dr::CUDAArray<float>>, 3>>>'
using Ray3f = typename Shape_::Ray3f;
~~~~~~~~~~~~~~~~~^~~~~
/home/merlin/Code/mitsuba3-master/ext/drjit/include/drjit/array_router.h:2044:21: note: in instantiation of template class 'mitsuba::PreliminaryIntersection<drjit::detail::MaskedArray<drjit::DiffArray<CUDAArray<float>>>, drjit::detail::MaskedArray<mitsuba::Shape<dr::DiffArray<dr::CUDAArray<float>>, Color<dr::DiffArray<dr::CUDAArray<float>>, 3>>>>' requested here
masked_t<T> result;
^
/home/merlin/Code/mitsuba3-master/src/render/scene.cpp:138:17: note: in instantiation of function template specialization 'drjit::masked<mitsuba::PreliminaryIntersection<drjit::DiffArray<CUDAArray<float>>, mitsuba::Shape<dr::DiffArray<dr::CUDAArray<float>>, Color<dr::DiffArray<dr::CUDAArray<float>>, 3>>>, drjit::DiffArray<drjit::CUDAArray<bool>>>' requested here
dr::masked(pi, valid) = prim_pi;
^
/home/merlin/Code/mitsuba3-master/src/render/scene.cpp:460:22: note: in instantiation of member function 'mitsuba::Scene<drjit::DiffArray<CUDAArray<float>>, mitsuba::Color<drjit::DiffArray<CUDAArray<float>>, 3>>::ray_intersect' requested here
MI_INSTANTIATE_CLASS(Scene)
^ |
||
} | ||
return pi.compute_surface_interaction(ray, ray_flags, | ||
active && pi.is_valid()); | ||
} | ||
|
||
if constexpr (dr::is_cuda_v<Float>) | ||
return ray_intersect_gpu(ray, ray_flags, active); | ||
else | ||
|
@@ -120,6 +155,28 @@ Scene<Float, Spectrum>::ray_intersect(const Ray3f &ray, uint32_t ray_flags, Mask | |
MI_VARIANT typename Scene<Float, Spectrum>::PreliminaryIntersection3f | ||
Scene<Float, Spectrum>::ray_intersect_preliminary(const Ray3f &ray, Mask coherent, Mask active) const { | ||
DRJIT_MARK_USED(coherent); | ||
|
||
if (m_use_naive_intersection) { | ||
// Naive intersection mode: bypass all acceleration data structures, | ||
// test for intersections explicitly against each shape. | ||
PreliminaryIntersection3f pi = dr::zeros<PreliminaryIntersection3f>(); | ||
|
||
for (size_t shape_index = 0; shape_index < m_shapes.size(); ++shape_index) { | ||
PreliminaryIntersection3f prim_pi = | ||
m_shapes[shape_index]->ray_intersect_preliminary(ray, active); | ||
// TODO: fix masked struct assignment | ||
Mask valid = prim_pi.is_valid() && prim_pi.t < pi.t; | ||
dr::masked(pi.t, valid) = prim_pi.t; | ||
dr::masked(pi.prim_uv, valid) = prim_pi.prim_uv; | ||
dr::masked(pi.prim_index, valid) = prim_pi.prim_index; | ||
dr::masked(pi.shape, valid) = prim_pi.shape; | ||
dr::masked(pi.instance, valid) = prim_pi.instance; | ||
dr::masked(pi.shape_index, valid) = shape_index; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Likewise. |
||
} | ||
|
||
return pi; | ||
} | ||
|
||
if constexpr (dr::is_cuda_v<Float>) | ||
return ray_intersect_preliminary_gpu(ray, active); | ||
else | ||
|
@@ -131,6 +188,14 @@ Scene<Float, Spectrum>::ray_test(const Ray3f &ray, Mask coherent, Mask active) c | |
MI_MASKED_FUNCTION(ProfilerPhase::RayTest, active); | ||
DRJIT_MARK_USED(coherent); | ||
|
||
if (m_use_naive_intersection) { | ||
Mask hit = false; | ||
for (const auto &shape : m_shapes) { | ||
hit |= shape->ray_test(ray, active); | ||
} | ||
return hit; | ||
} | ||
|
||
if constexpr (dr::is_cuda_v<Float>) | ||
return ray_test_gpu(ray, active); | ||
else | ||
|
@@ -299,18 +364,20 @@ MI_VARIANT void Scene<Float, Spectrum>::parameters_changed(const std::vector<std | |
if (m_environment) | ||
m_environment->set_scene(this); // TODO use parameters_changed({"scene"}) | ||
|
||
bool accel_is_dirty = false; | ||
for (auto &s : m_shapes) { | ||
accel_is_dirty = s->dirty(); | ||
if (accel_is_dirty) | ||
break; | ||
} | ||
if (!m_use_naive_intersection) { | ||
bool accel_is_dirty = false; | ||
for (auto &s : m_shapes) { | ||
accel_is_dirty = s->dirty(); | ||
if (accel_is_dirty) | ||
break; | ||
} | ||
|
||
if (accel_is_dirty) { | ||
if constexpr (dr::is_cuda_v<Float>) | ||
accel_parameters_changed_gpu(); | ||
else | ||
accel_parameters_changed_cpu(); | ||
if (accel_is_dirty) { | ||
if constexpr (dr::is_cuda_v<Float>) | ||
accel_parameters_changed_gpu(); | ||
else | ||
accel_parameters_changed_cpu(); | ||
} | ||
} | ||
|
||
// Check whether any shape parameters have gradient tracking enabled | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
As discussed with @Speierers, we may not want to enable this feature unless the user explicitly asks for it. The downside is that users may not find out it exists, but it's probably better than creating surprising performance jumps due to this heuristic.