Skip to content
Open
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
9 changes: 7 additions & 2 deletions kernels/builders/bvh_builder_morton.h
Original file line number Diff line number Diff line change
Expand Up @@ -32,12 +32,17 @@ namespace embree
if (RTC_BUILD_ARGUMENTS_HAS(settings,minLeafSize )) minLeafSize = settings.minLeafSize;
if (RTC_BUILD_ARGUMENTS_HAS(settings,maxLeafSize )) maxLeafSize = settings.maxLeafSize;

if (branchingFactor > MAX_BRANCHING_FACTOR)
branchingFactor = MAX_BRANCHING_FACTOR;

minLeafSize = min(minLeafSize,maxLeafSize);
}

Settings (size_t branchingFactor, size_t maxDepth, size_t minLeafSize, size_t maxLeafSize, size_t singleThreadThreshold)
: branchingFactor(branchingFactor), maxDepth(maxDepth), minLeafSize(minLeafSize), maxLeafSize(maxLeafSize), singleThreadThreshold(singleThreadThreshold)
Settings (size_t branchingFactor_, size_t maxDepth_, size_t minLeafSize_, size_t maxLeafSize_, size_t singleThreadThreshold_)
: branchingFactor(branchingFactor_), maxDepth(maxDepth_), minLeafSize(minLeafSize_), maxLeafSize(maxLeafSize_), singleThreadThreshold(singleThreadThreshold_)
{
if (branchingFactor > MAX_BRANCHING_FACTOR)
branchingFactor = MAX_BRANCHING_FACTOR;
minLeafSize = min(minLeafSize,maxLeafSize);
Comment thread
johguenther marked this conversation as resolved.
}

Expand Down
2 changes: 2 additions & 0 deletions tests/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,8 @@ FOREACH(xml ${PRIMITIVE_TESTS})
ENDFOREACH()
ENDFOREACH()

ADD_SUBDIRECTORY(regression)


IF (EMBREE_TESTING_INSTALL_TESTS)
# test resources
Expand Down
1 change: 0 additions & 1 deletion tests/integration/test_embree_release/test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -105,4 +105,3 @@ TEST_CASE("Minimal test", "[minimal]")

REQUIRE(true);
}

10 changes: 10 additions & 0 deletions tests/regression/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
# Copyright 2009-2021 Intel Corporation
# SPDX-License-Identifier: Apache-2.0

add_executable(embree_regression_morton_builder_clamp morton_builder_clamp_regression.cpp)
target_link_libraries(embree_regression_morton_builder_clamp PRIVATE embree)
set_property(TARGET embree_regression_morton_builder_clamp PROPERTY FOLDER tests/regression)

if (BUILD_TESTING)
add_test(NAME regression_morton_builder_clamp COMMAND embree_regression_morton_builder_clamp)
endif()
149 changes: 149 additions & 0 deletions tests/regression/morton_builder_clamp_regression.cpp
Comment thread
johguenther marked this conversation as resolved.
Original file line number Diff line number Diff line change
@@ -0,0 +1,149 @@
// Copyright 2026 Intel Corporation
// SPDX-License-Identifier: Apache-2.0

#include <embree4/rtcore.h>
#include <embree4/rtcore_builder.h>

#include <cassert>
#include <cstring>
#include <iostream>
#include <limits>
#include <vector>

constexpr unsigned int max_branching_factor = 8;

struct Node
{
Node()
{
for (unsigned int i = 0; i < max_branching_factor; ++i)
children[i] = nullptr;
}
virtual ~Node() = default;
Node *children[max_branching_factor];
};

static bool buildProgress(void * /*userPtr*/, double /*f*/)
{
return true;
}

bool memoryMonitor(void * /*userPtr*/, ssize_t /*bytes*/, bool /*post*/)
{
return true;
}

static void *createNode(RTCThreadLocalAllocator alloc, unsigned int childCount, void * /*userPtr*/)
{
assert(childCount <= max_branching_factor);
if (childCount > max_branching_factor)
return nullptr;

Node *node = (Node *)rtcThreadLocalAlloc(alloc, sizeof(Node), 16);
new (node) Node();
return node;
}

static void setNodeChildren(void *nodePtr, void **children, unsigned int childCount, void * /*userPtr*/)
{
assert(childCount <= max_branching_factor);
if (childCount > max_branching_factor)
return;
Node *node = (Node *)nodePtr;
for (unsigned int i = 0; i < childCount; ++i)
node->children[i] = (Node *)children[i];
}

static void setNodeBounds(void *nodePtr, const RTCBounds **bounds, unsigned int childCount, void * /*userPtr*/)
{
assert(childCount <= max_branching_factor);
/* deliberately empty in regression test */
}

static void *createLeaf(RTCThreadLocalAllocator alloc,
const RTCBuildPrimitive *prims,
size_t primCount,
void * /*userPtr*/)
{

Node *node = (Node *)rtcThreadLocalAlloc(alloc, sizeof(Node), 16);
new (node) Node();
return node;
}

static std::vector<RTCBuildPrimitive> makeGridPrimitives(size_t primitiveCount)
{
std::vector<RTCBuildPrimitive> prims(primitiveCount);
for (size_t i = 0; i < primitiveCount; ++i)
{
const float x = float(i % 32);
const float y = float((i / 32) % 32);

RTCBuildPrimitive p{};
p.lower_x = x * 2.0f;
p.lower_y = y * 2.0f;
p.lower_z = 0.0f;
p.upper_x = p.lower_x + 0.5f;
p.upper_y = p.lower_y + 0.5f;
p.upper_z = 0.5f;
p.geomID = 0;
p.primID = (unsigned int)i;
prims[i] = p;
}
return prims;
}

static bool runCase(unsigned int maxBranchingFactor)
{
RTCDevice device = rtcNewDevice(nullptr);
if (device == nullptr)
return false;

RTCBVH bvh = rtcNewBVH(device);
if (bvh == nullptr)
{
rtcReleaseDevice(device);
return false;
}

std::vector<RTCBuildPrimitive> prims = makeGridPrimitives(1024);

RTCBuildArguments args = rtcDefaultBuildArguments();
args.byteSize = sizeof(args);
args.buildQuality = RTC_BUILD_QUALITY_LOW;
args.maxBranchingFactor = maxBranchingFactor;
args.maxDepth = 1024;
args.minLeafSize = 1;
args.maxLeafSize = 1;
args.bvh = bvh;
args.primitives = prims.data();
args.primitiveCount = prims.size();
args.primitiveArrayCapacity = prims.size();
args.createNode = createNode;
args.setNodeChildren = setNodeChildren;
args.setNodeBounds = setNodeBounds;
args.createLeaf = createLeaf;
args.buildProgress = buildProgress;

void *root = rtcBuildBVH(&args);

rtcReleaseBVH(bvh);
rtcReleaseDevice(device);
return root != nullptr;
}

int main()
{
/* In the failure case, this test should assert or result in a segfault from stack overflow. */

bool okOversized = runCase(64);
bool okExtreme = runCase(std::numeric_limits<unsigned int>::max());

if (!okOversized)
std::cerr << "Morton clamp regression failed for maxBranchingFactor=64\n";
if (!okExtreme)
std::cerr << "Morton clamp regression failed for maxBranchingFactor=UINT_MAX\n";

std::cout << "Morton clamp regression test completed.\n";
return (okOversized && okExtreme) ? 0 : 1;
}
Loading