Halide 19.0.0
Halide compiler and libraries
Loading...
Searching...
No Matches
Buffer.h
Go to the documentation of this file.
1#ifndef HALIDE_BUFFER_H
2#define HALIDE_BUFFER_H
3
4#include "DeviceInterface.h"
5#include "Expr.h"
6#include "IntrusivePtr.h"
8
9namespace Halide {
10
11constexpr int AnyDims = Halide::Runtime::AnyDims; // -1
12
13template<typename T = void, int Dims = AnyDims>
14class Buffer;
15
16struct JITUserContext;
17
18namespace Internal {
19
25
26Expr buffer_accessor(const Buffer<> &buf, const std::vector<Expr> &args);
27
28template<typename... Args>
29struct all_ints_and_optional_name : std::false_type {};
30
31template<typename First, typename... Rest>
32struct all_ints_and_optional_name<First, Rest...> : meta_and<std::is_convertible<First, int>,
33 all_ints_and_optional_name<Rest...>> {};
34
35template<typename T>
36struct all_ints_and_optional_name<T> : meta_or<std::is_convertible<T, std::string>,
37 std::is_convertible<T, int>> {};
38
39template<>
40struct all_ints_and_optional_name<> : std::true_type {};
41
42template<typename T,
43 typename = typename std::enable_if<!std::is_convertible<T, std::string>::value>::type>
45 return "";
46}
47
48inline std::string get_name_from_end_of_parameter_pack(const std::string &n) {
49 return n;
50}
51
53 return "";
54}
55
56template<typename First,
57 typename Second,
58 typename... Args>
59std::string get_name_from_end_of_parameter_pack(First first, Second second, Args &&...rest) {
60 return get_name_from_end_of_parameter_pack(second, std::forward<Args>(rest)...);
61}
62
63inline void get_shape_from_start_of_parameter_pack_helper(std::vector<int> &, const std::string &) {
64}
65
66inline void get_shape_from_start_of_parameter_pack_helper(std::vector<int> &) {
67}
68
69template<typename... Args>
70void get_shape_from_start_of_parameter_pack_helper(std::vector<int> &result, int x, Args &&...rest) {
71 result.push_back(x);
72 get_shape_from_start_of_parameter_pack_helper(result, std::forward<Args>(rest)...);
73}
74
75template<typename... Args>
76std::vector<int> get_shape_from_start_of_parameter_pack(Args &&...args) {
77 std::vector<int> result;
78 get_shape_from_start_of_parameter_pack_helper(result, std::forward<Args>(args)...);
79 return result;
80}
81
82template<typename T, typename T2>
83using add_const_if_T_is_const = typename std::conditional<std::is_const<T>::value, const T2, T2>::type;
84
85// Helpers to produce the name of a Buffer element type (a Halide
86// scalar type, or void, possibly with const). Useful for an error
87// messages.
88template<typename T>
89void buffer_type_name_non_const(std::ostream &s) {
90 s << type_to_c_type(type_of<T>(), false);
91}
92
93template<>
94inline void buffer_type_name_non_const<void>(std::ostream &s) {
95 s << "void";
96}
97
98template<typename T>
99std::string buffer_type_name() {
100 std::ostringstream oss;
101 if (std::is_const<T>::value) {
102 oss << "const ";
103 }
104 buffer_type_name_non_const<typename std::remove_const<T>::type>(oss);
105 return oss.str();
106}
107
108} // namespace Internal
109
110/** A Halide::Buffer is a named shared reference to a
111 * Halide::Runtime::Buffer.
112 *
113 * A Buffer<T1, D> can refer to a Buffer<T2, D> if T1 is const whenever T2
114 * is const, and either T1 = T2 or T1 is void. A Buffer<void, D> can
115 * refer to any Buffer of any non-const type, and the default
116 * template parameter is T = void.
117 *
118 * A Buffer<T, D1> can refer to a Buffer<T, D2> if D1 == D2,
119 * or if D1 is AnyDims (meaning "dimensionality is checked at runtime, not compiletime").
120 */
121template<typename T, int Dims>
122class Buffer {
123 Internal::IntrusivePtr<Internal::BufferContents> contents;
124
125 template<typename T2, int D2>
126 friend class Buffer;
127
128 template<typename T2, int D2>
129 static void assert_can_convert_from(const Buffer<T2, D2> &other) {
130 if (!other.defined()) {
131 // Avoid UB of deferencing offset of a null contents ptr
132 static_assert((!std::is_const<T2>::value || std::is_const<T>::value),
133 "Can't convert from a Buffer<const T> to a Buffer<T>");
134 static_assert(std::is_same<typename std::remove_const<T>::type,
135 typename std::remove_const<T2>::type>::value ||
136 std::is_void<T>::value ||
137 std::is_void<T2>::value,
138 "type mismatch constructing Buffer");
139 static_assert(Dims == AnyDims || D2 == AnyDims || Dims == D2,
140 "Can't convert from a Buffer with static dimensionality to a Buffer with different static dimensionality");
141 } else {
142 // Don't delegate to
143 // Runtime::Buffer<T>::assert_can_convert_from. It might
144 // not assert if NDEBUG is defined. user_assert is
145 // friendlier anyway because it reports line numbers when
146 // debugging symbols are found, it throws an exception
147 // when exceptions are enabled, and we can print the
148 // actual types in question.
149 using BufType = Runtime::Buffer<T, Dims>; // alias because commas in user_assert() macro confuses compiler
150 user_assert(BufType::can_convert_from(*(other.get())))
151 << "Type mismatch constructing Buffer. Can't construct Buffer<"
152 << Internal::buffer_type_name<T>() << ", " << Dims << "> from Buffer<"
153 << type_to_c_type(other.type(), false) << ", " << D2 << ">, dimensions() = " << other.dimensions() << "\n";
154 }
155 }
156
157public:
158 static constexpr int AnyDims = Halide::AnyDims;
159 static_assert(Dims == AnyDims || Dims >= 0);
160
161 typedef T ElemType;
162
163 // This class isn't final (and is subclassed from the Python binding
164 // code, at least) so it needs a virtual dtor.
165 virtual ~Buffer() = default;
166
167 /** Make a null Buffer, which points to no Runtime::Buffer */
168 Buffer() = default;
169
170 /** Trivial copy constructor. */
171 Buffer(const Buffer &that) = default;
172
173 /** Trivial copy assignment operator. */
174 Buffer &operator=(const Buffer &that) = default;
175
176 /** Trivial move assignment operator. */
177 Buffer &operator=(Buffer &&) noexcept = default;
178
179 /** Make a Buffer from a Buffer of a different type */
180 template<typename T2, int D2>
181 Buffer(const Buffer<T2, D2> &other)
182 : contents(other.contents) {
183 assert_can_convert_from(other);
184 }
185
186 /** Move construct from a Buffer of a different type */
187 template<typename T2, int D2>
188 Buffer(Buffer<T2, D2> &&other) noexcept {
189 assert_can_convert_from(other);
190 contents = std::move(other.contents);
191 }
192
193 /** Construct a Buffer that captures and owns an rvalue Runtime::Buffer */
194 template<int D2>
195 Buffer(Runtime::Buffer<T, D2> &&buf, const std::string &name = "")
196 : contents(new Internal::BufferContents) {
197 contents->buf = std::move(buf);
198 if (name.empty()) {
199 contents->name = Internal::unique_name('b');
200 } else {
201 contents->name = name;
202 }
203 }
204
205 /** Constructors that match Runtime::Buffer with two differences:
206 * 1) They take a Type instead of a halide_type_t
207 * 2) There is an optional last string argument that gives the buffer a specific name
208 */
209 // @{
210 template<typename... Args,
211 typename = typename std::enable_if<Internal::all_ints_and_optional_name<Args...>::value>::type>
212 explicit Buffer(Type t,
213 int first, Args... rest)
214 : Buffer(Runtime::Buffer<T, Dims>(t, Internal::get_shape_from_start_of_parameter_pack(first, rest...)),
215 Internal::get_name_from_end_of_parameter_pack(rest...)) {
216 }
217
218 explicit Buffer(const halide_buffer_t &buf,
219 const std::string &name = "")
220 : Buffer(Runtime::Buffer<T, Dims>(buf), name) {
221 }
222
223 template<typename... Args,
224 typename = typename std::enable_if<Internal::all_ints_and_optional_name<Args...>::value>::type>
225 explicit Buffer(int first, Args... rest)
226 : Buffer(Runtime::Buffer<T, Dims>(Internal::get_shape_from_start_of_parameter_pack(first, rest...)),
227 Internal::get_name_from_end_of_parameter_pack(rest...)) {
228 }
229
230 explicit Buffer(Type t,
231 const std::vector<int> &sizes,
232 const std::string &name = "")
233 : Buffer(Runtime::Buffer<T, Dims>(t, sizes), name) {
234 }
235
236 explicit Buffer(Type t,
237 const std::vector<int> &sizes,
238 const std::vector<int> &storage_order,
239 const std::string &name = "")
240 : Buffer(Runtime::Buffer<T, Dims>(t, sizes, storage_order), name) {
241 }
242
243 explicit Buffer(const std::vector<int> &sizes,
244 const std::string &name = "")
245 : Buffer(Runtime::Buffer<T, Dims>(sizes), name) {
246 }
247
248 explicit Buffer(const std::vector<int> &sizes,
249 const std::vector<int> &storage_order,
250 const std::string &name = "")
251 : Buffer(Runtime::Buffer<T, Dims>(sizes, storage_order), name) {
252 }
253
254 template<typename Array, size_t N>
255 explicit Buffer(Array (&vals)[N],
256 const std::string &name = "")
257 : Buffer(Runtime::Buffer<T, Dims>(vals), name) {
258 }
259
260 template<typename... Args,
261 typename = typename std::enable_if<Internal::all_ints_and_optional_name<Args...>::value>::type>
262 explicit Buffer(Type t,
264 int first, Args &&...rest)
265 : Buffer(Runtime::Buffer<T, Dims>(t, data, Internal::get_shape_from_start_of_parameter_pack(first, rest...)),
266 Internal::get_name_from_end_of_parameter_pack(rest...)) {
267 }
268
269 template<typename... Args,
270 typename = typename std::enable_if<Internal::all_ints_and_optional_name<Args...>::value>::type>
271 explicit Buffer(Type t,
273 const std::vector<int> &sizes,
274 const std::string &name = "")
275 : Buffer(Runtime::Buffer<T, Dims>(t, data, sizes, name)) {
276 }
277
278 template<typename... Args,
279 typename = typename std::enable_if<Internal::all_ints_and_optional_name<Args...>::value>::type>
280 explicit Buffer(T *data,
281 int first, Args &&...rest)
282 : Buffer(Runtime::Buffer<T, Dims>(data, Internal::get_shape_from_start_of_parameter_pack(first, rest...)),
283 Internal::get_name_from_end_of_parameter_pack(rest...)) {
284 }
285
286 explicit Buffer(T *data,
287 const std::vector<int> &sizes,
288 const std::string &name = "")
289 : Buffer(Runtime::Buffer<T, Dims>(data, sizes), name) {
290 }
291
292 explicit Buffer(Type t,
294 const std::vector<int> &sizes,
295 const std::string &name = "")
296 : Buffer(Runtime::Buffer<T, Dims>(t, data, sizes), name) {
297 }
298
299 explicit Buffer(Type t,
301 int d,
302 const halide_dimension_t *shape,
303 const std::string &name = "")
304 : Buffer(Runtime::Buffer<T, Dims>(t, data, d, shape), name) {
305 }
306
307 explicit Buffer(T *data,
308 int d,
309 const halide_dimension_t *shape,
310 const std::string &name = "")
311 : Buffer(Runtime::Buffer<T, Dims>(data, d, shape), name) {
312 }
313
314 static Buffer<T, Dims> make_scalar(const std::string &name = "") {
316 }
317
318 static Buffer<> make_scalar(Type t, const std::string &name = "") {
320 }
321
322 static Buffer<T, Dims> make_scalar(T *data, const std::string &name = "") {
324 }
325
326 static Buffer<T, Dims> make_interleaved(int width, int height, int channels, const std::string &name = "") {
327 return Buffer<T, Dims>(Runtime::Buffer<T, Dims>::make_interleaved(width, height, channels), name);
328 }
329
330 static Buffer<> make_interleaved(Type t, int width, int height, int channels, const std::string &name = "") {
331 return Buffer<>(Runtime::Buffer<>::make_interleaved(t, width, height, channels), name);
332 }
333
334 static Buffer<T, Dims> make_interleaved(T *data, int width, int height, int channels, const std::string &name = "") {
335 return Buffer<T, Dims>(Runtime::Buffer<T, Dims>::make_interleaved(data, width, height, channels), name);
336 }
337
339 make_interleaved(Type t, T *data, int width, int height, int channels, const std::string &name = "") {
341 return Buffer<T2, Dims>(Runtime::Buffer<T2, Dims>::make_interleaved(t, data, width, height, channels), name);
342 }
343
344 template<typename T2, int D2>
346 void *(*allocate_fn)(size_t) = nullptr,
347 void (*deallocate_fn)(void *) = nullptr,
348 const std::string &name = "") {
349 return Buffer<T, Dims>(Runtime::Buffer<T, Dims>::make_with_shape_of(*src.get(), allocate_fn, deallocate_fn), name);
350 }
351
352 template<typename T2, int D2>
354 void *(*allocate_fn)(size_t) = nullptr,
355 void (*deallocate_fn)(void *) = nullptr,
356 const std::string &name = "") {
357 return Buffer<T, Dims>(Runtime::Buffer<T, Dims>::make_with_shape_of(src, allocate_fn, deallocate_fn), name);
358 }
359 // @}
360
361 /** Buffers are optionally named. */
362 // @{
363 void set_name(const std::string &n) {
364 contents->name = n;
365 }
366
367 const std::string &name() const {
368 return contents->name;
369 }
370 // @}
371
372 /** Check if two Buffer objects point to the same underlying Buffer */
373 template<typename T2, int D2>
374 bool same_as(const Buffer<T2, D2> &other) const {
375 return (const void *)(contents.get()) == (const void *)(other.contents.get());
376 }
377
378 /** Check if this Buffer refers to an existing
379 * Buffer. Default-constructed Buffer objects do not refer to any
380 * existing Buffer. */
381 bool defined() const {
382 return contents.defined();
383 }
384
385 /** Get a pointer to the underlying Runtime::Buffer */
386 // @{
388 // It's already type-checked, so no need to use as<T>.
389 return (Runtime::Buffer<T, Dims> *)(&contents->buf);
390 }
392 return (const Runtime::Buffer<T, Dims> *)(&contents->buf);
393 }
394 // @}
395
396 // We forward numerous methods from the underlying Buffer
397#define HALIDE_BUFFER_FORWARD_CONST(method) \
398 template<typename... Args> \
399 auto method(Args &&...args) const -> decltype(std::declval<const Runtime::Buffer<T, Dims>>().method(std::forward<Args>(args)...)) { \
400 user_assert(defined()) << "Undefined buffer calling const method " #method "\n"; \
401 return get()->method(std::forward<Args>(args)...); \
402 }
403
404#define HALIDE_BUFFER_FORWARD(method) \
405 template<typename... Args> \
406 auto method(Args &&...args) -> decltype(std::declval<Runtime::Buffer<T, Dims>>().method(std::forward<Args>(args)...)) { \
407 user_assert(defined()) << "Undefined buffer calling method " #method "\n"; \
408 return get()->method(std::forward<Args>(args)...); \
409 }
410
411// This is a weird-looking but effective workaround for a deficiency in "perfect forwarding":
412// namely, it can't really handle initializer-lists. The idea here is that we declare
413// the expected type to be passed on, and that allows the compiler to handle it.
414// The weirdness comes in with the variadic macro: the problem is that the type
415// we want to forward might be something like `std::vector<std::pair<int, int>>`,
416// which contains a comma, which throws a big wrench in C++ macro system.
417// However... since all we really need to do is capture the remainder of the macro,
418// and forward it as is, we can just use ... to allow an arbitrary number of commas,
419// then use __VA_ARGS__ to forward the mess as-is, and while it looks horrible, it
420// works.
421#define HALIDE_BUFFER_FORWARD_INITIALIZER_LIST(method, ...) \
422 inline auto method(const __VA_ARGS__ &a) -> decltype(std::declval<Runtime::Buffer<T, Dims>>().method(a)) { \
423 user_assert(defined()) << "Undefined buffer calling method " #method "\n"; \
424 return get()->method(a); \
425 }
426
427 /** Does the same thing as the equivalent Halide::Runtime::Buffer method */
428 // @{
429 HALIDE_BUFFER_FORWARD(raw_buffer)
443 HALIDE_BUFFER_FORWARD_CONST(number_of_elements)
444 HALIDE_BUFFER_FORWARD_CONST(size_in_bytes)
451 HALIDE_BUFFER_FORWARD_INITIALIZER_LIST(crop, std::vector<std::pair<int, int>>)
456 HALIDE_BUFFER_FORWARD(set_min)
457 HALIDE_BUFFER_FORWARD(translate)
458 HALIDE_BUFFER_FORWARD_INITIALIZER_LIST(translate, std::vector<int>)
459 HALIDE_BUFFER_FORWARD(transpose)
461 HALIDE_BUFFER_FORWARD(add_dimension)
462 HALIDE_BUFFER_FORWARD(copy_to_host)
464 HALIDE_BUFFER_FORWARD_CONST(has_device_allocation)
466 HALIDE_BUFFER_FORWARD_CONST(device_dirty)
467 HALIDE_BUFFER_FORWARD(set_host_dirty)
468 HALIDE_BUFFER_FORWARD(set_device_dirty)
469 HALIDE_BUFFER_FORWARD(device_sync)
472 HALIDE_BUFFER_FORWARD(device_detach_native)
473 HALIDE_BUFFER_FORWARD(allocate)
474 HALIDE_BUFFER_FORWARD(deallocate)
475 HALIDE_BUFFER_FORWARD(device_deallocate)
476 HALIDE_BUFFER_FORWARD(device_free)
478
479#undef HALIDE_BUFFER_FORWARD
480#undef HALIDE_BUFFER_FORWARD_CONST
481
482 template<typename Fn, typename... Args>
483 Buffer<T, Dims> &for_each_value(Fn &&f, Args... other_buffers) {
484 get()->for_each_value(std::forward<Fn>(f), (*std::forward<Args>(other_buffers).get())...);
485 return *this;
486 }
487
488 template<typename Fn, typename... Args>
489 const Buffer<T, Dims> &for_each_value(Fn &&f, Args... other_buffers) const {
490 get()->for_each_value(std::forward<Fn>(f), (*std::forward<Args>(other_buffers).get())...);
491 return *this;
492 }
493
494 template<typename Fn>
496 get()->for_each_element(std::forward<Fn>(f));
497 return *this;
498 }
499
500 template<typename Fn>
501 const Buffer<T, Dims> &for_each_element(Fn &&f) const {
502 get()->for_each_element(std::forward<Fn>(f));
503 return *this;
504 }
505
506 template<typename FnOrValue>
507 Buffer<T, Dims> &fill(FnOrValue &&f) {
508 get()->fill(std::forward<FnOrValue>(f));
509 return *this;
510 }
511
513
517
519
520 static constexpr int static_dimensions() {
522 }
523
524 template<typename T2, int D2>
525 static bool can_convert_from(const Buffer<T2, D2> &other) {
527 }
528
529 // Note that since Runtime::Buffer stores halide_type_t rather than Halide::Type,
530 // there is no handle-specific type information, so all handle types are
531 // considered equivalent to void* here. (This only matters if you are making
532 // a Buffer-of-handles, which is not really a real use case...)
533 Type type() const {
534 return contents->buf.type();
535 }
536
537 template<typename T2, int D2 = Dims>
539 return Buffer<T2, D2>(*this);
540 }
541
543 return Buffer<T, Dims>(std::move(contents->buf.as<T, Dims>().copy()));
544 }
545
546 template<typename T2, int D2>
547 void copy_from(const Buffer<T2, D2> &other) {
548 contents->buf.copy_from(*other.get());
549 }
550
551 template<typename... Args>
552 auto operator()(int first, Args &&...args) -> decltype(std::declval<Runtime::Buffer<T, Dims>>()(first, std::forward<Args>(args)...)) {
553 return (*get())(first, std::forward<Args>(args)...);
554 }
555
556 template<typename... Args>
557 auto operator()(int first, Args &&...args) const -> decltype(std::declval<const Runtime::Buffer<T, Dims>>()(first, std::forward<Args>(args)...)) {
558 return (*get())(first, std::forward<Args>(args)...);
559 }
560
561 auto operator()(const int *pos) -> decltype(std::declval<Runtime::Buffer<T, Dims>>()(pos)) {
562 return (*get())(pos);
563 }
564
565 auto operator()(const int *pos) const -> decltype(std::declval<const Runtime::Buffer<T, Dims>>()(pos)) {
566 return (*get())(pos);
567 }
568
569 auto operator()() -> decltype(std::declval<Runtime::Buffer<T, Dims>>()()) {
570 return (*get())();
571 }
572
573 auto operator()() const -> decltype(std::declval<const Runtime::Buffer<T, Dims>>()()) {
574 return (*get())();
575 }
576 // @}
577
578 /** Make an Expr that loads from this concrete buffer at a computed
579 * coordinate. Returned Expr is const so that it's not possible to
580 * accidentally treat a buffer like a Func and try to assign an Expr to a
581 * given symbolic coordinate. */
582 // @{
583 template<typename... Args>
584 const Expr operator()(const Expr &first, Args... rest) const { // NOLINT
585 std::vector<Expr> args = {first, rest...};
586 return (*this)(args);
587 }
588
589 template<typename... Args>
590 const Expr operator()(const std::vector<Expr> &args) const { // NOLINT
591 return buffer_accessor(Buffer<>(*this), args);
592 }
593 // @}
594
595 /** Copy to the GPU, using the device API that is the default for the given Target. */
597 return copy_to_device(DeviceAPI::Default_GPU, t, context);
598 }
599
600 /** Copy to the GPU, using the given device API */
601 int copy_to_device(const DeviceAPI &d, const Target &t = get_jit_target_from_environment(), JITUserContext *context = nullptr) {
602 return contents->buf.copy_to_device(get_device_interface_for_device_api(d, t, "Buffer::copy_to_device"), context);
603 }
604
605 /** Allocate on the GPU, using the device API that is the default for the given Target. */
607 return device_malloc(DeviceAPI::Default_GPU, t, context);
608 }
609
610 /** Allocate storage on the GPU, using the given device API */
611 int device_malloc(const DeviceAPI &d, const Target &t = get_jit_target_from_environment(), JITUserContext *context = nullptr) {
612 return contents->buf.device_malloc(get_device_interface_for_device_api(d, t, "Buffer::device_malloc"), context);
613 }
614
615 /** Wrap a native handle, using the given device API.
616 * It is a bad idea to pass DeviceAPI::Default_GPU to this routine
617 * as the handle argument must match the API that the default
618 * resolves to and it is clearer and more reliable to pass the
619 * resolved DeviceAPI explicitly. */
620 int device_wrap_native(const DeviceAPI &d, uint64_t handle, const Target &t = get_jit_target_from_environment(), JITUserContext *context = nullptr) {
621 return contents->buf.device_wrap_native(get_device_interface_for_device_api(d, t, "Buffer::device_wrap_native"), handle, context);
622 }
623};
624
625} // namespace Halide
626
627#endif
#define HALIDE_BUFFER_FORWARD(method)
Definition Buffer.h:404
#define HALIDE_BUFFER_FORWARD_INITIALIZER_LIST(method,...)
Definition Buffer.h:421
#define HALIDE_BUFFER_FORWARD_CONST(method)
Definition Buffer.h:397
Methods for managing device allocations when jitting.
Base classes for Halide expressions (Halide::Expr) and statements (Halide::Internal::Stmt)
Defines a Buffer type that wraps from halide_buffer_t and adds functionality, and methods for more co...
Support classes for reference-counting via intrusive shared pointers.
A Halide::Buffer is a named shared reference to a Halide::Runtime::Buffer.
Definition RDom.h:21
auto operator()() -> decltype(std::declval< Runtime::Buffer< T, Dims > >()())
Definition Buffer.h:569
Buffer & operator=(const Buffer &that)=default
Trivial copy assignment operator.
static Buffer< T, Dims > make_with_shape_of(const Runtime::Buffer< T2, D2 > &src, void *(*allocate_fn)(size_t)=nullptr, void(*deallocate_fn)(void *)=nullptr, const std::string &name="")
Definition Buffer.h:353
static constexpr int static_dimensions()
Definition Buffer.h:520
Type type() const
Definition Buffer.h:533
Buffer(Type t, const std::vector< int > &sizes, const std::string &name="")
Definition Buffer.h:230
Buffer(Runtime::Buffer< T, D2 > &&buf, const std::string &name="")
Construct a Buffer that captures and owns an rvalue Runtime::Buffer.
Definition Buffer.h:195
Buffer< T, Dims > & for_each_value(Fn &&f, Args... other_buffers)
Does the same thing as the equivalent Halide::Runtime::Buffer method.
Definition Buffer.h:483
void set_name(const std::string &n)
Buffers are optionally named.
Definition Buffer.h:363
static constexpr bool has_static_dimensions
Definition Buffer.h:518
const Buffer< T, Dims > & for_each_element(Fn &&f) const
Definition Buffer.h:501
int device_malloc(const DeviceAPI &d, const Target &t=get_jit_target_from_environment(), JITUserContext *context=nullptr)
Allocate storage on the GPU, using the given device API.
Definition Buffer.h:611
virtual ~Buffer()=default
Buffer(const Buffer &that)=default
Trivial copy constructor.
Buffer(Type t, int first, Args... rest)
Constructors that match Runtime::Buffer with two differences: 1) They take a Type instead of a halide...
Definition Buffer.h:212
friend class Buffer
Definition Buffer.h:126
const Buffer< T, Dims > & for_each_value(Fn &&f, Args... other_buffers) const
Definition Buffer.h:489
static Buffer< T, Dims > make_interleaved(int width, int height, int channels, const std::string &name="")
Definition Buffer.h:326
bool defined() const
Check if this Buffer refers to an existing Buffer.
Definition Buffer.h:381
const Expr operator()(const std::vector< Expr > &args) const
Definition Buffer.h:590
bool same_as(const Buffer< T2, D2 > &other) const
Check if two Buffer objects point to the same underlying Buffer.
Definition Buffer.h:374
auto operator()(const int *pos) -> decltype(std::declval< Runtime::Buffer< T, Dims > >()(pos))
Definition Buffer.h:561
Buffer< T, Dims > & for_each_element(Fn &&f)
Definition Buffer.h:495
static Buffer make_interleaved(Type t, int width, int height, int channels, const std::string &name="")
Definition Buffer.h:330
static Buffer make_scalar(Type t, const std::string &name="")
Definition Buffer.h:318
static Buffer< T, Dims > make_scalar(T *data, const std::string &name="")
Definition Buffer.h:322
Buffer(Type t, Internal::add_const_if_T_is_const< T, void > *data, int d, const halide_dimension_t *shape, const std::string &name="")
Definition Buffer.h:299
auto operator()(int first, Args &&...args) -> decltype(std::declval< Runtime::Buffer< T, Dims > >()(first, std::forward< Args >(args)...))
Definition Buffer.h:552
static constexpr int AnyDims
Definition Buffer.h:158
int copy_to_device(const DeviceAPI &d, const Target &t=get_jit_target_from_environment(), JITUserContext *context=nullptr)
Copy to the GPU, using the given device API.
Definition Buffer.h:601
static constexpr halide_type_t static_halide_type()
Definition Buffer.h:514
auto operator()(int first, Args &&...args) const -> decltype(std::declval< const Runtime::Buffer< T, Dims > >()(first, std::forward< Args >(args)...))
Definition Buffer.h:557
Buffer(Array(&vals)[N], const std::string &name="")
Definition Buffer.h:255
Buffer< T, Dims > copy() const
Definition Buffer.h:542
Buffer(const std::vector< int > &sizes, const std::vector< int > &storage_order, const std::string &name="")
Definition Buffer.h:248
Buffer< T, Dims > & fill(FnOrValue &&f)
Definition Buffer.h:507
const std::string & name() const
Definition Buffer.h:367
static Buffer< T, Dims > make_with_shape_of(Buffer< T2, D2 > src, void *(*allocate_fn)(size_t)=nullptr, void(*deallocate_fn)(void *)=nullptr, const std::string &name="")
Definition Buffer.h:345
Runtime::Buffer< T, Dims > * get()
Get a pointer to the underlying Runtime::Buffer.
Definition Buffer.h:387
int device_wrap_native(const DeviceAPI &d, uint64_t handle, const Target &t=get_jit_target_from_environment(), JITUserContext *context=nullptr)
Wrap a native handle, using the given device API.
Definition Buffer.h:620
Buffer()=default
Make a null Buffer, which points to no Runtime::Buffer.
int device_malloc(const Target &t=get_jit_target_from_environment(), JITUserContext *context=nullptr)
Allocate on the GPU, using the device API that is the default for the given Target.
Definition Buffer.h:606
Buffer(Type t, Internal::add_const_if_T_is_const< T, void > *data, const std::vector< int > &sizes, const std::string &name="")
Definition Buffer.h:292
static constexpr bool has_static_halide_type
Definition Buffer.h:512
Buffer(int first, Args... rest)
Definition Buffer.h:225
Buffer(T *data, const std::vector< int > &sizes, const std::string &name="")
Definition Buffer.h:286
Buffer(T *data, int first, Args &&...rest)
Definition Buffer.h:280
static Buffer< T, Dims > make_scalar(const std::string &name="")
Definition Buffer.h:314
Buffer(Type t, Internal::add_const_if_T_is_const< T, void > *data, int first, Args &&...rest)
Definition Buffer.h:262
Buffer(Buffer< T2, D2 > &&other) noexcept
Move construct from a Buffer of a different type.
Definition Buffer.h:188
Buffer & operator=(Buffer &&) noexcept=default
Trivial move assignment operator.
const Expr operator()(const Expr &first, Args... rest) const
Make an Expr that loads from this concrete buffer at a computed coordinate.
Definition Buffer.h:584
Buffer(Type t, const std::vector< int > &sizes, const std::vector< int > &storage_order, const std::string &name="")
Definition Buffer.h:236
auto operator()(const int *pos) const -> decltype(std::declval< const Runtime::Buffer< T, Dims > >()(pos))
Definition Buffer.h:565
int copy_to_device(const Target &t=get_jit_target_from_environment(), JITUserContext *context=nullptr)
Copy to the GPU, using the device API that is the default for the given Target.
Definition Buffer.h:596
static Buffer< Internal::add_const_if_T_is_const< T, void > > make_interleaved(Type t, T *data, int width, int height, int channels, const std::string &name="")
Definition Buffer.h:339
Buffer< T2, D2 > as() const
Definition Buffer.h:538
Buffer(const std::vector< int > &sizes, const std::string &name="")
Definition Buffer.h:243
Buffer(const halide_buffer_t &buf, const std::string &name="")
Definition Buffer.h:218
Buffer(T *data, int d, const halide_dimension_t *shape, const std::string &name="")
Definition Buffer.h:307
Buffer(Type t, Internal::add_const_if_T_is_const< T, void > *data, const std::vector< int > &sizes, const std::string &name="")
Definition Buffer.h:271
static bool can_convert_from(const Buffer< T2, D2 > &other)
Definition Buffer.h:525
const Runtime::Buffer< T, Dims > * get() const
Definition Buffer.h:391
auto operator()() const -> decltype(std::declval< const Runtime::Buffer< T, Dims > >()())
Definition Buffer.h:573
void copy_from(const Buffer< T2, D2 > &other)
Definition Buffer.h:547
static Buffer< T, Dims > make_interleaved(T *data, int width, int height, int channels, const std::string &name="")
Definition Buffer.h:334
A class representing a reference count to be used with IntrusivePtr.
A templated Buffer class that wraps halide_buffer_t and adds functionality.
static bool can_convert_from(const Buffer< T2, D2, S2 > &other)
Determine if a Buffer<T, Dims, InClassDimStorage> can be constructed from some other Buffer type.
static constexpr halide_type_t static_halide_type()
Get the Halide type of T.
static constexpr int static_dimensions()
Callers should not use the result if has_static_dimensions is false.
std::string get_name_from_end_of_parameter_pack()
Definition Buffer.h:52
std::vector< int > get_shape_from_start_of_parameter_pack(Args &&...args)
Definition Buffer.h:76
void buffer_type_name_non_const< void >(std::ostream &s)
Definition Buffer.h:94
void buffer_type_name_non_const(std::ostream &s)
Definition Buffer.h:89
Expr buffer_accessor(const Buffer<> &buf, const std::vector< Expr > &args)
std::string unique_name(char prefix)
Generate a unique name starting with the given prefix.
std::string buffer_type_name()
Definition Buffer.h:99
void get_shape_from_start_of_parameter_pack_helper(std::vector< int > &, const std::string &)
Definition Buffer.h:63
typename std::conditional< std::is_const< T >::value, const T2, T2 >::type add_const_if_T_is_const
Definition Buffer.h:83
constexpr int AnyDims
This file defines the class FunctionDAG, which is our representation of a Halide pipeline,...
std::string type_to_c_type(Type type, bool include_space, bool c_plus_plus=true)
Halide type to a C++ type.
@ Internal
Not visible externally, similar to 'static' linkage in C.
const halide_device_interface_t * get_device_interface_for_device_api(DeviceAPI d, const Target &t=get_jit_target_from_environment(), const char *error_site=nullptr)
Gets the appropriate halide_device_interface_t * for a DeviceAPI.
Target get_jit_target_from_environment()
Return the target that Halide will use for jit-compilation.
DeviceAPI
An enum describing a type of device API.
Definition DeviceAPI.h:15
constexpr int AnyDims
Definition Buffer.h:11
unsigned __INT64_TYPE__ uint64_t
A fragment of Halide syntax.
Definition Expr.h:258
A context to be passed to Pipeline::realize.
Definition JITModule.h:136
A struct representing a target machine and os to generate code for.
Definition Target.h:19
Types in the halide type system.
Definition Type.h:283
The raw representation of an image passed around by generated Halide code.
A runtime tag for a type in the halide type system.
#define user_assert(c)
Definition test.h:10