13template<
typename T =
void,
int Dims = AnyDims>
28template<
typename... Args>
31template<
typename First,
typename... Rest>
33 all_ints_and_optional_name<Rest...>> {};
37 std::is_convertible<T, int>> {};
43 typename =
typename std::enable_if<!std::is_convertible<T, std::string>::value>::type>
56template<
typename First,
69template<
typename... Args>
75template<
typename... Args>
77 std::vector<int> result;
82template<
typename T,
typename T2>
90 s << type_to_c_type(type_of<T>(),
false);
100 std::ostringstream oss;
101 if (std::is_const<T>::value) {
104 buffer_type_name_non_const<typename std::remove_const<T>::type>(oss);
121template<
typename T,
int Dims>
123 Internal::IntrusivePtr<Internal::BufferContents> contents;
125 template<
typename T2,
int D2>
128 template<
typename T2,
int D2>
129 static void assert_can_convert_from(
const Buffer<T2, D2> &other) {
130 if (!other.defined()) {
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");
140 "Can't convert from a Buffer with static dimensionality to a Buffer with different static dimensionality");
150 user_assert(BufType::can_convert_from(*(other.get())))
151 <<
"Type mismatch constructing Buffer. Can't construct Buffer<"
153 <<
type_to_c_type(other.type(),
false) <<
", " << D2 <<
">, dimensions() = " << other.dimensions() <<
"\n";
159 static_assert(Dims ==
AnyDims || Dims >= 0);
180 template<typename T2,
int D2>
182 : contents(other.contents) {
183 assert_can_convert_from(other);
187 template<
typename T2,
int D2>
189 assert_can_convert_from(other);
190 contents = std::move(other.contents);
196 : contents(new
Internal::BufferContents) {
197 contents->buf = std::move(buf);
201 contents->name =
name;
210 template<
typename... Args,
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...)) {
219 const std::string &
name =
"")
223 template<
typename... Args,
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...)) {
231 const std::vector<int> &sizes,
232 const std::string &
name =
"")
237 const std::vector<int> &sizes,
238 const std::vector<int> &storage_order,
239 const std::string &
name =
"")
243 explicit Buffer(
const std::vector<int> &sizes,
244 const std::string &
name =
"")
248 explicit Buffer(
const std::vector<int> &sizes,
249 const std::vector<int> &storage_order,
250 const std::string &
name =
"")
254 template<
typename Array,
size_t N>
256 const std::string &
name =
"")
260 template<
typename... Args,
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...)) {
269 template<
typename... Args,
273 const std::vector<int> &sizes,
274 const std::string &
name =
"")
278 template<
typename... Args,
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...)) {
287 const std::vector<int> &sizes,
288 const std::string &
name =
"")
294 const std::vector<int> &sizes,
295 const std::string &
name =
"")
303 const std::string &
name =
"")
310 const std::string &
name =
"")
344 template<
typename T2,
int D2>
346 void *(*allocate_fn)(
size_t) =
nullptr,
347 void (*deallocate_fn)(
void *) =
nullptr,
348 const std::string &
name =
"") {
352 template<
typename T2,
int D2>
354 void *(*allocate_fn)(
size_t) =
nullptr,
355 void (*deallocate_fn)(
void *) =
nullptr,
356 const std::string &
name =
"") {
367 const std::string &
name()
const {
368 return contents->name;
373 template<
typename T2,
int D2>
375 return (
const void *)(contents.get()) == (
const void *)(other.contents.get());
382 return contents.defined();
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)...); \
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)...); \
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); \
479#undef HALIDE_BUFFER_FORWARD
480#undef HALIDE_BUFFER_FORWARD_CONST
482 template<
typename Fn,
typename... Args>
484 get()->for_each_value(std::forward<Fn>(f), (*std::forward<Args>(other_buffers).
get())...);
488 template<
typename Fn,
typename... Args>
490 get()->for_each_value(std::forward<Fn>(f), (*std::forward<Args>(other_buffers).
get())...);
494 template<
typename Fn>
496 get()->for_each_element(std::forward<Fn>(f));
500 template<
typename Fn>
502 get()->for_each_element(std::forward<Fn>(f));
506 template<
typename FnOrValue>
508 get()->fill(std::forward<FnOrValue>(f));
524 template<
typename T2,
int D2>
534 return contents->buf.type();
537 template<
typename T2,
int D2 = Dims>
546 template<
typename T2,
int D2>
548 contents->buf.copy_from(*other.get());
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)...);
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)...);
561 auto operator()(
const int *pos) ->
decltype(std::declval<Runtime::Buffer<T, Dims>>()(pos)) {
562 return (*
get())(pos);
565 auto operator()(
const int *pos)
const ->
decltype(std::declval<const Runtime::Buffer<T, Dims>>()(pos)) {
566 return (*
get())(pos);
569 auto operator()() ->
decltype(std::declval<Runtime::Buffer<T, Dims>>()()) {
583 template<
typename... Args>
585 std::vector<Expr> args = {first, rest...};
586 return (*
this)(args);
589 template<
typename... Args>
591 return buffer_accessor(
Buffer<>(*
this), args);
#define HALIDE_BUFFER_FORWARD(method)
#define HALIDE_BUFFER_FORWARD_INITIALIZER_LIST(method,...)
#define HALIDE_BUFFER_FORWARD_CONST(method)
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.
auto operator()() -> decltype(std::declval< Runtime::Buffer< T, Dims > >()())
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="")
static constexpr int static_dimensions()
Buffer(Type t, const std::vector< int > &sizes, const std::string &name="")
Buffer(Runtime::Buffer< T, D2 > &&buf, const std::string &name="")
Construct a Buffer that captures and owns an rvalue Runtime::Buffer.
Buffer< T, Dims > & for_each_value(Fn &&f, Args... other_buffers)
Does the same thing as the equivalent Halide::Runtime::Buffer method.
void set_name(const std::string &n)
Buffers are optionally named.
static constexpr bool has_static_dimensions
const Buffer< T, Dims > & for_each_element(Fn &&f) const
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.
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...
const Buffer< T, Dims > & for_each_value(Fn &&f, Args... other_buffers) const
static Buffer< T, Dims > make_interleaved(int width, int height, int channels, const std::string &name="")
bool defined() const
Check if this Buffer refers to an existing Buffer.
const Expr operator()(const std::vector< Expr > &args) const
bool same_as(const Buffer< T2, D2 > &other) const
Check if two Buffer objects point to the same underlying Buffer.
auto operator()(const int *pos) -> decltype(std::declval< Runtime::Buffer< T, Dims > >()(pos))
Buffer< T, Dims > & for_each_element(Fn &&f)
static Buffer make_interleaved(Type t, int width, int height, int channels, const std::string &name="")
static Buffer make_scalar(Type t, const std::string &name="")
static Buffer< T, Dims > make_scalar(T *data, const std::string &name="")
Buffer(Type t, Internal::add_const_if_T_is_const< T, void > *data, int d, const halide_dimension_t *shape, const std::string &name="")
auto operator()(int first, Args &&...args) -> decltype(std::declval< Runtime::Buffer< T, Dims > >()(first, std::forward< Args >(args)...))
static constexpr int AnyDims
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.
static constexpr halide_type_t static_halide_type()
auto operator()(int first, Args &&...args) const -> decltype(std::declval< const Runtime::Buffer< T, Dims > >()(first, std::forward< Args >(args)...))
Buffer(Array(&vals)[N], const std::string &name="")
Buffer< T, Dims > copy() const
Buffer(const std::vector< int > &sizes, const std::vector< int > &storage_order, const std::string &name="")
Buffer< T, Dims > & fill(FnOrValue &&f)
const std::string & name() const
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="")
Runtime::Buffer< T, Dims > * get()
Get a pointer to the underlying Runtime::Buffer.
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.
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.
Buffer(Type t, Internal::add_const_if_T_is_const< T, void > *data, const std::vector< int > &sizes, const std::string &name="")
static constexpr bool has_static_halide_type
Buffer(int first, Args... rest)
Buffer(T *data, const std::vector< int > &sizes, const std::string &name="")
Buffer(T *data, int first, Args &&...rest)
static Buffer< T, Dims > make_scalar(const std::string &name="")
Buffer(Type t, Internal::add_const_if_T_is_const< T, void > *data, int first, Args &&...rest)
Buffer(Buffer< T2, D2 > &&other) noexcept
Move construct from a Buffer of a different type.
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.
Buffer(Type t, const std::vector< int > &sizes, const std::vector< int > &storage_order, const std::string &name="")
auto operator()(const int *pos) const -> decltype(std::declval< const Runtime::Buffer< T, Dims > >()(pos))
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.
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="")
Buffer< T2, D2 > as() const
Buffer(const std::vector< int > &sizes, const std::string &name="")
Buffer(const halide_buffer_t &buf, const std::string &name="")
Buffer(T *data, int d, const halide_dimension_t *shape, const std::string &name="")
Buffer(Type t, Internal::add_const_if_T_is_const< T, void > *data, const std::vector< int > &sizes, const std::string &name="")
static bool can_convert_from(const Buffer< T2, D2 > &other)
const Runtime::Buffer< T, Dims > * get() const
auto operator()() const -> decltype(std::declval< const Runtime::Buffer< T, Dims > >()())
void copy_from(const Buffer< T2, D2 > &other)
static Buffer< T, Dims > make_interleaved(T *data, int width, int height, int channels, const std::string &name="")
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()
std::vector< int > get_shape_from_start_of_parameter_pack(Args &&...args)
void buffer_type_name_non_const< void >(std::ostream &s)
void buffer_type_name_non_const(std::ostream &s)
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()
void get_shape_from_start_of_parameter_pack_helper(std::vector< int > &, const std::string &)
typename std::conditional< std::is_const< T >::value, const T2, T2 >::type add_const_if_T_is_const
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.
unsigned __INT64_TYPE__ uint64_t
A fragment of Halide syntax.
A context to be passed to Pipeline::realize.
A struct representing a target machine and os to generate code for.
Types in the halide type system.
The raw representation of an image passed around by generated Halide code.
A runtime tag for a type in the halide type system.