RavEngine
Loading...
Searching...
No Matches
NvFlowDeepCopy.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 "NvFlowReflect.h"
30#include "NvFlowArray.h"
31
32#include <string.h>
33
35{
36 const char* debugname;
37 NvFlowUint64 size;
38};
39
41
49
51{
52 NvFlowUint64 luid = 0llu;
54 NvFlowUint64 version = 0llu;
55 NvFlowReflectDeepCopy* deepCopy = nullptr;
56 NvFlowUint8* deepCopyData;
57 NvFlowUint64 lastUse = 0llu;
58};
59
60NV_FLOW_INLINE NvFlowReflectDeepCopy* NvFlowReflectDeepCopy_create()
61{
62 auto ptr = new NvFlowReflectDeepCopy();
63 return ptr;
64}
65
66NV_FLOW_INLINE void NvFlowReflectDeepCopyCached_destroy(NvFlowReflectDeepCopyCached* ptr);
67
68NV_FLOW_INLINE void NvFlowReflectDeepCopy_destroy(NvFlowReflectDeepCopy* ptr)
69{
70 for (NvFlowUint64 cachedIdx = 0u; cachedIdx < ptr->cached.size; cachedIdx++)
71 {
72 NvFlowReflectDeepCopyCached_destroy(ptr->cached[cachedIdx]);
73 ptr->cached[cachedIdx] = nullptr;
74 }
75 ptr->cached.size = 0u;
76 delete ptr;
77}
78
79NV_FLOW_INLINE NvFlowReflectDeepCopyCached* NvFlowReflectDeepCopyCached_create(NvFlowUint64 luid, const char** pathStacks, NvFlowUint64 pathStackCount)
80{
81 auto ptr = new NvFlowReflectDeepCopyCached();
82 ptr->luid = luid;
83 ptr->pathStack.size = 0u;
84 for (NvFlowUint64 pathStackIdx = 0u; pathStackIdx < pathStackCount; pathStackIdx++)
85 {
86 ptr->pathStack.pushBack(pathStacks[pathStackIdx]);
87 }
88 ptr->version = 0llu;
89 ptr->deepCopy = NvFlowReflectDeepCopy_create();
90 return ptr;
91}
92
93NV_FLOW_INLINE void NvFlowReflectDeepCopyCached_destroy(NvFlowReflectDeepCopyCached* ptr)
94{
95 NvFlowReflectDeepCopy_destroy(ptr->deepCopy);
96 ptr->deepCopy = nullptr;
97 delete ptr;
98}
99
100NV_FLOW_INLINE void NvFlowReflectDeepCopy_newHeap(NvFlowReflectDeepCopy* ptr, NvFlowUint64 allocSize)
101{
102 auto& currentHeap = ptr->heaps[ptr->heaps.allocateBack()];
103
104 NvFlowUint64 heapSize = 4096u; // default heap size
105 while (heapSize < allocSize)
106 {
107 heapSize *= 2u;
108 }
109
110 currentHeap.reserve(heapSize);
111}
112
113NV_FLOW_INLINE NvFlowUint64 NvFlowReflectDeepCopy_alignment(NvFlowUint64 size)
114{
115 return 8u * ((size + 7u) / 8u);
116}
117
118NV_FLOW_INLINE NvFlowUint8* NvFlowReflectDeepCopy_allocate(NvFlowReflectDeepCopy* ptr, NvFlowUint64 size, const char* debugName)
119{
120 NvFlowUint64 allocSize = NvFlowReflectDeepCopy_alignment(size);
121
122 if (ptr->heaps.size > 0u)
123 {
124 auto& currentHeap = ptr->heaps[ptr->heaps.size - 1u];
125
126 if (currentHeap.size + allocSize <= currentHeap.capacity)
127 {
128 NvFlowUint8* ret = currentHeap.data + currentHeap.size;
129 ret[size - 1] = 0;
130 currentHeap.size += allocSize;
131 NvFlowReflectDeepCopyInfo info = { debugName, size };
132 ptr->infos.pushBack(info);
133 return ret;
134 }
135 }
136
137 NvFlowReflectDeepCopy_newHeap(ptr, allocSize);
138
139 return NvFlowReflectDeepCopy_allocate(ptr, size, debugName);
140}
141
142NV_FLOW_INLINE void NvFlowReflectDeepCopy_reset(NvFlowReflectDeepCopy* ptr)
143{
144 for (NvFlowUint64 heapIdx = 0u; heapIdx < ptr->heaps.size; heapIdx++)
145 {
146 ptr->heaps[heapIdx].size = 0u;
147 }
148 ptr->heaps.size = 0u;
149 ptr->infos.size = 0u;
150 ptr->pathStack.size = 0u;
151}
152
153NV_FLOW_INLINE NvFlowUint8* NvFlowReflectDeepCopy_recursive(NvFlowReflectDeepCopy* ptr, NvFlowUint64 luid, const NvFlowUint8* src, const NvFlowReflectDataType* type, NvFlowUint64 elementCount, NvFlowBool32 isPointerArray);
154
155NV_FLOW_INLINE void NvFlowReflectDeepCopy_cleanCache(NvFlowReflectDeepCopy* ptr)
156{
157 static const NvFlowUint64 cacheFreeTreshold = 8u;
158
159 NvFlowUint cachedIdx = 0u;
160 while (cachedIdx < ptr->cached.size)
161 {
162 ptr->cached[cachedIdx]->lastUse++;
163 if (ptr->cached[cachedIdx]->lastUse > cacheFreeTreshold)
164 {
165 NvFlowReflectDeepCopyCached_destroy(ptr->cached[cachedIdx]);
166 ptr->cached[cachedIdx] = nullptr;
167 ptr->cached.removeSwapPointerAtIndex(cachedIdx);
168 }
169 else
170 {
171 cachedIdx++;
172 }
173 }
174}
175
176NV_FLOW_INLINE NvFlowUint8* NvFlowReflectDeepCopy_cached(NvFlowReflectDeepCopy* ptr, NvFlowUint64 luid, const NvFlowUint8* src, const NvFlowReflectDataType* type, NvFlowUint64 elementCount, NvFlowUint64 version, NvFlowBool32 isPointerArray)
177{
178 NvFlowUint64 cachedIdx = 0u;
179 for (; cachedIdx < ptr->cached.size; cachedIdx++)
180 {
181 auto& cached = ptr->cached[cachedIdx];
182 if (cached->luid == luid && ptr->pathStack.size == cached->pathStack.size)
183 {
184 // check path stack
185 bool pathStackMatches = true;
186 for (NvFlowUint64 pathStackIdx = 0u; pathStackIdx < ptr->pathStack.size; pathStackIdx++)
187 {
188 if (NvFlowReflectStringCompare(ptr->pathStack[pathStackIdx], cached->pathStack[pathStackIdx]) != 0)
189 {
190 pathStackMatches = false;
191 break;
192 }
193 }
194 if (pathStackMatches)
195 {
196 break;
197 }
198 }
199 }
200 if (cachedIdx == ptr->cached.size)
201 {
202 cachedIdx = ptr->cached.allocateBack();
203 ptr->cached[cachedIdx] = NvFlowReflectDeepCopyCached_create(luid, ptr->pathStack.data, ptr->pathStack.size);
204 }
205 auto cached = ptr->cached[cachedIdx];
206 if (ptr->cached[cachedIdx]->version != version)
207 {
208 NvFlowReflectDeepCopy_reset(cached->deepCopy);
209 NvFlowReflectDeepCopy_cleanCache(cached->deepCopy);
210 cached->deepCopyData = NvFlowReflectDeepCopy_recursive(cached->deepCopy, luid, src, type, elementCount, isPointerArray);
211
212 cached->version = version;
213 }
214 cached->lastUse = 0u;
215 return cached->deepCopyData;
216}
217
218NV_FLOW_INLINE void NvFlowReflectDeepCopy_structRecursive(NvFlowReflectDeepCopy* ptr, NvFlowUint64 luid, NvFlowUint8* dst, const NvFlowReflectDataType* type, NvFlowUint64 elementCount, NvFlowBool32 isPointerArray)
219{
220 if (type->dataType == eNvFlowType_struct)
221 {
222 for (NvFlowUint64 elementIdx = 0u; elementIdx < elementCount; elementIdx++)
223 {
224 NvFlowUint8* dstArray = dst + type->elementSize * elementIdx;
225
226 // attempt to find luid
227 for (NvFlowUint childIdx = 0u; childIdx < type->childReflectDataCount; childIdx++)
228 {
229 const auto& childReflectData = type->childReflectDatas[childIdx];
230 if (childReflectData.reflectMode == eNvFlowReflectMode_value &&
231 childReflectData.dataType->dataType == eNvFlowType_uint64)
232 {
233 if (NvFlowReflectStringCompare(childReflectData.name, "luid") == 0)
234 {
235 luid = *((NvFlowUint64*)(dst + childReflectData.dataOffset));
236 break;
237 }
238 }
239 }
240
241 // traverse all elements, searching for pointers/arrays
242 for (NvFlowUint64 childIdx = 0u; childIdx < type->childReflectDataCount; childIdx++)
243 {
244 const auto& childReflectData = type->childReflectDatas[childIdx];
245 ptr->pathStack.pushBack(childReflectData.name);
246 if (childReflectData.dataType->dataType == eNvFlowType_struct &&
247 (childReflectData.reflectMode == eNvFlowReflectMode_value ||
248 childReflectData.reflectMode == eNvFlowReflectMode_valueVersioned))
249 {
250 NvFlowReflectDeepCopy_structRecursive(ptr, luid, dstArray + childReflectData.dataOffset, childReflectData.dataType, 1u, NV_FLOW_FALSE);
251 }
252 if (childReflectData.reflectMode & eNvFlowReflectMode_pointerArray)
253 {
254 // get pointer to pointer
255 NvFlowUint8** childPtr = (NvFlowUint8**)(dstArray + childReflectData.dataOffset);
256 NvFlowUint64 childElementCount = 1u;
257 NvFlowUint64 childVersion = 0u;
258 if ((*childPtr))
259 {
260 if (childReflectData.reflectMode & eNvFlowReflectMode_array)
261 {
262 childElementCount = *(NvFlowUint64*)(dstArray + childReflectData.arraySizeOffset);
263 }
264 if (childReflectData.reflectMode & eNvFlowReflectMode_valueVersioned)
265 {
266 childVersion = *(NvFlowUint64*)(dstArray + childReflectData.versionOffset);
267 }
268 NvFlowBool32 isPointerArray = (childReflectData.reflectMode & eNvFlowReflectMode_pointerArray) == eNvFlowReflectMode_pointerArray;
269
270 // conditionally attempt cached array
271 if (luid > 0u && childElementCount > 0u && childVersion > 0u && childReflectData.dataType->dataType != eNvFlowType_struct)
272 {
273 *childPtr = NvFlowReflectDeepCopy_cached(ptr, luid, *childPtr, childReflectData.dataType, childElementCount, childVersion, isPointerArray);
274 }
275 else
276 {
277 // recurse
278 *childPtr = NvFlowReflectDeepCopy_recursive(ptr, luid, *childPtr, childReflectData.dataType, childElementCount, isPointerArray);
279 }
280 }
281 }
282 ptr->pathStack.size--;
283 }
284 }
285 }
286}
287
288NV_FLOW_INLINE NvFlowUint8* NvFlowReflectDeepCopy_recursive(NvFlowReflectDeepCopy* ptr, NvFlowUint64 luid, const NvFlowUint8* src, const NvFlowReflectDataType* type, NvFlowUint64 elementCount, NvFlowBool32 isPointerArray)
289{
290 const char* debugName = "root";
291 if (ptr->pathStack.size > 0u)
292 {
293 debugName = ptr->pathStack[ptr->pathStack.size - 1u];
294 }
295
296 if (isPointerArray)
297 {
298 NvFlowUint8* dstData = NvFlowReflectDeepCopy_allocate(ptr, sizeof(void*) * elementCount, debugName);
299
300 memcpy(dstData, src, sizeof(void*) * elementCount);
301
302 // for each non-null pointer, recurse
303 NvFlowUint8** dstArray = (NvFlowUint8**)dstData;
304 for (NvFlowUint64 elementIdx = 0u; elementIdx < elementCount; elementIdx++)
305 {
306 if (dstArray[elementIdx])
307 {
308 dstArray[elementIdx] = NvFlowReflectDeepCopy_recursive(ptr, luid, dstArray[elementIdx], type, 1u, NV_FLOW_FALSE);
309 }
310 }
311 return dstData;
312 }
313
314 NvFlowUint8* dstData = NvFlowReflectDeepCopy_allocate(ptr, type->elementSize * elementCount, debugName);
315
316 memcpy(dstData, src, type->elementSize * elementCount);
317
318 NvFlowReflectDeepCopy_structRecursive(ptr, luid, dstData, type, elementCount, isPointerArray);
319
320 return dstData;
321}
322
323NV_FLOW_INLINE NvFlowUint8* NvFlowReflectDeepCopy_update(NvFlowReflectDeepCopy* ptr, const void* srcVoid, const NvFlowReflectDataType* type)
324{
325 const NvFlowUint8* src = (const NvFlowUint8*)srcVoid;
326 NvFlowReflectDeepCopy_reset(ptr);
327 NvFlowReflectDeepCopy_cleanCache(ptr);
328 return NvFlowReflectDeepCopy_recursive(ptr, 0llu, src, type, 1u, NV_FLOW_FALSE);
329}
Definition NvFlowArray.h:213
Definition NvFlowArray.h:36
Definition NvFlowReflect.h:182
Definition NvFlowDeepCopy.h:51
Definition NvFlowDeepCopy.h:35
Definition NvFlowDeepCopy.h:43