1#ifndef PBAT_GPU_IMPL_COMMON_BUFFER_CUH
2#define PBAT_GPU_IMPL_COMMON_BUFFER_CUH
9#include <thrust/copy.h>
10#include <thrust/device_vector.h>
19template <
class T,
int D = 1>
23 using SelfType = Buffer<T, D>;
25 static auto constexpr kDims = D;
27 Buffer(std::size_t count = 0ULL);
29 SelfType& operator=(SelfType
const& other);
32 SelfType& operator=(Buffer<T, D2>
const& other);
34 thrust::device_vector<T>& operator[](
auto d);
35 thrust::device_vector<T>
const& operator[](
auto d)
const;
37 std::size_t Size()
const;
39 std::vector<T> Get()
const;
40 std::vector<T> Get(std::size_t count)
const;
42 std::conditional_t<(D > 1), std::array<thrust::device_ptr<T>, D>, thrust::device_ptr<T>> Data();
45 std::array<thrust::device_ptr<T const>, D>,
46 thrust::device_ptr<T const>>
49 void Resize(std::size_t count);
50 void SetConstant(T value);
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;
55 constexpr auto Dimensions()
const {
return D; }
58 std::array<thrust::device_vector<T>, D> mBuffers;
61template <
class T,
int D>
62Buffer<T, D>::Buffer(std::size_t count) : mBuffers()
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);
69template <class T,
int D>
72 PBAT_PROFILE_CUDA_NAMED_SCOPE(
"pbat.gpu.impl.common.Buffer.CopyToGpu");
73 for (
auto d = 0; d < D; ++d)
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());
82template <
class T,
int D>
84Buffer<T, D>& Buffer<T, D>::operator=(Buffer<T, D2>
const& other)
86 PBAT_PROFILE_CUDA_NAMED_SCOPE(
"pbat.gpu.impl.common.Buffer.CopyToGpu");
89 "Buffer<T, D>::operator=(Buffer<T, D2>) only works for D == 1 or D2 == 1");
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);
99 if constexpr (D2 == 1)
101 auto n = other.Size() / Dimensions();
102 if (this->Size() != 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());
111template <
class T,
int D>
112thrust::device_vector<T>& Buffer<T, D>::operator[](
auto d)
117template <
class T,
int D>
118thrust::device_vector<T>
const& Buffer<T, D>::operator[](
auto d)
const
123template <
class T,
int D>
124std::size_t Buffer<T, D>::Size()
const
126 return mBuffers[0].size();
129template <
class T,
int D>
130bool Buffer<T, D>::Empty()
const
132 return Size() == 0ULL;
135template <
class T,
int D>
136std::vector<T> Buffer<T, D>::Get()
const
141template <
class T,
int D>
142inline std::vector<T> Buffer<T, D>::Get(std::size_t count)
const
144 PBAT_PROFILE_CUDA_NAMED_SCOPE(
"pbat.gpu.impl.common.Buffer.CopyToCpu");
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);
151 std::vector<T> buffer(count * D);
152 for (
auto d = 0; d < D; ++d)
154 thrust::copy(mBuffers[d].begin(), mBuffers[d].begin() + count, buffer.begin() + d * count);
159template <
class T,
int D>
160std::conditional_t<(D > 1), std::array<thrust::device_ptr<T>, D>, thrust::device_ptr<T>>
163 std::array<thrust::device_ptr<T>, D> data{};
164 for (
auto d = 0; d < D; ++d)
165 data[d] = mBuffers[d].data();
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
180 std::array<thrust::device_ptr<T const>, D> data{};
181 for (
auto d = 0; d < D; ++d)
182 data[d] = mBuffers[d].data();
193template <
class T,
int D>
194void Buffer<T, D>::Resize(std::size_t count)
196 PBAT_PROFILE_CUDA_NAMED_SCOPE(
"pbat.gpu.impl.common.Buffer.Resize");
197 for (
auto d = 0; d < D; ++d)
199 mBuffers[d].resize(count);
203template <
class T,
int D>
204void Buffer<T, D>::SetConstant(T value)
206 PBAT_PROFILE_CUDA_NAMED_SCOPE(
"pbat.gpu.impl.common.Buffer.SetConstant");
207 for (
auto d = 0; d < Dimensions(); ++d)
209 thrust::fill(mBuffers[d].begin(), mBuffers[d].end(), value);
213template <
class T,
int D>
214std::conditional_t<(D > 1), std::array<T*, D>, T*> Buffer<T, D>::Raw()
216 std::array<T*, D> raw{};
217 for (
auto d = 0; d < D; ++d)
218 raw[d] = thrust::raw_pointer_cast(mBuffers[d].data());
229template <
class T,
int D>
230std::conditional_t<(D > 1), std::array<T const*, D>, T
const*> Buffer<T, D>::Raw()
const
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());
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