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