Skip to content

Commit 64fedcd

Browse files
committed
fix ImageBlock issues
This commit addresses an ImageBlock issue that occurred when ImageBlock was used with normalize=True, and when the sample footprint reached beyond the boundary. It also updates Dr.Jit-Core to fix a loop recording issue (size of side effects not correctly propagated) found along the way.
1 parent 16c8d2a commit 64fedcd

File tree

3 files changed

+42
-20
lines changed

3 files changed

+42
-20
lines changed

ext/drjit

src/render/imageblock.cpp

+16-19
Original file line numberDiff line numberDiff line change
@@ -242,13 +242,14 @@ MI_VARIANT void ImageBlock<Float, Spectrum>::put(const Point2f &pos,
242242

243243
// Compute the number of filter evaluations needed along each axis
244244
ScalarVector2u count;
245+
uint32_t count_max = dr::ceil2int<uint32_t>(2.f * radius);
245246
if constexpr (!JIT) {
246247
if (dr::any(pos_0_u > pos_1_u))
247248
return;
248249
count = count_u;
249250
} else {
250251
// Conservative bounds must be used in the vectorized case
251-
count = dr::ceil2int<uint32_t>(2.f * radius);
252+
count = count_max;
252253
active &= dr::all(pos_0_u <= pos_1_u);
253254
}
254255

@@ -264,16 +265,15 @@ MI_VARIANT void ImageBlock<Float, Spectrum>::put(const Point2f &pos,
264265
*weights_y = (Float *) alloca(sizeof(Float) * count.y());
265266

266267
// Evaluate filters weights along the X and Y axes
267-
268-
for (uint32_t i = 0; i < count.x(); ++i) {
269-
new (weights_x + i)
268+
for (uint32_t x = 0; x < count.x(); ++x) {
269+
new (weights_x + x)
270270
Float(JIT ? m_rfilter->eval(rel_f.x())
271271
: m_rfilter->eval_discretized(rel_f.x()));
272272
rel_f.x() += 1.f;
273273
}
274274

275-
for (uint32_t i = 0; i < count.y(); ++i) {
276-
new (weights_y + i)
275+
for (uint32_t y = 0; y < count.y(); ++y) {
276+
new (weights_y + y)
277277
Float(JIT ? m_rfilter->eval(rel_f.y())
278278
: m_rfilter->eval_discretized(rel_f.y()));
279279
rel_f.y() += 1.f;
@@ -283,11 +283,14 @@ MI_VARIANT void ImageBlock<Float, Spectrum>::put(const Point2f &pos,
283283
if (unlikely(m_normalize)) {
284284
Float wx = 0.f, wy = 0.f;
285285

286-
for (uint32_t i = 0; i < count.x(); ++i)
287-
wx += weights_x[i];
288-
289-
for (uint32_t i = 0; i < count.y(); ++i)
290-
wy += weights_y[i];
286+
Point2f rel_f2 = dr::ceil(pos_0_f) - pos_f;
287+
for (uint32_t i = 0; i < count_max; ++i) {
288+
wx += JIT ? m_rfilter->eval(rel_f2.x())
289+
: m_rfilter->eval_discretized(rel_f2.x());
290+
wy += JIT ? m_rfilter->eval(rel_f2.y())
291+
: m_rfilter->eval_discretized(rel_f2.y());
292+
rel_f2 += 1.f;
293+
}
291294

292295
Float factor = dr::detach(wx * wy);
293296

@@ -416,17 +419,11 @@ MI_VARIANT void ImageBlock<Float, Spectrum>::put(const Point2f &pos,
416419
*weights_y = (Float *) alloca(sizeof(Float) * count);
417420

418421
for (uint32_t i = 0; i < count; ++i) {
419-
Float weight_x = m_rfilter->eval(rel_f.x()),
420-
weight_y = m_rfilter->eval(rel_f.y());
421-
422-
if (unlikely(m_normalize)) {
423-
dr::masked(weight_x, x + i >= size.x()) = 0.f;
424-
dr::masked(weight_y, y + i >= size.y()) = 0.f;
425-
}
422+
Float weight_x = m_rfilter->eval(rel_f.x());
423+
Float weight_y = m_rfilter->eval(rel_f.y());
426424

427425
new (weights_x + i) Float(weight_x);
428426
new (weights_y + i) Float(weight_y);
429-
430427
rel_f += 1;
431428
}
432429

src/render/tests/test_imageblock.py

+25
Original file line numberDiff line numberDiff line change
@@ -192,3 +192,28 @@ def test04_read(variants_all, filter_name, border, offset, normalize, enable_ad)
192192
ref /= dr.sum(weight)
193193

194194
assert dr.allclose(value, ref, atol=1e-5)
195+
196+
197+
@pytest.mark.parametrize("coalesce", [ False, True ])
198+
@pytest.mark.parametrize("normalize", [ False, True ])
199+
def test05_boundary_effects(variants_vec_rgb, coalesce, normalize):
200+
# Check that everything works correctly even when the image block
201+
# is smaller than the filter kernel
202+
rfilter = mi.load_dict({'type':'gaussian'})
203+
ib = mi.ImageBlock(
204+
size=(1, 1),
205+
offset=(0, 0),
206+
channel_count=1,
207+
rfilter=rfilter,
208+
normalize=normalize,
209+
coalesce=coalesce
210+
)
211+
ib.put(pos=(0.49, 0.49), values=(dr.ones(mi.Float, 1),))
212+
213+
v1 = 0.9996645373720975
214+
v2 = 0.13499982060871019
215+
if normalize:
216+
ref = v1 / (v1 + 2*v2)**2
217+
else:
218+
ref = v1
219+
assert dr.allclose(ib.tensor().array, ref, rtol=1e-2)

0 commit comments

Comments
 (0)