Skip to content
Merged
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
30 changes: 28 additions & 2 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
# SPDX-License-Identifier: MIT

cmake_minimum_required(VERSION 3.10)
project(lightrt VERSION 1.0.0 LANGUAGES CXX)
project(lightrt VERSION 1.0.0 LANGUAGES CXX C)

include(CTest)

Expand All @@ -12,6 +12,11 @@ set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_CXX_EXTENSIONS OFF)

# C11 standard (for the pure-C binding lightrt_c.c and its test)
set(CMAKE_C_STANDARD 11)
set(CMAKE_C_STANDARD_REQUIRED ON)
set(CMAKE_C_EXTENSIONS OFF)

# Compiler flags: no RTTI, no exceptions
if(MSVC)
# Remove default /GR to avoid override warning, keep /EHsc for MSVC
Expand Down Expand Up @@ -123,11 +128,23 @@ elseif(CMAKE_SYSTEM_PROCESSOR MATCHES "^arm")
endif()
endif()

# C binding implementation. lightrt_c.cc is a thin C++ wrapper over the C++
# BVH; lightrt_c.c is a standalone pure-C11 reimplementation. Both expose the
# same lightrt_c.h API, so exactly one is linked into the library.
option(LIGHTRT_PURE_C_BINDING
"Use the standalone pure-C11 binding (lightrt_c.c) instead of the C++ wrapper (lightrt_c.cc)"
OFF)
if(LIGHTRT_PURE_C_BINDING)
set(LIGHTRT_C_BINDING_SRC lightrt_c.c)
else()
set(LIGHTRT_C_BINDING_SRC lightrt_c.cc)
endif()

# Library target
add_library(lightrt STATIC
lightrt.cc
lightrt.hh
lightrt_c.cc
${LIGHTRT_C_BINDING_SRC}
lightrt_c.h
)

Expand All @@ -153,6 +170,15 @@ target_link_libraries(lightrt_benchmark
lightrt
)

# Pure-C11 binding self-test (compiles lightrt_c.c directly; no C++ dependency).
if(BUILD_TESTING)
add_executable(lightrt_c_test lightrt_c.c tests/test_lightrt_c.c)
if(NOT MSVC)
target_link_libraries(lightrt_c_test m)
endif()
add_test(NAME lightrt_c_test COMMAND lightrt_c_test)
endif()

option(LIGHTRT_BUILD_WEBGPU "Build WebGPU software backend targets" ON)
if(LIGHTRT_BUILD_WEBGPU)
add_subdirectory(webgpu)
Expand Down
24 changes: 24 additions & 0 deletions lightrt.cc
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,9 @@ namespace lightrt {
// TaskSystem Implementation
// ============================================================================

#ifdef __EMSCRIPTEN__
// WASM stub: no actual threads, inline execution
#else
std::vector<std::thread> TaskSystem::threads_;
std::queue<std::function<void()>> TaskSystem::tasks_;
std::mutex TaskSystem::mutex_;
Expand All @@ -32,6 +35,7 @@ struct TaskSystemGuard {
}
};
static TaskSystemGuard g_task_system_guard;
#endif // __EMSCRIPTEN__

// ============================================================================
// Triangle Implementation
Expand Down Expand Up @@ -1497,7 +1501,11 @@ uint32_t BVH::buildRecursive(uint32_t* indices, uint32_t num_prims, uint32_t dep
// Work-stealing wait: help process tasks instead of blocking
while (!done.load()) {
if (!TaskSystem::tryProcessOne()) {
#ifndef __EMSCRIPTEN__
std::this_thread::yield();
#else
// WASM: just spin
#endif
}
}
} else {
Expand Down Expand Up @@ -9705,6 +9713,9 @@ void TriangleBVH::traverseBatch(const Ray* rays, uint32_t num_rays,
uint32_t num_threads) const noexcept {
if (num_rays == 0) return;

#ifdef __EMSCRIPTEN__
if (num_threads == 0) num_threads = 1;
#else
if (num_threads == 0) num_threads = std::thread::hardware_concurrency();
if (num_threads < 1) num_threads = 1;

Expand All @@ -9723,6 +9734,7 @@ void TriangleBVH::traverseBatch(const Ray* rays, uint32_t num_rays,
hit_prim_ids[i] = traverse(rays[i], hit_ts[i], hit_us[i], hit_vs[i]);
}
}, 64);
#endif
}

void TriangleBVH::traverseBatchAnyHit(const Ray* rays, uint32_t num_rays,
Expand All @@ -9731,6 +9743,9 @@ void TriangleBVH::traverseBatchAnyHit(const Ray* rays, uint32_t num_rays,
uint32_t num_threads) const noexcept {
if (num_rays == 0) return;

#ifdef __EMSCRIPTEN__
if (num_threads == 0) num_threads = 1;
#else
if (num_threads == 0) num_threads = std::thread::hardware_concurrency();
if (num_threads < 1) num_threads = 1;

Expand All @@ -9747,6 +9762,7 @@ void TriangleBVH::traverseBatchAnyHit(const Ray* rays, uint32_t num_rays,
hit_results[i] = traverseAnyHit(rays[i], exclude_prim_id);
}
}, 64);
#endif
}

// ============================================================================
Expand All @@ -9759,6 +9775,9 @@ void SBVH::traverseBatch(const Ray* rays, uint32_t num_rays,
uint32_t num_threads) const noexcept {
if (num_rays == 0) return;

#ifdef __EMSCRIPTEN__
if (num_threads == 0) num_threads = 1;
#else
if (num_threads == 0) num_threads = std::thread::hardware_concurrency();
if (num_threads < 1) num_threads = 1;

Expand All @@ -9777,6 +9796,7 @@ void SBVH::traverseBatch(const Ray* rays, uint32_t num_rays,
hit_prim_ids[i] = traverse(rays[i], hit_ts[i], hit_us[i], hit_vs[i]);
}
}, 64);
#endif
}

void SBVH::traverseBatchAnyHit(const Ray* rays, uint32_t num_rays,
Expand All @@ -9785,6 +9805,9 @@ void SBVH::traverseBatchAnyHit(const Ray* rays, uint32_t num_rays,
uint32_t num_threads) const noexcept {
if (num_rays == 0) return;

#ifdef __EMSCRIPTEN__
if (num_threads == 0) num_threads = 1;
#else
if (num_threads == 0) num_threads = std::thread::hardware_concurrency();
if (num_threads < 1) num_threads = 1;
Comment on lines +9808 to 9812

Expand All @@ -9801,6 +9824,7 @@ void SBVH::traverseBatchAnyHit(const Ray* rays, uint32_t num_rays,
hit_results[i] = traverseAnyHit(rays[i], exclude_prim_id);
}
}, 64);
#endif
}

// ============================================================================
Expand Down
24 changes: 23 additions & 1 deletion lightrt.hh
Original file line number Diff line number Diff line change
Expand Up @@ -19,12 +19,16 @@
#include <vector>
#include <limits>
#include <cmath>
#ifndef __EMSCRIPTEN__
#include <thread>
#include <mutex>
#include <condition_variable>
#endif
#include <atomic>
#include <functional>
#ifndef __EMSCRIPTEN__
#include <queue>
#endif

// SIMD detection
#if defined(__x86_64__) || defined(_M_X64) || defined(__i386__) || defined(_M_IX86)
Expand Down Expand Up @@ -66,6 +70,21 @@ constexpr uint32_t kInvalidIndex = 0xFFFFFFFF;
// Task System (Simple Thread Pool)
// ============================================================================

#ifdef __EMSCRIPTEN__
// WASM stub: threads not available, run tasks inline
class TaskSystem {
public:
static void initialize(uint32_t = 0) {}
static void shutdown() {}
static void submit(std::function<void()> task) { task(); }
static bool tryProcessOne() { return false; }
static void parallelFor(uint32_t start, uint32_t end,
std::function<void(uint32_t, uint32_t)> body,
uint32_t = 1024) {
body(start, end);
}
};
#else
class TaskSystem {
public:
// Initialize with hardware concurrency
Expand Down Expand Up @@ -127,7 +146,9 @@ public:

// Parallel For Loop
// splits range [start, end) into chunks and runs them in parallel
static void parallelFor(uint32_t start, uint32_t end, std::function<void(uint32_t, uint32_t)> body, uint32_t min_chunk_size = 1024) {
static void parallelFor(uint32_t start, uint32_t end,
std::function<void(uint32_t, uint32_t)> body,
uint32_t min_chunk_size = 1024) {
if (threads_.empty()) {
body(start, end);
return;
Expand Down Expand Up @@ -184,6 +205,7 @@ private:
static std::condition_variable condition_;
static bool stop_;
};
#endif // __EMSCRIPTEN__

// ============================================================================
// Vector Math
Expand Down
Loading