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