PhysicsBasedAnimationToolkit 0.0.10
Cross-platform C++20 library of algorithms and data structures commonly used in computer graphics research on physically-based simulation.
Loading...
Searching...
No Matches
Buffer.cuh
1#ifndef PBAT_GPU_IMPL_COMMON_BUFFER_CUH
2#define PBAT_GPU_IMPL_COMMON_BUFFER_CUH
3
5
6#include <cstddef>
7#include <exception>
8#include <string>
9#include <thrust/copy.h>
10#include <thrust/device_vector.h>
11#include <type_traits>
12#include <vector>
13
14namespace pbat {
15namespace gpu {
16namespace impl {
17namespace common {
18
19template <class T, int D = 1>
20class Buffer
21{
22 public:
23 using SelfType = Buffer<T, D>;
24 using ValueType = T;
25 static auto constexpr kDims = D;
26
27 Buffer(std::size_t count = 0ULL);
28
29 SelfType& operator=(SelfType const& other);
30
31 template <int D2>
32 SelfType& operator=(Buffer<T, D2> const& other);
33
34 thrust::device_vector<T>& operator[](auto d);
35 thrust::device_vector<T> const& operator[](auto d) const;
36
37 std::size_t Size() const;
38 bool Empty() const;
39 std::vector<T> Get() const;
40 std::vector<T> Get(std::size_t count) const;
41
42 std::conditional_t<(D > 1), std::array<thrust::device_ptr<T>, D>, thrust::device_ptr<T>> Data();
43 std::conditional_t<
44 (D > 1),
45 std::array<thrust::device_ptr<T const>, D>,
46 thrust::device_ptr<T const>>
47 Data() const;
48
49 void Resize(std::size_t count);
50 void SetConstant(T value);
51
52 std::conditional_t<(D > 1), std::array<T*, D>, T*> Raw();
53 std::conditional_t<(D > 1), std::array<T const*, D>, T const*> Raw() const;
54
55 constexpr auto Dimensions() const { return D; }
56
57 private:
58 std::array<thrust::device_vector<T>, D> mBuffers;
59};
60
61template <class T, int D>
62Buffer<T, D>::Buffer(std::size_t count) : mBuffers()
63{
64 PBAT_PROFILE_CUDA_NAMED_SCOPE("pbat.gpu.impl.common.Buffer.Construct")
65 for (auto d = 0; d < D; ++d)
66 mBuffers[d].resize(count);
67}
68
69template <class T, int D>
70inline Buffer<T, D>& Buffer<T, D>::operator=(Buffer<T, D> const& other)
71{
72 PBAT_PROFILE_CUDA_NAMED_SCOPE("pbat.gpu.impl.common.Buffer.CopyToGpu");
73 for (auto d = 0; d < D; ++d)
74 {
75 if (this->Size() != other.Size())
76 mBuffers[d].resize(other.Size());
77 thrust::copy(other.mBuffers[d].begin(), other.mBuffers[d].end(), mBuffers[d].begin());
78 }
79 return *this;
80}
81
82template <class T, int D>
83template <int D2>
84Buffer<T, D>& Buffer<T, D>::operator=(Buffer<T, D2> const& other)
85{
86 PBAT_PROFILE_CUDA_NAMED_SCOPE("pbat.gpu.impl.common.Buffer.CopyToGpu");
87 static_assert(
88 D == 1 or D2 == 1,
89 "Buffer<T, D>::operator=(Buffer<T, D2>) only works for D == 1 or D2 == 1");
90 if constexpr (D == 1)
91 {
92 if (this->Size() != other.Size() * other.Dimensions())
93 Resize(other.Size() * other.Dimensions());
94 auto n = other.Size();
95 auto begin = mBuffers[0].begin();
96 for (auto d = 0; d < D2; ++d)
97 thrust::copy(other[d].begin(), other[d].end(), begin + d * n);
98 }
99 if constexpr (D2 == 1)
100 {
101 auto n = other.Size() / Dimensions();
102 if (this->Size() != n)
103 Resize(n);
104 auto begin = other.Data();
105 for (auto d = 0; d < D; ++d)
106 thrust::copy(begin + d * n, begin + (d + 1) * n, mBuffers[d].begin());
107 }
108 return *this;
109}
110
111template <class T, int D>
112thrust::device_vector<T>& Buffer<T, D>::operator[](auto d)
113{
114 return mBuffers[d];
115}
116
117template <class T, int D>
118thrust::device_vector<T> const& Buffer<T, D>::operator[](auto d) const
119{
120 return mBuffers[d];
121}
122
123template <class T, int D>
124std::size_t Buffer<T, D>::Size() const
125{
126 return mBuffers[0].size();
127}
128
129template <class T, int D>
130bool Buffer<T, D>::Empty() const
131{
132 return Size() == 0ULL;
133}
134
135template <class T, int D>
136std::vector<T> Buffer<T, D>::Get() const
137{
138 return Get(Size());
139}
140
141template <class T, int D>
142inline std::vector<T> Buffer<T, D>::Get(std::size_t count) const
143{
144 PBAT_PROFILE_CUDA_NAMED_SCOPE("pbat.gpu.impl.common.Buffer.CopyToCpu");
145 if (count > Size())
146 {
147 std::string const what = "Requested " + std::to_string(count) +
148 " buffer elements, but buffer has size " + std::to_string(Size());
149 throw std::invalid_argument(what);
150 }
151 std::vector<T> buffer(count * D);
152 for (auto d = 0; d < D; ++d)
153 {
154 thrust::copy(mBuffers[d].begin(), mBuffers[d].begin() + count, buffer.begin() + d * count);
155 }
156 return buffer;
157}
158
159template <class T, int D>
160std::conditional_t<(D > 1), std::array<thrust::device_ptr<T>, D>, thrust::device_ptr<T>>
161Buffer<T, D>::Data()
162{
163 std::array<thrust::device_ptr<T>, D> data{};
164 for (auto d = 0; d < D; ++d)
165 data[d] = mBuffers[d].data();
166 if constexpr (D > 1)
167 {
168 return data;
169 }
170 else
171 {
172 return data[0];
173 }
174}
175
176template <class T, int D>
177std::conditional_t<(D > 1), std::array<thrust::device_ptr<T const>, D>, thrust::device_ptr<T const>>
178Buffer<T, D>::Data() const
179{
180 std::array<thrust::device_ptr<T const>, D> data{};
181 for (auto d = 0; d < D; ++d)
182 data[d] = mBuffers[d].data();
183 if constexpr (D > 1)
184 {
185 return data;
186 }
187 else
188 {
189 return data[0];
190 }
191}
192
193template <class T, int D>
194void Buffer<T, D>::Resize(std::size_t count)
195{
196 PBAT_PROFILE_CUDA_NAMED_SCOPE("pbat.gpu.impl.common.Buffer.Resize");
197 for (auto d = 0; d < D; ++d)
198 {
199 mBuffers[d].resize(count);
200 }
201}
202
203template <class T, int D>
204void Buffer<T, D>::SetConstant(T value)
205{
206 PBAT_PROFILE_CUDA_NAMED_SCOPE("pbat.gpu.impl.common.Buffer.SetConstant");
207 for (auto d = 0; d < Dimensions(); ++d)
208 {
209 thrust::fill(mBuffers[d].begin(), mBuffers[d].end(), value);
210 }
211}
212
213template <class T, int D>
214std::conditional_t<(D > 1), std::array<T*, D>, T*> Buffer<T, D>::Raw()
215{
216 std::array<T*, D> raw{};
217 for (auto d = 0; d < D; ++d)
218 raw[d] = thrust::raw_pointer_cast(mBuffers[d].data());
219 if constexpr (D > 1)
220 {
221 return raw;
222 }
223 else
224 {
225 return raw[0];
226 }
227}
228
229template <class T, int D>
230std::conditional_t<(D > 1), std::array<T const*, D>, T const*> Buffer<T, D>::Raw() const
231{
232 std::array<T const*, D> raw{};
233 for (auto d = 0; d < D; ++d)
234 raw[d] = thrust::raw_pointer_cast(mBuffers[d].data());
235 if constexpr (D > 1)
236 {
237 return raw;
238 }
239 else
240 {
241 return raw[0];
242 }
243}
244
245} // namespace common
246} // namespace impl
247} // namespace gpu
248} // namespace pbat
249
250#endif // PBAT_GPU_IMPL_COMMON_BUFFER_CUH
Definition Buffer.cuh:21
Profiling utilities for host-side GPU code.
GPU algorithm implementations.
Definition VertexTriangleMixedCcdDcd.h:21
GPU related public functionality.
Definition Buffer.cu:16
The main namespace of the library.
Definition Aliases.h:15