28#define SGN(x) (x == 0) ? 0 : ((x > 0) ? 1 : -1)
45template<
class u_morton>
48 u32 internal_cell_count,
57 if (internal_cell_count == 0) {
72 [morton_length = internal_cell_count + 1](
74 const u_morton *__restrict morton,
75 u32 *__restrict lchild_id,
76 u32 *__restrict rchild_id,
77 u8 *__restrict lchild_flag,
78 u8 *__restrict rchild_flag,
79 u32 *__restrict end_range_cell) {
80 auto DELTA = [=](
i32 x,
i32 y) {
84 int ddelta = DELTA(i, i + 1) - DELTA(i, i - 1);
89 int delta_min = DELTA(i, i - d);
91 while (DELTA(i, i + lmax * d) > delta_min) {
99 if (DELTA(i, i + (l + t) * d) > delta_min) {
106 end_range_cell[i] = j;
109 int delta_node = DELTA(i, j);
114 t = sycl::ceil(l / div);
116 int tmp_ = i + (s + t) * d;
117 if (DELTA(i, tmp_) > delta_node) {
123 t = sycl::ceil(l / div);
125 int gamma = i + s * d + sycl::min(d, 0);
127 if (sycl::min(i, j) == gamma) {
128 lchild_id[i] = gamma;
131 lchild_id[i] = gamma;
135 if (sycl::max(i, j) == gamma + 1) {
136 rchild_id[i] = gamma + 1;
139 rchild_id[i] = gamma + 1;
147 template<
class Tmorton>
148 inline u32 get_tree_depth() {
152 template<
class Tmorton>
154 sham::DeviceScheduler_ptr dev_sched,
159 u32 internal_cell_count = morton_count - 1;
161 recycled_tree.tree_depth = get_tree_depth<Tmorton>();
163 recycled_tree.buf_lchild_id.resize(internal_cell_count);
164 recycled_tree.buf_rchild_id.resize(internal_cell_count);
165 recycled_tree.buf_lchild_flag.resize(internal_cell_count);
166 recycled_tree.buf_rchild_flag.resize(internal_cell_count);
167 recycled_tree.buf_endrange.resize(internal_cell_count);
170 dev_sched->get_queue(),
173 recycled_tree.buf_lchild_id,
174 recycled_tree.buf_rchild_id,
175 recycled_tree.buf_lchild_flag,
176 recycled_tree.buf_rchild_flag,
177 recycled_tree.buf_endrange);
179 return std::forward<KarrasRadixTree>(recycled_tree);
186 template<
class Tmorton>
188 sham::DeviceScheduler_ptr dev_sched,
192 u32 internal_cell_count = morton_count - 1;
201 std::move(buf_lchild_id),
202 std::move(buf_rchild_id),
203 std::move(buf_lchild_flag),
204 std::move(buf_rchild_flag),
205 std::move(buf_endrange),
206 get_tree_depth<Tmorton>());
216 template KarrasRadixTree karras_tree_from_morton_set(
217 sham::DeviceScheduler_ptr dev_sched,
220 KarrasRadixTree &&recycled_tree);
222 template KarrasRadixTree karras_tree_from_morton_set(
223 sham::DeviceScheduler_ptr dev_sched,
227 template KarrasRadixTree karras_tree_from_morton_set(
228 sham::DeviceScheduler_ptr dev_sched,
231 KarrasRadixTree &&recycled_tree);
233 template KarrasRadixTree karras_tree_from_morton_set(
234 sham::DeviceScheduler_ptr dev_sched,
241 std::vector<u32> lchild_id = {};
242 std::vector<u8> lchild_flag = {};
243 std::vector<u32> rchild_id = {};
244 std::vector<u8> rchild_flag = {};
245 std::vector<u32> endrange = {};
253 std::string dot_graph =
"";
255 dot_graph +=
"digraph G {\n";
256 dot_graph +=
"rankdir=LR;\n";
260 if (lchild_flag[i] == 0) {
262 +=
"i" + std::to_string(i) +
" -> i" + std::to_string(lchild_id[i]) +
";\n";
265 +=
"i" + std::to_string(i) +
" -> l" + std::to_string(lchild_id[i]) +
";\n";
268 if (rchild_flag[i] == 0) {
270 +=
"i" + std::to_string(i) +
" -> i" + std::to_string(rchild_id[i]) +
";\n";
273 +=
"i" + std::to_string(i) +
" -> l" + std::to_string(rchild_id[i]) +
";\n";
#define SGN(x)
Macro to get the sign of a number.
void __karras_alg(sham::DeviceQueue &queue, u32 internal_cell_count, sham::DeviceBuffer< u_morton > &in_morton, sham::DeviceBuffer< u32 > &out_buf_lchild_id, sham::DeviceBuffer< u32 > &out_buf_rchild_id, sham::DeviceBuffer< u8 > &out_buf_lchild_flag, sham::DeviceBuffer< u8 > &out_buf_rchild_flag, sham::DeviceBuffer< u32 > &out_buf_endrange)
Karras 2012 algorithm with addition endrange buffer.
KarrasRadixTree karras_tree_from_morton_set(sham::DeviceScheduler_ptr dev_sched, u32 morton_count, sham::DeviceBuffer< Tmorton > &morton_codes, KarrasRadixTree &&recycled_tree)
Constructs a KarrasRadixTree from a set of reduced Morton codes.
std::string karras_tree_to_dot_graph(KarrasRadixTree &recycled_tree)
Get tree as dot graph.
std::uint8_t u8
8 bit unsigned integer
std::uint32_t u32
32 bit unsigned integer
std::int32_t i32
32 bit integer
A buffer allocated in USM (Unified Shared Memory)
std::vector< T > copy_to_stdvec() const
Copy the content of the buffer to a std::vector.
A SYCL queue associated with a device and a context.
A data structure representing a Karras Radix Tree.
sham::DeviceBuffer< u8 > buf_rchild_flag
right child flag (size = internal_count)
sham::DeviceBuffer< u32 > buf_rchild_id
right child id (size = internal_count)
sham::DeviceBuffer< u32 > buf_endrange
endrange (size = internal_count)
sham::DeviceBuffer< u32 > buf_lchild_id
left child id (size = internal_count)
u32 get_internal_cell_count() const
Get internal cell count.
sham::DeviceBuffer< u8 > buf_lchild_flag
left child flag (size = internal_count)
Morton curve implementation.
i32 karras_delta(i32 x, i32 y, u32 morton_length, Acc m) noexcept
delta operator defined in Karras 2012
void kernel_call(sham::DeviceQueue &q, RefIn in, RefOut in_out, u32 n, Functor &&func, SourceLocation &&callsite=SourceLocation{})
Submit a kernel to a SYCL queue.
void throw_with_loc(std::string message, SourceLocation loc=SourceLocation{})
Throw an exception and append the source location to it.
A class that references multiple buffers or similar objects.