Skip to content

Commit 4824a56

Browse files
committed
Merge branch 'release-0.12.x'
2 parents 62e54f8 + d7c4960 commit 4824a56

File tree

6 files changed

+161
-97
lines changed

6 files changed

+161
-97
lines changed

CHANGELOG.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,11 @@
11
Version History
22
---------------
33

4+
### Open VKL 0.12.1
5+
6+
- Fixed bug in VDB volume interval iterator implementation which could lead to
7+
missed intervals or incorrect value ranges in returned intervals
8+
49
### Open VKL 0.12.0
510

611
- Added support for temporally varying volumes with associated API changes for

CMakeLists.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ set(CMAKE_POSITION_INDEPENDENT_CODE ON)
1919

2020
## Establish project ##
2121

22-
project(openvkl VERSION 0.12.0 LANGUAGES C CXX)
22+
project(openvkl VERSION 0.12.1 LANGUAGES C CXX)
2323

2424
## Add openvkl specific macros ##
2525

README.md

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# Intel® Open Volume Kernel Library
22

3-
This is release v0.12.0 of Intel® Open VKL. For changes and new features
3+
This is release v0.12.1 of Intel® Open VKL. For changes and new features
44
see the [changelog](CHANGELOG.md). Visit http://www.openvkl.org for more
55
information.
66

@@ -32,6 +32,12 @@ example renderers to demonstrate how to best use the Open VKL API.
3232

3333
## Version History
3434

35+
### Open VKL 0.12.1
36+
37+
- Fixed bug in VDB volume interval iterator implementation which could
38+
lead to missed intervals or incorrect value ranges in returned
39+
intervals
40+
3541
### Open VKL 0.12.0
3642

3743
- Added support for temporally varying volumes with associated API

gitlab/.gitlab-ci.yml

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,8 @@
44
variables:
55
GIT_DEPTH: "15"
66
KW_PROJECT_NAME: openvkl
7-
OPENVKL_RELEASE_PACKAGE_VERSION: "0.12.0"
7+
OPENVKL_RELEASE_PACKAGE_VERSION: "0.12.1"
8+
MACOSX_DEPLOYMENT_TARGET: "10.13"
89

910
stages:
1011
- build
@@ -164,6 +165,7 @@ build-arch-devel-rkdeps:
164165
image: $DOCKER_REGISTRY/ospray/docker-images:arch
165166
script:
166167
- gitlab/build.sh -D RKCOMMON_VERSION=devel -D RKCOMMON_HASH="" -D EMBREE_VERSION=devel -D EMBREE_HASH=""
168+
allow_failure: true
167169

168170
build-arch-TBB2021:
169171
<<: *build_job_docker
@@ -298,6 +300,7 @@ test-functional-arch-devel-rkdeps:
298300
image: $DOCKER_REGISTRY/ospray/docker-images:arch
299301
needs:
300302
- build-arch-devel-rkdeps
303+
allow_failure: true
301304

302305
test-functional-arch-TBB2021:
303306
<<: *test_functional_job_docker

openvkl/drivers/ispc/volume/vdb/VdbSampler.ispc

Lines changed: 131 additions & 64 deletions
Original file line numberDiff line numberDiff line change
@@ -308,85 +308,152 @@ inline uniform float VdbSampler_sample(const VdbSampler *uniform sampler,
308308
// Value range computation.
309309
// ---------------------------------------------------------------------------
310310

311-
inline void extendValueRangeFilterFloat(const void *uniform _grid,
312-
const vec3ui *uniform offset,
313-
uniform uint32 level,
314-
uniform uint32 attributeIndex,
315-
uniform box1f *uniform range)
316-
{
317-
uniform VdbSampler sampler;
318-
memset(&sampler, 0, sizeof(uniform VdbSampler));
319-
sampler.grid = (const VdbGrid *uniform)_grid;
320-
sampler.maxSamplingDepth = VKL_VDB_NUM_LEVELS - 1;
321-
// We set none of the other members as the internal code does not require
322-
// them.
323-
324-
float vminFilter = pos_inf;
325-
float vmaxFilter = neg_inf;
326-
const uniform uint32 res = vklVdbLevelRes(level);
327-
const VdbGrid *uniform grid = (const VdbGrid *uniform)_grid;
328-
const uniform vec3ui os = *offset;
329-
const uniform int radius = 1; // TRILINEAR INTERPOLATION!
330-
// We compute min/max over the voxels (one filter radius) after upper bound.
331-
// These are voxels that can be interpolated into our node, so we must include
332-
// them for conservative value ranges.
333-
foreach (z = -radius... res + radius, y = -radius... res + radius) {
334-
const int32 x = res;
335-
const float sample = VdbSampler_sample(
336-
&sampler, make_vec3i(x + os.x, y + os.y, z + os.z), attributeIndex);
337-
vminFilter = min(vminFilter, sample);
338-
vmaxFilter = max(vmaxFilter, sample);
339-
}
340-
// We only have to go to x = res+radius as we added those voxels above.
341-
foreach (z = -radius... res + radius, x = -radius... res) {
342-
const int32 y = res;
343-
const float sample = VdbSampler_sample(
344-
&sampler, make_vec3i(x + os.x, y + os.y, z + os.z), attributeIndex);
345-
vminFilter = min(vminFilter, sample);
346-
vmaxFilter = max(vmaxFilter, sample);
347-
}
348-
// We only have to go to x = res+radius and y = res+radius as we added those
349-
// voxels above.
350-
foreach (y = -radius... res, x = -radius... res) {
351-
const int32 z = res;
352-
const float sample = VdbSampler_sample(
353-
&sampler, make_vec3i(x + os.x, y + os.y, z + os.z), attributeIndex);
354-
vminFilter = min(vminFilter, sample);
355-
vmaxFilter = max(vmaxFilter, sample);
356-
}
357-
358-
range->lower = min(reduce_min(vminFilter), range->lower);
359-
range->upper = max(reduce_max(vmaxFilter), range->upper);
360-
}
361-
362311
/*
363-
* Compute the value range on the given tile
312+
* Compute the value range for the given node and index range.
364313
*/
365-
export void EXPORT_UNIQUE(VdbSampler_valueRangeTileFloat,
366-
const void *uniform _grid,
367-
const vec3ui *uniform offset,
368-
uniform uint32 level,
369-
uniform uint32 attributeIndex,
370-
uniform box1f *uniform range)
314+
inline uniform box1f
315+
VdbSampler_computeNodeValueRange(const VdbGrid *uniform grid,
316+
uniform uint64 voxel,
317+
const uniform vec2ui &rangeX,
318+
const uniform vec2ui &rangeY,
319+
const uniform vec2ui &rangeZ,
320+
uniform uint32 attributeIndex)
371321
{
372-
range->lower = pos_inf;
373-
range->upper = neg_inf;
374-
extendValueRangeFilterFloat(_grid, offset, level, attributeIndex, range);
322+
const uniform VKLFormat leafFormat = vklVdbVoxelIsLeafPtr(voxel)
323+
? vklVdbVoxelLeafGetFormat(voxel)
324+
: VKL_FORMAT_INVALID;
325+
const void *uniform leafPtr = vklVdbVoxelLeafGetPtr(voxel);
326+
const uniform float background = 0.f;
327+
uniform box1f valueRange = make_box1f(background, background);
328+
329+
switch (leafFormat) {
330+
case VKL_FORMAT_TILE:
331+
valueRange.lower = VdbSampler_sampleTileFloatLeaf(
332+
((const Data1D *uniform)leafPtr), attributeIndex);
333+
valueRange.upper = valueRange.lower;
334+
break;
335+
case VKL_FORMAT_CONSTANT_ZYX:
336+
valueRange = make_box1f(pos_inf, neg_inf);
337+
if (grid->allLeavesCompact) {
338+
for (uniform unsigned int x = rangeX.x; x < rangeX.y; ++x) {
339+
for (uniform unsigned int y = rangeY.x; y < rangeY.y; ++y) {
340+
for (uniform unsigned int z = rangeZ.x; z < rangeZ.y; ++z) {
341+
const uniform float sample =
342+
VdbSampler_sampleConstantFloatLeafCompact(
343+
((const uniform Data1D *uniform)leafPtr),
344+
make_vec3ui(x, y, z),
345+
attributeIndex);
346+
extend(valueRange, sample);
347+
}
348+
}
349+
}
350+
} else {
351+
for (uniform unsigned int x = rangeX.x; x < rangeX.y; ++x) {
352+
for (uniform unsigned int y = rangeY.x; y < rangeY.y; ++y) {
353+
for (uniform unsigned int z = rangeZ.x; z < rangeZ.y; ++z) {
354+
const uniform float sample =
355+
VdbSampler_sampleConstantFloatLeafStrided(
356+
((const uniform Data1D *uniform)leafPtr),
357+
make_vec3ui(x, y, z),
358+
attributeIndex);
359+
extend(valueRange, sample);
360+
}
361+
}
362+
}
363+
}
364+
break;
365+
default:
366+
break;
367+
}
368+
369+
return valueRange;
375370
}
376371

377372
/*
378373
* Compute the value range on the given constant float leaf.
379374
*/
380-
export void EXPORT_UNIQUE(VdbSampler_valueRangeConstantFloat,
375+
export void EXPORT_UNIQUE(VdbSampler_computeValueRange,
381376
const void *uniform _grid,
382-
const vec3ui *uniform offset,
377+
const vec3ui *uniform centerNodeOffset,
383378
uniform uint32 level,
384379
uniform uint32 attributeIndex,
385380
uniform box1f *uniform range)
386381
{
382+
const VdbGrid *uniform grid = (const VdbGrid *uniform)_grid;
383+
384+
// We need to consider voxels outside this node in the value range because of
385+
// reconstruction filter support.
386+
//
387+
// In particular, we support filters that use up to a 4x4x4 neighborhood.
388+
//
389+
// In the following 1D illustration, we show voxels in the current leaf node
390+
// marked as a '#'. We also show voxels from neighboring nodes, and
391+
// mark those that could be used for interpolation with a '?'.
392+
//
393+
// | | | | | | | |?|#|#|#|#|#|#|#|#|?|?| | | | | | |
394+
//
395+
// We therefore iterate over a 3x3x3 neighborhood of nodes and compute the
396+
// value range over the following voxel range (in each dimension):
397+
//
398+
// "previous node" : [VKL_VDB_RES_LEAF - 1, VKL_VDB_RES_LEAF[
399+
// "central node" : [0, VKL_VDB_RES_LEAF[
400+
// "next node" : [0, 2[
401+
//
402+
// Note that the upper limit is exclusive. In 3D, each dimension follows
403+
// the same pattern.
404+
//
405+
// The following array encodes the iteration range for the previous,
406+
// central, and next leaf node:
407+
const uniform vec2ui voxelRange[] = {
408+
make_vec2ui(VKL_VDB_RES_LEAF - 1, VKL_VDB_RES_LEAF),
409+
make_vec2ui(0, VKL_VDB_RES_LEAF),
410+
make_vec2ui(0, 2)
411+
};
412+
387413
range->lower = pos_inf;
388414
range->upper = neg_inf;
389-
extendValueRangeFilterFloat(_grid, offset, level, attributeIndex, range);
415+
416+
uniform VdbSampler sampler;
417+
memset(&sampler, 0, sizeof(uniform VdbSampler));
418+
sampler.grid = (const VdbGrid *uniform)_grid;
419+
sampler.maxSamplingDepth = VKL_VDB_NUM_LEVELS - 1;
420+
421+
// Iterate over a 3x3x3 neighborhood of leaf nodes, and compute the value
422+
// range for each of those nodes.
423+
for (uniform int ix = 0; ix < 3; ++ix) {
424+
for (uniform int iy = 0; iy < 3; ++iy) {
425+
for (uniform int iz = 0; iz < 3; ++iz) {
426+
// This is the offset of the current node relative to the central node.
427+
const uniform vec3i nodeOffset =
428+
make_vec3i((ix - 1) * VKL_VDB_RES_LEAF,
429+
(iy - 1) * VKL_VDB_RES_LEAF,
430+
(iz - 1) * VKL_VDB_RES_LEAF);
431+
432+
// *centerNodeOffset is relative to the rootOrigin, but
433+
// VdbSampler_traverse expects an index space coordinate.
434+
const uniform vec3i nodeOrigin = make_vec3i(
435+
grid->rootOrigin.x + centerNodeOffset->x + nodeOffset.x,
436+
grid->rootOrigin.y + centerNodeOffset->y + nodeOffset.y,
437+
grid->rootOrigin.z + centerNodeOffset->z + nodeOffset.z
438+
);
439+
440+
uniform uint64 voxel;
441+
uniform vec3ui domainOffset;
442+
VdbSampler_traverse(&sampler, nodeOrigin, voxel, domainOffset);
443+
444+
const uniform range1f nodeValueRange =
445+
VdbSampler_computeNodeValueRange(grid,
446+
voxel,
447+
voxelRange[ix],
448+
voxelRange[iy],
449+
voxelRange[iz],
450+
attributeIndex);
451+
452+
range->lower = min(range->lower, nodeValueRange.lower);
453+
range->upper = max(range->upper, nodeValueRange.upper);
454+
}
455+
}
456+
}
390457
}
391458

392459
// ---------------------------------------------------------------------------

openvkl/drivers/ispc/volume/vdb/VdbVolume.cpp

Lines changed: 13 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -251,32 +251,12 @@ namespace openvkl {
251251
{
252252
range1f range;
253253

254-
switch (format) {
255-
case VKL_FORMAT_TILE: {
256-
CALL_ISPC(VdbSampler_valueRangeTileFloat,
257-
grid,
258-
reinterpret_cast<const ispc::vec3ui *>(&offset),
259-
level,
260-
attributeIndex,
261-
reinterpret_cast<ispc::box1f *>(&range));
262-
break;
263-
}
264-
265-
case VKL_FORMAT_CONSTANT_ZYX: {
266-
range1f leafRange;
267-
CALL_ISPC(VdbSampler_valueRangeConstantFloat,
268-
grid,
269-
reinterpret_cast<const ispc::vec3ui *>(&offset),
270-
level,
271-
attributeIndex,
272-
reinterpret_cast<ispc::box1f *>(&range));
273-
break;
274-
}
275-
276-
default:
277-
runtimeError(
278-
"Only VKL_FORMAT_TILE and VKL_FORMAT_CONSTANT_ZYX are supported.");
279-
}
254+
CALL_ISPC(VdbSampler_computeValueRange,
255+
grid,
256+
reinterpret_cast<const ispc::vec3ui *>(&offset),
257+
level,
258+
attributeIndex,
259+
reinterpret_cast<ispc::box1f *>(&range));
280260

281261
return range;
282262
}
@@ -373,9 +353,10 @@ namespace openvkl {
373353
const auto format = static_cast<VKLFormat>(leafFormat[idx]);
374354
const vec3ui &offset = leafOffsets[idx];
375355

376-
for (unsigned int j = 0; j < grid->numAttributes; j++)
356+
for (unsigned int j = 0; j < grid->numAttributes; j++) {
377357
valueRanges[idx][j] =
378358
computeValueRangeFloat(grid, format, leafLevel[idx], offset, j);
359+
}
379360
});
380361

381362
for (size_t idx = 0; idx < numLeaves; ++idx) {
@@ -388,20 +369,22 @@ namespace openvkl {
388369
assert(nodeIndex < level.numNodes);
389370

390371
const uint64_t voxelIndex = offsetToLinearVoxelIndex(offset, l);
391-
// NOTE: If this is every greater than 2^32-1 then we will have to
372+
// NOTE: If this is ever greater than 2^32-1 then we will have to
392373
// use 64 bit addressing.
393374
const uint64_t v = nodeIndex * vklVdbLevelNumVoxels(l) + voxelIndex;
394375
assert(v < ((uint64_t)1) << 32);
395376

396-
for (unsigned int j = 0; j < grid->numAttributes; j++)
377+
for (unsigned int j = 0; j < grid->numAttributes; j++) {
397378
level.valueRange[v * grid->numAttributes + j].extend(
398379
valueRanges[idx][j]);
380+
}
399381

400382
uint64_t &voxel = level.voxels[v];
401383
assert(!vklVdbVoxelIsEmpty(voxel));
402384

403-
if (vklVdbVoxelIsLeafPtr(voxel))
385+
if (vklVdbVoxelIsLeafPtr(voxel)) {
404386
break;
387+
}
405388

406389
nodeIndex = vklVdbVoxelChildGetIndex(voxel);
407390
assert(nodeIndex < grid->levels[l + 1].numNodes);

0 commit comments

Comments
 (0)