RavEngine
Loading...
Searching...
No Matches
NvFlowLocationHashTable.h
1// Redistribution and use in source and binary forms, with or without
2// modification, are permitted provided that the following conditions
3// are met:
4// * Redistributions of source code must retain the above copyright
5// notice, this list of conditions and the following disclaimer.
6// * Redistributions in binary form must reproduce the above copyright
7// notice, this list of conditions and the following disclaimer in the
8// documentation and/or other materials provided with the distribution.
9// * Neither the name of NVIDIA CORPORATION nor the names of its
10// contributors may be used to endorse or promote products derived
11// from this software without specific prior written permission.
12//
13// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
14// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
17// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24//
25// Copyright (c) 2014-2022 NVIDIA Corporation. All rights reserved.
26
27#pragma once
28
29#include "NvFlowTypes.h"
30#include "NvFlowArray.h"
31
33{
34 NvFlowUint64 beginIdx;
35 NvFlowUint64 endIdx;
36};
37
39{
40 NvFlowUint tableDimBits = 0llu;
41 NvFlowUint tableDimLessOne = 0llu;
42 NvFlowUint tableDim3 = 1u;
43
45 NvFlowArray<NvFlowUint64> nextIndices;
46
49
50 NvFlowInt4 locationMin = { 0, 0, 0, 0 };
51 NvFlowInt4 locationMax = { 0, 0, 0, 0 };
52
53 NvFlowArray<NvFlowInt4> tmpLocations;
55
56 void reset()
57 {
58 tableDimBits = 0llu;
59 tableDimLessOne = 0llu;
60 tableDim3 = 1u;
61
62 ranges.size = 0u;
63 nextIndices.size = 0u;
64 NvFlowLocationHashTableRange nullRange = { ~0llu, ~0llu };
65 ranges.pushBack(nullRange);
66
67 locations.size = 0u;
68 masks.size = 0u;
69 }
70
72 {
73 reset();
74 }
75
76 void rebuildTable()
77 {
78 ranges.size = 0u;
79 ranges.reserve(tableDim3);
80 ranges.size = tableDim3;
81
82 nextIndices.size = 0u;
83 nextIndices.reserve(locations.size);
84 nextIndices.size = locations.size;
85
86 // invalidate ranges
87 NvFlowLocationHashTableRange nullRange = { ~0llu, ~0llu };
88 for (NvFlowUint64 rangeIdx = 0u; rangeIdx < ranges.size; rangeIdx++)
89 {
90 ranges[rangeIdx] = nullRange;
91 }
92 for (NvFlowUint64 locationIdx = 0u; locationIdx < locations.size; locationIdx++)
93 {
94 NvFlowInt4 location = locations[locationIdx];
95 NvFlowUint64 baseRangeIdx = (location.x & tableDimLessOne) |
96 ((location.y & tableDimLessOne) << tableDimBits) |
97 ((location.z & tableDimLessOne) << (tableDimBits + tableDimBits));
98
99 // reset next for this location
100 nextIndices[locationIdx] = ~0llu;
101
102 NvFlowUint64 beginIdx = ranges[baseRangeIdx].beginIdx;
103 NvFlowUint64 endIdx = ranges[baseRangeIdx].endIdx;
104 if (beginIdx >= endIdx)
105 {
106 ranges[baseRangeIdx].beginIdx = locationIdx;
107 ranges[baseRangeIdx].endIdx = locationIdx + 1u;
108 }
109 else if (endIdx == locationIdx)
110 {
111 ranges[baseRangeIdx].endIdx = locationIdx + 1u;
112 nextIndices[endIdx - 1u] = locationIdx;
113 }
114 else
115 {
116 NvFlowUint64 prevIdx = endIdx - 1u;
117 NvFlowUint64 currentIdx = nextIndices[prevIdx];
118 while (currentIdx < nextIndices.size)
119 {
120 prevIdx = currentIdx;
121 currentIdx = nextIndices[currentIdx];
122 }
123 nextIndices[prevIdx] = locationIdx;
124 }
125 }
126 }
127
128 void compactNonZeroWithLimit(NvFlowUint64 maxLocations)
129 {
130 NvFlowUint64 dstIdx = 0u;
131 for (NvFlowUint64 srcIdx = 0u; srcIdx < locations.size && dstIdx < maxLocations; srcIdx++)
132 {
133 if (masks[srcIdx])
134 {
135 locations[dstIdx] = locations[srcIdx];
136 masks[dstIdx] = masks[srcIdx];
137 dstIdx++;
138 }
139 }
140 locations.size = dstIdx;
141 masks.size = dstIdx;
142
143 // optimize compacted table dim
144 tableDimBits = 0llu;
145 tableDimLessOne = 0llu;
146 tableDim3 = 1u;
147 while (locations.size > tableDim3)
148 {
149 tableDimBits++;
150 tableDimLessOne = (1u << tableDimBits) - 1u;
151 tableDim3 = (1 << (tableDimBits + tableDimBits + tableDimBits));
152 }
153
154 rebuildTable();
155 }
156
157 void sort()
158 {
159 NvFlowArray_copy(tmpLocations, locations);
160 NvFlowArray_copy(tmpMasks, masks);
161
162 NvFlowUint64 globalOffset = 0u;
163 for (NvFlowUint64 baseRangeIdx = 0u; baseRangeIdx < ranges.size; baseRangeIdx++)
164 {
165 NvFlowUint64 beginIdx = ranges[baseRangeIdx].beginIdx;
166 NvFlowUint64 endIdx = ranges[baseRangeIdx].endIdx;
167 for (NvFlowUint64 currentIdx = beginIdx; currentIdx < endIdx; currentIdx++)
168 {
169 locations[globalOffset] = tmpLocations[currentIdx];
170 masks[globalOffset] = tmpMasks[currentIdx];
171 globalOffset++;
172 }
173 if (beginIdx < endIdx)
174 {
175 NvFlowUint64 currentIdx = nextIndices[endIdx - 1u];
176 while (currentIdx < nextIndices.size)
177 {
178 locations[globalOffset] = tmpLocations[currentIdx];
179 masks[globalOffset] = tmpMasks[currentIdx];
180 globalOffset++;
181
182 currentIdx = nextIndices[currentIdx];
183 }
184 }
185 }
186
187 rebuildTable();
188 }
189
190 NvFlowUint64 find(NvFlowInt4 location)
191 {
192 NvFlowUint64 baseRangeIdx = (location.x & tableDimLessOne) |
193 ((location.y & tableDimLessOne) << tableDimBits) |
194 ((location.z & tableDimLessOne) << (tableDimBits + tableDimBits));
195
196 NvFlowUint64 beginIdx = ranges[baseRangeIdx].beginIdx;
197 NvFlowUint64 endIdx = ranges[baseRangeIdx].endIdx;
198 for (NvFlowUint64 currentIdx = beginIdx; currentIdx < endIdx; currentIdx++)
199 {
200 if (location.x == locations[currentIdx].x &&
201 location.y == locations[currentIdx].y &&
202 location.z == locations[currentIdx].z &&
203 location.w == locations[currentIdx].w)
204 {
205 return currentIdx;
206 }
207 }
208 if (beginIdx < endIdx)
209 {
210 NvFlowUint64 currentIdx = nextIndices[endIdx - 1u];
211 while (currentIdx < nextIndices.size)
212 {
213 if (location.x == locations[currentIdx].x &&
214 location.y == locations[currentIdx].y &&
215 location.z == locations[currentIdx].z &&
216 location.w == locations[currentIdx].w)
217 {
218 return currentIdx;
219 }
220 currentIdx = nextIndices[currentIdx];
221 }
222 }
223 return ~0llu;
224 }
225
226 void pushNoResize(NvFlowInt4 location, NvFlowUint mask)
227 {
228 NvFlowUint64 baseRangeIdx = (location.x & tableDimLessOne) |
229 ((location.y & tableDimLessOne) << tableDimBits) |
230 ((location.z & tableDimLessOne) << (tableDimBits + tableDimBits));
231
232 NvFlowUint64 beginIdx = ranges[baseRangeIdx].beginIdx;
233 NvFlowUint64 endIdx = ranges[baseRangeIdx].endIdx;
234 for (NvFlowUint64 currentIdx = beginIdx; currentIdx < endIdx; currentIdx++)
235 {
236 if (location.x == locations[currentIdx].x &&
237 location.y == locations[currentIdx].y &&
238 location.z == locations[currentIdx].z &&
239 location.w == locations[currentIdx].w)
240 {
241 masks[currentIdx] |= mask;
242 return;
243 }
244 }
245 if (beginIdx >= endIdx)
246 {
247 locations.pushBack(location);
248 masks.pushBack(mask);
249 nextIndices.pushBack(~0llu);
250
251 ranges[baseRangeIdx].beginIdx = locations.size - 1u;
252 ranges[baseRangeIdx].endIdx = locations.size;
253 }
254 else if (endIdx == locations.size)
255 {
256 locations.pushBack(location);
257 masks.pushBack(mask);
258 nextIndices.pushBack(~0llu);
259
260 ranges[baseRangeIdx].endIdx = locations.size;
261 nextIndices[endIdx - 1u] = locations.size - 1u;
262 }
263 else
264 {
265 NvFlowUint64 prevIdx = endIdx - 1u;
266 NvFlowUint64 currentIdx = nextIndices[prevIdx];
267 while (currentIdx < nextIndices.size)
268 {
269 if (location.x == locations[currentIdx].x &&
270 location.y == locations[currentIdx].y &&
271 location.z == locations[currentIdx].z &&
272 location.w == locations[currentIdx].w)
273 {
274 masks[currentIdx] |= mask;
275 return;
276 }
277 prevIdx = currentIdx;
278 currentIdx = nextIndices[currentIdx];
279 }
280
281 locations.pushBack(location);
282 masks.pushBack(mask);
283 nextIndices.pushBack(~0llu);
284
285 nextIndices[prevIdx] = locations.size - 1u;
286 }
287 }
288
289 void conditionalGrowTable()
290 {
291 if (locations.size > tableDim3)
292 {
293 tableDimBits++;
294 tableDimLessOne = (1u << tableDimBits) - 1u;
295 tableDim3 = (1 << (tableDimBits + tableDimBits + tableDimBits));
296
297 rebuildTable();
298 }
299 }
300
301 void push(NvFlowInt4 location, NvFlowUint mask)
302 {
303 pushNoResize(location, mask);
304 conditionalGrowTable();
305 }
306
307 void computeStats()
308 {
309 locationMin = NvFlowInt4{ 0, 0, 0, 0 };
310 locationMax = NvFlowInt4{ 0, 0, 0, 0 };
311 if (locations.size > 0)
312 {
313 locationMin = locations[0];
314 locationMax.x = locations[0].x + 1;
315 locationMax.y = locations[0].y + 1;
316 locationMax.z = locations[0].z + 1;
317 locationMax.w = locations[0].w + 1;
318 }
319 for (NvFlowUint64 locationIdx = 1u; locationIdx < locations.size; locationIdx++)
320 {
321 NvFlowInt4 location = locations[locationIdx];
322
323 if (location.x < locationMin.x)
324 {
325 locationMin.x = location.x;
326 }
327 if (location.y < locationMin.y)
328 {
329 locationMin.y = location.y;
330 }
331 if (location.z < locationMin.z)
332 {
333 locationMin.z = location.z;
334 }
335 if (location.w < locationMin.w)
336 {
337 locationMin.w = location.w;
338 }
339
340 // plus one, since max is exclusive
341 if (location.x + 1 > locationMax.x)
342 {
343 locationMax.x = location.x + 1;
344 }
345 if (location.y + 1 > locationMax.y)
346 {
347 locationMax.y = location.y + 1;
348 }
349 if (location.z + 1 > locationMax.z)
350 {
351 locationMax.z = location.z + 1;
352 }
353 if (location.w + 1 > locationMax.w)
354 {
355 locationMax.w = location.w + 1;
356 }
357 }
358 }
359};
Definition NvFlowArray.h:36
Definition NvFlowLocationHashTable.h:33
Definition NvFlowLocationHashTable.h:39