RavEngine
Loading...
Searching...
No Matches
NvFlowUploadBuffer.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 "NvFlowContext.h"
30#include "NvFlowArray.h"
31
32#define NV_FLOW_DISPATCH_BATCH_SIZE 32768u
33//#define NV_FLOW_DISPATCH_BATCH_SIZE 256
34
36{
37 NvFlowBufferTransient* globalTransient = nullptr;
38 NvFlowUint blockIdxOffset = 0u;
39 NvFlowUint blockCount = 0u;
40};
41
43
44NV_FLOW_INLINE void NvFlowDispatchBatches_init_custom(NvFlowDispatchBatches* ptr, NvFlowUint totalBlockCount, NvFlowUint batchSize)
45{
46 ptr->size = 0u;
47 for (NvFlowUint blockIdxOffset = 0u; blockIdxOffset < totalBlockCount; blockIdxOffset += batchSize)
48 {
49 NvFlowDispatchBatch batch = {};
50 batch.globalTransient = nullptr;
51 batch.blockIdxOffset = blockIdxOffset;
52 batch.blockCount = totalBlockCount - blockIdxOffset;
53 if (batch.blockCount > batchSize)
54 {
55 batch.blockCount = batchSize;
56 }
57 ptr->pushBack(batch);
58 }
59}
60
61NV_FLOW_INLINE void NvFlowDispatchBatches_init(NvFlowDispatchBatches* ptr, NvFlowUint totalBlockCount)
62{
63 NvFlowDispatchBatches_init_custom(ptr, totalBlockCount, NV_FLOW_DISPATCH_BATCH_SIZE);
64}
65
67{
68 NvFlowUint64 mappedIdx = ~0llu;
69 NvFlowUint64 frontIdx = ~0llu;
70 NvFlowArray<NvFlowUint64, 16u> recycleFenceValues;
71};
72
73NV_FLOW_INLINE NvFlowUint64 NvFlowBufferVersioning_map(NvFlowBufferVersioning* ptr, NvFlowUint64 lastFenceCompleted)
74{
75 NvFlowUint64 index = ptr->frontIdx + 1u;
76 for (; index < ptr->recycleFenceValues.size; index++)
77 {
78 if (ptr->recycleFenceValues[index] <= lastFenceCompleted)
79 {
80 break;
81 }
82 }
83 if (index == ptr->recycleFenceValues.size)
84 {
85 for (index = 0; index < ptr->frontIdx; index++)
86 {
87 if (ptr->recycleFenceValues[index] <= lastFenceCompleted)
88 {
89 break;
90 }
91 }
92 }
93 if (!(index < ptr->recycleFenceValues.size && ptr->recycleFenceValues[index] <= lastFenceCompleted))
94 {
95 index = ptr->recycleFenceValues.allocateBack();
96 }
97 ptr->recycleFenceValues[index] = ~0llu;
98 ptr->mappedIdx = index;
99 return ptr->mappedIdx;
100}
101
102NV_FLOW_INLINE void NvFlowBufferVersioning_unmap(NvFlowBufferVersioning* ptr, NvFlowUint64 nextFenceValue)
103{
104 if (ptr->frontIdx < ptr->recycleFenceValues.size)
105 {
106 ptr->recycleFenceValues[ptr->frontIdx] = nextFenceValue;
107 }
108 ptr->frontIdx = ptr->mappedIdx;
109}
110
112{
113 NvFlowContextInterface* contextInterface = nullptr;
114 NvFlowBuffer*(NV_FLOW_ABI* createBuffer)(NvFlowContext* context, NvFlowMemoryType memoryType, const NvFlowBufferDesc* desc, void* userdata) = nullptr;
115 void(NV_FLOW_ABI* addPassCopyBuffer)(NvFlowContext* context, const NvFlowPassCopyBufferParams* params, void* userdata) = nullptr;
116 void* userdata = nullptr;
117 NvFlowBufferUsageFlags flags = 0u;
118 NvFlowFormat format = eNvFlowFormat_unknown;
119 NvFlowUint structureStride = 0u;
120
121 NvFlowBufferVersioning versioning;
124
125 NvFlowBuffer* deviceBuffer = nullptr;
126 NvFlowUint64 deviceNumBytes = 0llu;
127};
128
129NV_FLOW_INLINE void NvFlowUploadBuffer_init_custom(
130 NvFlowContextInterface* contextInterface,
131 NvFlowContext* context, NvFlowUploadBuffer* ptr,
132 NvFlowBufferUsageFlags flags, NvFlowFormat format, NvFlowUint structureStride,
133 NvFlowBuffer*(NV_FLOW_ABI* createBuffer)(NvFlowContext* context, NvFlowMemoryType memoryType, const NvFlowBufferDesc* desc, void* userdata),
134 void(NV_FLOW_ABI* addPassCopyBuffer)(NvFlowContext* context, const NvFlowPassCopyBufferParams* params, void* userdata),
135 void* userdata
136)
137{
138 ptr->contextInterface = contextInterface;
139 ptr->createBuffer = createBuffer;
140 ptr->addPassCopyBuffer = addPassCopyBuffer;
141 ptr->userdata = userdata;
142
143 ptr->flags = flags;
144 ptr->format = format;
145 ptr->structureStride = structureStride;
146}
147
148NV_FLOW_INLINE NvFlowBuffer* NvFlowUploadBuffer_createBuffer(NvFlowContext* context, NvFlowMemoryType memoryType, const NvFlowBufferDesc* desc, void* userdata)
149{
150 NvFlowUploadBuffer* ptr = (NvFlowUploadBuffer*)userdata;
151 return ptr->contextInterface->createBuffer(context, memoryType, desc);
152}
153
154NV_FLOW_INLINE void NvFlowUploadBuffer_addPassCopyBuffer(NvFlowContext* context, const NvFlowPassCopyBufferParams* params, void* userdata)
155{
156 NvFlowUploadBuffer* ptr = (NvFlowUploadBuffer*)userdata;
157 ptr->contextInterface->addPassCopyBuffer(context, params);
158}
159
160NV_FLOW_INLINE void NvFlowUploadBuffer_init(NvFlowContextInterface* contextInterface, NvFlowContext* context, NvFlowUploadBuffer* ptr, NvFlowBufferUsageFlags flags, NvFlowFormat format, NvFlowUint structureStride)
161{
162 NvFlowUploadBuffer_init_custom(contextInterface, context, ptr, flags, format, structureStride, NvFlowUploadBuffer_createBuffer, NvFlowUploadBuffer_addPassCopyBuffer, ptr);
163}
164
165NV_FLOW_INLINE void NvFlowUploadBuffer_destroy(NvFlowContext* context, NvFlowUploadBuffer* ptr)
166{
167 for (NvFlowUint64 idx = 0u; idx < ptr->buffers.size; idx++)
168 {
169 if (ptr->buffers[idx])
170 {
171 ptr->contextInterface->destroyBuffer(context, ptr->buffers[idx]);
172 ptr->buffers[idx] = nullptr;
173 }
174 }
175 ptr->buffers.size = 0u;
176 ptr->bufferSizes.size = 0u;
177
178 if (ptr->deviceBuffer)
179 {
180 ptr->contextInterface->destroyBuffer(context, ptr->deviceBuffer);
181 ptr->deviceBuffer = nullptr;
182 }
183}
184
185NV_FLOW_INLINE NvFlowUint64 NvFlowUploadBuffer_computeBufferSize(NvFlowUint64 requested)
186{
187 NvFlowUint64 bufferSize = 65536u;
188 while (bufferSize < requested)
189 {
190 bufferSize *= 2u;
191 }
192 return bufferSize;
193}
194
195NV_FLOW_INLINE void* NvFlowUploadBuffer_map(NvFlowContext* context, NvFlowUploadBuffer* ptr, NvFlowUint64 numBytes)
196{
197 NvFlowUint64 instanceIdx = NvFlowBufferVersioning_map(&ptr->versioning, ptr->contextInterface->getLastFrameCompleted(context));
198 while (instanceIdx >= ptr->buffers.size)
199 {
200 ptr->buffers.pushBack(nullptr);
201 ptr->bufferSizes.pushBack(0llu);
202 }
203
204 if (ptr->buffers[instanceIdx] && ptr->bufferSizes[instanceIdx] < numBytes)
205 {
206 ptr->contextInterface->destroyBuffer(context, ptr->buffers[instanceIdx]);
207 ptr->buffers[instanceIdx] = nullptr;
208 }
209
210 if (!ptr->buffers[instanceIdx])
211 {
212 NvFlowBufferDesc bufDesc = {};
213 bufDesc.format = ptr->format;
214 bufDesc.usageFlags = ptr->flags;
215 bufDesc.structureStride = ptr->structureStride;
216 bufDesc.sizeInBytes = NvFlowUploadBuffer_computeBufferSize(numBytes);
217
218 ptr->bufferSizes[instanceIdx] = bufDesc.sizeInBytes;
219 ptr->buffers[instanceIdx] = ptr->contextInterface->createBuffer(context, eNvFlowMemoryType_upload, &bufDesc);
220 }
221
222 return ptr->contextInterface->mapBuffer(context, ptr->buffers[instanceIdx]);
223}
224
225NV_FLOW_INLINE NvFlowBufferTransient* NvFlowUploadBuffer_unmap(NvFlowContext* context, NvFlowUploadBuffer* ptr)
226{
227 ptr->contextInterface->unmapBuffer(context, ptr->buffers[ptr->versioning.mappedIdx]);
228
229 NvFlowBufferVersioning_unmap(&ptr->versioning, ptr->contextInterface->getCurrentFrame(context));
230
231 return ptr->contextInterface->registerBufferAsTransient(context, ptr->buffers[ptr->versioning.frontIdx]);
232}
233
235{
236 NvFlowUint64 offset;
237 NvFlowUint64 numBytes;
238};
239
240NV_FLOW_INLINE NvFlowBufferTransient* NvFlowUploadBuffer_getDevice(NvFlowContext* context, NvFlowUploadBuffer* ptr, NvFlowUint64 numBytes)
241{
242 NvFlowUint64 srcNumBytes = NvFlowUploadBuffer_computeBufferSize(numBytes);
243
244 if (ptr->deviceBuffer && ptr->deviceNumBytes < srcNumBytes)
245 {
246 ptr->contextInterface->destroyBuffer(context, ptr->deviceBuffer);
247 ptr->deviceBuffer = nullptr;
248 ptr->deviceNumBytes = 0llu;
249 }
250 if (!ptr->deviceBuffer)
251 {
252 NvFlowBufferDesc bufDesc = {};
253 bufDesc.format = ptr->format;
254 bufDesc.usageFlags = ptr->flags | eNvFlowBufferUsage_bufferCopyDst;
255 bufDesc.structureStride = ptr->structureStride;
256 bufDesc.sizeInBytes = srcNumBytes;
257
258 ptr->deviceBuffer = ptr->createBuffer(context, eNvFlowMemoryType_device, &bufDesc, ptr->userdata);
259 ptr->deviceNumBytes = srcNumBytes;
260 }
261
262 return ptr->contextInterface->registerBufferAsTransient(context, ptr->deviceBuffer);
263}
264
265NV_FLOW_INLINE NvFlowBufferTransient* NvFlowUploadBuffer_unmapDeviceN(NvFlowContext* context, NvFlowUploadBuffer* ptr, NvFlowUploadBufferCopyRange* copyRanges, NvFlowUint64 copyRangeCount, const char* debugName)
266{
267 NvFlowBufferTransient* src = NvFlowUploadBuffer_unmap(context, ptr);
268
269 NvFlowUint64 srcNumBytes = ptr->bufferSizes[ptr->versioning.frontIdx];
270
271 NvFlowBufferTransient* dst = NvFlowUploadBuffer_getDevice(context, ptr, srcNumBytes);
272
273 NvFlowUint activeCopyCount = 0u;
274 for (NvFlowUint64 copyRangeIdx = 0u; copyRangeIdx < copyRangeCount; copyRangeIdx++)
275 {
276 NvFlowPassCopyBufferParams copyParams = {};
277 copyParams.srcOffset = copyRanges[copyRangeIdx].offset;
278 copyParams.dstOffset = copyRanges[copyRangeIdx].offset;
279 copyParams.numBytes = copyRanges[copyRangeIdx].numBytes;
280 copyParams.src = src;
281 copyParams.dst = dst;
282
283 copyParams.debugLabel = debugName ? debugName : "UploadBufferUnmapDevice";
284
285 if (copyParams.numBytes > 0u)
286 {
287 ptr->addPassCopyBuffer(context, &copyParams, ptr->userdata);
288 activeCopyCount++;
289 }
290 }
291 // this ensures proper barriers
292 if (activeCopyCount == 0u)
293 {
294 NvFlowPassCopyBufferParams copyParams = {};
295 copyParams.srcOffset = 0llu;
296 copyParams.dstOffset = 0llu;
297 copyParams.numBytes = 0llu;
298 copyParams.src = src;
299 copyParams.dst = dst;
300
301 copyParams.debugLabel = debugName ? debugName : "UploadBufferUnmapDevice";
302
303 ptr->addPassCopyBuffer(context, &copyParams, ptr->userdata);
304 }
305
306 return dst;
307}
308
309NV_FLOW_INLINE NvFlowBufferTransient* NvFlowUploadBuffer_unmapDevice(NvFlowContext* context, NvFlowUploadBuffer* ptr, NvFlowUint64 offset, NvFlowUint64 numBytes, const char* debugName)
310{
311 NvFlowUploadBufferCopyRange copyRange = { offset, numBytes };
312 return NvFlowUploadBuffer_unmapDeviceN(context, ptr, &copyRange, 1u, debugName);
313}
Definition base.h:1940
Definition NvFlowArray.h:36
Definition NvFlowContext.h:96
Definition NvFlowUploadBuffer.h:67
Definition NvFlowContext.h:362
Definition NvFlowUploadBuffer.h:36
Definition NvFlowContext.h:300
Definition NvFlowUploadBuffer.h:235
Definition NvFlowUploadBuffer.h:112