WEAK void CacheEntry::destroy() { halide_free(NULL, key); for (uint32_t i = 0; i < tuple_count; i++) { halide_device_free(NULL, &buffer(i)); halide_free(NULL, get_pointer_to_header(buffer(i).host)); } }
WEAK void CacheEntry::destroy() { halide_free(NULL, key); for (int32_t i = 0; i < tuple_count; i++) { halide_device_free(NULL, &buffer(i)); halide_free(NULL, buffer(i).host - extra_bytes_host_bytes); } }
WEAK void CacheEntry::destroy() { for (uint32_t i = 0; i < tuple_count; i++) { halide_device_free(NULL, &buf[i]); halide_free(NULL, get_pointer_to_header(buf[i].host)); } halide_free(NULL, metadata_storage); }
/** Free host and device memory associated with a buffer_t. */ WEAK int halide_device_and_host_free(void *user_context, struct halide_buffer_t *buf) { debug(user_context) << "halide_device_and_host_free: " << buf << " buf dev " << buf->device << " interface " << buf->device_interface << "\n"; if (buf != NULL) { const halide_device_interface_t *device_interface = buf->device_interface; if (device_interface != NULL) { // Ensure interface is not freed prematurely. // TODO: Exception safety... device_interface->use_module(); int result = device_interface->device_and_host_free(user_context, buf); device_interface->release_module(); halide_assert(user_context, buf->device == 0); if (result) { return halide_error_code_device_free_failed; } else { return 0; } } else if (buf->host) { // device_free must have been called on this buffer (which // must be legal for the device interface that was // used). We'd better still free the host pointer. halide_free(user_context, buf->host); buf->host = NULL; } } buf->set_device_dirty(false); return 0; }
WEAK int halide_default_device_and_host_free(void *user_context, struct buffer_t *buf, const halide_device_interface *device_interface) { int result = halide_device_free(user_context, buf); halide_free(user_context, buf->host); buf->host = NULL; buf->host_dirty = false; buf->dev_dirty = false; return result; }
WEAK void prune_cache() { #if CACHE_DEBUGGING validate_cache(); #endif CacheEntry *prune_candidate = least_recently_used; while (current_cache_size > max_cache_size && prune_candidate != NULL) { CacheEntry *more_recent = prune_candidate->more_recent; if (prune_candidate->in_use_count == 0) { uint32_t h = prune_candidate->hash; uint32_t index = h % kHashTableSize; // Remove from hash table CacheEntry *prev_hash_entry = cache_entries[index]; if (prev_hash_entry == prune_candidate) { cache_entries[index] = prune_candidate->next; } else { while (prev_hash_entry != NULL && prev_hash_entry->next != prune_candidate) { prev_hash_entry = prev_hash_entry->next; } halide_assert(NULL, prev_hash_entry != NULL); prev_hash_entry->next = prune_candidate->next; } // Remove from less recent chain. if (least_recently_used == prune_candidate) { least_recently_used = more_recent; } if (more_recent != NULL) { more_recent->less_recent = prune_candidate->less_recent; } // Remove from more recent chain. if (most_recently_used == prune_candidate) { most_recently_used = prune_candidate->less_recent; } if (prune_candidate->less_recent != NULL) { prune_candidate->less_recent = more_recent; } // Decrease cache used amount. for (int32_t i = 0; i < prune_candidate->tuple_count; i++) { current_cache_size -= full_extent(prune_candidate->buffer(i)); } // Deallocate the entry. prune_candidate->destroy(); halide_free(NULL, prune_candidate); } prune_candidate = more_recent; } #if CACHE_DEBUGGING validate_cache(); #endif }
WEAK int halide_default_device_and_host_free(void *user_context, struct halide_buffer_t *buf, const halide_device_interface_t *device_interface) { int result = halide_device_free(user_context, buf); if (buf->host) { halide_free(user_context, buf->host); buf->host = NULL; } buf->set_host_dirty(false); buf->set_device_dirty(false); return result; }
WEAK int halide_default_device_and_host_malloc(void *user_context, struct buffer_t *buf, const halide_device_interface *device_interface) { size_t size = buf_size(buf); buf->host = (uint8_t *)halide_malloc(user_context, size); if (buf->host == NULL) { return -1; } int result = halide_device_malloc(user_context, buf, device_interface); if (result != 0) { halide_free(user_context, buf->host); buf->host = NULL; } return result; }
WEAK void prune_cache() { #if CACHE_DEBUGGING validate_cache(); #endif while (current_cache_size > max_cache_size && least_recently_used != NULL) { CacheEntry *lru_entry = least_recently_used; uint32_t h = lru_entry->hash; uint32_t index = h % kHashTableSize; CacheEntry *entry = cache_entries[index]; if (entry == lru_entry) { cache_entries[index] = lru_entry->next; } else { while (entry != NULL && entry->next != lru_entry) { entry = entry->next; } halide_assert(NULL, entry != NULL); entry->next = lru_entry->next; } least_recently_used = lru_entry->more_recent; if (least_recently_used != NULL) { least_recently_used->less_recent = NULL; } if (most_recently_used == lru_entry) { most_recently_used = NULL; } for (int32_t i = 0; i < lru_entry->tuple_count; i++) { current_cache_size -= full_extent(lru_entry->buffer(i)); } lru_entry->destroy(); halide_free(NULL, lru_entry); } #if CACHE_DEBUGGING validate_cache(); #endif }
// Copy image data from texture back to host memory. EXPORT int halide_opengl_copy_to_host(void *user_context, buffer_t *buf) { CHECK_INITIALIZED(1); if (!buf->dev_dirty) { return 0; } if (!buf->host || !buf->dev) { #ifdef DEBUG print_buffer(user_context, buf); #endif halide_error(user_context, "Invalid copy_to_host operation"); return 1; } GLuint tex = get_texture_id(buf); #ifdef DEBUG halide_printf(user_context, "halide_copy_to_host: %d\n", tex); #endif GLint format; GLint type; if (!get_texture_format(user_context, buf, &format, &type)) { halide_error(user_context, "Invalid texture format\n"); return 1; } GLint width = buf->extent[0]; GLint height = buf->extent[1]; ST.BindTexture(GL_TEXTURE_2D, tex); CHECK_GLERROR(1); bool is_interleaved = (buf->stride[2] == 1 && buf->stride[0] == buf->extent[2]); if (is_interleaved) { // TODO: GL_UNPACK_ROW_LENGTH ST.PixelStorei(GL_PACK_ROW_LENGTH, buf->extent[1]); ST.PixelStorei(GL_PACK_ALIGNMENT, 1); ST.GetTexImage(GL_TEXTURE_2D, 0, format, type, buf->host); CHECK_GLERROR(1); } else { #ifdef DEBUG halide_printf(user_context, "Warning: In copy_to_host, host buffer is not interleaved. Doing slow deinterleave.\n"); #endif size_t size = width * height * buf->extent[2] * buf->elem_size; uint8_t *tmp = (uint8_t*)halide_malloc(user_context, size); ST.PixelStorei(GL_PACK_ALIGNMENT, 1); ST.GetTexImage(GL_TEXTURE_2D, 0, format, type, tmp); CHECK_GLERROR(1); switch (type) { case GL_UNSIGNED_BYTE: interleaved_to_halide<uint8_t>(buf, (uint8_t*)tmp, width, height, buf->extent[2]); break; case GL_UNSIGNED_SHORT: interleaved_to_halide<uint16_t>(buf, (uint16_t*)tmp, width, height, buf->extent[2]); break; case GL_FLOAT: interleaved_to_halide<float>(buf, (float*)tmp, width, height, buf->extent[2]); break; } halide_free(user_context, tmp); } ST.BindTexture(GL_TEXTURE_2D, 0); buf->dev_dirty = false; return 0; }