Compute Graph Framework SDK Reference
5.4.5418 Release
For Test and Development only

Buffer.hpp
Go to the documentation of this file.
1 // This code contains NVIDIA Confidential Information and is disclosed
3 // under the Mutual Non-Disclosure Agreement.
4 //
5 // Notice
6 // ALL NVIDIA DESIGN SPECIFICATIONS AND CODE ("MATERIALS") ARE PROVIDED "AS IS" NVIDIA MAKES
7 // NO REPRESENTATIONS, WARRANTIES, EXPRESSED, IMPLIED, STATUTORY, OR OTHERWISE WITH RESPECT TO
8 // THE MATERIALS, AND EXPRESSLY DISCLAIMS ANY IMPLIED WARRANTIES OF NONINFRINGEMENT,
9 // MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE.
10 //
11 // NVIDIA Corporation assumes no responsibility for the consequences of use of such
12 // information or for any infringement of patents or other rights of third parties that may
13 // result from its use. No license is granted by implication or otherwise under any patent
14 // or patent rights of NVIDIA Corporation. No third party distribution is allowed unless
15 // expressly authorized by NVIDIA. Details are subject to change without notice.
16 // This code supersedes and replaces all information previously supplied.
17 // NVIDIA Corporation products are not authorized for use as critical
18 // components in life support devices or systems without express written approval of
19 // NVIDIA Corporation.
20 //
21 // Copyright (c) 2021 NVIDIA Corporation. All rights reserved.
22 //
23 // NVIDIA Corporation and its licensors retain all intellectual property and proprietary
24 // rights in and to this software and related documentation and any modifications thereto.
25 // Any use, reproduction, disclosure or distribution of this software and related
26 // documentation without an express license agreement from NVIDIA Corporation is
27 // strictly prohibited.
28 //
30 
31 #ifndef DW_FRAMEWORK_BUFFER_HPP_
32 #define DW_FRAMEWORK_BUFFER_HPP_
33 
34 #include <cstddef>
35 #include <dwcgf/Types.hpp>
36 #include <nvscibuf.h>
37 #include <dw/core/language/Optional.hpp>
38 #include <dw/cuda/misc/DevicePtr.hpp>
39 
40 namespace dw
41 {
42 namespace framework
43 {
44 
45 enum class BufferBackendType : uint32_t
46 {
47  CPU = 0,
48  CUDA = 1,
49  // Add others as appropriate
50 };
51 
52 using BufferFlags = uint32_t;
53 
55 {
56  return (static_cast<uint32_t>(flags) & (1U << static_cast<uint32_t>(type))) != 0U;
57 }
58 
60 {
61  flags |= (1U << static_cast<uint32_t>(type));
62 }
63 
65 {
67  size_t byteSize;
68 };
69 
71 {
72 public:
73  static constexpr char LOG_TAG[] = "Buffer";
74 
76  : m_properties(std::move(properties))
77  {
78  }
79 
81  {
82  return m_properties;
83  }
84 
85  virtual void bindNvSciBufObj(NvSciBufObj bufObj)
86  {
87  if (m_bufObj)
88  {
89  throw Exception(DW_CALL_NOT_ALLOWED, "BufferBase: Cannot bind NvSciBufObj twice");
90  }
91  m_bufObj = bufObj;
92  }
93 
94  void fillNvSciBufAttrs(NvSciBufAttrList attrList) const
95  {
96  const NvSciBufType bufferType = NvSciBufType_RawBuffer;
97  const NvSciBufAttrValAccessPerm permissions = NvSciBufAccessPerm_ReadWrite;
98  const uint64_t rawAlign = 4;
99 
100  Array<NvSciBufAttrKeyValuePair, 3> rawBufferAttributes =
101  {{{NvSciBufGeneralAttrKey_Types, &bufferType, sizeof(bufferType)},
102  {NvSciBufGeneralAttrKey_RequiredPerm, &permissions, sizeof(permissions)},
103  {NvSciBufRawBufferAttrKey_Align, &rawAlign, sizeof(rawAlign)}}};
104 
105  FRWK_CHECK_NVSCI_ERROR(NvSciBufAttrListSetAttrs(attrList,
106  rawBufferAttributes.data(),
107  rawBufferAttributes.size()));
108 
109  if (m_properties.byteSize > 0U)
110  {
111  const uint64_t rawSize = m_properties.byteSize;
112  Array<NvSciBufAttrKeyValuePair, 1> rawBufferSizeAttributes =
113  {{{NvSciBufRawBufferAttrKey_Size, &rawSize, sizeof(rawSize)}}};
114  FRWK_CHECK_NVSCI_ERROR(NvSciBufAttrListSetAttrs(attrList,
115  rawBufferSizeAttributes.data(),
116  rawBufferSizeAttributes.size()));
117  }
118  }
119 
120  NvSciBufObj getNvSci()
121  {
122  return m_bufObj;
123  }
124 
125 protected:
126  BufferProperties m_properties{};
127  NvSciBufObj m_bufObj{};
128 };
129 
130 class BufferCPU : public BufferBase
131 {
132 public:
133  explicit BufferCPU(BufferProperties properties)
134  : BufferBase(properties)
135  {
136  }
137 
138  void fillSpecificAttributes(NvSciBufAttrList attrList) const
139  {
140  const bool cpuAccessFlag = true;
141 
142  Array<NvSciBufAttrKeyValuePair, 1> rawBufferAttributes =
143  {{{NvSciBufGeneralAttrKey_NeedCpuAccess, &cpuAccessFlag, sizeof(cpuAccessFlag)}}};
144 
145  FRWK_CHECK_NVSCI_ERROR(NvSciBufAttrListSetAttrs(attrList,
146  rawBufferAttributes.data(),
147  rawBufferAttributes.size()));
148  }
149 
150  void bindNvSciBufObj(NvSciBufObj bufObj) override
151  {
153  FRWK_CHECK_NVSCI_ERROR(NvSciBufObjGetCpuPtr(m_bufObj, &m_ptr));
154  }
155 
156  void* getCpuPtr(size_t offset)
157  {
158  return &(static_cast<uint8_t*>(m_ptr)[offset]);
159  }
160 
161 private:
162  void* m_ptr;
163 };
164 
165 // BufferCUDA class encapsulates API mapping operations on single nvscibuf for cuda.
166 // @note - If a buffer needs to be mapped for multiple cuda devices, multiple instances of this class
167 // should be used and the appropriate device must be set as current before calling into each instance.
168 class BufferCUDA : public BufferBase
169 {
170 public:
171  explicit BufferCUDA(BufferProperties properties)
172  : BufferBase(properties)
173  {
174  }
175 
177  {
178  if (m_cudaHandle)
179  {
180  FRWK_CHECK_CUDA_ERROR_NOTHROW(cudaFree(m_ptr));
181  FRWK_CHECK_CUDA_ERROR_NOTHROW(cudaDestroyExternalMemory(m_cudaHandle));
182  }
183  }
184 
185  void fillSpecificAttributes(NvSciBufAttrList attrList) const
186  {
187  NvSciRmGpuId gpuIds[] = {{0}};
188  int32_t cudaDevice;
189  cudaDeviceProp deviceProps{};
190  FRWK_CHECK_CUDA_ERROR(cudaGetDevice(&cudaDevice));
191  FRWK_CHECK_CUDA_ERROR(cudaGetDeviceProperties(&deviceProps, cudaDevice));
192  static_assert(sizeof(deviceProps.uuid) == sizeof(gpuIds[0]), "BufferCUDA: cuda uuid size does not match size of NvSciRmGpuId");
193  memcpy(static_cast<void*>(&gpuIds[0]), static_cast<void*>(&deviceProps.uuid), sizeof(gpuIds[0]));
194 
195  Array<NvSciBufAttrKeyValuePair, 1> rawBufferAttributes =
196  {{{NvSciBufGeneralAttrKey_GpuId, &gpuIds, sizeof(gpuIds)}}};
197 
198  FRWK_CHECK_NVSCI_ERROR(NvSciBufAttrListSetAttrs(attrList,
199  rawBufferAttributes.data(),
200  rawBufferAttributes.size()));
201  }
202 
203  void bindNvSciBufObj(NvSciBufObj bufObj) override
204  {
206  cudaExternalMemoryHandleDesc cudaMemHandleDesc = {};
207  cudaMemHandleDesc.type = cudaExternalMemoryHandleTypeNvSciBuf;
208  cudaMemHandleDesc.handle.nvSciBufObject = bufObj;
209  cudaMemHandleDesc.size = m_properties.byteSize;
210  cudaMemHandleDesc.flags = 0;
211  FRWK_CHECK_CUDA_ERROR(cudaImportExternalMemory(&m_cudaHandle, &cudaMemHandleDesc));
212 
213  cudaExternalMemoryBufferDesc cudaBufferDesc = {};
214  memset(&cudaBufferDesc, 0, sizeof(cudaBufferDesc));
215  cudaBufferDesc.size = m_properties.byteSize;
216  cudaBufferDesc.offset = 0;
217  FRWK_CHECK_CUDA_ERROR(cudaExternalMemoryGetMappedBuffer(&m_ptr, m_cudaHandle, &cudaBufferDesc));
218  }
219 
220  core::DevicePtr<void> getCudaPtr(size_t offset)
221  {
222  void* ptr = &(static_cast<uint8_t*>(m_ptr)[offset]);
223  return core::MakeDevicePtr(ptr);
224  }
225 
226 private:
227  cudaExternalMemory_t m_cudaHandle{};
228  void* m_ptr{};
229 };
230 
231 // Buffer class encapsulates API mapping operations on single nvscibuf.
232 // @note - If a buffer needs to be mapped for multiple cuda devices, multiple instances of this class
233 // should be used and the appropriate device must be set as current before calling into each instance.
234 class Buffer : public BufferBase
235 {
236 
237 public:
238  explicit Buffer(BufferProperties properties)
239  : BufferBase(properties)
240  {
241  auto enabledBackends = m_properties.enabledBackends;
243  {
244  m_bufferCpu.emplace(properties);
245  }
247  {
248  m_bufferCuda.emplace(properties);
249  }
250  }
251 
252  void bindNvSciBufObj(NvSciBufObj bufObj) override
253  {
255  if (m_bufferCpu)
256  {
257  m_bufferCpu.value().bindNvSciBufObj(bufObj);
258  }
259  if (m_bufferCuda)
260  {
261  m_bufferCuda.value().bindNvSciBufObj(bufObj);
262  }
263  }
264 
265  void fillNvSciBufAttrs(NvSciBufAttrList attrList) const
266  {
268  if (m_bufferCpu)
269  {
270  m_bufferCpu.value().fillSpecificAttributes(attrList);
271  }
272  if (m_bufferCuda)
273  {
274  m_bufferCuda.value().fillSpecificAttributes(attrList);
275  }
276  }
277 
278  void* getCpuPtr(size_t offset)
279  {
280  return m_bufferCpu.value().getCpuPtr(offset);
281  }
282 
283  core::DevicePtr<void> getCudaPtr(size_t offset)
284  {
285  return m_bufferCuda.value().getCudaPtr(offset);
286  }
287 
288 private:
289  dw::core::Optional<BufferCPU> m_bufferCpu{};
290  dw::core::Optional<BufferCUDA> m_bufferCuda{};
291 };
292 
293 } // namespace framework
294 } // namespace dw
295 
296 #endif // DW_FRAMEWORK_BUFFER_HPP_
void bindNvSciBufObj(NvSciBufObj bufObj) override
Definition: Buffer.hpp:150
virtual void bindNvSciBufObj(NvSciBufObj bufObj)
Definition: Buffer.hpp:85
void fillNvSciBufAttrs(NvSciBufAttrList attrList) const
Definition: Buffer.hpp:94
void fillSpecificAttributes(NvSciBufAttrList attrList) const
Definition: Buffer.hpp:138
void * getCpuPtr(size_t offset)
Definition: Buffer.hpp:278
BufferBase(BufferProperties properties)
Definition: Buffer.hpp:75
NvSciBufObj getNvSci()
Definition: Buffer.hpp:120
#define FRWK_CHECK_NVSCI_ERROR(e)
Definition: Exception.hpp:354
uint32_t BufferFlags
Definition: Buffer.hpp:52
void bindNvSciBufObj(NvSciBufObj bufObj) override
Definition: Buffer.hpp:203
#define FRWK_CHECK_CUDA_ERROR_NOTHROW(x)
Definition: Exception.hpp:331
void fillNvSciBufAttrs(NvSciBufAttrList attrList) const
Definition: Buffer.hpp:265
void * getCpuPtr(size_t offset)
Definition: Buffer.hpp:156
#define FRWK_CHECK_CUDA_ERROR(x)
Definition: Exception.hpp:321
void bindNvSciBufObj(NvSciBufObj bufObj) override
Definition: Buffer.hpp:252
bool BufferFlagsBackendEnabled(BufferFlags flags, BufferBackendType type)
Definition: Buffer.hpp:54
Definition: Exception.hpp:46
void BufferFlagsEnableBackend(BufferFlags &flags, BufferBackendType type)
Definition: Buffer.hpp:59
const BufferProperties & getProperties() const
Definition: Buffer.hpp:80
Buffer(BufferProperties properties)
Definition: Buffer.hpp:238
BufferCUDA(BufferProperties properties)
Definition: Buffer.hpp:171
core::DevicePtr< void > getCudaPtr(size_t offset)
Definition: Buffer.hpp:220
void fillSpecificAttributes(NvSciBufAttrList attrList) const
Definition: Buffer.hpp:185
core::DevicePtr< void > getCudaPtr(size_t offset)
Definition: Buffer.hpp:283
BufferCPU(BufferProperties properties)
Definition: Buffer.hpp:133