//===- Auto-generated file, part of the LLVM/Offload project --------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//

// Auto-generated file, do not manually edit.

#pragma once

#include <stddef.h>
#include <stdint.h>

#if defined(__cplusplus)
extern "C" {
#endif

///////////////////////////////////////////////////////////////////////////////
#ifndef OL_APICALL
#if defined(_WIN32)
/// @brief Calling convention for all API functions
#define OL_APICALL __cdecl
#else
#define OL_APICALL
#endif // defined(_WIN32)
#endif // OL_APICALL

///////////////////////////////////////////////////////////////////////////////
#ifndef OL_APIEXPORT
#if defined(_WIN32)
/// @brief Microsoft-specific dllexport storage-class attribute
#define OL_APIEXPORT __declspec(dllexport)
#else
#define OL_APIEXPORT
#endif // defined(_WIN32)
#endif // OL_APIEXPORT

///////////////////////////////////////////////////////////////////////////////
#ifndef OL_SUCCESS
/// @brief Success condition
#define OL_SUCCESS NULL
#endif // OL_SUCCESS

///////////////////////////////////////////////////////////////////////////////
#ifndef OL_VERSION_MAJOR
/// @brief Major version of the Offload API
#define OL_VERSION_MAJOR 0
#endif // OL_VERSION_MAJOR

///////////////////////////////////////////////////////////////////////////////
#ifndef OL_VERSION_MINOR
/// @brief Minor version of the Offload API
#define OL_VERSION_MINOR 0
#endif // OL_VERSION_MINOR

///////////////////////////////////////////////////////////////////////////////
#ifndef OL_VERSION_PATCH
/// @brief Patch version of the Offload API
#define OL_VERSION_PATCH 1
#endif // OL_VERSION_PATCH

///////////////////////////////////////////////////////////////////////////////
/// @brief Handle of context object
typedef struct ol_context_impl_t *ol_context_handle_t;

///////////////////////////////////////////////////////////////////////////////
/// @brief Handle of platform's device object
typedef struct ol_device_impl_t *ol_device_handle_t;

///////////////////////////////////////////////////////////////////////////////
/// @brief Handle of event object
typedef struct ol_event_impl_t *ol_event_handle_t;

///////////////////////////////////////////////////////////////////////////////
/// @brief Handle of a platform instance
typedef struct ol_platform_impl_t *ol_platform_handle_t;

///////////////////////////////////////////////////////////////////////////////
/// @brief Handle of program object
typedef struct ol_program_impl_t *ol_program_handle_t;

///////////////////////////////////////////////////////////////////////////////
/// @brief Handle of queue object
typedef struct ol_queue_impl_t *ol_queue_handle_t;

///////////////////////////////////////////////////////////////////////////////
/// @brief Handle of an object in a device's memory for a specific program
typedef struct ol_symbol_impl_t *ol_symbol_handle_t;

///////////////////////////////////////////////////////////////////////////////
/// @brief Represents the type of allocation made with olMemAlloc.
typedef enum ol_alloc_type_t {
  /// Host allocation
  OL_ALLOC_TYPE_HOST = 0,
  /// Device allocation
  OL_ALLOC_TYPE_DEVICE = 1,
  /// Managed allocation
  OL_ALLOC_TYPE_MANAGED = 2,
  /// @cond
  OL_ALLOC_TYPE_LAST = 3,
  OL_ALLOC_TYPE_FORCE_UINT32 = 0x7fffffff
  /// @endcond

} ol_alloc_type_t;

///////////////////////////////////////////////////////////////////////////////
/// @brief Device floating-point capability flags
typedef enum ol_device_fp_capability_flag_t {
  /// Support correctly rounded divide and sqrt
  OL_DEVICE_FP_CAPABILITY_FLAG_CORRECTLY_ROUNDED_DIVIDE_SQRT = 1,
  /// Support round to nearest
  OL_DEVICE_FP_CAPABILITY_FLAG_ROUND_TO_NEAREST = 2,
  /// Support round to zero
  OL_DEVICE_FP_CAPABILITY_FLAG_ROUND_TO_ZERO = 4,
  /// Support round to infinity
  OL_DEVICE_FP_CAPABILITY_FLAG_ROUND_TO_INF = 8,
  /// Support INF to NAN
  OL_DEVICE_FP_CAPABILITY_FLAG_INF_NAN = 16,
  /// Support denorm
  OL_DEVICE_FP_CAPABILITY_FLAG_DENORM = 32,
  /// Support fused multiply-add
  OL_DEVICE_FP_CAPABILITY_FLAG_FMA = 64,
  /// Basic floating point operations implemented in software
  OL_DEVICE_FP_CAPABILITY_FLAG_SOFT_FLOAT = 128,
  /// @cond
  OL_DEVICE_FP_CAPABILITY_FLAG_LAST = 256,
  OL_DEVICE_FP_CAPABILITY_FLAG_FORCE_UINT32 = 0x7fffffff
  /// @endcond

} ol_device_fp_capability_flag_t;

///////////////////////////////////////////////////////////////////////////////
/// @brief Supported device info.
typedef enum ol_device_info_t {
  /// [ol_device_type_t] type of the device
  OL_DEVICE_INFO_TYPE = 0,
  /// [ol_platform_handle_t] the platform associated with the device
  OL_DEVICE_INFO_PLATFORM = 1,
  /// [char[]] Device name
  OL_DEVICE_INFO_NAME = 2,
  /// [char[]] Device user-facing marketing name
  OL_DEVICE_INFO_PRODUCT_NAME = 3,
  /// [char[]] Device vendor
  OL_DEVICE_INFO_VENDOR = 4,
  /// [char[]] Driver version
  OL_DEVICE_INFO_DRIVER_VERSION = 5,
  /// [uint32_t] Maximum total work group size in work items
  OL_DEVICE_INFO_MAX_WORK_GROUP_SIZE = 6,
  /// [ol_dimensions_t] Maximum work group size in each dimension
  OL_DEVICE_INFO_MAX_WORK_GROUP_SIZE_PER_DIMENSION = 7,
  /// [uint32_t] Maximum total work items
  OL_DEVICE_INFO_MAX_WORK_SIZE = 8,
  /// [ol_dimensions_t] Maximum work items in each dimension
  OL_DEVICE_INFO_MAX_WORK_SIZE_PER_DIMENSION = 9,
  /// [uint32_t] A unique vendor device identifier assigned by PCI-SIG
  OL_DEVICE_INFO_VENDOR_ID = 10,
  /// [uint32_t] The number of parallel compute units available to the device
  OL_DEVICE_INFO_NUM_COMPUTE_UNITS = 11,
  /// [uint32_t] The maximum configured clock frequency of this device in MHz
  OL_DEVICE_INFO_MAX_CLOCK_FREQUENCY = 12,
  /// [uint32_t] Memory clock frequency in MHz
  OL_DEVICE_INFO_MEMORY_CLOCK_RATE = 13,
  /// [uint32_t] Number of bits used to represent an address in device memory
  OL_DEVICE_INFO_ADDRESS_BITS = 14,
  /// [uint64_t] The maximum size of memory object allocation in bytes
  OL_DEVICE_INFO_MAX_MEM_ALLOC_SIZE = 15,
  /// [uint64_t] The size of global device memory in bytes
  OL_DEVICE_INFO_GLOBAL_MEM_SIZE = 16,
  /// [ol_device_fp_capability_flags_t] Single precision floating point
  /// capability
  OL_DEVICE_INFO_SINGLE_FP_CONFIG = 17,
  /// [ol_device_fp_capability_flags_t] Double precision floating point
  /// capability
  OL_DEVICE_INFO_DOUBLE_FP_CONFIG = 18,
  /// [ol_device_fp_capability_flags_t] Half precision floating point capability
  OL_DEVICE_INFO_HALF_FP_CONFIG = 19,
  /// [uint32_t] Native vector width for char
  OL_DEVICE_INFO_NATIVE_VECTOR_WIDTH_CHAR = 20,
  /// [uint32_t] Native vector width for short
  OL_DEVICE_INFO_NATIVE_VECTOR_WIDTH_SHORT = 21,
  /// [uint32_t] Native vector width for int
  OL_DEVICE_INFO_NATIVE_VECTOR_WIDTH_INT = 22,
  /// [uint32_t] Native vector width for long
  OL_DEVICE_INFO_NATIVE_VECTOR_WIDTH_LONG = 23,
  /// [uint32_t] Native vector width for float
  OL_DEVICE_INFO_NATIVE_VECTOR_WIDTH_FLOAT = 24,
  /// [uint32_t] Native vector width for double
  OL_DEVICE_INFO_NATIVE_VECTOR_WIDTH_DOUBLE = 25,
  /// [uint32_t] Native vector width for half
  OL_DEVICE_INFO_NATIVE_VECTOR_WIDTH_HALF = 26,
  /// @cond
  OL_DEVICE_INFO_LAST = 27,
  OL_DEVICE_INFO_FORCE_UINT32 = 0x7fffffff
  /// @endcond

} ol_device_info_t;

///////////////////////////////////////////////////////////////////////////////
/// @brief Supported device types.
typedef enum ol_device_type_t {
  /// The default device type as preferred by the runtime
  OL_DEVICE_TYPE_DEFAULT = 0,
  /// Devices of all types
  OL_DEVICE_TYPE_ALL = 1,
  /// GPU device type
  OL_DEVICE_TYPE_GPU = 2,
  /// CPU device type
  OL_DEVICE_TYPE_CPU = 3,
  /// Host device type
  OL_DEVICE_TYPE_HOST = 4,
  /// @cond
  OL_DEVICE_TYPE_LAST = 5,
  OL_DEVICE_TYPE_FORCE_UINT32 = 0x7fffffff
  /// @endcond

} ol_device_type_t;

///////////////////////////////////////////////////////////////////////////////
/// @brief Defines Return/Error codes
typedef enum ol_errc_t {
  /// success
  OL_ERRC_SUCCESS = 0,
  /// unknown or internal error
  OL_ERRC_UNKNOWN = 1,
  /// I/O error on host
  OL_ERRC_HOST_IO = 2,
  /// a provided binary image is malformed
  OL_ERRC_INVALID_BINARY = 3,
  /// a pointer argument is null when it should not be
  OL_ERRC_INVALID_NULL_POINTER = 4,
  /// an argument is invalid
  OL_ERRC_INVALID_ARGUMENT = 5,
  /// requested object was not found in the binary image
  OL_ERRC_NOT_FOUND = 6,
  /// out of resources
  OL_ERRC_OUT_OF_RESOURCES = 7,
  /// invalid size or dimensions (e.g., must not be zero, or is out of bounds)
  OL_ERRC_INVALID_SIZE = 8,
  /// enumerator argument is not valid
  OL_ERRC_INVALID_ENUMERATION = 9,
  /// a required binary (linker, etc.) was not found on the host
  OL_ERRC_HOST_TOOL_NOT_FOUND = 10,
  /// invalid value
  OL_ERRC_INVALID_VALUE = 11,
  /// generic error code for features currently unimplemented by the
  /// device/backend
  OL_ERRC_UNIMPLEMENTED = 12,
  /// generic error code for features unsupported by the device/backend
  OL_ERRC_UNSUPPORTED = 13,
  /// assembler failure while processing binary image
  OL_ERRC_ASSEMBLE_FAILURE = 14,
  /// jit compile failure while processing binary image
  OL_ERRC_COMPILE_FAILURE = 15,
  /// linker failure while processing binary image
  OL_ERRC_LINK_FAILURE = 16,
  /// the plugin backend is in an invalid or unsupported state
  OL_ERRC_BACKEND_FAILURE = 17,
  /// not initialized
  OL_ERRC_UNINITIALIZED = 18,
  /// a handle argument is null when it should not be
  OL_ERRC_INVALID_NULL_HANDLE = 19,
  /// invalid platform
  OL_ERRC_INVALID_PLATFORM = 20,
  /// invalid device
  OL_ERRC_INVALID_DEVICE = 21,
  /// invalid queue
  OL_ERRC_INVALID_QUEUE = 22,
  /// invalid event
  OL_ERRC_INVALID_EVENT = 23,
  /// the operation does not support this symbol kind
  OL_ERRC_SYMBOL_KIND = 24,
  /// @cond
  OL_ERRC_LAST = 25,
  OL_ERRC_FORCE_UINT32 = 0x7fffffff
  /// @endcond

} ol_errc_t;

///////////////////////////////////////////////////////////////////////////////
/// @brief Supported event info.
typedef enum ol_event_info_t {
  /// [ol_queue_handle_t] The handle of the queue associated with the device.
  OL_EVENT_INFO_QUEUE = 0,
  /// [bool] True if and only if the event is complete.
  OL_EVENT_INFO_IS_COMPLETE = 1,
  /// @cond
  OL_EVENT_INFO_LAST = 2,
  OL_EVENT_INFO_FORCE_UINT32 = 0x7fffffff
  /// @endcond

} ol_event_info_t;

///////////////////////////////////////////////////////////////////////////////
/// @brief Supported memory info.
typedef enum ol_mem_info_t {
  /// [ol_device_handle_t] The handle of the device associated with the
  /// allocation.
  OL_MEM_INFO_DEVICE = 0,
  /// [void *] Base address of this allocation.
  OL_MEM_INFO_BASE = 1,
  /// [size_t] Size of this allocation in bytes.
  OL_MEM_INFO_SIZE = 2,
  /// [ol_alloc_type_t] Type of this allocation.
  OL_MEM_INFO_TYPE = 3,
  /// @cond
  OL_MEM_INFO_LAST = 4,
  OL_MEM_INFO_FORCE_UINT32 = 0x7fffffff
  /// @endcond

} ol_mem_info_t;

///////////////////////////////////////////////////////////////////////////////
/// @brief Identifies the native backend of the platform.
typedef enum ol_platform_backend_t {
  /// The backend is not recognized
  OL_PLATFORM_BACKEND_UNKNOWN = 0,
  /// The backend is CUDA
  OL_PLATFORM_BACKEND_CUDA = 1,
  /// The backend is AMDGPU
  OL_PLATFORM_BACKEND_AMDGPU = 2,
  /// The backend is the host
  OL_PLATFORM_BACKEND_HOST = 3,
  /// @cond
  OL_PLATFORM_BACKEND_LAST = 4,
  OL_PLATFORM_BACKEND_FORCE_UINT32 = 0x7fffffff
  /// @endcond

} ol_platform_backend_t;

///////////////////////////////////////////////////////////////////////////////
/// @brief Supported platform info.
typedef enum ol_platform_info_t {
  /// [char[]] The string denoting name of the platform. The size of the info
  /// needs to be dynamically queried.
  OL_PLATFORM_INFO_NAME = 0,
  /// [char[]] The string denoting name of the vendor of the platform. The size
  /// of the info needs to be dynamically queried.
  OL_PLATFORM_INFO_VENDOR_NAME = 1,
  /// [char[]] The string denoting the version of the platform. The size of the
  /// info needs to be dynamically queried.
  OL_PLATFORM_INFO_VERSION = 2,
  /// [ol_platform_backend_t] The native backend of the platform.
  OL_PLATFORM_INFO_BACKEND = 3,
  /// @cond
  OL_PLATFORM_INFO_LAST = 4,
  OL_PLATFORM_INFO_FORCE_UINT32 = 0x7fffffff
  /// @endcond

} ol_platform_info_t;

///////////////////////////////////////////////////////////////////////////////
/// @brief Supported queue info.
typedef enum ol_queue_info_t {
  /// [ol_device_handle_t] The handle of the device associated with the queue.
  OL_QUEUE_INFO_DEVICE = 0,
  /// [bool] True if the queue is known to be empty. May be unconditionally
  /// false if the device does not support status queries.
  OL_QUEUE_INFO_EMPTY = 1,
  /// @cond
  OL_QUEUE_INFO_LAST = 2,
  OL_QUEUE_INFO_FORCE_UINT32 = 0x7fffffff
  /// @endcond

} ol_queue_info_t;

///////////////////////////////////////////////////////////////////////////////
/// @brief Supported symbol info.
typedef enum ol_symbol_info_t {
  /// [ol_symbol_kind_t] The kind of this symbol.
  OL_SYMBOL_INFO_KIND = 0,
  /// [void *] The address in memory for this global variable.
  OL_SYMBOL_INFO_GLOBAL_VARIABLE_ADDRESS = 1,
  /// [size_t] The size in bytes for this global variable.
  OL_SYMBOL_INFO_GLOBAL_VARIABLE_SIZE = 2,
  /// @cond
  OL_SYMBOL_INFO_LAST = 3,
  OL_SYMBOL_INFO_FORCE_UINT32 = 0x7fffffff
  /// @endcond

} ol_symbol_info_t;

///////////////////////////////////////////////////////////////////////////////
/// @brief The kind of a symbol
typedef enum ol_symbol_kind_t {
  /// a kernel object
  OL_SYMBOL_KIND_KERNEL = 0,
  /// a global variable
  OL_SYMBOL_KIND_GLOBAL_VARIABLE = 1,
  /// @cond
  OL_SYMBOL_KIND_LAST = 2,
  OL_SYMBOL_KIND_FORCE_UINT32 = 0x7fffffff
  /// @endcond

} ol_symbol_kind_t;

///////////////////////////////////////////////////////////////////////////////
/// @brief Device floating-point capability flags
typedef uint32_t ol_device_fp_capability_flags_t;

///////////////////////////////////////////////////////////////////////////////
/// @brief Result type returned by all entry points.
typedef const struct ol_error_struct_t *ol_result_t;

///////////////////////////////////////////////////////////////////////////////
/// @brief User-provided function to be used with `olIterateDevices`
typedef bool (*ol_device_iterate_cb_t)(
    // the device handle of the current iteration
    ol_device_handle_t Device,
    // optional user data
    void *UserData);

///////////////////////////////////////////////////////////////////////////////
/// @brief Host function for use by `olLaunchHostFunction`.
typedef void (*ol_host_function_cb_t)(
    // user specified data passed into `olLaunchHostFunction`.
    void *UserData);

///////////////////////////////////////////////////////////////////////////////
/// @brief Code location information that can optionally be associated with an
/// API call
typedef struct ol_code_location_t {
  const char *FunctionName; /// Function name
  const char *SourceFile;   /// Source code file
  uint32_t LineNumber;      /// Source code line number
  uint32_t ColumnNumber;    /// Source code column number
} ol_code_location_t;

///////////////////////////////////////////////////////////////////////////////
/// @brief A three element vector
typedef struct ol_dimensions_t {
  uint32_t x; /// X
  uint32_t y; /// Y
  uint32_t z; /// Z
} ol_dimensions_t;

///////////////////////////////////////////////////////////////////////////////
/// @brief Details of the error condition returned by an API call
typedef struct ol_error_struct_t {
  ol_errc_t Code;      /// The error code
  const char *Details; /// String containing error details
} ol_error_struct_t;

///////////////////////////////////////////////////////////////////////////////
/// @brief Size-related arguments for a kernel launch.
typedef struct ol_kernel_launch_size_args_t {
  size_t Dimensions;                /// Number of work dimensions
  struct ol_dimensions_t NumGroups; /// Number of work groups in each dimension
  struct ol_dimensions_t GroupSize; /// Size of a work group in each dimension
  size_t DynSharedMemory;           /// Size of dynamic shared memory in bytes.
} ol_kernel_launch_size_args_t;

///////////////////////////////////////////////////////////////////////////////
/// @brief Function parameters for olCalculateOptimalOccupancy
/// @details Each entry is a pointer to the parameter passed to the function;
typedef struct ol_calculate_optimal_occupancy_params_t {
  ol_device_handle_t *pDevice;
  ol_symbol_handle_t *pKernel;
  size_t *pSharedMemory;
  size_t **pGroupSize;
} ol_calculate_optimal_occupancy_params_t;

///////////////////////////////////////////////////////////////////////////////
/// @brief Given dynamic memory size, query the device for a workgroup size that
/// will result in optimal occupancy.
///
/// @details
///    - For most devices, this will be the largest workgroup size that will
///    result in all work items fitting on the device at once.
///
/// @returns
///     - ::OL_RESULT_SUCCESS
///     - ::OL_ERRC_UNINITIALIZED
///     - ::OL_ERRC_DEVICE_LOST
///     - ::OL_ERRC_SYMBOL_KIND
///         + The provided symbol is not a kernel
///     - ::OL_ERRC_UNSUPPORTED
///         + The backend cannot provide this information
///     - ::OL_ERRC_INVALID_NULL_HANDLE
///         + `NULL == Device`
///         + `NULL == Kernel`
///     - ::OL_ERRC_INVALID_NULL_POINTER
///         + `NULL == GroupSize`
OL_APIEXPORT ol_result_t OL_APICALL olCalculateOptimalOccupancy(
    // [in] device intended to run the kernel
    ol_device_handle_t Device,
    // [in] handle of the kernel
    ol_symbol_handle_t Kernel,
    // [in] dynamic shared memory required per work item in bytes
    size_t SharedMemory,
    // [out] optimal block size
    size_t *GroupSize);

///////////////////////////////////////////////////////////////////////////////
/// @brief Variant of olCalculateOptimalOccupancy that also sets source code
/// location information
/// @details See also ::olCalculateOptimalOccupancy
OL_APIEXPORT ol_result_t OL_APICALL olCalculateOptimalOccupancyWithCodeLoc(
    ol_device_handle_t Device, ol_symbol_handle_t Kernel, size_t SharedMemory,
    size_t *GroupSize, ol_code_location_t *CodeLocation);

///////////////////////////////////////////////////////////////////////////////
/// @brief Function parameters for olCreateEvent
/// @details Each entry is a pointer to the parameter passed to the function;
typedef struct ol_create_event_params_t {
  ol_queue_handle_t *pQueue;
  ol_event_handle_t **pEvent;
} ol_create_event_params_t;

///////////////////////////////////////////////////////////////////////////////
/// @brief Enqueue an event to `Queue` and return it.
///
/// @details
///    - This event can be used with `olSyncEvent` and `olWaitEvents` and will
///    be complete once all enqueued work prior to the `olCreateEvent` call is
///    complete.
///
/// @returns
///     - ::OL_RESULT_SUCCESS
///     - ::OL_ERRC_UNINITIALIZED
///     - ::OL_ERRC_DEVICE_LOST
///     - ::OL_ERRC_INVALID_NULL_HANDLE
///         + `NULL == Queue`
///     - ::OL_ERRC_INVALID_NULL_POINTER
///         + `NULL == Event`
OL_APIEXPORT ol_result_t OL_APICALL olCreateEvent(
    // [in] queue to create the event for
    ol_queue_handle_t Queue,
    // [out] output pointer for the created event
    ol_event_handle_t *Event);

///////////////////////////////////////////////////////////////////////////////
/// @brief Variant of olCreateEvent that also sets source code location
/// information
/// @details See also ::olCreateEvent
OL_APIEXPORT ol_result_t OL_APICALL
olCreateEventWithCodeLoc(ol_queue_handle_t Queue, ol_event_handle_t *Event,
                         ol_code_location_t *CodeLocation);

///////////////////////////////////////////////////////////////////////////////
/// @brief Function parameters for olCreateProgram
/// @details Each entry is a pointer to the parameter passed to the function;
typedef struct ol_create_program_params_t {
  ol_device_handle_t *pDevice;
  const void **pProgData;
  size_t *pProgDataSize;
  ol_program_handle_t **pProgram;
} ol_create_program_params_t;

///////////////////////////////////////////////////////////////////////////////
/// @brief Create a program for the device from the binary image pointed to by
/// `ProgData`.
///
/// @details
///    - The provided `ProgData` will be copied and need not outlive the
///    returned handle
///
/// @returns
///     - ::OL_RESULT_SUCCESS
///     - ::OL_ERRC_UNINITIALIZED
///     - ::OL_ERRC_DEVICE_LOST
///     - ::OL_ERRC_INVALID_NULL_HANDLE
///         + `NULL == Device`
///     - ::OL_ERRC_INVALID_NULL_POINTER
///         + `NULL == ProgData`
///         + `NULL == Program`
OL_APIEXPORT ol_result_t OL_APICALL olCreateProgram(
    // [in] handle of the device
    ol_device_handle_t Device,
    // [in] pointer to the program binary data
    const void *ProgData,
    // [in] size of the program binary in bytes
    size_t ProgDataSize,
    // [out] output pointer for the created program
    ol_program_handle_t *Program);

///////////////////////////////////////////////////////////////////////////////
/// @brief Variant of olCreateProgram that also sets source code location
/// information
/// @details See also ::olCreateProgram
OL_APIEXPORT ol_result_t OL_APICALL olCreateProgramWithCodeLoc(
    ol_device_handle_t Device, const void *ProgData, size_t ProgDataSize,
    ol_program_handle_t *Program, ol_code_location_t *CodeLocation);

///////////////////////////////////////////////////////////////////////////////
/// @brief Function parameters for olCreateQueue
/// @details Each entry is a pointer to the parameter passed to the function;
typedef struct ol_create_queue_params_t {
  ol_device_handle_t *pDevice;
  ol_queue_handle_t **pQueue;
} ol_create_queue_params_t;

///////////////////////////////////////////////////////////////////////////////
/// @brief Create a queue for the given device.
///
/// @details
///
/// @returns
///     - ::OL_RESULT_SUCCESS
///     - ::OL_ERRC_UNINITIALIZED
///     - ::OL_ERRC_DEVICE_LOST
///     - ::OL_ERRC_INVALID_NULL_HANDLE
///         + `NULL == Device`
///     - ::OL_ERRC_INVALID_NULL_POINTER
///         + `NULL == Queue`
OL_APIEXPORT ol_result_t OL_APICALL olCreateQueue(
    // [in] handle of the device
    ol_device_handle_t Device,
    // [out] output pointer for the created queue
    ol_queue_handle_t *Queue);

///////////////////////////////////////////////////////////////////////////////
/// @brief Variant of olCreateQueue that also sets source code location
/// information
/// @details See also ::olCreateQueue
OL_APIEXPORT ol_result_t OL_APICALL
olCreateQueueWithCodeLoc(ol_device_handle_t Device, ol_queue_handle_t *Queue,
                         ol_code_location_t *CodeLocation);

///////////////////////////////////////////////////////////////////////////////
/// @brief Function parameters for olDestroyEvent
/// @details Each entry is a pointer to the parameter passed to the function;
typedef struct ol_destroy_event_params_t {
  ol_event_handle_t *pEvent;
} ol_destroy_event_params_t;

///////////////////////////////////////////////////////////////////////////////
/// @brief Destroy the event and free all underlying resources.
///
/// @details
///
/// @returns
///     - ::OL_RESULT_SUCCESS
///     - ::OL_ERRC_UNINITIALIZED
///     - ::OL_ERRC_DEVICE_LOST
///     - ::OL_ERRC_INVALID_NULL_HANDLE
///         + `NULL == Event`
///     - ::OL_ERRC_INVALID_NULL_POINTER
OL_APIEXPORT ol_result_t OL_APICALL olDestroyEvent(
    // [in] handle of the event
    ol_event_handle_t Event);

///////////////////////////////////////////////////////////////////////////////
/// @brief Variant of olDestroyEvent that also sets source code location
/// information
/// @details See also ::olDestroyEvent
OL_APIEXPORT ol_result_t OL_APICALL olDestroyEventWithCodeLoc(
    ol_event_handle_t Event, ol_code_location_t *CodeLocation);

///////////////////////////////////////////////////////////////////////////////
/// @brief Function parameters for olDestroyProgram
/// @details Each entry is a pointer to the parameter passed to the function;
typedef struct ol_destroy_program_params_t {
  ol_program_handle_t *pProgram;
} ol_destroy_program_params_t;

///////////////////////////////////////////////////////////////////////////////
/// @brief Destroy the program and free all underlying resources.
///
/// @details
///
/// @returns
///     - ::OL_RESULT_SUCCESS
///     - ::OL_ERRC_UNINITIALIZED
///     - ::OL_ERRC_DEVICE_LOST
///     - ::OL_ERRC_INVALID_NULL_HANDLE
///         + `NULL == Program`
///     - ::OL_ERRC_INVALID_NULL_POINTER
OL_APIEXPORT ol_result_t OL_APICALL olDestroyProgram(
    // [in] handle of the program
    ol_program_handle_t Program);

///////////////////////////////////////////////////////////////////////////////
/// @brief Variant of olDestroyProgram that also sets source code location
/// information
/// @details See also ::olDestroyProgram
OL_APIEXPORT ol_result_t OL_APICALL olDestroyProgramWithCodeLoc(
    ol_program_handle_t Program, ol_code_location_t *CodeLocation);

///////////////////////////////////////////////////////////////////////////////
/// @brief Function parameters for olDestroyQueue
/// @details Each entry is a pointer to the parameter passed to the function;
typedef struct ol_destroy_queue_params_t {
  ol_queue_handle_t *pQueue;
} ol_destroy_queue_params_t;

///////////////////////////////////////////////////////////////////////////////
/// @brief Destroy the queue and free all underlying resources.
///
/// @details
///    - Any work previously enqueued to the queue is still performed and any
///    events generated for this queue remain valid.
///
/// @returns
///     - ::OL_RESULT_SUCCESS
///     - ::OL_ERRC_UNINITIALIZED
///     - ::OL_ERRC_DEVICE_LOST
///     - ::OL_ERRC_INVALID_NULL_HANDLE
///         + `NULL == Queue`
///     - ::OL_ERRC_INVALID_NULL_POINTER
OL_APIEXPORT ol_result_t OL_APICALL olDestroyQueue(
    // [in] handle of the queue
    ol_queue_handle_t Queue);

///////////////////////////////////////////////////////////////////////////////
/// @brief Variant of olDestroyQueue that also sets source code location
/// information
/// @details See also ::olDestroyQueue
OL_APIEXPORT ol_result_t OL_APICALL olDestroyQueueWithCodeLoc(
    ol_queue_handle_t Queue, ol_code_location_t *CodeLocation);

///////////////////////////////////////////////////////////////////////////////
/// @brief Function parameters for olGetDeviceInfo
/// @details Each entry is a pointer to the parameter passed to the function;
typedef struct ol_get_device_info_params_t {
  ol_device_handle_t *pDevice;
  ol_device_info_t *pPropName;
  size_t *pPropSize;
  void **pPropValue;
} ol_get_device_info_params_t;

///////////////////////////////////////////////////////////////////////////////
/// @brief Queries the given property of the device.
///
/// @details
///
/// @returns
///     - ::OL_RESULT_SUCCESS
///     - ::OL_ERRC_UNINITIALIZED
///     - ::OL_ERRC_DEVICE_LOST
///     - ::OL_ERRC_UNSUPPORTED_ENUMERATION
///         + If `PropName` is not supported by the device.
///     - ::OL_ERRC_INVALID_SIZE
///         + `PropSize == 0`
///         + If `PropSize` is less than the real number of bytes needed to
///         return the info.
///     - ::OL_ERRC_INVALID_DEVICE
///     - ::OL_ERRC_INVALID_NULL_HANDLE
///         + `NULL == Device`
///     - ::OL_ERRC_INVALID_NULL_POINTER
///         + `NULL == PropValue`
OL_APIEXPORT ol_result_t OL_APICALL olGetDeviceInfo(
    // [in] handle of the device instance
    ol_device_handle_t Device,
    // [in] type of the info to retrieve
    ol_device_info_t PropName,
    // [in] the number of bytes pointed to by PropValue.
    size_t PropSize,
    // [out] array of bytes holding the info. If PropSize is not equal to or
    // greater than the real number of bytes needed to return the info then the
    // OL_ERRC_INVALID_SIZE error is returned and PropValue is not used.
    void *PropValue);

///////////////////////////////////////////////////////////////////////////////
/// @brief Variant of olGetDeviceInfo that also sets source code location
/// information
/// @details See also ::olGetDeviceInfo
OL_APIEXPORT ol_result_t OL_APICALL olGetDeviceInfoWithCodeLoc(
    ol_device_handle_t Device, ol_device_info_t PropName, size_t PropSize,
    void *PropValue, ol_code_location_t *CodeLocation);

///////////////////////////////////////////////////////////////////////////////
/// @brief Function parameters for olGetDeviceInfoSize
/// @details Each entry is a pointer to the parameter passed to the function;
typedef struct ol_get_device_info_size_params_t {
  ol_device_handle_t *pDevice;
  ol_device_info_t *pPropName;
  size_t **pPropSizeRet;
} ol_get_device_info_size_params_t;

///////////////////////////////////////////////////////////////////////////////
/// @brief Returns the storage size of the given device query.
///
/// @details
///
/// @returns
///     - ::OL_RESULT_SUCCESS
///     - ::OL_ERRC_UNINITIALIZED
///     - ::OL_ERRC_DEVICE_LOST
///     - ::OL_ERRC_UNSUPPORTED_ENUMERATION
///         + If `PropName` is not supported by the device.
///     - ::OL_ERRC_INVALID_DEVICE
///     - ::OL_ERRC_INVALID_NULL_HANDLE
///         + `NULL == Device`
///     - ::OL_ERRC_INVALID_NULL_POINTER
///         + `NULL == PropSizeRet`
OL_APIEXPORT ol_result_t OL_APICALL olGetDeviceInfoSize(
    // [in] handle of the device instance
    ol_device_handle_t Device,
    // [in] type of the info to retrieve
    ol_device_info_t PropName,
    // [out] pointer to the number of bytes required to store the query
    size_t *PropSizeRet);

///////////////////////////////////////////////////////////////////////////////
/// @brief Variant of olGetDeviceInfoSize that also sets source code location
/// information
/// @details See also ::olGetDeviceInfoSize
OL_APIEXPORT ol_result_t OL_APICALL olGetDeviceInfoSizeWithCodeLoc(
    ol_device_handle_t Device, ol_device_info_t PropName, size_t *PropSizeRet,
    ol_code_location_t *CodeLocation);

///////////////////////////////////////////////////////////////////////////////
/// @brief Function parameters for olGetEventInfo
/// @details Each entry is a pointer to the parameter passed to the function;
typedef struct ol_get_event_info_params_t {
  ol_event_handle_t *pEvent;
  ol_event_info_t *pPropName;
  size_t *pPropSize;
  void **pPropValue;
} ol_get_event_info_params_t;

///////////////////////////////////////////////////////////////////////////////
/// @brief Queries the given property of the event.
///
/// @details
///    - `olGetEventInfoSize` can be used to query the storage size required for
///    the given query.
///
/// @returns
///     - ::OL_RESULT_SUCCESS
///     - ::OL_ERRC_UNINITIALIZED
///     - ::OL_ERRC_DEVICE_LOST
///     - ::OL_ERRC_INVALID_SIZE
///         + `PropSize == 0`
///         + If `PropSize` is less than the real number of bytes needed to
///         return the info.
///     - ::OL_ERRC_INVALID_EVENT
///     - ::OL_ERRC_INVALID_NULL_HANDLE
///         + `NULL == Event`
///     - ::OL_ERRC_INVALID_NULL_POINTER
///         + `NULL == PropValue`
OL_APIEXPORT ol_result_t OL_APICALL olGetEventInfo(
    // [in] handle of the event
    ol_event_handle_t Event,
    // [in] type of the info to retrieve
    ol_event_info_t PropName,
    // [in] the number of bytes pointed to by PropValue.
    size_t PropSize,
    // [out] array of bytes holding the info. If PropSize is not equal to or
    // greater to the real number of bytes needed to return the info then the
    // OL_ERRC_INVALID_SIZE error is returned and PropValue is not used.
    void *PropValue);

///////////////////////////////////////////////////////////////////////////////
/// @brief Variant of olGetEventInfo that also sets source code location
/// information
/// @details See also ::olGetEventInfo
OL_APIEXPORT ol_result_t OL_APICALL olGetEventInfoWithCodeLoc(
    ol_event_handle_t Event, ol_event_info_t PropName, size_t PropSize,
    void *PropValue, ol_code_location_t *CodeLocation);

///////////////////////////////////////////////////////////////////////////////
/// @brief Function parameters for olGetEventInfoSize
/// @details Each entry is a pointer to the parameter passed to the function;
typedef struct ol_get_event_info_size_params_t {
  ol_event_handle_t *pEvent;
  ol_event_info_t *pPropName;
  size_t **pPropSizeRet;
} ol_get_event_info_size_params_t;

///////////////////////////////////////////////////////////////////////////////
/// @brief Returns the storage size of the given event query.
///
/// @details
///
/// @returns
///     - ::OL_RESULT_SUCCESS
///     - ::OL_ERRC_UNINITIALIZED
///     - ::OL_ERRC_DEVICE_LOST
///     - ::OL_ERRC_INVALID_EVENT
///     - ::OL_ERRC_INVALID_NULL_HANDLE
///         + `NULL == Event`
///     - ::OL_ERRC_INVALID_NULL_POINTER
///         + `NULL == PropSizeRet`
OL_APIEXPORT ol_result_t OL_APICALL olGetEventInfoSize(
    // [in] handle of the event
    ol_event_handle_t Event,
    // [in] type of the info to query
    ol_event_info_t PropName,
    // [out] pointer to the number of bytes required to store the query
    size_t *PropSizeRet);

///////////////////////////////////////////////////////////////////////////////
/// @brief Variant of olGetEventInfoSize that also sets source code location
/// information
/// @details See also ::olGetEventInfoSize
OL_APIEXPORT ol_result_t OL_APICALL olGetEventInfoSizeWithCodeLoc(
    ol_event_handle_t Event, ol_event_info_t PropName, size_t *PropSizeRet,
    ol_code_location_t *CodeLocation);

///////////////////////////////////////////////////////////////////////////////
/// @brief Function parameters for olGetMemInfo
/// @details Each entry is a pointer to the parameter passed to the function;
typedef struct ol_get_mem_info_params_t {
  const void **pPtr;
  ol_mem_info_t *pPropName;
  size_t *pPropSize;
  void **pPropValue;
} ol_get_mem_info_params_t;

///////////////////////////////////////////////////////////////////////////////
/// @brief Queries the given property of a memory allocation allocated with
/// olMemAlloc.
///
/// @details
///    - `olGetMemInfoSize` can be used to query the storage size required for
///    the given query.
///    - The provided pointer can point to any location inside the allocation.
///
/// @returns
///     - ::OL_RESULT_SUCCESS
///     - ::OL_ERRC_UNINITIALIZED
///     - ::OL_ERRC_DEVICE_LOST
///     - ::OL_ERRC_INVALID_SIZE
///         + `PropSize == 0`
///         + If `PropSize` is less than the real number of bytes needed to
///         return the info.
///     - ::OL_ERRC_NOT_FOUND
///         + memory was not allocated by liboffload
///     - ::OL_ERRC_INVALID_NULL_HANDLE
///     - ::OL_ERRC_INVALID_NULL_POINTER
///         + `NULL == Ptr`
///         + `NULL == PropValue`
OL_APIEXPORT ol_result_t OL_APICALL olGetMemInfo(
    // [in] pointer to the allocated memory
    const void *Ptr,
    // [in] type of the info to retrieve
    ol_mem_info_t PropName,
    // [in] the number of bytes pointed to by PropValue.
    size_t PropSize,
    // [out] array of bytes holding the info. If Size is not equal to or greater
    // to the real number of bytes needed to return the info then the
    // OL_ERRC_INVALID_SIZE error is returned and pPlatformInfo is not used.
    void *PropValue);

///////////////////////////////////////////////////////////////////////////////
/// @brief Variant of olGetMemInfo that also sets source code location
/// information
/// @details See also ::olGetMemInfo
OL_APIEXPORT ol_result_t OL_APICALL olGetMemInfoWithCodeLoc(
    const void *Ptr, ol_mem_info_t PropName, size_t PropSize, void *PropValue,
    ol_code_location_t *CodeLocation);

///////////////////////////////////////////////////////////////////////////////
/// @brief Function parameters for olGetMemInfoSize
/// @details Each entry is a pointer to the parameter passed to the function;
typedef struct ol_get_mem_info_size_params_t {
  const void **pPtr;
  ol_mem_info_t *pPropName;
  size_t **pPropSizeRet;
} ol_get_mem_info_size_params_t;

///////////////////////////////////////////////////////////////////////////////
/// @brief Returns the storage size of the given queue query.
///
/// @details
///    - The provided pointer can point to any location inside the allocation.
///
/// @returns
///     - ::OL_RESULT_SUCCESS
///     - ::OL_ERRC_UNINITIALIZED
///     - ::OL_ERRC_DEVICE_LOST
///     - ::OL_ERRC_NOT_FOUND
///         + memory was not allocated by liboffload
///     - ::OL_ERRC_INVALID_NULL_HANDLE
///     - ::OL_ERRC_INVALID_NULL_POINTER
///         + `NULL == Ptr`
///         + `NULL == PropSizeRet`
OL_APIEXPORT ol_result_t OL_APICALL olGetMemInfoSize(
    // [in] pointer to the allocated memory
    const void *Ptr,
    // [in] type of the info to query
    ol_mem_info_t PropName,
    // [out] pointer to the number of bytes required to store the query
    size_t *PropSizeRet);

///////////////////////////////////////////////////////////////////////////////
/// @brief Variant of olGetMemInfoSize that also sets source code location
/// information
/// @details See also ::olGetMemInfoSize
OL_APIEXPORT ol_result_t OL_APICALL olGetMemInfoSizeWithCodeLoc(
    const void *Ptr, ol_mem_info_t PropName, size_t *PropSizeRet,
    ol_code_location_t *CodeLocation);

///////////////////////////////////////////////////////////////////////////////
/// @brief Function parameters for olGetPlatformInfo
/// @details Each entry is a pointer to the parameter passed to the function;
typedef struct ol_get_platform_info_params_t {
  ol_platform_handle_t *pPlatform;
  ol_platform_info_t *pPropName;
  size_t *pPropSize;
  void **pPropValue;
} ol_get_platform_info_params_t;

///////////////////////////////////////////////////////////////////////////////
/// @brief Queries the given property of the platform.
///
/// @details
///    - `olGetPlatformInfoSize` can be used to query the storage size required
///    for the given query.
///
/// @returns
///     - ::OL_RESULT_SUCCESS
///     - ::OL_ERRC_UNINITIALIZED
///     - ::OL_ERRC_DEVICE_LOST
///     - ::OL_ERRC_UNSUPPORTED_ENUMERATION
///         + If `PropName` is not supported by the platform.
///     - ::OL_ERRC_INVALID_SIZE
///         + `PropSize == 0`
///         + If `PropSize` is less than the real number of bytes needed to
///         return the info.
///     - ::OL_ERRC_INVALID_PLATFORM
///     - ::OL_ERRC_INVALID_NULL_HANDLE
///         + `NULL == Platform`
///     - ::OL_ERRC_INVALID_NULL_POINTER
///         + `NULL == PropValue`
OL_APIEXPORT ol_result_t OL_APICALL olGetPlatformInfo(
    // [in] handle of the platform
    ol_platform_handle_t Platform,
    // [in] type of the info to retrieve
    ol_platform_info_t PropName,
    // [in] the number of bytes pointed to by pPlatformInfo.
    size_t PropSize,
    // [out] array of bytes holding the info. If Size is not equal to or greater
    // to the real number of bytes needed to return the info then the
    // OL_ERRC_INVALID_SIZE error is returned and pPlatformInfo is not used.
    void *PropValue);

///////////////////////////////////////////////////////////////////////////////
/// @brief Variant of olGetPlatformInfo that also sets source code location
/// information
/// @details See also ::olGetPlatformInfo
OL_APIEXPORT ol_result_t OL_APICALL olGetPlatformInfoWithCodeLoc(
    ol_platform_handle_t Platform, ol_platform_info_t PropName, size_t PropSize,
    void *PropValue, ol_code_location_t *CodeLocation);

///////////////////////////////////////////////////////////////////////////////
/// @brief Function parameters for olGetPlatformInfoSize
/// @details Each entry is a pointer to the parameter passed to the function;
typedef struct ol_get_platform_info_size_params_t {
  ol_platform_handle_t *pPlatform;
  ol_platform_info_t *pPropName;
  size_t **pPropSizeRet;
} ol_get_platform_info_size_params_t;

///////////////////////////////////////////////////////////////////////////////
/// @brief Returns the storage size of the given platform query.
///
/// @details
///
/// @returns
///     - ::OL_RESULT_SUCCESS
///     - ::OL_ERRC_UNINITIALIZED
///     - ::OL_ERRC_DEVICE_LOST
///     - ::OL_ERRC_UNSUPPORTED_ENUMERATION
///         + If `PropName` is not supported by the platform.
///     - ::OL_ERRC_INVALID_PLATFORM
///     - ::OL_ERRC_INVALID_NULL_HANDLE
///         + `NULL == Platform`
///     - ::OL_ERRC_INVALID_NULL_POINTER
///         + `NULL == PropSizeRet`
OL_APIEXPORT ol_result_t OL_APICALL olGetPlatformInfoSize(
    // [in] handle of the platform
    ol_platform_handle_t Platform,
    // [in] type of the info to query
    ol_platform_info_t PropName,
    // [out] pointer to the number of bytes required to store the query
    size_t *PropSizeRet);

///////////////////////////////////////////////////////////////////////////////
/// @brief Variant of olGetPlatformInfoSize that also sets source code location
/// information
/// @details See also ::olGetPlatformInfoSize
OL_APIEXPORT ol_result_t OL_APICALL olGetPlatformInfoSizeWithCodeLoc(
    ol_platform_handle_t Platform, ol_platform_info_t PropName,
    size_t *PropSizeRet, ol_code_location_t *CodeLocation);

///////////////////////////////////////////////////////////////////////////////
/// @brief Function parameters for olGetQueueInfo
/// @details Each entry is a pointer to the parameter passed to the function;
typedef struct ol_get_queue_info_params_t {
  ol_queue_handle_t *pQueue;
  ol_queue_info_t *pPropName;
  size_t *pPropSize;
  void **pPropValue;
} ol_get_queue_info_params_t;

///////////////////////////////////////////////////////////////////////////////
/// @brief Queries the given property of the queue.
///
/// @details
///    - `olGetQueueInfoSize` can be used to query the storage size required for
///    the given query.
///
/// @returns
///     - ::OL_RESULT_SUCCESS
///     - ::OL_ERRC_UNINITIALIZED
///     - ::OL_ERRC_DEVICE_LOST
///     - ::OL_ERRC_INVALID_SIZE
///         + `PropSize == 0`
///         + If `PropSize` is less than the real number of bytes needed to
///         return the info.
///     - ::OL_ERRC_INVALID_QUEUE
///     - ::OL_ERRC_INVALID_NULL_HANDLE
///         + `NULL == Queue`
///     - ::OL_ERRC_INVALID_NULL_POINTER
///         + `NULL == PropValue`
OL_APIEXPORT ol_result_t OL_APICALL olGetQueueInfo(
    // [in] handle of the queue
    ol_queue_handle_t Queue,
    // [in] type of the info to retrieve
    ol_queue_info_t PropName,
    // [in] the number of bytes pointed to by PropValue.
    size_t PropSize,
    // [out] array of bytes holding the info. If Size is not equal to or greater
    // to the real number of bytes needed to return the info then the
    // OL_ERRC_INVALID_SIZE error is returned and pPlatformInfo is not used.
    void *PropValue);

///////////////////////////////////////////////////////////////////////////////
/// @brief Variant of olGetQueueInfo that also sets source code location
/// information
/// @details See also ::olGetQueueInfo
OL_APIEXPORT ol_result_t OL_APICALL olGetQueueInfoWithCodeLoc(
    ol_queue_handle_t Queue, ol_queue_info_t PropName, size_t PropSize,
    void *PropValue, ol_code_location_t *CodeLocation);

///////////////////////////////////////////////////////////////////////////////
/// @brief Function parameters for olGetQueueInfoSize
/// @details Each entry is a pointer to the parameter passed to the function;
typedef struct ol_get_queue_info_size_params_t {
  ol_queue_handle_t *pQueue;
  ol_queue_info_t *pPropName;
  size_t **pPropSizeRet;
} ol_get_queue_info_size_params_t;

///////////////////////////////////////////////////////////////////////////////
/// @brief Returns the storage size of the given queue query.
///
/// @details
///
/// @returns
///     - ::OL_RESULT_SUCCESS
///     - ::OL_ERRC_UNINITIALIZED
///     - ::OL_ERRC_DEVICE_LOST
///     - ::OL_ERRC_INVALID_QUEUE
///     - ::OL_ERRC_INVALID_NULL_HANDLE
///         + `NULL == Queue`
///     - ::OL_ERRC_INVALID_NULL_POINTER
///         + `NULL == PropSizeRet`
OL_APIEXPORT ol_result_t OL_APICALL olGetQueueInfoSize(
    // [in] handle of the queue
    ol_queue_handle_t Queue,
    // [in] type of the info to query
    ol_queue_info_t PropName,
    // [out] pointer to the number of bytes required to store the query
    size_t *PropSizeRet);

///////////////////////////////////////////////////////////////////////////////
/// @brief Variant of olGetQueueInfoSize that also sets source code location
/// information
/// @details See also ::olGetQueueInfoSize
OL_APIEXPORT ol_result_t OL_APICALL olGetQueueInfoSizeWithCodeLoc(
    ol_queue_handle_t Queue, ol_queue_info_t PropName, size_t *PropSizeRet,
    ol_code_location_t *CodeLocation);

///////////////////////////////////////////////////////////////////////////////
/// @brief Function parameters for olGetSymbol
/// @details Each entry is a pointer to the parameter passed to the function;
typedef struct ol_get_symbol_params_t {
  ol_program_handle_t *pProgram;
  const char **pName;
  ol_symbol_kind_t *pKind;
  ol_symbol_handle_t **pSymbol;
} ol_get_symbol_params_t;

///////////////////////////////////////////////////////////////////////////////
/// @brief Get a symbol (kernel or global variable) identified by `Name` in the
/// given program.
///
/// @details
///    - Symbol handles are owned by the program and do not need to be manually
///    destroyed.
///
/// @returns
///     - ::OL_RESULT_SUCCESS
///     - ::OL_ERRC_UNINITIALIZED
///     - ::OL_ERRC_DEVICE_LOST
///     - ::OL_ERRC_INVALID_NULL_HANDLE
///         + `NULL == Program`
///     - ::OL_ERRC_INVALID_NULL_POINTER
///         + `NULL == Name`
///         + `NULL == Symbol`
OL_APIEXPORT ol_result_t OL_APICALL olGetSymbol(
    // [in] handle of the program
    ol_program_handle_t Program,
    // [in] name of the symbol to look up
    const char *Name,
    // [in] symbol kind to look up
    ol_symbol_kind_t Kind,
    // [out] output pointer for the symbol
    ol_symbol_handle_t *Symbol);

///////////////////////////////////////////////////////////////////////////////
/// @brief Variant of olGetSymbol that also sets source code location
/// information
/// @details See also ::olGetSymbol
OL_APIEXPORT ol_result_t OL_APICALL olGetSymbolWithCodeLoc(
    ol_program_handle_t Program, const char *Name, ol_symbol_kind_t Kind,
    ol_symbol_handle_t *Symbol, ol_code_location_t *CodeLocation);

///////////////////////////////////////////////////////////////////////////////
/// @brief Function parameters for olGetSymbolInfo
/// @details Each entry is a pointer to the parameter passed to the function;
typedef struct ol_get_symbol_info_params_t {
  ol_symbol_handle_t *pSymbol;
  ol_symbol_info_t *pPropName;
  size_t *pPropSize;
  void **pPropValue;
} ol_get_symbol_info_params_t;

///////////////////////////////////////////////////////////////////////////////
/// @brief Queries the given property of the symbol.
///
/// @details
///    - `olGetSymbolInfoSize` can be used to query the storage size required
///    for the given query.
///
/// @returns
///     - ::OL_RESULT_SUCCESS
///     - ::OL_ERRC_UNINITIALIZED
///     - ::OL_ERRC_DEVICE_LOST
///     - ::OL_ERRC_INVALID_SIZE
///         + `PropSize == 0`
///         + If `PropSize` is less than the real number of bytes needed to
///         return the info.
///     - ::OL_ERRC_SYMBOL_KIND
///         + If the requested info isn't applicable to the type of symbol.
///     - ::OL_ERRC_INVALID_SYMBOL
///     - ::OL_ERRC_INVALID_NULL_HANDLE
///         + `NULL == Symbol`
///     - ::OL_ERRC_INVALID_NULL_POINTER
///         + `NULL == PropValue`
OL_APIEXPORT ol_result_t OL_APICALL olGetSymbolInfo(
    // [in] handle of the symbol
    ol_symbol_handle_t Symbol,
    // [in] type of the info to retrieve
    ol_symbol_info_t PropName,
    // [in] the number of bytes pointed to by PropValue.
    size_t PropSize,
    // [out] array of bytes holding the info. If PropSize is not equal to or
    // greater to the real number of bytes needed to return the info then the
    // OL_ERRC_INVALID_SIZE error is returned and PropValue is not used.
    void *PropValue);

///////////////////////////////////////////////////////////////////////////////
/// @brief Variant of olGetSymbolInfo that also sets source code location
/// information
/// @details See also ::olGetSymbolInfo
OL_APIEXPORT ol_result_t OL_APICALL olGetSymbolInfoWithCodeLoc(
    ol_symbol_handle_t Symbol, ol_symbol_info_t PropName, size_t PropSize,
    void *PropValue, ol_code_location_t *CodeLocation);

///////////////////////////////////////////////////////////////////////////////
/// @brief Function parameters for olGetSymbolInfoSize
/// @details Each entry is a pointer to the parameter passed to the function;
typedef struct ol_get_symbol_info_size_params_t {
  ol_symbol_handle_t *pSymbol;
  ol_symbol_info_t *pPropName;
  size_t **pPropSizeRet;
} ol_get_symbol_info_size_params_t;

///////////////////////////////////////////////////////////////////////////////
/// @brief Returns the storage size of the given symbol query.
///
/// @details
///
/// @returns
///     - ::OL_RESULT_SUCCESS
///     - ::OL_ERRC_UNINITIALIZED
///     - ::OL_ERRC_DEVICE_LOST
///     - ::OL_ERRC_INVALID_SYMBOL
///     - ::OL_ERRC_SYMBOL_KIND
///         + If the requested info isn't applicable to the type of symbol.
///     - ::OL_ERRC_INVALID_NULL_HANDLE
///         + `NULL == Symbol`
///     - ::OL_ERRC_INVALID_NULL_POINTER
///         + `NULL == PropSizeRet`
OL_APIEXPORT ol_result_t OL_APICALL olGetSymbolInfoSize(
    // [in] handle of the symbol
    ol_symbol_handle_t Symbol,
    // [in] type of the info to query
    ol_symbol_info_t PropName,
    // [out] pointer to the number of bytes required to store the query
    size_t *PropSizeRet);

///////////////////////////////////////////////////////////////////////////////
/// @brief Variant of olGetSymbolInfoSize that also sets source code location
/// information
/// @details See also ::olGetSymbolInfoSize
OL_APIEXPORT ol_result_t OL_APICALL olGetSymbolInfoSizeWithCodeLoc(
    ol_symbol_handle_t Symbol, ol_symbol_info_t PropName, size_t *PropSizeRet,
    ol_code_location_t *CodeLocation);

///////////////////////////////////////////////////////////////////////////////
/// @brief Perform initialization of the Offload library and plugins
///
/// @details
///    - This must be the first API call made by a user of the Offload library
///    - Each call will increment an internal reference count that is
///    decremented by `olShutDown`
///
/// @returns
///     - ::OL_RESULT_SUCCESS
///     - ::OL_ERRC_UNINITIALIZED
///     - ::OL_ERRC_DEVICE_LOST
///     - ::OL_ERRC_INVALID_NULL_HANDLE
///     - ::OL_ERRC_INVALID_NULL_POINTER
OL_APIEXPORT ol_result_t OL_APICALL olInit();

///////////////////////////////////////////////////////////////////////////////
/// @brief Variant of olInit that also sets source code location information
/// @details See also ::olInit
OL_APIEXPORT ol_result_t OL_APICALL
olInitWithCodeLoc(ol_code_location_t *CodeLocation);

///////////////////////////////////////////////////////////////////////////////
/// @brief Function parameters for olIsValidBinary
/// @details Each entry is a pointer to the parameter passed to the function;
typedef struct ol_is_valid_binary_params_t {
  ol_device_handle_t *pDevice;
  const void **pProgData;
  size_t *pProgDataSize;
  bool **pValid;
} ol_is_valid_binary_params_t;

///////////////////////////////////////////////////////////////////////////////
/// @brief Validate if the binary image pointed to by `ProgData` is compatible
/// with the device.
///
/// @details
///    - The provided `ProgData` will not be loaded onto the device
///
/// @returns
///     - ::OL_RESULT_SUCCESS
///     - ::OL_ERRC_UNINITIALIZED
///     - ::OL_ERRC_DEVICE_LOST
///     - ::OL_ERRC_INVALID_NULL_HANDLE
///         + `NULL == Device`
///     - ::OL_ERRC_INVALID_NULL_POINTER
///         + `NULL == ProgData`
///         + `NULL == Valid`
OL_APIEXPORT ol_result_t OL_APICALL olIsValidBinary(
    // [in] handle of the device
    ol_device_handle_t Device,
    // [in] pointer to the program binary data
    const void *ProgData,
    // [in] size of the program binary in bytes
    size_t ProgDataSize,
    // [out] output is true if the image is compatible
    bool *Valid);

///////////////////////////////////////////////////////////////////////////////
/// @brief Variant of olIsValidBinary that also sets source code location
/// information
/// @details See also ::olIsValidBinary
OL_APIEXPORT ol_result_t OL_APICALL olIsValidBinaryWithCodeLoc(
    ol_device_handle_t Device, const void *ProgData, size_t ProgDataSize,
    bool *Valid, ol_code_location_t *CodeLocation);

///////////////////////////////////////////////////////////////////////////////
/// @brief Function parameters for olIterateDevices
/// @details Each entry is a pointer to the parameter passed to the function;
typedef struct ol_iterate_devices_params_t {
  ol_device_iterate_cb_t *pCallback;
  void **pUserData;
} ol_iterate_devices_params_t;

///////////////////////////////////////////////////////////////////////////////
/// @brief Iterates over all available devices, calling the callback for each
/// device.
///
/// @details
///    - If the user-provided callback returns `false`, the iteration is
///    stopped.
///
/// @returns
///     - ::OL_RESULT_SUCCESS
///     - ::OL_ERRC_UNINITIALIZED
///     - ::OL_ERRC_DEVICE_LOST
///     - ::OL_ERRC_INVALID_DEVICE
///     - ::OL_ERRC_INVALID_NULL_HANDLE
///     - ::OL_ERRC_INVALID_NULL_POINTER
///         + `NULL == Callback`
OL_APIEXPORT ol_result_t OL_APICALL olIterateDevices(
    // [in] User-provided function called for each available device
    ol_device_iterate_cb_t Callback,
    // [in][optional] Optional user data to pass to the callback
    void *UserData);

///////////////////////////////////////////////////////////////////////////////
/// @brief Variant of olIterateDevices that also sets source code location
/// information
/// @details See also ::olIterateDevices
OL_APIEXPORT ol_result_t OL_APICALL
olIterateDevicesWithCodeLoc(ol_device_iterate_cb_t Callback, void *UserData,
                            ol_code_location_t *CodeLocation);

///////////////////////////////////////////////////////////////////////////////
/// @brief Function parameters for olLaunchHostFunction
/// @details Each entry is a pointer to the parameter passed to the function;
typedef struct ol_launch_host_function_params_t {
  ol_queue_handle_t *pQueue;
  ol_host_function_cb_t *pCallback;
  void **pUserData;
} ol_launch_host_function_params_t;

///////////////////////////////////////////////////////////////////////////////
/// @brief Enqueue a callback function on the host.
///
/// @details
///    - The provided function will be called from the same process as the one
///    that called `olLaunchHostFunction`.
///    - The callback will not run until all previous work submitted to the
///    queue has completed.
///    - The callback must return before any work submitted to the queue after
///    it is started.
///    - The callback must not call any liboffload API functions or any backend
///    specific functions (such as Cuda or HSA library functions).
///
/// @returns
///     - ::OL_RESULT_SUCCESS
///     - ::OL_ERRC_UNINITIALIZED
///     - ::OL_ERRC_DEVICE_LOST
///     - ::OL_ERRC_INVALID_NULL_HANDLE
///         + `NULL == Queue`
///     - ::OL_ERRC_INVALID_NULL_POINTER
///         + `NULL == Callback`
OL_APIEXPORT ol_result_t OL_APICALL olLaunchHostFunction(
    // [in] handle of the queue
    ol_queue_handle_t Queue,
    // [in] the callback function to call on the host
    ol_host_function_cb_t Callback,
    // [in][optional] a pointer that will be passed verbatim to the callback
    // function
    void *UserData);

///////////////////////////////////////////////////////////////////////////////
/// @brief Variant of olLaunchHostFunction that also sets source code location
/// information
/// @details See also ::olLaunchHostFunction
OL_APIEXPORT ol_result_t OL_APICALL olLaunchHostFunctionWithCodeLoc(
    ol_queue_handle_t Queue, ol_host_function_cb_t Callback, void *UserData,
    ol_code_location_t *CodeLocation);

///////////////////////////////////////////////////////////////////////////////
/// @brief Function parameters for olLaunchKernel
/// @details Each entry is a pointer to the parameter passed to the function;
typedef struct ol_launch_kernel_params_t {
  ol_queue_handle_t *pQueue;
  ol_device_handle_t *pDevice;
  ol_symbol_handle_t *pKernel;
  const void **pArgumentsData;
  size_t *pArgumentsSize;
  const ol_kernel_launch_size_args_t **pLaunchSizeArgs;
} ol_launch_kernel_params_t;

///////////////////////////////////////////////////////////////////////////////
/// @brief Enqueue a kernel launch with the specified size and parameters.
///
/// @details
///    - If a queue is not specified, kernel execution happens synchronously
///    - ArgumentsData may be set to NULL (to indicate no parameters)
///
/// @returns
///     - ::OL_RESULT_SUCCESS
///     - ::OL_ERRC_UNINITIALIZED
///     - ::OL_ERRC_DEVICE_LOST
///     - ::OL_ERRC_INVALID_ARGUMENT
///         + `ArgumentsSize > 0 && ArgumentsData == NULL`
///     - ::OL_ERRC_INVALID_DEVICE
///         + If Queue is non-null but does not belong to Device
///     - ::OL_ERRC_SYMBOL_KIND
///         + The provided symbol is not a kernel
///     - ::OL_ERRC_INVALID_NULL_HANDLE
///         + `NULL == Device`
///         + `NULL == Kernel`
///     - ::OL_ERRC_INVALID_NULL_POINTER
///         + `NULL == LaunchSizeArgs`
OL_APIEXPORT ol_result_t OL_APICALL olLaunchKernel(
    // [in][optional] handle of the queue
    ol_queue_handle_t Queue,
    // [in] handle of the device to execute on
    ol_device_handle_t Device,
    // [in] handle of the kernel
    ol_symbol_handle_t Kernel,
    // [in][optional] pointer to the kernel argument struct
    const void *ArgumentsData,
    // [in] size of the kernel argument struct
    size_t ArgumentsSize,
    // [in] pointer to the struct containing launch size parameters
    const ol_kernel_launch_size_args_t *LaunchSizeArgs);

///////////////////////////////////////////////////////////////////////////////
/// @brief Variant of olLaunchKernel that also sets source code location
/// information
/// @details See also ::olLaunchKernel
OL_APIEXPORT ol_result_t OL_APICALL olLaunchKernelWithCodeLoc(
    ol_queue_handle_t Queue, ol_device_handle_t Device,
    ol_symbol_handle_t Kernel, const void *ArgumentsData, size_t ArgumentsSize,
    const ol_kernel_launch_size_args_t *LaunchSizeArgs,
    ol_code_location_t *CodeLocation);

///////////////////////////////////////////////////////////////////////////////
/// @brief Function parameters for olMemAlloc
/// @details Each entry is a pointer to the parameter passed to the function;
typedef struct ol_mem_alloc_params_t {
  ol_device_handle_t *pDevice;
  ol_alloc_type_t *pType;
  size_t *pSize;
  void ***pAllocationOut;
} ol_mem_alloc_params_t;

///////////////////////////////////////////////////////////////////////////////
/// @brief Creates a memory allocation on the specified device.
///
/// @details
///    - All allocations through olMemAlloc regardless of source share a single
///    virtual address range. There is no risk of multiple devices returning
///    equal pointers to different memory.
///
/// @returns
///     - ::OL_RESULT_SUCCESS
///     - ::OL_ERRC_UNINITIALIZED
///     - ::OL_ERRC_DEVICE_LOST
///     - ::OL_ERRC_INVALID_SIZE
///         + `Size == 0`
///     - ::OL_ERRC_INVALID_NULL_HANDLE
///         + `NULL == Device`
///     - ::OL_ERRC_INVALID_NULL_POINTER
///         + `NULL == AllocationOut`
OL_APIEXPORT ol_result_t OL_APICALL olMemAlloc(
    // [in] handle of the device to allocate on
    ol_device_handle_t Device,
    // [in] type of the allocation
    ol_alloc_type_t Type,
    // [in] size of the allocation in bytes
    size_t Size,
    // [out] output for the allocated pointer
    void **AllocationOut);

///////////////////////////////////////////////////////////////////////////////
/// @brief Variant of olMemAlloc that also sets source code location information
/// @details See also ::olMemAlloc
OL_APIEXPORT ol_result_t OL_APICALL olMemAllocWithCodeLoc(
    ol_device_handle_t Device, ol_alloc_type_t Type, size_t Size,
    void **AllocationOut, ol_code_location_t *CodeLocation);

///////////////////////////////////////////////////////////////////////////////
/// @brief Function parameters for olMemFill
/// @details Each entry is a pointer to the parameter passed to the function;
typedef struct ol_mem_fill_params_t {
  ol_queue_handle_t *pQueue;
  void **pPtr;
  size_t *pPatternSize;
  const void **pPatternPtr;
  size_t *pFillSize;
} ol_mem_fill_params_t;

///////////////////////////////////////////////////////////////////////////////
/// @brief Fill memory with copies of the given pattern
///
/// @details
///    - Filling with patterns larger than 4 bytes may be less performant
///    - The destination pointer and queue must be associated with the same
///    device
///    - The fill size must be a multiple of the pattern size
///
/// @returns
///     - ::OL_RESULT_SUCCESS
///     - ::OL_ERRC_UNINITIALIZED
///     - ::OL_ERRC_DEVICE_LOST
///     - ::OL_ERRC_INVALID_SIZE
///         + `FillSize % PatternSize != 0`
///     - ::OL_ERRC_INVALID_NULL_HANDLE
///     - ::OL_ERRC_INVALID_NULL_POINTER
///         + `NULL == Ptr`
///         + `NULL == PatternPtr`
OL_APIEXPORT ol_result_t OL_APICALL olMemFill(
    // [in][optional] handle of the queue
    ol_queue_handle_t Queue,
    // [in] destination pointer to start filling at
    void *Ptr,
    // [in] the size of the pattern in bytes
    size_t PatternSize,
    // [in]
    const void *PatternPtr,
    // [in] number of bytes to fill
    size_t FillSize);

///////////////////////////////////////////////////////////////////////////////
/// @brief Variant of olMemFill that also sets source code location information
/// @details See also ::olMemFill
OL_APIEXPORT ol_result_t OL_APICALL olMemFillWithCodeLoc(
    ol_queue_handle_t Queue, void *Ptr, size_t PatternSize,
    const void *PatternPtr, size_t FillSize, ol_code_location_t *CodeLocation);

///////////////////////////////////////////////////////////////////////////////
/// @brief Function parameters for olMemFree
/// @details Each entry is a pointer to the parameter passed to the function;
typedef struct ol_mem_free_params_t {
  void **pAddress;
} ol_mem_free_params_t;

///////////////////////////////////////////////////////////////////////////////
/// @brief Frees a memory allocation previously made by olMemAlloc.
///
/// @details
///
/// @returns
///     - ::OL_RESULT_SUCCESS
///     - ::OL_ERRC_UNINITIALIZED
///     - ::OL_ERRC_DEVICE_LOST
///     - ::OL_ERRC_INVALID_NULL_HANDLE
///     - ::OL_ERRC_INVALID_NULL_POINTER
///         + `NULL == Address`
OL_APIEXPORT ol_result_t OL_APICALL olMemFree(
    // [in] address of the allocation to free
    void *Address);

///////////////////////////////////////////////////////////////////////////////
/// @brief Variant of olMemFree that also sets source code location information
/// @details See also ::olMemFree
OL_APIEXPORT ol_result_t OL_APICALL
olMemFreeWithCodeLoc(void *Address, ol_code_location_t *CodeLocation);

///////////////////////////////////////////////////////////////////////////////
/// @brief Function parameters for olMemcpy
/// @details Each entry is a pointer to the parameter passed to the function;
typedef struct ol_memcpy_params_t {
  ol_queue_handle_t *pQueue;
  void **pDstPtr;
  ol_device_handle_t *pDstDevice;
  const void **pSrcPtr;
  ol_device_handle_t *pSrcDevice;
  size_t *pSize;
} ol_memcpy_params_t;

///////////////////////////////////////////////////////////////////////////////
/// @brief Enqueue a memcpy operation.
///
/// @details
///    - For host pointers, use the host device belonging to the
///    OL_PLATFORM_BACKEND_HOST platform.
///    - If a queue is specified, at least one device must be a non-host device
///    - If a queue is not specified, the memcpy happens synchronously
///
/// @returns
///     - ::OL_RESULT_SUCCESS
///     - ::OL_ERRC_UNINITIALIZED
///     - ::OL_ERRC_DEVICE_LOST
///     - ::OL_ERRC_INVALID_NULL_HANDLE
///         + `NULL == DstDevice`
///         + `NULL == SrcDevice`
///     - ::OL_ERRC_INVALID_NULL_POINTER
///         + `NULL == DstPtr`
///         + `NULL == SrcPtr`
OL_APIEXPORT ol_result_t OL_APICALL olMemcpy(
    // [in][optional] handle of the queue.
    ol_queue_handle_t Queue,
    // [in] pointer to copy to
    void *DstPtr,
    // [in] device that DstPtr belongs to
    ol_device_handle_t DstDevice,
    // [in] pointer to copy from
    const void *SrcPtr,
    // [in] device that SrcPtr belongs to
    ol_device_handle_t SrcDevice,
    // [in] size in bytes of data to copy
    size_t Size);

///////////////////////////////////////////////////////////////////////////////
/// @brief Variant of olMemcpy that also sets source code location information
/// @details See also ::olMemcpy
OL_APIEXPORT ol_result_t OL_APICALL olMemcpyWithCodeLoc(
    ol_queue_handle_t Queue, void *DstPtr, ol_device_handle_t DstDevice,
    const void *SrcPtr, ol_device_handle_t SrcDevice, size_t Size,
    ol_code_location_t *CodeLocation);

///////////////////////////////////////////////////////////////////////////////
/// @brief Release the resources in use by Offload
///
/// @details
///    - This decrements an internal reference count. When this reaches 0, all
///    resources will be released
///    - Subsequent API calls to methods other than `olInit` made after
///    resources are released will return OL_ERRC_UNINITIALIZED
///
/// @returns
///     - ::OL_RESULT_SUCCESS
///     - ::OL_ERRC_UNINITIALIZED
///     - ::OL_ERRC_DEVICE_LOST
///     - ::OL_ERRC_INVALID_NULL_HANDLE
///     - ::OL_ERRC_INVALID_NULL_POINTER
OL_APIEXPORT ol_result_t OL_APICALL olShutDown();

///////////////////////////////////////////////////////////////////////////////
/// @brief Variant of olShutDown that also sets source code location information
/// @details See also ::olShutDown
OL_APIEXPORT ol_result_t OL_APICALL
olShutDownWithCodeLoc(ol_code_location_t *CodeLocation);

///////////////////////////////////////////////////////////////////////////////
/// @brief Function parameters for olSyncEvent
/// @details Each entry is a pointer to the parameter passed to the function;
typedef struct ol_sync_event_params_t {
  ol_event_handle_t *pEvent;
} ol_sync_event_params_t;

///////////////////////////////////////////////////////////////////////////////
/// @brief Block the calling thread until the event is complete.
///
/// @details
///
/// @returns
///     - ::OL_RESULT_SUCCESS
///     - ::OL_ERRC_UNINITIALIZED
///     - ::OL_ERRC_DEVICE_LOST
///     - ::OL_ERRC_INVALID_NULL_HANDLE
///         + `NULL == Event`
///     - ::OL_ERRC_INVALID_NULL_POINTER
OL_APIEXPORT ol_result_t OL_APICALL olSyncEvent(
    // [in] handle of the event
    ol_event_handle_t Event);

///////////////////////////////////////////////////////////////////////////////
/// @brief Variant of olSyncEvent that also sets source code location
/// information
/// @details See also ::olSyncEvent
OL_APIEXPORT ol_result_t OL_APICALL olSyncEventWithCodeLoc(
    ol_event_handle_t Event, ol_code_location_t *CodeLocation);

///////////////////////////////////////////////////////////////////////////////
/// @brief Function parameters for olSyncQueue
/// @details Each entry is a pointer to the parameter passed to the function;
typedef struct ol_sync_queue_params_t {
  ol_queue_handle_t *pQueue;
} ol_sync_queue_params_t;

///////////////////////////////////////////////////////////////////////////////
/// @brief Block the calling thread until the enqueued work on a queue is
/// complete.
///
/// @details
///
/// @returns
///     - ::OL_RESULT_SUCCESS
///     - ::OL_ERRC_UNINITIALIZED
///     - ::OL_ERRC_DEVICE_LOST
///     - ::OL_ERRC_INVALID_NULL_HANDLE
///         + `NULL == Queue`
///     - ::OL_ERRC_INVALID_NULL_POINTER
OL_APIEXPORT ol_result_t OL_APICALL olSyncQueue(
    // [in] handle of the queue
    ol_queue_handle_t Queue);

///////////////////////////////////////////////////////////////////////////////
/// @brief Variant of olSyncQueue that also sets source code location
/// information
/// @details See also ::olSyncQueue
OL_APIEXPORT ol_result_t OL_APICALL olSyncQueueWithCodeLoc(
    ol_queue_handle_t Queue, ol_code_location_t *CodeLocation);

///////////////////////////////////////////////////////////////////////////////
/// @brief Function parameters for olWaitEvents
/// @details Each entry is a pointer to the parameter passed to the function;
typedef struct ol_wait_events_params_t {
  ol_queue_handle_t *pQueue;
  ol_event_handle_t **pEvents;
  size_t *pNumEvents;
} ol_wait_events_params_t;

///////////////////////////////////////////////////////////////////////////////
/// @brief Make any future work submitted to this queue wait until the provided
/// events are complete.
///
/// @details
///    - All events in `Events` must complete before the queue is unblocked.
///    - The input events can be from any queue on any device provided by the
///    same platform as `Queue`.
///
/// @returns
///     - ::OL_RESULT_SUCCESS
///     - ::OL_ERRC_UNINITIALIZED
///     - ::OL_ERRC_DEVICE_LOST
///     - ::OL_ERRC_INVALID_NULL_HANDLE
///         + Any event handle in the list is NULL
///         + `NULL == Queue`
///     - ::OL_ERRC_INVALID_NULL_POINTER
///         + `NULL == Events`
OL_APIEXPORT ol_result_t OL_APICALL olWaitEvents(
    // [in] handle of the queue
    ol_queue_handle_t Queue,
    // [in] list of `NumEvents` events to wait for
    ol_event_handle_t *Events,
    // [in] size of `Events`
    size_t NumEvents);

///////////////////////////////////////////////////////////////////////////////
/// @brief Variant of olWaitEvents that also sets source code location
/// information
/// @details See also ::olWaitEvents
OL_APIEXPORT ol_result_t OL_APICALL
olWaitEventsWithCodeLoc(ol_queue_handle_t Queue, ol_event_handle_t *Events,
                        size_t NumEvents, ol_code_location_t *CodeLocation);

#if defined(__cplusplus)
} // extern "C"
#endif
