Runtime::Buffer#

template<typename T = void, int Dims = AnyDims, int InClassDimStorage = (Dims == AnyDims ? 4 : std::max(Dims, 1))>
class Buffer#

A templated Buffer class that wraps halide_buffer_t and adds functionality.

When using Halide from C++, this is the preferred way to create input and output buffers. The overhead of using this class relative to a naked halide_buffer_t is minimal - it uses another ~16 bytes on the stack, and does no dynamic allocations when using it to represent existing memory of a known maximum dimensionality.

The template parameter T is the element type. For buffers where the element type is unknown, or may vary, use void or const void.

The template parameter Dims is the number of dimensions. For buffers where the dimensionality type is unknown at, or may vary, use AnyDims.

InClassDimStorage is the maximum number of dimensions that can be represented using space inside the class itself. Set it to the maximum dimensionality you expect this buffer to be. If the actual dimensionality exceeds this, heap storage is allocated to track the shape of the buffer. InClassDimStorage defaults to 4, which should cover nearly all usage.

The class optionally allocates and owns memory for the image using a shared pointer allocated with the provided allocator. If they are null, malloc and free are used. Any device-side allocation is considered as owned if and only if the host-side allocation is owned.

Public Functions

inline bool owns_host_memory() const#

Does this Buffer own the host memory it refers to?

inline Dimension dim(int i) const#

Access the shape of the buffer.

inline int min(int i) const#

Access to the mins, strides, extents.

Will be deprecated. Do not use.

inline size_t number_of_elements() const#

The total number of elements this buffer represents.

Equal to the product of the extents

inline int dimensions() const#

Get the dimensionality of the buffer.

inline halide_type_t type() const#

Get the type of the elements.

inline T *begin() const#

A pointer to the element with the lowest address.

If all strides are positive, equal to the host pointer.

inline T *end() const#

A pointer to one beyond the element with the highest address.

inline size_t size_in_bytes() const#

The total number of bytes spanned by the data in memory.

inline void reset()#

Reset the Buffer to be equivalent to a default-constructed Buffer of the same static type (if any); Buffer<void> will have its runtime type reset to uint8.

inline explicit Buffer(const halide_buffer_t &buf, BufferDeviceOwnership ownership = BufferDeviceOwnership::Unmanaged)#

Make a Buffer from a halide_buffer_t.

inline Buffer(const Buffer<T, Dims, InClassDimStorage> &other)#

Copy constructor.

Does not copy underlying data.

template<typename T2, int D2, int S2>
inline Buffer(const Buffer<T2, D2, S2> &other)#

Construct a Buffer from a Buffer of different dimensionality and type.

Asserts that the type and dimensionality matches (at runtime, if one of the types is void). Note that this constructor is implicit. This, for example, lets you pass things like Buffer<T> or Buffer<const void> to functions expected Buffer<const T>.

inline Buffer(Buffer<T, Dims, InClassDimStorage> &&other) noexcept#

Move constructor.

template<typename T2, int D2, int S2>
inline Buffer(Buffer<T2, D2, S2> &&other)#

Move-construct a Buffer from a Buffer of different dimensionality and type.

Asserts that the types match (at runtime if one of the types is void).

template<typename T2, int D2, int S2>
inline Buffer<T, Dims, InClassDimStorage> &operator=(const Buffer<T2, D2, S2> &other)#

Assign from another Buffer of possibly-different dimensionality and type.

Asserts that the types match (at runtime if one of the types is void).

inline Buffer<T, Dims, InClassDimStorage> &operator=(const Buffer<T, Dims, InClassDimStorage> &other)#

Standard assignment operator.

template<typename T2, int D2, int S2>
inline Buffer<T, Dims, InClassDimStorage> &operator=(Buffer<T2, D2, S2> &&other)#

Move from another Buffer of possibly-different dimensionality and type.

Asserts that the types match (at runtime if one of the types is void).

inline Buffer<T, Dims, InClassDimStorage> &operator=(Buffer<T, Dims, InClassDimStorage> &&other) noexcept#

Standard move-assignment operator.

inline void check_overflow()#

Check the product of the extents fits in memory.

inline void allocate(void *(*allocate_fn)(size_t) = nullptr, void (*deallocate_fn)(void*) = nullptr)#

Allocate memory for this Buffer.

Drops the reference to any owned memory.

inline void deallocate()#

Drop reference to any owned host or device memory, possibly freeing it, if this buffer held the last reference to it.

Retains the shape of the buffer. Does nothing if this buffer did not allocate its own memory.

inline void device_deallocate()#

Drop reference to any owned device memory, possibly freeing it if this buffer held the last reference to it.

Asserts that device_dirty is false.

template<typename ...Args, typename = std::enable_if_t<AllInts<Args...>::value>>
inline Buffer(halide_type_t t, int first, Args... rest)#

Allocate a new image of the given size with a runtime type.

Only used when you do know what size you want but you don’t know statically what type the elements are. Pass zeros to make a buffer suitable for bounds query calls.

inline explicit Buffer(int first)#

Allocate a new image of the given size.

Pass zeros to make a buffer suitable for bounds query calls.

inline Buffer(halide_type_t t, const std::vector<int> &sizes)#

Allocate a new image of unknown type using a vector of ints as the size.

inline explicit Buffer(const std::vector<int> &sizes)#

Allocate a new image of known type using a vector of ints as the size.

inline Buffer(halide_type_t t, const std::vector<int> &sizes, const std::vector<int> &storage_order)#

Allocate a new image of unknown type using a vector of ints as the size and a vector of indices indicating the storage order for each dimension.

The length of the sizes vector and the storage-order vector must match. For instance, to allocate an interleaved RGB buffer, you would pass {2, 0, 1} for storage_order.

template<typename Array, size_t N>
inline explicit Buffer(Array (&vals)[N])#

Make an Buffer that refers to a statically sized array.

Does not take ownership of the data, and does not set the host_dirty flag.

template<typename ...Args, typename = std::enable_if_t<AllInts<Args...>::value>>
inline explicit Buffer(halide_type_t t, add_const_if_T_is_const<void> *data, int first, Args&&... rest)#

Initialize an Buffer of runtime type from a pointer and some sizes.

Assumes dense row-major packing and a min coordinate of zero. Does not take ownership of the data and does not set the host_dirty flag.

template<typename ...Args, typename = std::enable_if_t<AllInts<Args...>::value>>
inline explicit Buffer(T *data, int first, Args&&... rest)#

Initialize an Buffer from a pointer and some sizes.

Assumes dense row-major packing and a min coordinate of zero. Does not take ownership of the data and does not set the host_dirty flag.

inline explicit Buffer(T *data, const std::vector<int> &sizes)#

Initialize an Buffer from a pointer and a vector of sizes.

Assumes dense row-major packing and a min coordinate of zero. Does not take ownership of the data and does not set the host_dirty flag.

inline explicit Buffer(halide_type_t t, add_const_if_T_is_const<void> *data, const std::vector<int> &sizes)#

Initialize an Buffer of runtime type from a pointer and a vector of sizes.

Assumes dense row-major packing and a min coordinate of zero. Does not take ownership of the data and does not set the host_dirty flag.

inline explicit Buffer(halide_type_t t, add_const_if_T_is_const<void> *data, int d, const halide_dimension_t *shape)#

Initialize an Buffer from a pointer to the min coordinate and an array describing the shape.

Does not take ownership of the data, and does not set the host_dirty flag.

inline explicit Buffer(halide_type_t t, add_const_if_T_is_const<void> *data, const std::vector<halide_dimension_t> &shape)#

Initialize a Buffer from a pointer to the min coordinate and a vector describing the shape.

Does not take ownership of the data, and does not set the host_dirty flag.

inline explicit Buffer(T *data, int d, const halide_dimension_t *shape)#

Initialize an Buffer from a pointer to the min coordinate and an array describing the shape.

Does not take ownership of the data and does not set the host_dirty flag.

inline explicit Buffer(T *data, const std::vector<halide_dimension_t> &shape)#

Initialize a Buffer from a pointer to the min coordinate and a vector describing the shape.

Does not take ownership of the data, and does not set the host_dirty flag.

inline ~Buffer()#

Destructor.

Will release any underlying owned allocation if this is the last reference to it. Will assert fail if there are weak references to this Buffer outstanding.

inline halide_buffer_t *raw_buffer()#

Get a pointer to the raw halide_buffer_t this wraps.

inline operator halide_buffer_t*()#

Provide a cast operator to halide_buffer_t *, so that instances can be passed directly to Halide filters.

template<typename T2, int D2 = Dims>
inline Buffer<T2, D2, InClassDimStorage> &as() &#

Return a typed reference to this Buffer.

Useful for converting a reference to a Buffer<void> to a reference to, for example, a Buffer<const uint8_t>, or converting a Buffer<T>& to Buffer<const T>&. You can also optionally sspecify a new value for Dims; this is useful mainly for removing the dimensionality constraint on a Buffer with explicit dimensionality. Does a runtime assert if the source buffer type is void or the new dimensionality is incompatible.

template<typename T2, int D2 = Dims>
inline const Buffer<T2, D2, InClassDimStorage> &as() const &#

Return a const typed reference to this Buffer.

Useful for converting a reference to a Buffer<void> to a reference to, for example, a Buffer<const uint8_t>, or converting a Buffer<T>& to Buffer<const T>&. You can also optionally sspecify a new value for Dims; this is useful mainly for removing the dimensionality constraint on a Buffer with explicit dimensionality. Does a runtime assert if the source buffer type is void or the new dimensionality is incompatible.

template<typename T2, int D2 = Dims>
inline Buffer<T2, D2, InClassDimStorage> as() &&#

Return an rval reference to this Buffer.

Useful for converting a reference to a Buffer<void> to a reference to, for example, a Buffer<const uint8_t>, or converting a Buffer<T>& to Buffer<const T>&. You can also optionally sspecify a new value for Dims; this is useful mainly for removing the dimensionality constraint on a Buffer with explicit dimensionality. Does a runtime assert if the source buffer type is void or the new dimensionality is incompatible.

inline Buffer<std::add_const_t<T>, Dims, InClassDimStorage> &as_const() &#

as_const() is syntactic sugar for .as<const T>(), to avoid the need to recapitulate the type argument.

template<typename T2 = T, typename = std::enable_if_t<!std::is_const_v<T2>>>
inline operator Buffer<std::add_const_t<T2>, Dims, InClassDimStorage>&() &#

Add some syntactic sugar to allow autoconversion from Buffer<T> to Buffer<const T>& when passing arguments.

template<typename TVoid, typename T2 = T, typename = std::enable_if_t<std::is_same_v<TVoid, void> && !std::is_void_v<T2> && !std::is_const_v<T2>>>
inline operator Buffer<TVoid, Dims, InClassDimStorage>&() &#

Add some syntactic sugar to allow autoconversion from Buffer<T> to Buffer<void>& when passing arguments.

template<typename TVoid, typename T2 = T, typename = std::enable_if_t<std::is_same_v<TVoid, void> && !std::is_void_v<T2> && std::is_const_v<T2>>>
inline operator Buffer<const TVoid, Dims, InClassDimStorage>&() &#

Add some syntactic sugar to allow autoconversion from Buffer<const T> to Buffer<const void>& when passing arguments.

inline int width() const#

Conventional names for the first three dimensions.

inline int left() const#

Conventional names for the min and max value of each dimension.

inline Buffer<not_const_T, Dims, InClassDimStorage> copy(void *(*allocate_fn)(size_t) = nullptr, void (*deallocate_fn)(void*) = nullptr) const#

Make a new image which is a deep copy of this image.

Use crop or slice followed by copy to make a copy of only a portion of the image. The new image has the same nesting order of dimensions (e.g. channels innermost), but resets the strides to the default (each stride is the product of the extents of the inner dimensions). Note that this means any strides of zero get broadcast into a non-zero stride.

Note that the returned Buffer is always of a non-const type T (ie:

Buffer<const T>.copy() -> Buffer<T> rather than Buffer<const T>

which is always safe, since we are making a deep copy. (The caller can easily cast it back to Buffer<const T> if desired, which is always safe and free.)

inline Buffer<not_const_T, Dims, InClassDimStorage> copy_to_interleaved(void *(*allocate_fn)(size_t) = nullptr, void (*deallocate_fn)(void*) = nullptr) const#

Like copy(), but the copy is created in interleaved memory layout (vs.

keeping the same memory layout as the original). Requires that ‘this’ has exactly 3 dimensions.

inline Buffer<not_const_T, Dims, InClassDimStorage> copy_to_planar(void *(*allocate_fn)(size_t) = nullptr, void (*deallocate_fn)(void*) = nullptr) const#

Like copy(), but the copy is created in planar memory layout (vs.

keeping the same memory layout as the original).

inline Buffer<T, Dims, InClassDimStorage> alias() const#

Make a copy of the Buffer which shares the underlying host and/or device allocations as the existing Buffer.

This is purely syntactic sugar for cases where you have a const reference to a Buffer but need a temporary non-const copy (e.g. to make a call into AOT-generated Halide code), and want a terse inline way to create a temporary.

void call_my_func(const Buffer<const uint8_t>& input) {
    my_func(input.alias(), output);
}

template<typename T2, int D2, int S2>
inline void copy_from(Buffer<T2, D2, S2> src)#

Fill a Buffer with the values at the same coordinates in another Buffer.

Restricts itself to coordinates contained within the intersection of the two buffers. If the two Buffers are not in the same coordinate system, you will need to translate the argument Buffer first. E.g. if you’re blitting a sprite onto a framebuffer, you’ll want to translate the sprite to the correct location first like so:

framebuffer.copy_from(sprite.translated({x, y})); 

inline Buffer<T, Dims, InClassDimStorage> cropped(int d, int min, int extent) const#

Make an image that refers to a sub-range of this image along the given dimension.

Asserts that the crop region is within the existing bounds: you cannot “crop outwards”, even if you know there is valid Buffer storage (e.g. because you already cropped inwards).

inline void crop(int d, int min, int extent)#

Crop an image in-place along the given dimension.

This does not move any data around in memory - it just changes the min and extent of the given dimension.

inline Buffer<T, Dims, InClassDimStorage> cropped(const std::vector<std::pair<int, int>> &rect) const#

Make an image that refers to a sub-rectangle of this image along the first N dimensions.

Asserts that the crop region is within the existing bounds. The cropped image may drop any device handle if the device_interface cannot accomplish the crop in-place.

inline void crop(const std::vector<std::pair<int, int>> &rect)#

Crop an image in-place along the first N dimensions.

This does not move any data around in memory, nor does it free memory. It just rewrites the min/extent of each dimension to refer to a subregion of the same allocation.

inline Buffer<T, Dims, InClassDimStorage> translated(int d, int dx) const#

Make an image which refers to the same data with using translated coordinates in the given dimension.

Positive values move the image data to the right or down relative to the coordinate system. Drops any device handle.

inline void translate(int d, int delta)#

Translate an image in-place along one dimension by changing how it is indexed.

Does not move any data around in memory.

inline Buffer<T, Dims, InClassDimStorage> translated(const std::vector<int> &delta) const#

Make an image which refers to the same data translated along the first N dimensions.

inline void translate(const std::vector<int> &delta)#

Translate an image along the first N dimensions by changing how it is indexed.

Does not move any data around in memory.

inline void set_min(const std::vector<int> &mins)#

Set the min coordinate of an image in the first N dimensions.

inline bool contains(const std::vector<int> &coords) const#

Test if a given coordinate is within the bounds of an image.

inline Buffer<T, Dims, InClassDimStorage> transposed(int d1, int d2) const#

Make a buffer which refers to the same data in the same layout using a swapped indexing order for the dimensions given.

So A = B.transposed(0, 1) means that A(i, j) == B(j, i), and more strongly that A.address_of(i, j) == B.address_of(j, i).

inline void transpose(int d1, int d2)#

Transpose a buffer in-place by changing how it is indexed.

For example, transpose(0, 1) on a two-dimensional buffer means that the value referred to by coordinates (i, j) is now reached at the coordinates (j, i), and vice versa. This is done by reordering the per-dimension metadata rather than by moving data around in memory, so other views of the same memory will not see the data as having been transposed.

inline void transpose(const std::vector<int> &order)#

A generalized transpose: instead of swapping two dimensions, pass a vector that lists each dimension index exactly once, in the desired order.

This does not move any data around in memory

  • it just permutes how it is indexed.

inline Buffer<T, Dims, InClassDimStorage> transposed(const std::vector<int> &order) const#

Make a buffer which refers to the same data in the same layout using a different ordering of the dimensions.

inline Buffer<T, (Dims == AnyDims ? AnyDims : Dims - 1)> sliced(int d, int pos) const#

Make a lower-dimensional buffer that refers to one slice of this buffer.

inline Buffer<T, (Dims == AnyDims ? AnyDims : Dims - 1)> sliced(int d) const#

Make a lower-dimensional buffer that refers to one slice of this buffer at the dimension’s minimum.

inline void slice(int d, int pos)#

Rewrite the buffer to refer to a single lower-dimensional slice of itself along the given dimension at the given coordinate.

Does not move any data around or free the original memory, so other views of the same data are unaffected. Can only be called on a Buffer with dynamic dimensionality.

inline void slice(int d)#

Slice a buffer in-place at the dimension’s minimum.

inline Buffer<T, (Dims == AnyDims ? AnyDims : Dims + 1)> embedded(int d, int pos = 0) const#

Make a new buffer that views this buffer as a single slice in a higher-dimensional space.

The new dimension has extent one and the given min. This operation is the opposite of slice. As an example, the following condition is true:

im2 = im.embedded(1, 17);
&im(x, y, c) == &im2(x, 17, y, c);
inline void embed(int d, int pos = 0)#

Embed a buffer in-place, increasing the dimensionality.

inline void add_dimension()#

Add a new dimension with a min of zero and an extent of one.

The stride is the extent of the outermost dimension times its stride. The new dimension is the last dimension. This is a special case of embed.

inline void add_dimension_with_stride(int s)#

Add a new dimension with a min of zero, an extent of one, and the specified stride.

The new dimension is the last dimension. This is a special case of embed.

inline void set_host_dirty(bool v = true)#

Methods for managing any GPU allocation.

inline BufferDeviceOwnership device_ownership() const#

Return the method by which the device field is managed.

inline T *data() const#

Get a pointer to the address of the min coordinate.

template<typename ...Args, typename = std::enable_if_t<AllInts<Args...>::value>>
inline const not_void_T &operator()(int first, Args... rest) const#

Access elements.

Use im(…) to get a reference to an element, and use &im(…) to get the address of an element. If you pass fewer arguments than the buffer has dimensions, the rest are treated as their min coordinate. The non-const versions set the host_dirty flag to true.

inline bool all_equal(not_void_T val) const#

Tests that all values in this buffer are equal to val.

template<typename Fn, typename ...Args, int N = sizeof...(Args) + 1>
inline const Buffer<T, Dims, InClassDimStorage> &for_each_value(Fn &&f, Args&&... other_buffers) const#

Call a function on every value in the buffer, and the corresponding values in some number of other buffers of the same size.

The function should take a reference, const reference, or value of the correct type for each buffer. This effectively lifts a function of scalars to an element-wise function of buffers. This produces code that the compiler can autovectorize. This is slightly cheaper than for_each_element, because it does not need to track the coordinates.

Note that constness of Buffers is preserved: a const Buffer<T> (for either ‘this’ or the other-buffers arguments) will allow mutation of the buffer contents, while a Buffer<const T> will not. Attempting to specify a mutable reference for the lambda argument of a Buffer<const T> will result in a compilation error.

template<typename Fn>
inline const Buffer<T, Dims, InClassDimStorage> &for_each_element(Fn &&f) const#

Call a function at each site in a buffer.

This is likely to be much slower than using Halide code to populate a buffer, but is convenient for tests. The function must take a number of int arguments equal to the dimensionality of the buffer. For example, the following code sets a floating point RGB image to red:

Buffer<float, 3> im(100, 100, 3);
im.for_each_element([&](int x, int y, int c) {
    im(x, y, c) = (c == 0) ? 1.0f : 0.0f;
});

The compiled code is equivalent to writing the a nested for loop, and compilers are capable of optimizing it in the same way.

If the callable can be called with an int * as the sole argument, that version is called instead. Each location in the buffer is passed to it in a coordinate array. This version is higher-overhead than the variadic version, but is useful for writing generic code that accepts buffers of arbitrary dimensionality. For example, the following sets the value at all sites in an arbitrary-dimensional buffer to their first coordinate:

im.for_each_element([&](const int *pos) {im(pos) = pos[0];});

It is also possible to use for_each_element to iterate over entire rows or columns by cropping the buffer to a single column or row respectively and iterating over elements of the result. For example, to set the diagonal of the image to 1 by iterating over the columns:

Buffer<float, 3> im(100, 100, 3);
    im.sliced(1, 0).for_each_element([&](int x, int c) {
    im(x, x, c) = 1.0f;
});

Or, assuming the memory layout is known to be dense per row, one can memset each row of an image like so:

Buffer<float, 3> im(100, 100, 3);
im.sliced(0, 0).for_each_element([&](int y, int c) {
    memset(&im(0, y, c), 0, sizeof(float) * im.width());
});
template<typename Fn, typename = std::enable_if_t<!std::is_arithmetic_v<std::decay_t<Fn>>>>
inline Buffer<T, Dims, InClassDimStorage> &fill(Fn &&f)#

Fill a buffer by evaluating a callable at every site.

The callable should look much like a callable passed to for_each_element, but it should return the value that should be stored to the coordinate corresponding to the arguments. A callable that takes no arguments (for example a random number generator) is evaluated once per element, ignoring the coordinate.

inline bool is_bounds_query() const#

Check if an input buffer passed extern stage is a querying bounds.

Compared to doing the host pointer check directly, this both adds clarity to code and will facilitate moving to another representation for bounds query arguments.

inline void msan_check_mem_is_initialized(bool entire = false) const#

Convenient check to verify that all of the interesting bytes in the Buffer are initialized under MSAN.

Note that by default, we use for_each_value() here so that we skip any unused padding that isn’t part of the Buffer; this isn’t efficient, but in MSAN mode, it doesn’t matter. (Pass true for the flag to force check the entire Buffer storage.)

Public Static Functions

static inline halide_type_t static_halide_type()#

Get the Halide type of T.

Callers should not use the result if has_static_halide_type is false.

static inline int static_dimensions()#

Callers should not use the result if has_static_dimensions is false.

template<typename T2, int D2, int S2>
static inline 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.

If this can be determined at compile time, fail with a static assert; otherwise return a boolean based on runtime typing.

template<typename T2, int D2, int S2>
static inline void assert_can_convert_from(const Buffer<T2, D2, S2> &other)#

Fail an assertion at runtime or compile-time if an Buffer<T, Dims, InClassDimStorage> cannot be constructed from some other Buffer type.

static inline 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.

This function constructs an interleaved RGB or RGBA image that can still be indexed using (x, y, c). Passing it to a generator requires that the generator has been compiled with support for interleaved (also known as packed or chunky) memory layouts.

static inline Buffer<T, Dims, InClassDimStorage> make_interleaved(int width, int height, int channels)#

If you use the (x, y, c) indexing convention, then Halide Buffers are stored planar by default.

This function constructs an interleaved RGB or RGBA image that can still be indexed using (x, y, c). Passing it to a generator requires that the generator has been compiled with support for interleaved (also known as packed or chunky) memory layouts.

static inline Buffer<add_const_if_T_is_const<void>, Dims, InClassDimStorage> make_interleaved(halide_type_t t, T *data, int width, int height, int channels)#

Wrap an existing interleaved image.

static inline Buffer<T, Dims, InClassDimStorage> make_interleaved(T *data, int width, int height, int channels)#

Wrap an existing interleaved image.

static inline Buffer<add_const_if_T_is_const<void>, Dims, InClassDimStorage> make_scalar(halide_type_t t)#

Make a zero-dimensional Buffer.

static inline Buffer<T, Dims, InClassDimStorage> make_scalar()#

Make a zero-dimensional Buffer.

static inline Buffer<T, Dims, InClassDimStorage> make_scalar(T *data)#

Make a zero-dimensional Buffer that points to non-owned, existing data.

template<typename T2, int D2, int S2>
static inline 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.

It may have a different type.

Public Static Attributes

static bool has_static_halide_type = !T_is_void#

True if the Halide type is not void (or const void).

Friends

friend class Buffer
class Dimension#

Read-only access to the shape.

Public Functions

inline int min() const#

The lowest coordinate in this dimension.

inline int stride() const#

The number of elements in memory you have to step over to increment this coordinate by one.

inline int extent() const#

The extent of the image along this dimension.

inline int max() const#

The highest coordinate in this dimension.

inline iterator begin() const#

An iterator that points to the min coordinate.

inline iterator end() const#

An iterator that points to one past the max coordinate.

struct iterator#

An iterator class, so that you can iterate over coordinates in a dimensions using a range-based for loop.