Loading...
Searching...
No Matches
Buffer.h
Go to the documentation of this file.
#ifndef HALIDE_BUFFER_H
#define HALIDE_BUFFER_H
#include "DeviceInterface.h"
#include "Expr.h"
#include "IntrusivePtr.h"
#include "runtime/HalideBuffer.h"
namespace Halide {
constexpr int AnyDims = Halide::Runtime::AnyDims; // -1
template<typename T = void, int Dims = AnyDims>
class Buffer;
struct JITUserContext;
namespace Internal {
struct BufferContents {
mutable RefCount ref_count;
std::string name;
Runtime::Buffer<> buf;
};
Expr buffer_accessor(const Buffer<> &buf, const std::vector<Expr> &args);
template<typename... Args>
struct all_ints_and_optional_name : std::false_type {};
template<typename First, typename... Rest>
struct all_ints_and_optional_name<First, Rest...> : meta_and<std::is_convertible<First, int>,
all_ints_and_optional_name<Rest...>> {};
template<typename T>
struct all_ints_and_optional_name<T> : meta_or<std::is_convertible<T, std::string>,
std::is_convertible<T, int>> {};
template<>
struct all_ints_and_optional_name<> : std::true_type {};
template<typename T,
typename = typename std::enable_if<!std::is_convertible<T, std::string>::value>::type>
std::string get_name_from_end_of_parameter_pack(T &&) {
return "";
}
inline std::string get_name_from_end_of_parameter_pack(const std::string &n) {
return n;
}
inline std::string get_name_from_end_of_parameter_pack() {
return "";
}
template<typename First,
typename Second,
typename... Args>
std::string get_name_from_end_of_parameter_pack(First first, Second second, Args &&...rest) {
return get_name_from_end_of_parameter_pack(second, std::forward<Args>(rest)...);
}
inline void get_shape_from_start_of_parameter_pack_helper(std::vector<int> &, const std::string &) {
}
inline void get_shape_from_start_of_parameter_pack_helper(std::vector<int> &) {
}
template<typename... Args>
void get_shape_from_start_of_parameter_pack_helper(std::vector<int> &result, int x, Args &&...rest) {
result.push_back(x);
get_shape_from_start_of_parameter_pack_helper(result, std::forward<Args>(rest)...);
}
template<typename... Args>
std::vector<int> get_shape_from_start_of_parameter_pack(Args &&...args) {
std::vector<int> result;
get_shape_from_start_of_parameter_pack_helper(result, std::forward<Args>(args)...);
return result;
}
template<typename T, typename T2>
using add_const_if_T_is_const = typename std::conditional<std::is_const<T>::value, const T2, T2>::type;
// Helpers to produce the name of a Buffer element type (a Halide
// scalar type, or void, possibly with const). Useful for an error
// messages.
template<typename T>
void buffer_type_name_non_const(std::ostream &s) {
s << type_to_c_type(type_of<T>(), false);
}
template<>
inline void buffer_type_name_non_const<void>(std::ostream &s) {
s << "void";
}
template<typename T>
std::string buffer_type_name() {
std::ostringstream oss;
if (std::is_const<T>::value) {
oss << "const ";
}
buffer_type_name_non_const<typename std::remove_const<T>::type>(oss);
return oss.str();
}
} // namespace Internal
/** A Halide::Buffer is a named shared reference to a
* Halide::Runtime::Buffer.
*
* A Buffer<T1, D> can refer to a Buffer<T2, D> if T1 is const whenever T2
* is const, and either T1 = T2 or T1 is void. A Buffer<void, D> can
* refer to any Buffer of any non-const type, and the default
* template parameter is T = void.
*
* A Buffer<T, D1> can refer to a Buffer<T, D2> if D1 == D2,
* or if D1 is AnyDims (meaning "dimensionality is checked at runtime, not compiletime").
*/
template<typename T, int Dims>
class Buffer {
Internal::IntrusivePtr<Internal::BufferContents> contents;
template<typename T2, int D2>
friend class Buffer;
template<typename T2, int D2>
static void assert_can_convert_from(const Buffer<T2, D2> &other) {
if (!other.defined()) {
// Avoid UB of deferencing offset of a null contents ptr
static_assert((!std::is_const<T2>::value || std::is_const<T>::value),
"Can't convert from a Buffer<const T> to a Buffer<T>");
static_assert(std::is_same<typename std::remove_const<T>::type,
typename std::remove_const<T2>::type>::value ||
std::is_void<T>::value ||
std::is_void<T2>::value,
"type mismatch constructing Buffer");
static_assert(Dims == AnyDims || D2 == AnyDims || Dims == D2,
"Can't convert from a Buffer with static dimensionality to a Buffer with different static dimensionality");
} else {
// Don't delegate to
// Runtime::Buffer<T>::assert_can_convert_from. It might
// not assert if NDEBUG is defined. user_assert is
// friendlier anyway because it reports line numbers when
// debugging symbols are found, it throws an exception
// when exceptions are enabled, and we can print the
// actual types in question.
using BufType = Runtime::Buffer<T, Dims>; // alias because commas in user_assert() macro confuses compiler
user_assert(BufType::can_convert_from(*(other.get())))
<< "Type mismatch constructing Buffer. Can't construct Buffer<"
<< Internal::buffer_type_name<T>() << ", " << Dims << "> from Buffer<"
<< type_to_c_type(other.type(), false) << ", " << D2 << ">, dimensions() = " << other.dimensions() << "\n";
}
}
public:
static constexpr int AnyDims = Halide::AnyDims;
static_assert(Dims == AnyDims || Dims >= 0);
typedef T ElemType;
// This class isn't final (and is subclassed from the Python binding
// code, at least) so it needs a virtual dtor.
virtual ~Buffer() = default;
/** Make a null Buffer, which points to no Runtime::Buffer */
Buffer() = default;
/** Trivial copy constructor. */
Buffer(const Buffer &that) = default;
/** Trivial copy assignment operator. */
Buffer &operator=(const Buffer &that) = default;
/** Trivial move assignment operator. */
Buffer &operator=(Buffer &&) noexcept = default;
/** Make a Buffer from a Buffer of a different type */
template<typename T2, int D2>
Buffer(const Buffer<T2, D2> &other)
: contents(other.contents) {
assert_can_convert_from(other);
}
/** Move construct from a Buffer of a different type */
template<typename T2, int D2>
Buffer(Buffer<T2, D2> &&other) noexcept {
assert_can_convert_from(other);
contents = std::move(other.contents);
}
/** Construct a Buffer that captures and owns an rvalue Runtime::Buffer */
template<int D2>
Buffer(Runtime::Buffer<T, D2> &&buf, const std::string &name = "")
: contents(new Internal::BufferContents) {
contents->buf = std::move(buf);
if (name.empty()) {
contents->name = Internal::unique_name('b');
} else {
contents->name = name;
}
}
/** Constructors that match Runtime::Buffer with two differences:
* 1) They take a Type instead of a halide_type_t
* 2) There is an optional last string argument that gives the buffer a specific name
*/
// @{
template<typename... Args,
typename = typename std::enable_if<Internal::all_ints_and_optional_name<Args...>::value>::type>
explicit Buffer(Type t,
int first, Args... rest)
: Buffer(Runtime::Buffer<T, Dims>(t, Internal::get_shape_from_start_of_parameter_pack(first, rest...)),
Internal::get_name_from_end_of_parameter_pack(rest...)) {
}
explicit Buffer(const halide_buffer_t &buf,
const std::string &name = "")
: Buffer(Runtime::Buffer<T, Dims>(buf), name) {
}
template<typename... Args,
typename = typename std::enable_if<Internal::all_ints_and_optional_name<Args...>::value>::type>
explicit Buffer(int first, const Args &...rest)
: Buffer(Runtime::Buffer<T, Dims>(Internal::get_shape_from_start_of_parameter_pack(first, rest...)),
Internal::get_name_from_end_of_parameter_pack(rest...)) {
}
explicit Buffer(Type t,
const std::vector<int> &sizes,
const std::string &name = "")
: Buffer(Runtime::Buffer<T, Dims>(t, sizes), name) {
}
explicit Buffer(Type t,
const std::vector<int> &sizes,
const std::vector<int> &storage_order,
const std::string &name = "")
: Buffer(Runtime::Buffer<T, Dims>(t, sizes, storage_order), name) {
}
explicit Buffer(const std::vector<int> &sizes,
const std::string &name = "")
: Buffer(Runtime::Buffer<T, Dims>(sizes), name) {
}
explicit Buffer(const std::vector<int> &sizes,
const std::vector<int> &storage_order,
const std::string &name = "")
: Buffer(Runtime::Buffer<T, Dims>(sizes, storage_order), name) {
}
template<typename Array, size_t N>
explicit Buffer(Array (&vals)[N],
const std::string &name = "")
: Buffer(Runtime::Buffer<T, Dims>(vals), name) {
}
template<typename... Args,
typename = typename std::enable_if<Internal::all_ints_and_optional_name<Args...>::value>::type>
explicit Buffer(Type t,
Internal::add_const_if_T_is_const<T, void> *data,
int first, Args &&...rest)
: Buffer(Runtime::Buffer<T, Dims>(t, data, Internal::get_shape_from_start_of_parameter_pack(first, rest...)),
Internal::get_name_from_end_of_parameter_pack(rest...)) {
}
template<typename... Args,
typename = typename std::enable_if<Internal::all_ints_and_optional_name<Args...>::value>::type>
explicit Buffer(Type t,
Internal::add_const_if_T_is_const<T, void> *data,
const std::vector<int> &sizes,
const std::string &name = "")
: Buffer(Runtime::Buffer<T, Dims>(t, data, sizes, name)) {
}
template<typename... Args,
typename = typename std::enable_if<Internal::all_ints_and_optional_name<Args...>::value>::type>
explicit Buffer(T *data,
int first, Args &&...rest)
: Buffer(Runtime::Buffer<T, Dims>(data, Internal::get_shape_from_start_of_parameter_pack(first, rest...)),
Internal::get_name_from_end_of_parameter_pack(rest...)) {
}
explicit Buffer(T *data,
const std::vector<int> &sizes,
const std::string &name = "")
: Buffer(Runtime::Buffer<T, Dims>(data, sizes), name) {
}
explicit Buffer(Type t,
Internal::add_const_if_T_is_const<T, void> *data,
const std::vector<int> &sizes,
const std::string &name = "")
: Buffer(Runtime::Buffer<T, Dims>(t, data, sizes), name) {
}
explicit Buffer(Type t,
Internal::add_const_if_T_is_const<T, void> *data,
int d,
const halide_dimension_t *shape,
const std::string &name = "")
: Buffer(Runtime::Buffer<T, Dims>(t, data, d, shape), name) {
}
explicit Buffer(T *data,
int d,
const halide_dimension_t *shape,
const std::string &name = "")
: Buffer(Runtime::Buffer<T, Dims>(data, d, shape), name) {
}
static Buffer<T, Dims> make_scalar(const std::string &name = "") {
return Buffer<T, Dims>(Runtime::Buffer<T, Dims>::make_scalar(), name);
}
static Buffer<> make_scalar(Type t, const std::string &name = "") {
return Buffer<>(Runtime::Buffer<>::make_scalar(t), name);
}
static Buffer<T, Dims> make_scalar(T *data, const std::string &name = "") {
return Buffer<T, Dims>(Runtime::Buffer<T, Dims>::make_scalar(data), name);
}
static Buffer<T, Dims> make_interleaved(int width, int height, int channels, const std::string &name = "") {
return Buffer<T, Dims>(Runtime::Buffer<T, Dims>::make_interleaved(width, height, channels), name);
}
static Buffer<> make_interleaved(Type t, int width, int height, int channels, const std::string &name = "") {
return Buffer<>(Runtime::Buffer<>::make_interleaved(t, width, height, channels), name);
}
static Buffer<T, Dims> make_interleaved(T *data, int width, int height, int channels, const std::string &name = "") {
return Buffer<T, Dims>(Runtime::Buffer<T, Dims>::make_interleaved(data, width, height, channels), name);
}
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 = "") {
using T2 = Internal::add_const_if_T_is_const<T, void>;
return Buffer<T2, Dims>(Runtime::Buffer<T2, Dims>::make_interleaved(t, data, width, height, channels), name);
}
template<typename T2, int D2>
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 = "") {
return Buffer<T, Dims>(Runtime::Buffer<T, Dims>::make_with_shape_of(*src.get(), allocate_fn, deallocate_fn), name);
}
template<typename T2, int D2>
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 = "") {
return Buffer<T, Dims>(Runtime::Buffer<T, Dims>::make_with_shape_of(src, allocate_fn, deallocate_fn), name);
}
// @}
/** Buffers are optionally named. */
// @{
void set_name(const std::string &n) {
contents->name = n;
}
const std::string &name() const {
return contents->name;
}
// @}
/** Check if two Buffer objects point to the same underlying Buffer */
template<typename T2, int D2>
bool same_as(const Buffer<T2, D2> &other) const {
return (const void *)(contents.get()) == (const void *)(other.contents.get());
}
/** Check if this Buffer refers to an existing
* Buffer. Default-constructed Buffer objects do not refer to any
* existing Buffer. */
bool defined() const {
return contents.defined();
}
/** Get a pointer to the underlying Runtime::Buffer */
// @{
Runtime::Buffer<T, Dims> *get() {
// It's already type-checked, so no need to use as<T>.
return (Runtime::Buffer<T, Dims> *)(&contents->buf);
}
const Runtime::Buffer<T, Dims> *get() const {
return (const Runtime::Buffer<T, Dims> *)(&contents->buf);
}
// @}
// We forward numerous methods from the underlying Buffer
#define HALIDE_BUFFER_FORWARD_CONST(method) \
template<typename... Args> \
auto method(Args &&...args) const -> decltype(std::declval<const Runtime::Buffer<T, Dims>>().method(std::forward<Args>(args)...)) { \
user_assert(defined()) << "Undefined buffer calling const method " #method "\n"; \
return get()->method(std::forward<Args>(args)...); \
}
#define HALIDE_BUFFER_FORWARD(method) \
template<typename... Args> \
auto method(Args &&...args) -> decltype(std::declval<Runtime::Buffer<T, Dims>>().method(std::forward<Args>(args)...)) { \
user_assert(defined()) << "Undefined buffer calling method " #method "\n"; \
return get()->method(std::forward<Args>(args)...); \
}
// This is a weird-looking but effective workaround for a deficiency in "perfect forwarding":
// namely, it can't really handle initializer-lists. The idea here is that we declare
// the expected type to be passed on, and that allows the compiler to handle it.
// The weirdness comes in with the variadic macro: the problem is that the type
// we want to forward might be something like `std::vector<std::pair<int, int>>`,
// which contains a comma, which throws a big wrench in C++ macro system.
// However... since all we really need to do is capture the remainder of the macro,
// and forward it as is, we can just use ... to allow an arbitrary number of commas,
// then use __VA_ARGS__ to forward the mess as-is, and while it looks horrible, it
// works.
#define HALIDE_BUFFER_FORWARD_INITIALIZER_LIST(method, ...) \
inline auto method(const __VA_ARGS__ &a) -> decltype(std::declval<Runtime::Buffer<T, Dims>>().method(a)) { \
user_assert(defined()) << "Undefined buffer calling method " #method "\n"; \
return get()->method(a); \
}
/** Does the same thing as the equivalent Halide::Runtime::Buffer method */
// @{
HALIDE_BUFFER_FORWARD(raw_buffer)
HALIDE_BUFFER_FORWARD_CONST(raw_buffer)
HALIDE_BUFFER_FORWARD_CONST(dimensions)
HALIDE_BUFFER_FORWARD_CONST(dim)
HALIDE_BUFFER_FORWARD_CONST(width)
HALIDE_BUFFER_FORWARD_CONST(height)
HALIDE_BUFFER_FORWARD_CONST(channels)
HALIDE_BUFFER_FORWARD_CONST(min)
HALIDE_BUFFER_FORWARD_CONST(extent)
HALIDE_BUFFER_FORWARD_CONST(stride)
HALIDE_BUFFER_FORWARD_CONST(left)
HALIDE_BUFFER_FORWARD_CONST(right)
HALIDE_BUFFER_FORWARD_CONST(top)
HALIDE_BUFFER_FORWARD_CONST(bottom)
HALIDE_BUFFER_FORWARD_CONST(number_of_elements)
HALIDE_BUFFER_FORWARD_CONST(size_in_bytes)
HALIDE_BUFFER_FORWARD_CONST(begin)
HALIDE_BUFFER_FORWARD_CONST(end)
HALIDE_BUFFER_FORWARD(data)
HALIDE_BUFFER_FORWARD_CONST(data)
HALIDE_BUFFER_FORWARD_CONST(contains)
HALIDE_BUFFER_FORWARD(crop)
HALIDE_BUFFER_FORWARD_INITIALIZER_LIST(crop, std::vector<std::pair<int, int>>)
HALIDE_BUFFER_FORWARD_CONST(cropped)
HALIDE_BUFFER_FORWARD(slice)
HALIDE_BUFFER_FORWARD_CONST(sliced)
HALIDE_BUFFER_FORWARD(embed)
HALIDE_BUFFER_FORWARD_CONST(embedded)
HALIDE_BUFFER_FORWARD(set_min)
HALIDE_BUFFER_FORWARD(translate)
HALIDE_BUFFER_FORWARD_INITIALIZER_LIST(translate, std::vector<int>)
HALIDE_BUFFER_FORWARD_CONST(translated)
HALIDE_BUFFER_FORWARD(transpose)
HALIDE_BUFFER_FORWARD_CONST(transposed)
HALIDE_BUFFER_FORWARD(add_dimension)
HALIDE_BUFFER_FORWARD(copy_to_host)
HALIDE_BUFFER_FORWARD(copy_to_device)
HALIDE_BUFFER_FORWARD_CONST(has_device_allocation)
HALIDE_BUFFER_FORWARD_CONST(host_dirty)
HALIDE_BUFFER_FORWARD_CONST(device_dirty)
HALIDE_BUFFER_FORWARD(set_host_dirty)
HALIDE_BUFFER_FORWARD(set_device_dirty)
HALIDE_BUFFER_FORWARD(device_sync)
HALIDE_BUFFER_FORWARD(device_malloc)
HALIDE_BUFFER_FORWARD(device_wrap_native)
HALIDE_BUFFER_FORWARD(device_detach_native)
HALIDE_BUFFER_FORWARD(allocate)
HALIDE_BUFFER_FORWARD(deallocate)
HALIDE_BUFFER_FORWARD(device_deallocate)
HALIDE_BUFFER_FORWARD(device_free)
HALIDE_BUFFER_FORWARD_CONST(all_equal)
#undef HALIDE_BUFFER_FORWARD
#undef HALIDE_BUFFER_FORWARD_CONST
template<typename Fn, typename... Args>
Buffer<T, Dims> &for_each_value(Fn &&f, Args... other_buffers) {
get()->for_each_value(std::forward<Fn>(f), (*std::forward<Args>(other_buffers).get())...);
return *this;
}
template<typename Fn, typename... Args>
const Buffer<T, Dims> &for_each_value(Fn &&f, Args... other_buffers) const {
get()->for_each_value(std::forward<Fn>(f), (*std::forward<Args>(other_buffers).get())...);
return *this;
}
template<typename Fn>
Buffer<T, Dims> &for_each_element(Fn &&f) {
get()->for_each_element(std::forward<Fn>(f));
return *this;
}
template<typename Fn>
const Buffer<T, Dims> &for_each_element(Fn &&f) const {
get()->for_each_element(std::forward<Fn>(f));
return *this;
}
template<typename FnOrValue>
Buffer<T, Dims> &fill(FnOrValue &&f) {
get()->fill(std::forward<FnOrValue>(f));
return *this;
}
static constexpr bool has_static_halide_type = Runtime::Buffer<T, Dims>::has_static_halide_type;
static constexpr halide_type_t static_halide_type() {
return Runtime::Buffer<T, Dims>::static_halide_type();
}
static constexpr bool has_static_dimensions = Runtime::Buffer<T, Dims>::has_static_dimensions;
static constexpr int static_dimensions() {
return Runtime::Buffer<T, Dims>::static_dimensions();
}
template<typename T2, int D2>
static bool can_convert_from(const Buffer<T2, D2> &other) {
return Halide::Runtime::Buffer<T, Dims>::can_convert_from(*other.get());
}
// Note that since Runtime::Buffer stores halide_type_t rather than Halide::Type,
// there is no handle-specific type information, so all handle types are
// considered equivalent to void* here. (This only matters if you are making
// a Buffer-of-handles, which is not really a real use case...)
Type type() const {
return contents->buf.type();
}
template<typename T2, int D2 = Dims>
Buffer<T2, D2> as() const {
return Buffer<T2, D2>(*this);
}
Buffer<T, Dims> copy() const {
return Buffer<T, Dims>(std::move(contents->buf.as<T, Dims>().copy()));
}
template<typename T2, int D2>
void copy_from(const Buffer<T2, D2> &other) {
contents->buf.copy_from(*other.get());
}
template<typename... Args>
auto operator()(int first, Args &&...args) -> decltype(std::declval<Runtime::Buffer<T, Dims>>()(first, std::forward<Args>(args)...)) {
return (*get())(first, std::forward<Args>(args)...);
}
template<typename... Args>
auto operator()(int first, Args &&...args) const -> decltype(std::declval<const Runtime::Buffer<T, Dims>>()(first, std::forward<Args>(args)...)) {
return (*get())(first, std::forward<Args>(args)...);
}
auto operator()(const int *pos) -> decltype(std::declval<Runtime::Buffer<T, Dims>>()(pos)) {
return (*get())(pos);
}
auto operator()(const int *pos) const -> decltype(std::declval<const Runtime::Buffer<T, Dims>>()(pos)) {
return (*get())(pos);
}
auto operator()() -> decltype(std::declval<Runtime::Buffer<T, Dims>>()()) {
return (*get())();
}
auto operator()() const -> decltype(std::declval<const Runtime::Buffer<T, Dims>>()()) {
return (*get())();
}
// @}
/** Make an Expr that loads from this concrete buffer at a computed
* coordinate. Returned Expr is const so that it's not possible to
* accidentally treat a buffer like a Func and try to assign an Expr to a
* given symbolic coordinate. */
// @{
template<typename... Args>
const Expr operator()(const Expr &first, Args... rest) const { // NOLINT
std::vector<Expr> args = {first, rest...};
return (*this)(args);
}
template<typename... Args>
const Expr operator()(const std::vector<Expr> &args) const { // NOLINT
return buffer_accessor(Buffer<>(*this), args);
}
// @}
/** Copy to the GPU, using the device API that is the default for the given Target. */
int copy_to_device(const Target &t = get_jit_target_from_environment(), JITUserContext *context = nullptr) {
return copy_to_device(DeviceAPI::Default_GPU, t, context);
}
/** Copy to the GPU, using the given device API */
int copy_to_device(const DeviceAPI &d, const Target &t = get_jit_target_from_environment(), JITUserContext *context = nullptr) {
return contents->buf.copy_to_device(get_device_interface_for_device_api(d, t, "Buffer::copy_to_device"), context);
}
/** Allocate on the GPU, using the device API that is the default for the given Target. */
int device_malloc(const Target &t = get_jit_target_from_environment(), JITUserContext *context = nullptr) {
return device_malloc(DeviceAPI::Default_GPU, t, context);
}
/** Allocate storage on the GPU, using the given device API */
int device_malloc(const DeviceAPI &d, const Target &t = get_jit_target_from_environment(), JITUserContext *context = nullptr) {
return contents->buf.device_malloc(get_device_interface_for_device_api(d, t, "Buffer::device_malloc"), context);
}
/** Wrap a native handle, using the given device API.
* It is a bad idea to pass DeviceAPI::Default_GPU to this routine
* as the handle argument must match the API that the default
* resolves to and it is clearer and more reliable to pass the
* resolved DeviceAPI explicitly. */
int device_wrap_native(const DeviceAPI &d, uint64_t handle, const Target &t = get_jit_target_from_environment(), JITUserContext *context = nullptr) {
return contents->buf.device_wrap_native(get_device_interface_for_device_api(d, t, "Buffer::device_wrap_native"), handle, context);
}
};
} // namespace Halide
#endif
HALIDE_BUFFER_FORWARD
#define HALIDE_BUFFER_FORWARD(method)
Definition Buffer.h:404
HALIDE_BUFFER_FORWARD_INITIALIZER_LIST
#define HALIDE_BUFFER_FORWARD_INITIALIZER_LIST(method,...)
Definition Buffer.h:421
HALIDE_BUFFER_FORWARD_CONST
#define HALIDE_BUFFER_FORWARD_CONST(method)
Definition Buffer.h:397
DeviceInterface.h
Methods for managing device allocations when jitting.
user_assert
#define user_assert(c)
Definition Error.h:219
Expr.h
Base classes for Halide expressions (Halide::Expr) and statements (Halide::Internal::Stmt).
HalideBuffer.h
Defines a Buffer type that wraps from halide_buffer_t and adds functionality, and methods for more co...
IntrusivePtr.h
Support classes for reference-counting via intrusive shared pointers.
Halide::Buffer
A Halide::Buffer is a named shared reference to a Halide::Runtime::Buffer.
Definition Buffer.h:122
Halide::Buffer::operator()
auto operator()() -> decltype(std::declval< Runtime::Buffer< T, Dims > >()())
Definition Buffer.h:571
Halide::Buffer::operator=
Buffer & operator=(const Buffer &that)=default
Trivial copy assignment operator.
Halide::Buffer::make_with_shape_of
static Buffer< T, Dims > make_with_shape_of(const Runtime::Buffer< T2, D2 > &src, void *(*allocate_fn)(size_t)=nullptr, void(*deallocate_fn)(void *)=nullptr, const std::string &name="")
Definition Buffer.h:353
Halide::Buffer::static_dimensions
static constexpr int static_dimensions()
Definition Buffer.h:522
Halide::Buffer::type
Type type() const
Definition Buffer.h:535
Halide::Buffer::Buffer
Buffer(Type t, const std::vector< int > &sizes, const std::string &name="")
Definition Buffer.h:230
Halide::Buffer::Buffer
Buffer(Runtime::Buffer< T, D2 > &&buf, const std::string &name="")
Construct a Buffer that captures and owns an rvalue Runtime::Buffer.
Definition Buffer.h:195
Halide::Buffer::for_each_value
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:485
Halide::Buffer::set_name
void set_name(const std::string &n)
Buffers are optionally named.
Definition Buffer.h:363
Halide::Buffer< T, D >::has_static_dimensions
static constexpr bool has_static_dimensions
Definition Buffer.h:520
Halide::Buffer::for_each_element
const Buffer< T, Dims > & for_each_element(Fn &&f) const
Definition Buffer.h:503
Halide::Buffer::device_malloc
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:613
Halide::Buffer::~Buffer
virtual ~Buffer()=default
Halide::Buffer::Buffer
Buffer(const Buffer &that)=default
Trivial copy constructor.
Halide::Buffer::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:212
Halide::Buffer::Buffer
friend class Buffer
Definition Buffer.h:126
Halide::Buffer::for_each_value
const Buffer< T, Dims > & for_each_value(Fn &&f, Args... other_buffers) const
Definition Buffer.h:491
Halide::Buffer::make_interleaved
static Buffer< T, Dims > make_interleaved(int width, int height, int channels, const std::string &name="")
Definition Buffer.h:326
Halide::Buffer::defined
bool defined() const
Check if this Buffer refers to an existing Buffer.
Definition Buffer.h:381
Halide::Buffer::operator()
const Expr operator()(const std::vector< Expr > &args) const
Definition Buffer.h:592
Halide::Buffer::same_as
bool same_as(const Buffer< T2, D2 > &other) const
Check if two Buffer objects point to the same underlying Buffer.
Definition Buffer.h:374
Halide::Buffer::operator()
auto operator()(const int *pos) -> decltype(std::declval< Runtime::Buffer< T, Dims > >()(pos))
Definition Buffer.h:563
Halide::Buffer::for_each_element
Buffer< T, Dims > & for_each_element(Fn &&f)
Definition Buffer.h:497
Halide::Buffer::make_interleaved
static Buffer make_interleaved(Type t, int width, int height, int channels, const std::string &name="")
Definition Buffer.h:330
Halide::Buffer::make_scalar
static Buffer make_scalar(Type t, const std::string &name="")
Definition Buffer.h:318
Halide::Buffer::make_scalar
static Buffer< T, Dims > make_scalar(T *data, const std::string &name="")
Definition Buffer.h:322
Halide::Buffer::Buffer
Buffer(Type t, Internal::add_const_if_T_is_const< T, void > *data, int d, const halide_dimension_t *shape, const std::string &name="")
Definition Buffer.h:299
Halide::Buffer::operator()
auto operator()(int first, Args &&...args) -> decltype(std::declval< Runtime::Buffer< T, Dims > >()(first, std::forward< Args >(args)...))
Definition Buffer.h:554
Halide::Buffer< T, D >::AnyDims
static constexpr int AnyDims
Definition Buffer.h:158
Halide::Buffer::copy_to_device
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:603
Halide::Buffer::static_halide_type
static constexpr halide_type_t static_halide_type()
Definition Buffer.h:516
Halide::Buffer::operator()
auto operator()(int first, Args &&...args) const -> decltype(std::declval< const Runtime::Buffer< T, Dims > >()(first, std::forward< Args >(args)...))
Definition Buffer.h:559
Halide::Buffer::Buffer
Buffer(Array(&vals)[N], const std::string &name="")
Definition Buffer.h:255
Halide::Buffer::copy
Buffer< T, Dims > copy() const
Definition Buffer.h:544
Halide::Buffer::Buffer
Buffer(const std::vector< int > &sizes, const std::vector< int > &storage_order, const std::string &name="")
Definition Buffer.h:248
Halide::Buffer::fill
Buffer< T, Dims > & fill(FnOrValue &&f)
Definition Buffer.h:509
Halide::Buffer< T, D >::name
const std::string & name() const
Definition Buffer.h:367
Halide::Buffer::make_with_shape_of
static Buffer< T, Dims > make_with_shape_of(Buffer< T2, D2 > src, void *(*allocate_fn)(size_t)=nullptr, void(*deallocate_fn)(void *)=nullptr, const std::string &name="")
Definition Buffer.h:345
Halide::Buffer::get
Runtime::Buffer< T, Dims > * get()
Get a pointer to the underlying Runtime::Buffer.
Definition Buffer.h:387
Halide::Buffer::device_wrap_native
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:622
Halide::Buffer::Buffer
Buffer()=default
Make a null Buffer, which points to no Runtime::Buffer.
Halide::Buffer::device_malloc
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:608
Halide::Buffer::Buffer
Buffer(Type t, Internal::add_const_if_T_is_const< T, void > *data, const std::vector< int > &sizes, const std::string &name="")
Definition Buffer.h:292
Halide::Buffer< T, D >::has_static_halide_type
static constexpr bool has_static_halide_type
Definition Buffer.h:514
Halide::Buffer::Buffer
Buffer(T *data, const std::vector< int > &sizes, const std::string &name="")
Definition Buffer.h:286
Halide::Buffer::Buffer
Buffer(T *data, int first, Args &&...rest)
Definition Buffer.h:280
Halide::Buffer::make_scalar
static Buffer< T, Dims > make_scalar(const std::string &name="")
Definition Buffer.h:314
Halide::Buffer::Buffer
Buffer(Type t, Internal::add_const_if_T_is_const< T, void > *data, int first, Args &&...rest)
Definition Buffer.h:262
Halide::Buffer::Buffer
Buffer(Buffer< T2, D2 > &&other) noexcept
Move construct from a Buffer of a different type.
Definition Buffer.h:188
Halide::Buffer::operator=
Buffer & operator=(Buffer &&) noexcept=default
Trivial move assignment operator.
Halide::Buffer::operator()
const Expr operator()(const Expr &first, Args... rest) const
Make an Expr that loads from this concrete buffer at a computed coordinate.
Definition Buffer.h:586
Halide::Buffer::Buffer
Buffer(int first, const Args &...rest)
Definition Buffer.h:225
Halide::Buffer::Buffer
Buffer(Type t, const std::vector< int > &sizes, const std::vector< int > &storage_order, const std::string &name="")
Definition Buffer.h:236
Halide::Buffer::operator()
auto operator()(const int *pos) const -> decltype(std::declval< const Runtime::Buffer< T, Dims > >()(pos))
Definition Buffer.h:567
Halide::Buffer::copy_to_device
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:598
Halide::Buffer::ElemType
T ElemType
Definition Buffer.h:161
Halide::Buffer::make_interleaved
static Buffer< Internal::add_const_if_T_is_const< T, void > > make_interleaved(Type t, T *data, int width, int height, int channels, const std::string &name="")
Definition Buffer.h:339
Halide::Buffer::as
Buffer< T2, D2 > as() const
Definition Buffer.h:540
Halide::Buffer::Buffer
Buffer(const std::vector< int > &sizes, const std::string &name="")
Definition Buffer.h:243
Halide::Buffer::Buffer
Buffer(const halide_buffer_t &buf, const std::string &name="")
Definition Buffer.h:218
Halide::Buffer::Buffer
Buffer(T *data, int d, const halide_dimension_t *shape, const std::string &name="")
Definition Buffer.h:307
Halide::Buffer::Buffer
Buffer(Type t, Internal::add_const_if_T_is_const< T, void > *data, const std::vector< int > &sizes, const std::string &name="")
Definition Buffer.h:271
Halide::Buffer::can_convert_from
static bool can_convert_from(const Buffer< T2, D2 > &other)
Definition Buffer.h:527
Halide::Buffer::get
const Runtime::Buffer< T, Dims > * get() const
Definition Buffer.h:391
Halide::Buffer::operator()
auto operator()() const -> decltype(std::declval< const Runtime::Buffer< T, Dims > >()())
Definition Buffer.h:575
Halide::Buffer::copy_from
void copy_from(const Buffer< T2, D2 > &other)
Definition Buffer.h:549
Halide::Buffer::make_interleaved
static Buffer< T, Dims > make_interleaved(T *data, int width, int height, int channels, const std::string &name="")
Definition Buffer.h:334
Halide::Internal::RefCount
A class representing a reference count to be used with IntrusivePtr.
Definition IntrusivePtr.h:19
Halide::Runtime::Buffer
A templated Buffer class that wraps halide_buffer_t and adds functionality.
Definition HalideBuffer.h:224
Halide::Runtime::Buffer::has_static_halide_type
static constexpr bool has_static_halide_type
True if the Halide type is not void (or const void).
Definition HalideBuffer.h:263
Halide::Runtime::Buffer::can_convert_from
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:741
Halide::Runtime::Buffer::make_interleaved
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.
Definition HalideBuffer.h:1934
Halide::Runtime::Buffer::static_halide_type
static constexpr halide_type_t static_halide_type()
Get the Halide type of T.
Definition HalideBuffer.h:267
Halide::Runtime::Buffer::static_dimensions
static constexpr int static_dimensions()
Callers should not use the result if has_static_dimensions is false.
Definition HalideBuffer.h:280
Halide::Runtime::Buffer::has_static_dimensions
static constexpr bool has_static_dimensions
Definition HalideBuffer.h:276
Halide::Runtime::Buffer::make_with_shape_of
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.
Definition HalideBuffer.h:1997
Halide::Runtime::Buffer::make_scalar
static Buffer< add_const_if_T_is_const< void >, Dims, InClassDimStorage > make_scalar(halide_type_t t)
Make a zero-dimensional Buffer.
Definition HalideBuffer.h:1970
Halide::Internal
Definition AbstractGenerator.h:24
Halide::Internal::get_name_from_end_of_parameter_pack
std::string get_name_from_end_of_parameter_pack()
Definition Buffer.h:52
Halide::Internal::get_shape_from_start_of_parameter_pack
std::vector< int > get_shape_from_start_of_parameter_pack(Args &&...args)
Definition Buffer.h:76
Halide::Internal::buffer_type_name_non_const< void >
void buffer_type_name_non_const< void >(std::ostream &s)
Definition Buffer.h:94
Halide::Internal::buffer_type_name_non_const
void buffer_type_name_non_const(std::ostream &s)
Definition Buffer.h:89
Halide::Internal::buffer_accessor
Expr buffer_accessor(const Buffer<> &buf, const std::vector< Expr > &args)
Halide::Internal::unique_name
std::string unique_name(char prefix)
Generate a unique name starting with the given prefix.
Halide::Internal::buffer_type_name
std::string buffer_type_name()
Definition Buffer.h:99
Halide::Internal::get_shape_from_start_of_parameter_pack_helper
void get_shape_from_start_of_parameter_pack_helper(std::vector< int > &, const std::string &)
Definition Buffer.h:63
Halide::Internal::add_const_if_T_is_const
typename std::conditional< std::is_const< T >::value, const T2, T2 >::type add_const_if_T_is_const
Definition Buffer.h:83
Halide::Runtime
Definition constants.h:12
Halide::Runtime::AnyDims
constexpr int AnyDims
Definition HalideBuffer.h:195
Halide
This file defines the class FunctionDAG, which is our representation of a Halide pipeline,...
Definition AbstractGenerator.h:19
Halide::type_to_c_type
std::string type_to_c_type(Type type, bool include_space, bool c_plus_plus=true)
Halide type to a C++ type.
Halide::get_device_interface_for_device_api
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.
Halide::min
Expr min(const FuncRef &a, const FuncRef &b)
Explicit overloads of min and max for FuncRef.
Definition Func.h:603
Halide::get_jit_target_from_environment
Target get_jit_target_from_environment()
Return the target that Halide will use for jit-compilation.
Halide::DeviceAPI
DeviceAPI
An enum describing a type of device API.
Definition DeviceAPI.h:15
Halide::DeviceAPI::Default_GPU
@ Default_GPU
Definition DeviceAPI.h:18
Halide::AnyDims
constexpr int AnyDims
Definition Buffer.h:11
uint64_t
unsigned __INT64_TYPE__ uint64_t
Definition runtime_internal.h:23
Halide::Expr
A fragment of Halide syntax.
Definition Expr.h:258
Halide::Internal::BufferContents
Definition Buffer.h:20
Halide::Internal::BufferContents::buf
Runtime::Buffer buf
Definition Buffer.h:23
Halide::Internal::BufferContents::ref_count
RefCount ref_count
Definition Buffer.h:21
Halide::Internal::BufferContents::name
std::string name
Definition Buffer.h:22
Halide::Internal::IntrusivePtr
Intrusive shared pointers have a reference count (a RefCount object) stored in the class itself.
Definition IntrusivePtr.h:71
Halide::Internal::all_ints_and_optional_name
Definition Buffer.h:29
Halide::Internal::meta_and
Definition Util.h:244
Halide::Internal::meta_or
Definition Util.h:250
Halide::JITUserContext
A context to be passed to Pipeline::realize.
Definition JITModule.h:136
Halide::Target
A struct representing a target machine and os to generate code for.
Definition Target.h:19
Halide::Type
Types in the halide type system.
Definition Type.h:283
halide_buffer_t
The raw representation of an image passed around by generated Halide code.
Definition HalideRuntime.h:1569
halide_dimension_t
Definition HalideRuntime.h:1516
halide_type_t
A runtime tag for a type in the halide type system.
Definition HalideRuntime.h:503