#ifdef COMPILING_HALIDE_RUNTIME #include "HalideRuntime.h" #define HALIDE_BUFFER_HELPER_ATTRS WEAK_INLINE #else #define HALIDE_BUFFER_HELPER_ATTRS inline #endif // Structs are annoying to deal with from within Halide Stmts. These // utility functions are for dealing with halide_buffer_t in that // context. They are not intended for use outside of Halide code, and // not exposed in HalideRuntime.h. The symbols are private to the // module and should be inlined and then stripped. This blob of code // also gets copy-pasted into C outputs. extern "C" { HALIDE_BUFFER_HELPER_ATTRS int _halide_buffer_get_dimensions(const halide_buffer_t *buf) { return buf->dimensions; } HALIDE_BUFFER_HELPER_ATTRS uint8_t *_halide_buffer_get_host(const halide_buffer_t *buf) { return buf->host; } HALIDE_BUFFER_HELPER_ATTRS uint64_t _halide_buffer_get_device(const halide_buffer_t *buf) { return buf->device; } HALIDE_BUFFER_HELPER_ATTRS const struct halide_device_interface_t *_halide_buffer_get_device_interface(const halide_buffer_t *buf) { return buf->device_interface; } HALIDE_BUFFER_HELPER_ATTRS int _halide_buffer_get_min(const halide_buffer_t *buf, int d) { return buf->dim[d].min; } HALIDE_BUFFER_HELPER_ATTRS int _halide_buffer_get_max(const halide_buffer_t *buf, int d) { return buf->dim[d].min + buf->dim[d].extent - 1; } HALIDE_BUFFER_HELPER_ATTRS int _halide_buffer_get_extent(const halide_buffer_t *buf, int d) { return buf->dim[d].extent; } HALIDE_BUFFER_HELPER_ATTRS int _halide_buffer_get_stride(const halide_buffer_t *buf, int d) { return buf->dim[d].stride; } HALIDE_BUFFER_HELPER_ATTRS int _halide_buffer_set_host_dirty(halide_buffer_t *buf, bool val) { buf->set_host_dirty(val); return 0; } HALIDE_BUFFER_HELPER_ATTRS int _halide_buffer_set_device_dirty(halide_buffer_t *buf, bool val) { buf->set_device_dirty(val); return 0; } HALIDE_BUFFER_HELPER_ATTRS bool _halide_buffer_get_host_dirty(const halide_buffer_t *buf) { return buf->host_dirty(); } HALIDE_BUFFER_HELPER_ATTRS bool _halide_buffer_get_device_dirty(const halide_buffer_t *buf) { return buf->device_dirty(); } HALIDE_BUFFER_HELPER_ATTRS halide_dimension_t *_halide_buffer_get_shape(halide_buffer_t *buf) { return buf->dim; } HALIDE_BUFFER_HELPER_ATTRS bool _halide_buffer_is_bounds_query(const halide_buffer_t *buf) { return buf->host == nullptr && buf->device == 0; } HALIDE_BUFFER_HELPER_ATTRS uint32_t _halide_buffer_get_type(const halide_buffer_t *buf) { return buf->type.as_u32(); } HALIDE_BUFFER_HELPER_ATTRS halide_buffer_t *_halide_buffer_init(halide_buffer_t *dst, halide_dimension_t *dst_shape, void *host, uint64_t device, const halide_device_interface_t *device_interface, int type_code, int type_bits, int dimensions, halide_dimension_t *shape, uint64_t flags) { dst->host = (uint8_t *)host; dst->device = device; dst->device_interface = device_interface; dst->type.code = (halide_type_code_t)type_code; dst->type.bits = (uint8_t)type_bits; dst->type.lanes = 1; dst->dimensions = dimensions; dst->dim = dst_shape; if (shape != dst->dim) { for (int i = 0; i < dimensions; i++) { dst->dim[i] = shape[i]; } } dst->flags = flags; return dst; } HALIDE_BUFFER_HELPER_ATTRS halide_buffer_t *_halide_buffer_init_from_buffer(halide_buffer_t *dst, halide_dimension_t *dst_shape, const halide_buffer_t *src) { dst->host = src->host; dst->device = src->device; dst->device_interface = src->device_interface; dst->type = src->type; dst->dimensions = src->dimensions; dst->dim = dst_shape; dst->flags = src->flags; for (int i = 0; i < dst->dimensions; i++) { dst->dim[i] = src->dim[i]; } return dst; } HALIDE_BUFFER_HELPER_ATTRS halide_buffer_t *_halide_buffer_crop(void *user_context, halide_buffer_t *dst, halide_dimension_t *dst_shape, const halide_buffer_t *src, const int *min, const int *extent) { *dst = *src; dst->dim = dst_shape; int64_t offset = 0; for (int i = 0; i < dst->dimensions; i++) { dst->dim[i] = src->dim[i]; dst->dim[i].min = min[i]; dst->dim[i].extent = extent[i]; offset += (min[i] - src->dim[i].min) * (int64_t)src->dim[i].stride; } if (dst->host) { dst->host += offset * src->type.bytes(); } dst->device_interface = nullptr; dst->device = 0; if (src->device_interface) { src->device_interface->device_crop(user_context, src, dst); } return dst; } // Called on return from an extern stage where the output buffer was a // crop of some other larger buffer. This happens for extern stages // with distinct store_at/compute_at levels. Each call to the stage // only fills in part of the buffer. HALIDE_BUFFER_HELPER_ATTRS int _halide_buffer_retire_crop_after_extern_stage(void *user_context, void *obj) { halide_buffer_t **buffers = (halide_buffer_t **)obj; halide_buffer_t *crop = buffers[0]; halide_buffer_t *parent = buffers[1]; if (crop->device) { if (!parent->device) { // We have been given a device allocation by the extern // stage. It only represents the cropped region, so we // can't just give it to the parent. if (crop->device_dirty()) { crop->device_interface->copy_to_host(user_context, crop); } crop->device_interface->device_free(user_context, crop); } else { // We are a crop of an existing device allocation. if (crop->device_dirty()) { parent->set_device_dirty(); } crop->device_interface->device_release_crop(user_context, crop); } } if (crop->host_dirty()) { parent->set_host_dirty(); } return 0; } HALIDE_BUFFER_HELPER_ATTRS int _halide_buffer_retire_crops_after_extern_stage(void *user_context, void *obj) { halide_buffer_t **buffers = (halide_buffer_t **)obj; while (*buffers) { _halide_buffer_retire_crop_after_extern_stage(user_context, buffers); buffers += 2; } return 0; } HALIDE_BUFFER_HELPER_ATTRS halide_buffer_t *_halide_buffer_set_bounds(halide_buffer_t *buf, int dim, int min, int extent) { buf->dim[dim].min = min; buf->dim[dim].extent = extent; return buf; } } #undef HALIDE_BUFFER_HELPER_ATTRS