1+ /*
2+ * Copyright (c) 2019-2024 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
3+ * SPDX-License-Identifier: BSD-3-Clause
4+ *
5+ * Redistribution and use in source and binary forms, with or without
6+ * modification, are permitted provided that the following conditions are met:
7+ *
8+ * 1. Redistributions of source code must retain the above copyright notice,
9+ * this list of conditions and the following disclaimer.
10+ *
11+ * 2. Redistributions in binary form must reproduce the above copyright notice,
12+ * this list of conditions and the following disclaimer in the documentation
13+ * and/or other materials provided with the distribution.
14+ *
15+ * 3. Neither the name of the copyright holder nor the names of its
16+ * contributors may be used to endorse or promote products derived from
17+ * this software without specific prior written permission.
18+ *
19+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
20+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
23+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29+ * POSSIBILITY OF SUCH DAMAGE.
30+ */
31+
32+ #include " MemoryAllocation.h"
33+ // cuda
34+ #include < cuda_runtime.h>
35+ // std
36+ #include < cstdlib>
37+
38+ namespace visrtx {
39+
40+ // HostMemoryAllocation definitions ///////////////////////////////////////////
41+
42+ HostMemoryAllocation::HostMemoryAllocation (void *externalMemory,
43+ size_t bytes,
44+ anari::MemoryDeleter deleter,
45+ const void *deleterPtr)
46+ : m_bytes(bytes),
47+ m_ptr (externalMemory),
48+ m_deleter(deleter),
49+ m_deleterPtr(deleterPtr),
50+ m_owner(false )
51+ {}
52+
53+ HostMemoryAllocation::HostMemoryAllocation (size_t bytes)
54+ : m_bytes(bytes), m_owner(true )
55+ {
56+ if (bytes > 0 )
57+ m_ptr = std::malloc (bytes);
58+ }
59+
60+ HostMemoryAllocation::~HostMemoryAllocation ()
61+ {
62+ freeMemory ();
63+ }
64+
65+ void *HostMemoryAllocation::ptr () const
66+ {
67+ return m_ptr;
68+ }
69+
70+ size_t HostMemoryAllocation::bytes () const
71+ {
72+ return m_bytes;
73+ }
74+
75+ bool HostMemoryAllocation::isOwner () const
76+ {
77+ return m_owner;
78+ }
79+
80+ bool HostMemoryAllocation::isValid () const
81+ {
82+ return (ptr () != nullptr ) && (bytes () > 0 );
83+ }
84+
85+ HostMemoryAllocation::operator bool () const
86+ {
87+ return isValid ();
88+ }
89+
90+ HostMemoryAllocation &HostMemoryAllocation::operator =(
91+ const CudaMemoryAllocation &o)
92+ {
93+ if (!isValid ())
94+ *this = HostMemoryAllocation (o.bytes ());
95+ if (bytes () != o.bytes ()) {
96+ throw std::runtime_error (
97+ " cannot copy CudaMemoryAllocation to host: size mismatch" );
98+ }
99+ cudaMemcpy (ptr (), o.ptr (), bytes (), cudaMemcpyDeviceToHost);
100+ return *this ;
101+ }
102+
103+ void HostMemoryAllocation::privatize ()
104+ {
105+ if (!isValid () || isOwner ())
106+ return ;
107+ void *dst = std::malloc (bytes ());
108+ std::memcpy (dst, ptr (), bytes ());
109+ freeMemory ();
110+ m_ptr = dst;
111+ m_owner = true ;
112+ }
113+
114+ HostMemoryAllocation::HostMemoryAllocation (HostMemoryAllocation &&o)
115+ {
116+ freeMemory ();
117+ m_ptr = o.m_ptr ;
118+ m_bytes = o.m_bytes ;
119+ m_deleter = o.m_deleter ;
120+ m_deleterPtr = o.m_deleterPtr ;
121+ m_owner = o.m_owner ;
122+ o.clearPointers ();
123+ }
124+
125+ HostMemoryAllocation &HostMemoryAllocation::operator =(HostMemoryAllocation &&o)
126+ {
127+ freeMemory ();
128+ m_ptr = o.m_ptr ;
129+ m_bytes = o.m_bytes ;
130+ m_deleter = o.m_deleter ;
131+ m_deleterPtr = o.m_deleterPtr ;
132+ m_owner = o.m_owner ;
133+ o.clearPointers ();
134+ return *this ;
135+ }
136+
137+ void HostMemoryAllocation::freeMemory ()
138+ {
139+ if (isValid ()) {
140+ if (isOwner ())
141+ std::free (m_ptr);
142+ else if (m_deleter)
143+ m_deleter (m_deleterPtr, m_ptr);
144+ }
145+ clearPointers ();
146+ }
147+
148+ void HostMemoryAllocation::clearPointers ()
149+ {
150+ m_ptr = nullptr ;
151+ m_deleter = nullptr ;
152+ m_deleterPtr = nullptr ;
153+ }
154+
155+ // CudaMemoryAllocation definitions ///////////////////////////////////////////
156+
157+ CudaMemoryAllocation::CudaMemoryAllocation (void *externalMemory,
158+ size_t bytes,
159+ anari::MemoryDeleter deleter,
160+ const void *deleterPtr)
161+ : m_bytes(bytes),
162+ m_ptr (externalMemory),
163+ m_deleter(deleter),
164+ m_deleterPtr(deleterPtr),
165+ m_owner(false )
166+ {}
167+
168+ CudaMemoryAllocation::CudaMemoryAllocation (size_t bytes)
169+ : m_bytes(bytes), m_owner(true )
170+ {
171+ if (bytes > 0 )
172+ cudaMalloc (&m_ptr, bytes);
173+ }
174+
175+ CudaMemoryAllocation::~CudaMemoryAllocation ()
176+ {
177+ freeMemory ();
178+ }
179+
180+ void *CudaMemoryAllocation::ptr () const
181+ {
182+ return m_ptr;
183+ }
184+
185+ size_t CudaMemoryAllocation::bytes () const
186+ {
187+ return m_bytes;
188+ }
189+
190+ bool CudaMemoryAllocation::isOwner () const
191+ {
192+ return m_owner;
193+ }
194+
195+ bool CudaMemoryAllocation::isValid () const
196+ {
197+ return ptr () != nullptr && bytes () > 0 ;
198+ }
199+
200+ CudaMemoryAllocation::operator bool () const
201+ {
202+ return isValid ();
203+ }
204+
205+ CudaMemoryAllocation &CudaMemoryAllocation::operator =(
206+ const HostMemoryAllocation &o)
207+ {
208+ if (!isValid ())
209+ *this = CudaMemoryAllocation (o.bytes ());
210+ if (bytes () != o.bytes ()) {
211+ throw std::runtime_error (
212+ " cannot copy HostMemoryAllocation to GPU: size mismatch" );
213+ }
214+ cudaMemcpy (ptr (), o.ptr (), bytes (), cudaMemcpyHostToDevice);
215+ return *this ;
216+ }
217+
218+ void CudaMemoryAllocation::privatize ()
219+ {
220+ if (!isValid () || isOwner ())
221+ return ;
222+ void *dst = nullptr ;
223+ cudaMalloc (&dst, bytes ());
224+ cudaMemcpy (dst, ptr (), bytes (), cudaMemcpyDeviceToDevice);
225+ freeMemory ();
226+ m_ptr = dst;
227+ m_owner = true ;
228+ }
229+
230+ CudaMemoryAllocation::CudaMemoryAllocation (CudaMemoryAllocation &&o)
231+ {
232+ freeMemory ();
233+ m_ptr = o.m_ptr ;
234+ m_bytes = o.m_bytes ;
235+ m_deleter = o.m_deleter ;
236+ m_deleterPtr = o.m_deleterPtr ;
237+ m_owner = o.m_owner ;
238+ o.clearPointers ();
239+ }
240+
241+ CudaMemoryAllocation &CudaMemoryAllocation::operator =(CudaMemoryAllocation &&o)
242+ {
243+ freeMemory ();
244+ m_ptr = o.m_ptr ;
245+ m_bytes = o.m_bytes ;
246+ m_deleter = o.m_deleter ;
247+ m_deleterPtr = o.m_deleterPtr ;
248+ m_owner = o.m_owner ;
249+ o.clearPointers ();
250+ return *this ;
251+ }
252+
253+ void CudaMemoryAllocation::freeMemory ()
254+ {
255+ if (isValid ()) {
256+ if (isOwner ())
257+ cudaFree (m_ptr);
258+ else if (m_deleter)
259+ m_deleter (m_deleterPtr, m_ptr);
260+ }
261+ clearPointers ();
262+ }
263+
264+ void CudaMemoryAllocation::clearPointers ()
265+ {
266+ m_ptr = nullptr ;
267+ m_deleter = nullptr ;
268+ m_deleterPtr = nullptr ;
269+ }
270+
271+ } // namespace visrtx
0 commit comments