1 #ifndef HALIDE_BUFFER_H 2 #define HALIDE_BUFFER_H 13 template<
typename T =
void,
int Dims = AnyDims>
28 template<
typename... Args>
31 template<
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>
56 template<
typename First,
69 template<
typename... Args>
75 template<
typename... Args>
77 std::vector<int> result;
82 template<
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);
121 template<
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<" 152 << Internal::buffer_type_name<T>() <<
", " << Dims <<
"> from Buffer<" 153 <<
type_to_c_type(other.type(),
false) <<
", " << D2 <<
">, dimensions() = " << other.dimensions() <<
"\n";
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)
219 const std::string &
name =
"")
223 template<
typename... Args,
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)
269 template<
typename... Args,
273 const std::vector<int> &sizes,
274 const std::string &
name =
"")
278 template<
typename... Args,
281 int first, Args &&...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>
500 template<
typename Fn>
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>
553 return (*
get())(first, std::forward<Args>(args)...);
556 template<
typename... Args>
558 return (*
get())(first, std::forward<Args>(args)...);
562 return (*
get())(pos);
566 return (*
get())(pos);
583 template<
typename... Args>
585 std::vector<Expr> args = {first, rest...};
586 return (*
this)(args);
589 template<
typename... Args>
Expr buffer_accessor(const Buffer<> &buf, const std::vector< Expr > &args)
A fragment of Halide syntax.
#define HALIDE_BUFFER_FORWARD_CONST(method)
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="")
Constructors that match Runtime::Buffer with two differences: 1) They take a Type instead of a halide...
Buffer(T *data, int first, Args &&...rest)
Constructors that match Runtime::Buffer with two differences: 1) They take a Type instead of a halide...
typename std::conditional< std::is_const< T >::value, const T2, T2 >::type add_const_if_T_is_const
static constexpr halide_type_t static_halide_type()
Get the Halide type of T.
Expr min(const FuncRef &a, const FuncRef &b)
Explicit overloads of min and max for FuncRef.
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(First first, Second second, Args &&...rest)
Buffer(Type t, int first, Args... rest)
Constructors that match Runtime::Buffer with two differences: 1) They take a Type instead of a halide...
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 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 bool has_static_halide_type
Does the same thing as the equivalent Halide::Runtime::Buffer method.
static Buffer< T, Dims > make_scalar(const std::string &name="")
Constructors that match Runtime::Buffer with two differences: 1) They take a Type instead of a halide...
A struct representing a target machine and os to generate code for.
void buffer_type_name_non_const(std::ostream &s)
Buffer(Type t, Internal::add_const_if_T_is_const< T, void > *data, const std::vector< int > &sizes, const std::string &name="")
Constructors that match Runtime::Buffer with two differences: 1) They take a Type instead of a halide...
Buffer(int first, Args... rest)
Constructors that match Runtime::Buffer with two differences: 1) They take a Type instead of a halide...
#define HALIDE_BUFFER_FORWARD(method)
Buffer(Array(&vals)[N], const std::string &name="")
Constructors that match Runtime::Buffer with two differences: 1) They take a Type instead of a halide...
Defines a Buffer type that wraps from halide_buffer_t and adds functionality, and methods for more co...
Buffer(T *data, int d, const halide_dimension_t *shape, const std::string &name="")
Constructors that match Runtime::Buffer with two differences: 1) They take a Type instead of a halide...
Buffer(Type t, const std::vector< int > &sizes, const std::vector< int > &storage_order, const std::string &name="")
Constructors that match Runtime::Buffer with two differences: 1) They take a Type instead of a halide...
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.
bool same_as(const Buffer< T2, D2 > &other) const
Check if two Buffer objects point to the same underlying Buffer.
Buffer(Type t, Internal::add_const_if_T_is_const< T, void > *data, int first, Args &&...rest)
Constructors that match Runtime::Buffer with two differences: 1) They take a Type instead of a halide...
A Halide::Buffer is a named shared reference to a Halide::Runtime::Buffer.
auto operator()(const int *pos) -> decltype(std::declval< Runtime::Buffer< T, Dims >>()(pos))
Does the same thing as the equivalent Halide::Runtime::Buffer method.
This file defines the class FunctionDAG, which is our representation of a Halide pipeline, and contains methods to using Halide's bounds tools to query properties of it.
static constexpr halide_type_t static_halide_type()
Does the same thing as the equivalent Halide::Runtime::Buffer method.
const std::string & name() const
Buffers are optionally named.
static Buffer< T, Dims > make_interleaved(int width, int height, int channels, const std::string &name="")
Constructors that match Runtime::Buffer with two differences: 1) They take a Type instead of a halide...
static bool can_convert_from(const Buffer< T2, D2 > &other)
Does the same thing as the equivalent Halide::Runtime::Buffer method.
static Buffer< T, Dims > make_scalar(T *data, const std::string &name="")
Constructors that match Runtime::Buffer with two differences: 1) They take a Type instead of a halide...
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="")
Constructors that match Runtime::Buffer with two differences: 1) They take a Type instead of a halide...
Methods for managing device allocations when jitting.
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.
static constexpr int static_dimensions()
Does the same thing as the equivalent Halide::Runtime::Buffer method.
Buffer< T2, D2 > as() const
Does the same thing as the equivalent Halide::Runtime::Buffer method.
Buffer(Type t, Internal::add_const_if_T_is_const< T, void > *data, int d, const halide_dimension_t *shape, const std::string &name="")
Constructors that match Runtime::Buffer with two differences: 1) They take a Type instead of a halide...
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="")
Constructors that match Runtime::Buffer with two differences: 1) They take a Type instead of a halide...
Base classes for Halide expressions (Halide::Expr) and statements (Halide::Internal::Stmt) ...
Buffer(T *data, const std::vector< int > &sizes, const std::string &name="")
Constructors that match Runtime::Buffer with two differences: 1) They take a Type instead of a halide...
auto operator()(int first, Args &&...args) -> decltype(std::declval< Runtime::Buffer< T, Dims >>()(first, std::forward< Args >(args)...))
Does the same thing as the equivalent Halide::Runtime::Buffer method.
static Buffer< T, Dims > make_interleaved(T *data, int width, int height, int channels, const std::string &name="")
Constructors that match Runtime::Buffer with two differences: 1) They take a Type instead of a halide...
static Buffer make_interleaved(Type t, int width, int height, int channels, const std::string &name="")
Constructors that match Runtime::Buffer with two differences: 1) They take a Type instead of a halide...
Buffer & operator=(const Buffer &that)=default
Trivial copy assignment operator.
static Buffer< T, Dims, InClassDimStorage > make_with_shape_of(Buffer< T2, D2, S2 > src, void *(*allocate_fn)(size_t)=nullptr, void(*deallocate_fn)(void *)=nullptr)
Make a buffer with the same shape and memory nesting order as another buffer.
virtual ~Buffer()=default
A templated Buffer class that wraps halide_buffer_t and adds functionality.
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.
#define HALIDE_BUFFER_FORWARD_INITIALIZER_LIST(method,...)
static Buffer< T, Dims, InClassDimStorage > make_scalar()
Make a zero-dimensional Buffer.
Buffer(Buffer< T2, D2 > &&other) noexcept
Move construct from a Buffer of a different type.
Buffer(Type t, const std::vector< int > &sizes, const std::string &name="")
Constructors that match Runtime::Buffer with two differences: 1) They take a Type instead of a halide...
Not visible externally, similar to 'static' linkage in C.
const Buffer< T, Dims > & for_each_value(Fn &&f, Args... other_buffers) const
Does the same thing as the equivalent Halide::Runtime::Buffer method.
static constexpr bool has_static_dimensions
Does the same thing as the equivalent Halide::Runtime::Buffer method.
Buffer(Runtime::Buffer< T, D2 > &&buf, const std::string &name="")
Construct a Buffer that captures and owns an rvalue Runtime::Buffer.
Support classes for reference-counting via intrusive shared pointers.
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.
Buffer< T, Dims > & for_each_value(Fn &&f, Args... other_buffers)
Does the same thing as the equivalent Halide::Runtime::Buffer method.
const Buffer< T, Dims > & for_each_element(Fn &&f) const
Does the same thing as the equivalent Halide::Runtime::Buffer method.
auto operator()(const int *pos) const -> decltype(std::declval< const Runtime::Buffer< T, Dims >>()(pos))
Does the same thing as the equivalent Halide::Runtime::Buffer method.
Buffer(const std::vector< int > &sizes, const std::vector< int > &storage_order, const std::string &name="")
Constructors that match Runtime::Buffer with two differences: 1) They take a Type instead of a halide...
A runtime tag for a type in the halide type system.
void copy_from(const Buffer< T2, D2 > &other)
Does the same thing as the equivalent Halide::Runtime::Buffer method.
A context to be passed to Pipeline::realize.
Buffer< T, Dims > copy() const
Does the same thing as the equivalent Halide::Runtime::Buffer method.
const Expr operator()(const std::vector< Expr > &args) const
Make an Expr that loads from this concrete buffer at a computed coordinate.
std::string buffer_type_name()
Types in the halide type system.
const Expr operator()(const Expr &first, Args... rest) const
Make an Expr that loads from this concrete buffer at a computed coordinate.
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(const halide_buffer_t &buf, const std::string &name="")
Constructors that match Runtime::Buffer with two differences: 1) They take a Type instead of a halide...
void get_shape_from_start_of_parameter_pack_helper(std::vector< int > &, const std::string &)
Target get_jit_target_from_environment()
Return the target that Halide will use for jit-compilation.
static Buffer make_scalar(Type t, const std::string &name="")
Constructors that match Runtime::Buffer with two differences: 1) They take a Type instead of a halide...
auto operator()() -> decltype(std::declval< Runtime::Buffer< T, Dims >>()())
Does the same thing as the equivalent Halide::Runtime::Buffer method.
Buffer(Type t, Internal::add_const_if_T_is_const< T, void > *data, const std::vector< int > &sizes, const std::string &name="")
Constructors that match Runtime::Buffer with two differences: 1) They take a Type instead of a halide...
bool defined() const
Check if this Buffer refers to an existing Buffer.
std::string get_name_from_end_of_parameter_pack(T &&)
void buffer_type_name_non_const< void >(std::ostream &s)
Buffer()=default
Make a null Buffer, which points to no Runtime::Buffer.
Buffer(const std::vector< int > &sizes, const std::string &name="")
Constructors that match Runtime::Buffer with two differences: 1) They take a Type instead of a halide...
Buffer< T, Dims > & for_each_element(Fn &&f)
Does the same thing as the equivalent Halide::Runtime::Buffer method.
The raw representation of an image passed around by generated Halide code.
HALIDE_ALWAYS_INLINE auto slice(Vec vec, Base base, Stride stride, Lanes lanes) noexcept -> SliceOp< decltype(pattern_arg(vec)), decltype(pattern_arg(base)), decltype(pattern_arg(stride)), decltype(pattern_arg(lanes))>
unsigned __INT64_TYPE__ uint64_t
auto operator()() const -> decltype(std::declval< const Runtime::Buffer< T, Dims >>()())
Does the same thing as the equivalent Halide::Runtime::Buffer method.
A class representing a reference count to be used with IntrusivePtr.
DeviceAPI
An enum describing a type of device API.
std::vector< int > get_shape_from_start_of_parameter_pack(Args &&...args)
static Buffer< void, Dims, InClassDimStorage > make_interleaved(halide_type_t t, int width, int height, int channels)
If you use the (x, y, c) indexing convention, then Halide Buffers are stored planar by default...
static constexpr int AnyDims
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< T, Dims > & fill(FnOrValue &&f)
Does the same thing as the equivalent Halide::Runtime::Buffer method.
Type type() const
Does the same thing as the equivalent Halide::Runtime::Buffer method.
auto operator()(int first, Args &&...args) const -> decltype(std::declval< const Runtime::Buffer< T, Dims >>()(first, std::forward< Args >(args)...))
Does the same thing as the equivalent Halide::Runtime::Buffer method.
std::string type_to_c_type(Type type, bool include_space, bool c_plus_plus=true)
Halide type to a C++ type.
void set_name(const std::string &n)
Buffers are optionally named.