Skip to content

Commit bf5919b

Browse files
workaround dx ray query bug
1 parent 22011fb commit bf5919b

File tree

2 files changed

+43
-17
lines changed

2 files changed

+43
-17
lines changed

src/base/geometry.cpp

+39-16
Original file line numberDiff line numberDiff line change
@@ -162,12 +162,10 @@ void Geometry::_process_shape(
162162
}
163163
}
164164

165-
void Geometry::_alpha_skip(SurfaceCandidate &c) const noexcept {
166-
auto hit = c.hit();
167-
auto ray = c.ray();
165+
Bool Geometry::_alpha_skip(const Var<Ray> &ray, const Var<SurfaceHit> &hit) const noexcept {
168166
auto bary = make_float3(1.f - hit.bary.x - hit.bary.y, hit.bary);
169167
auto it = interaction(hit.inst, hit.prim, bary, -ray->direction());
170-
auto committed = def(false);
168+
auto skip = def(true);
171169
$if(it->shape().maybe_non_opaque() & it->shape().has_surface()) {
172170
auto u = xxhash32(make_uint4(hit.inst, hit.prim, compute::as<uint2>(hit.bary))) * 0x1p-32f;
173171
$switch(it->shape().surface_tag()) {
@@ -177,23 +175,20 @@ void Geometry::_alpha_skip(SurfaceCandidate &c) const noexcept {
177175
$case(i) {
178176
// TODO: pass the correct swl and time
179177
if (auto opacity = surface->evaluate_opacity(*it, _pipeline.spectrum()->sample(.5f), 0.f)) {
180-
committed = u <= *opacity;
178+
skip = u > *opacity;
181179
} else {
182-
committed = true;
180+
skip = false;
183181
}
184182
};
185-
}
183+
}
186184
}
187185
$default { compute::unreachable(); };
188186
};
189187
}
190188
$else {
191-
committed = true;
192-
};
193-
$if(committed) {
194-
c.commit();
195-
// $if (terminate_on_any) { c.terminate(); };
189+
skip = false;
196190
};
191+
return skip;
197192
}
198193

199194
bool Geometry::update(CommandBuffer &command_buffer, float time) noexcept {
@@ -220,16 +215,42 @@ bool Geometry::update(CommandBuffer &command_buffer, float time) noexcept {
220215
return updated;
221216
}
222217

223-
Var<Hit> Geometry::trace_closest(const Var<Ray> &ray) const noexcept {
218+
Var<Hit> Geometry::trace_closest(const Var<Ray> &ray_in) const noexcept {
224219
if (!_any_non_opaque) {
225220
// happy path
221+
auto hit = _accel->intersect(ray_in, {});
222+
return Var<Hit>{hit.inst, hit.prim, hit.bary};
223+
}
224+
// TODO: DirectX has bug with ray query, so we manually march the ray here
225+
if (_pipeline.device().backend_name() == "dx") {
226+
auto ray = ray_in;
226227
auto hit = _accel->intersect(ray, {});
228+
constexpr auto max_iterations = 100u;
229+
constexpr auto epsilone = 1e-5f;
230+
$for(i [[maybe_unused]], max_iterations) {
231+
$if(hit->miss()) { $break; };
232+
$if(!this->_alpha_skip(ray, hit)) { $break; };
233+
#ifndef NDEBUG
234+
$if(i == max_iterations - 1u) {
235+
compute::device_log(luisa::format(
236+
"ERROR: max iterations ({}) exceeded in trace closest",
237+
max_iterations));
238+
};
239+
#endif
240+
ray = compute::make_ray(ray->origin(), ray->direction(),
241+
hit.committed_ray_t + epsilone,
242+
ray->t_max());
243+
hit = _accel->intersect(ray, {});
244+
};
227245
return Var<Hit>{hit.inst, hit.prim, hit.bary};
228246
}
247+
// use ray query
229248
auto rq_hit =
230-
_accel->traverse(ray, {})
249+
_accel->traverse(ray_in, {})
231250
.on_surface_candidate([&](compute::SurfaceCandidate &c) noexcept {
232-
this->_alpha_skip(c);
251+
$if(!this->_alpha_skip(c.ray(), c.hit())) {
252+
c.commit();
253+
};
233254
})
234255
.trace();
235256
return Var<Hit>{rq_hit.inst, rq_hit.prim, rq_hit.bary};
@@ -243,7 +264,9 @@ Var<bool> Geometry::trace_any(const Var<Ray> &ray) const noexcept {
243264
auto rq_hit =
244265
_accel->traverse_any(ray, {})
245266
.on_surface_candidate([&](compute::SurfaceCandidate &c) noexcept {
246-
this->_alpha_skip(c);
267+
$if(!this->_alpha_skip(c.ray(), c.hit())) {
268+
c.commit();
269+
};
247270
})
248271
.trace();
249272
return !rq_hit->miss();

src/base/geometry.h

+4-1
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,8 @@ using compute::Buffer;
3535
using compute::Expr;
3636
using compute::Float4x4;
3737
using compute::Mesh;
38+
using compute::Ray;
39+
using compute::SurfaceHit;
3840
using compute::Var;
3941

4042
class Pipeline;
@@ -82,7 +84,8 @@ class Geometry {
8284
const Medium *overridden_medium = nullptr,
8385
bool overridden_visible = true) noexcept;
8486

85-
void _alpha_skip(SurfaceCandidate &c) const noexcept;
87+
[[nodiscard]] Bool _alpha_skip(const Var<Ray> &ray,
88+
const Var<SurfaceHit> &hit) const noexcept;
8689

8790
public:
8891
explicit Geometry(Pipeline &pipeline) noexcept : _pipeline{pipeline} {};

0 commit comments

Comments
 (0)