From eef1a3fc4f9e9eb105e9cdfb3393a7e78d382e64 Mon Sep 17 00:00:00 2001 From: Piotr Balcer Date: Tue, 6 Dec 2022 13:03:39 +0100 Subject: [PATCH] add UR loader, null adapter and basic example The components this patch implements are mostly derived from the ones implemented by level-zero. This patch otherwise makes only the minimal amount of changes required for loader: - adds new CI that builds the loader - updates cmake scripts to build and install the loader - adds generate and check-generated custom cmake targets - adds a tiny hello-world example to verify loader functionality Co-authored-by: Brandon Yates Co-authored-by: Lisanna Dettwyler Co-authored-by: Patryk Kaminski Co-authored-by: Krzysztof Swiecicki --- .github/workflows/cmake.yml | 36 + .github/workflows/pull_request.yaml | 37 - .gitignore | 4 + CHANGELOG.md | 4 + CMakeLists.txt | 33 +- LICENSE | 2 +- README.md | 29 +- SECURITY.md | 11 + examples/CMakeLists.txt | 3 + examples/hello_world/CMakeLists.txt | 22 + examples/hello_world/hello_world.cpp | 94 + scripts/generate_code.py | 144 + scripts/json2src.py | 58 + scripts/run.py | 6 +- scripts/templates/api.py.mako | 2 +- scripts/templates/helper.py | 110 +- scripts/templates/ldrddi.cpp.mako | 292 + scripts/templates/ldrddi.h.mako | 38 + scripts/templates/libapi.cpp.mako | 79 + scripts/templates/libddi.cpp.mako | 43 + scripts/templates/nullddi.cpp.mako | 119 + source/CMakeLists.txt | 16 +- source/common/ur_singleton.h | 79 + source/common/ur_util.h | 114 + source/drivers/CMakeLists.txt | 1 + source/drivers/null/CMakeLists.txt | 25 + source/drivers/null/ur_null.cpp | 87 + source/drivers/null/ur_null.h | 40 + source/drivers/null/ur_nullddi.cpp | 3630 ++++++++++++ source/loader/CMakeLists.txt | 90 + source/loader/UrLoaderVersion.rc.in | 33 + source/loader/libur_loader.pc.in | 14 + source/loader/linux/lib_init.cpp | 22 + source/loader/linux/loader_init.cpp | 22 + .../loader/linux/platform_discovery_lin.cpp | 43 + source/loader/platform_discovery.h | 23 + source/loader/ur_ldrddi.cpp | 5008 +++++++++++++++++ source/loader/ur_ldrddi.h | 51 + source/loader/ur_lib.cpp | 42 + source/loader/ur_lib.h | 46 + source/loader/ur_libapi.cpp | 3963 +++++++++++++ source/loader/ur_libddi.cpp | 92 + source/loader/ur_loader.cpp | 57 + source/loader/ur_loader.h | 54 + source/loader/ur_object.h | 44 + source/loader/windows/lib_init.cpp | 26 + source/loader/windows/loader_init.cpp | 14 + .../loader/windows/platform_discovery_win.cpp | 28 + test/CMakeLists.txt | 5 + test/python/CMakeLists.txt | 14 + test/python/basic.py | 20 + third_party/requirements.txt | 3 +- 52 files changed, 14808 insertions(+), 64 deletions(-) create mode 100644 .github/workflows/cmake.yml delete mode 100644 .github/workflows/pull_request.yaml create mode 100644 CHANGELOG.md create mode 100644 SECURITY.md create mode 100644 examples/CMakeLists.txt create mode 100644 examples/hello_world/CMakeLists.txt create mode 100644 examples/hello_world/hello_world.cpp create mode 100755 scripts/json2src.py mode change 100644 => 100755 scripts/run.py create mode 100644 scripts/templates/ldrddi.cpp.mako create mode 100644 scripts/templates/ldrddi.h.mako create mode 100644 scripts/templates/libapi.cpp.mako create mode 100644 scripts/templates/libddi.cpp.mako create mode 100644 scripts/templates/nullddi.cpp.mako create mode 100644 source/common/ur_singleton.h create mode 100644 source/common/ur_util.h create mode 100644 source/drivers/CMakeLists.txt create mode 100644 source/drivers/null/CMakeLists.txt create mode 100644 source/drivers/null/ur_null.cpp create mode 100644 source/drivers/null/ur_null.h create mode 100644 source/drivers/null/ur_nullddi.cpp create mode 100644 source/loader/CMakeLists.txt create mode 100644 source/loader/UrLoaderVersion.rc.in create mode 100644 source/loader/libur_loader.pc.in create mode 100644 source/loader/linux/lib_init.cpp create mode 100644 source/loader/linux/loader_init.cpp create mode 100644 source/loader/linux/platform_discovery_lin.cpp create mode 100644 source/loader/platform_discovery.h create mode 100644 source/loader/ur_ldrddi.cpp create mode 100644 source/loader/ur_ldrddi.h create mode 100644 source/loader/ur_lib.cpp create mode 100644 source/loader/ur_lib.h create mode 100644 source/loader/ur_libapi.cpp create mode 100644 source/loader/ur_libddi.cpp create mode 100644 source/loader/ur_loader.cpp create mode 100644 source/loader/ur_loader.h create mode 100644 source/loader/ur_object.h create mode 100644 source/loader/windows/lib_init.cpp create mode 100644 source/loader/windows/loader_init.cpp create mode 100644 source/loader/windows/platform_discovery_win.cpp create mode 100644 test/CMakeLists.txt create mode 100644 test/python/CMakeLists.txt create mode 100755 test/python/basic.py diff --git a/.github/workflows/cmake.yml b/.github/workflows/cmake.yml new file mode 100644 index 0000000000..6ca8b85c97 --- /dev/null +++ b/.github/workflows/cmake.yml @@ -0,0 +1,36 @@ +name: CMake + +on: + push: + branches: [ "main" ] + pull_request: + branches: [ "main" ] + +env: + BUILD_TYPE: Release + +jobs: + build: + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v3 + + - name: Install apt package + run: sudo apt-get install -y doxygen + + - name: Install pip packages + run: pip install -r third_party/requirements.txt + + - name: Configure CMake + run: cmake -B ${{github.workspace}}/build -DCMAKE_BUILD_TYPE=${{env.BUILD_TYPE}} + + - name: Generate source from spec, check for uncommitted diff + run: cmake --build ${{github.workspace}}/build --target check-generated + + - name: Build + run: cmake --build ${{github.workspace}}/build + + - name: Test + working-directory: ${{github.workspace}}/build + run: ctest -C ${{env.BUILD_TYPE}} --output-on-failure diff --git a/.github/workflows/pull_request.yaml b/.github/workflows/pull_request.yaml deleted file mode 100644 index da187f66ee..0000000000 --- a/.github/workflows/pull_request.yaml +++ /dev/null @@ -1,37 +0,0 @@ ---- -name: Build spec and check for changes - -on: - pull_request: - branches: - - main - -jobs: - generate: - runs-on: ubuntu-20.04 - - steps: - - uses: actions/checkout@v3 - - - name: Install apt package - run: sudo apt-get install -y doxygen - - - name: Install pip packages - run: pip install -r third_party/requirements.txt - - - name: Generate specification, check for uncommitted diff, check python module. - run: | - cd scripts - python run.py --core - if [ $(git diff | wc -l) != 0 ]; then - git diff - exit 1 - fi - cd ../include - error_file=$(mktemp) - python -c "import ur" >& $error_file - if [ $? != 0 ]; then - echo "Importing the generated ur.py module failed with the following:" - cat $error_file - exit 1 - fi diff --git a/.gitignore b/.gitignore index 0a8a572b55..a1a488bc14 100644 --- a/.gitignore +++ b/.gitignore @@ -53,6 +53,10 @@ # Debug files scripts/**/*.json +# Python cache +__pycache__/ +*.py[cod] + # Generated docs docs/ diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 0000000000..73ac29eb0a --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,4 @@ +# Unified Runtime changelog + +## v.X.X.X +* Placeholder for first release diff --git a/CMakeLists.txt b/CMakeLists.txt index dca9043f83..a36f53f75e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,13 +1,19 @@ -cmake_minimum_required(VERSION 3.2.0 FATAL_ERROR) +cmake_minimum_required(VERSION 3.8.0 FATAL_ERROR) project(unified-runtime VERSION 0.5.0) include(GNUInstallDirs) include(CMakePackageConfigHelpers) +include(CTest) + +find_package(Python3 COMPONENTS Interpreter) set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin) set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin) set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib) +# define rpath for libraries so that adapters can be found automatically +set(CMAKE_BUILD_RPATH "${CMAKE_LIBRARY_OUTPUT_DIRECTORY}") + #Define a path for custom commands to work around MSVC set(CUSTOM_COMMAND_BINARY_DIR ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}) if(MSVC) @@ -70,6 +76,8 @@ install( EXPORT ${PROJECT_NAME}-targets) add_subdirectory(source) +add_subdirectory(examples) +add_subdirectory(test) # Add the list of installed targets to the install. This includes the namespace # which all installed targets will be prefixed with, e.g. for the headers @@ -90,9 +98,32 @@ configure_package_config_file( ${PROJECT_SOURCE_DIR}/cmake/${PROJECT_NAME}-config.cmake.in ${PROJECT_BINARY_DIR}/cmake/${PROJECT_NAME}-config.cmake INSTALL_DESTINATION lib/cmake/${PROJECT_NAME}) + # Add the package files to the install. install( FILES ${PROJECT_BINARY_DIR}/cmake/${PROJECT_NAME}-config.cmake ${PROJECT_BINARY_DIR}/cmake/${PROJECT_NAME}-config-version.cmake DESTINATION lib/cmake/${PROJECT_NAME}) + +set(API_JSON_FILE ${PROJECT_BINARY_DIR}/unified_runtime.json) + +# generate source from the specification +add_custom_command ( + WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}/scripts + DEPENDS ${CMAKE_SOURCE_DIR}/scripts/* + OUTPUT ${API_JSON_FILE} + COMMAND ${Python3_EXECUTABLE} run.py --api-json ${API_JSON_FILE} + COMMAND ${Python3_EXECUTABLE} json2src.py --api-json ${API_JSON_FILE} ${CMAKE_SOURCE_DIR} +) + +add_custom_target(generate ALL + DEPENDS ${API_JSON_FILE} +) + +# generate source and check for uncommitted diffs +add_custom_target(check-generated + WORKING_DIRECTORY ${CMAKE_SOURCE_DIR} + COMMAND git diff --exit-code + DEPENDS generate +) diff --git a/LICENSE b/LICENSE index d550e3c531..d6db7e7bc1 100644 --- a/LICENSE +++ b/LICENSE @@ -1,6 +1,6 @@ MIT License -Copyright (c) 2019 Intel Corporation +Copyright (C) 2022 Intel Corporation Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/README.md b/README.md index 302e769637..700ca8a1ff 100644 --- a/README.md +++ b/README.md @@ -1,11 +1,15 @@ # Unified Runtime +[![GHA build status](https://github.com/oneapi-src/unified-runtime/actions/workflows/cmake.yml/badge.svg?branch=main)](https://github.com/oneapi-src/unified-runtime/actions) + ## Contents This repo contains the following: - API specification in YaML - API programming guide in RST +- Loader and a null adapter implementation (partially generated) +- Example applications - API C/C++ header files (generated) - API Python module (generated) - Sample C++ wrapper (generated) @@ -33,7 +37,7 @@ target_link_libraries(example PUBLIC unified-runtime::headers) ## Source Code Generation -Code is generated using included [Python scripts](/scripts/README.md). +Code is generated using included [Python scripts](/scripts/README.md). ## Documentation @@ -48,12 +52,13 @@ Tools can be acquired via instructions in [third_party](/third_party/README.md). Project is defined using [CMake](https://cmake.org/). **Windows**: + Generating Visual Studio Project. EXE and binaries will be in **build/bin/{build_config}** ~~~~ -mkdir build -cd build -cmake {path_to_source_dir} -G "Visual Studio 15 2017 Win64" +$ mkdir build +$ cd build +$ cmake {path_to_source_dir} -G "Visual Studio 15 2017 Win64" ~~~~ **Linux**: @@ -61,9 +66,17 @@ cmake {path_to_source_dir} -G "Visual Studio 15 2017 Win64" Executable and binaries will be in **build/bin** ~~~~ -mkdir build -cd build -cmake {path_to_source_dir} -make +$ mkdir build +$ cd build +$ cmake {path_to_source_dir} +$ make +~~~~ + +**General**: + +If you've made modifications to the specification, you can also run a custom `generate` target prior to building. +~~~~ +$ make generate ~~~~ +This call will automatically generate the source code. diff --git a/SECURITY.md b/SECURITY.md new file mode 100644 index 0000000000..11f869114d --- /dev/null +++ b/SECURITY.md @@ -0,0 +1,11 @@ +# Security Policy + +## Report a Vulnerability + +Please report security issues or vulnerabilities to the [Intel Security Center]. + +For more information on how Intel works to resolve security issues, see [Vulnerability Handling Guidelines]. + +[Intel Security Center]:https://www.intel.com/security + +[Vulnerability Handling Guidelines]:https://www.intel.com/content/www/us/en/security-center/vulnerability-handling-guidelines.html diff --git a/examples/CMakeLists.txt b/examples/CMakeLists.txt new file mode 100644 index 0000000000..e35d6f31de --- /dev/null +++ b/examples/CMakeLists.txt @@ -0,0 +1,3 @@ +include_directories(${CMAKE_CURRENT_SOURCE_DIR}/include) + +add_subdirectory(hello_world) diff --git a/examples/hello_world/CMakeLists.txt b/examples/hello_world/CMakeLists.txt new file mode 100644 index 0000000000..c8aad872a0 --- /dev/null +++ b/examples/hello_world/CMakeLists.txt @@ -0,0 +1,22 @@ +set(TARGET_NAME hello_world) + +add_executable(${TARGET_NAME} + ${CMAKE_CURRENT_SOURCE_DIR}/hello_world.cpp +) + +target_include_directories(${TARGET_NAME} PRIVATE + ${CMAKE_SOURCE_DIR}/include +) + +if(MSVC) + set_target_properties(${TARGET_NAME} + PROPERTIES + VS_DEBUGGER_COMMAND_ARGUMENTS "" + VS_DEBUGGER_WORKING_DIRECTORY "$(OutDir)" + ) +endif() + +target_link_libraries(${TARGET_NAME} + ${PROJECT_NAME}::loader + ${CMAKE_DL_LIBS} +) diff --git a/examples/hello_world/hello_world.cpp b/examples/hello_world/hello_world.cpp new file mode 100644 index 0000000000..4e3deca7e8 --- /dev/null +++ b/examples/hello_world/hello_world.cpp @@ -0,0 +1,94 @@ +/* + * + * Copyright (C) 2020-2021 Intel Corporation + * + * SPDX-License-Identifier: MIT + * + */ +#include +#include +#include +#include + +#include "ur_api.h" + +////////////////////////////////////////////////////////////////////////// +int main(int argc, char *argv[]) +{ + ur_result_t status; + + ur_platform_handle_t platform = nullptr; + ur_device_handle_t pDevice = nullptr; + + // Initialize the platform + status = urInit(0, 0); + if (status != UR_RESULT_SUCCESS) + { + std::cout << "urInit failed with return code: " << status << std::endl; + return 1; + } + std::cout << "Platform initialized.\n"; + + uint32_t platformCount = 0; + std::vector platforms; + + status = urPlatformGet(1, nullptr, &platformCount); + if (status != UR_RESULT_SUCCESS) + { + std::cout << "urPlatformGet failed with return code: " << status << std::endl; + goto out; + } + + platforms.resize(platformCount); + status = urPlatformGet(platformCount, platforms.data(), nullptr); + if (status != UR_RESULT_SUCCESS) + { + std::cout << "urPlatformGet failed with return code: " << status << std::endl; + goto out; + } + + for (auto p : platforms) + { + uint32_t deviceCount = 0; + status = urDeviceGet(p, UR_DEVICE_TYPE_GPU, 0, nullptr, &deviceCount); + if (status != UR_RESULT_SUCCESS) + { + std::cout << "urDeviceGet failed with return code: " << status << std::endl; + goto out; + } + + std::vector devices(deviceCount); + status = urDeviceGet(p, UR_DEVICE_TYPE_GPU, deviceCount, devices.data(), nullptr); + if (status != UR_RESULT_SUCCESS) + { + std::cout << "urDeviceGet failed with return code: " << status << std::endl; + goto out; + } + for (auto d : devices) + { + ur_device_type_t device_type; + status = urDeviceGetInfo(d, UR_DEVICE_INFO_TYPE, sizeof(ur_device_type_t), static_cast(&device_type), nullptr); + if (status != UR_RESULT_SUCCESS) + { + std::cout << "urDeviceGet failed with return code: " << status << std::endl; + goto out; + } + static const size_t DEVICE_NAME_MAX_LEN = 1024; + char device_name[DEVICE_NAME_MAX_LEN] = {0}; + status = urDeviceGetInfo(d, UR_DEVICE_INFO_NAME, DEVICE_NAME_MAX_LEN - 1, static_cast(&device_name), nullptr); + if (status != UR_RESULT_SUCCESS) + { + std::cout << "urDeviceGet failed with return code: " << status << std::endl; + goto out; + } + if (device_type == UR_DEVICE_TYPE_GPU) + { + std::cout << "Found a " << device_name << " gpu.\n"; + } + } + } + +out: + urTearDown(nullptr); + return status == UR_RESULT_SUCCESS ? 0 : 1; +} diff --git a/scripts/generate_code.py b/scripts/generate_code.py index 8600bfbc42..b283f0f6e0 100644 --- a/scripts/generate_code.py +++ b/scripts/generate_code.py @@ -117,3 +117,147 @@ def generate_api(incpath, srcpath, namespace, tags, version, revision, specs, me loc += _generate_api_cpp(incpath, srcpath, namespace, tags, version, revision, specs, meta) loc += _generate_api_py(incpath, namespace, tags, version, revision, specs, meta) print("Generated %s lines of code.\n"%loc) + +loader_templates_dir = os.path.join(os.path.dirname(os.path.realpath(__file__)), "templates") + +""" + generates c/c++ files from the specification documents +""" +def _mako_lib_cpp(path, namespace, tags, version, specs, meta): + loc = 0 + template = "libapi.cpp.mako" + fin = os.path.join(loader_templates_dir, template) + + name = "%s_libapi"%(namespace) + filename = "%s.cpp"%(name) + fout = os.path.join(path, filename) + + print("Generating %s..."%fout) + loc += util.makoWrite( + fin, fout, + name = name, + ver=version, + namespace=namespace, + tags=tags, + specs=specs, + meta = meta) + + template = "libddi.cpp.mako" + fin = os.path.join(loader_templates_dir, template) + + name = "%s_libddi"%(namespace) + filename = "%s.cpp"%(name) + fout = os.path.join(path, filename) + + print("Generating %s..."%fout) + loc += util.makoWrite( + fin, fout, + name=name, + ver=version, + namespace=namespace, + tags=tags, + specs=specs, + meta=meta) + return loc + +""" + generates c/c++ files from the specification documents +""" +def _mako_loader_cpp(path, namespace, tags, version, specs, meta): + print("make_loader_cpp path %s namespace %s version %s\n" %(path, namespace, version)) + loc = 0 + template = "ldrddi.h.mako" + fin = os.path.join(loader_templates_dir, template) + + name = "%s_ldrddi"%(namespace) + filename = "%s.h"%(name) + fout = os.path.join(path, filename) + + print("Generating %s..."%fout) + loc += util.makoWrite( + fin, fout, + name=name, + ver=version, + namespace=namespace, + tags=tags, + specs=specs, + meta=meta) + + template = "ldrddi.cpp.mako" + fin = os.path.join(loader_templates_dir, template) + + name = "%s_ldrddi"%(namespace) + filename = "%s.cpp"%(name) + fout = os.path.join(path, filename) + + print("Generating %s..."%fout) + loc += util.makoWrite( + fin, fout, + name=name, + ver=version, + namespace=namespace, + tags=tags, + specs=specs, + meta=meta) + return loc + +""" + generates c/c++ files from the specification documents +""" +def _mako_null_driver_cpp(path, namespace, tags, version, specs, meta): + dstpath = os.path.join(path, "null") + os.makedirs(dstpath, exist_ok=True) + + template = "nullddi.cpp.mako" + fin = os.path.join(loader_templates_dir, template) + + name = "%s_nullddi"%(namespace) + filename = "%s.cpp"%(name) + fout = os.path.join(dstpath, filename) + + print("Generating %s..."%fout) + return util.makoWrite( + fin, fout, + name=name, + ver=version, + namespace=namespace, + tags=tags, + specs=specs, + meta=meta) + +""" +Entry-point: + generates lib code +""" +def generate_lib(path, section, namespace, tags, version, specs, meta): + dstpath = os.path.join(path, "loader") # lib code lives alongside the loader + os.makedirs(dstpath, exist_ok=True) + + loc = 0 + loc += _mako_lib_cpp(dstpath, namespace, tags, version, specs, meta) + print("Generated %s lines of code.\n"%loc) + +""" +Entry-point: + generates loader for unified_runtime driver +""" +def generate_loader(path, section, namespace, tags, version, specs, meta): + dstpath = os.path.join(path, "loader") + os.makedirs(dstpath, exist_ok=True) + + loc = 0 + loc += _mako_loader_cpp(dstpath, namespace, tags, version, specs, meta) + print("Generated %s lines of code.\n"%loc) + +""" +Entry-point: + generates drivers for unified_runtime driver +""" +def generate_drivers(path, section, namespace, tags, version, specs, meta): + dstpath = os.path.join(path, "drivers") + os.makedirs(dstpath, exist_ok=True) + + loc = 0 + loc += _mako_null_driver_cpp(dstpath, namespace, tags, version, specs, meta) + print("Generated %s lines of code.\n"%loc) + diff --git a/scripts/json2src.py b/scripts/json2src.py new file mode 100755 index 0000000000..ebddcfd90d --- /dev/null +++ b/scripts/json2src.py @@ -0,0 +1,58 @@ +#! /usr/bin/env python3 +""" + Copyright (C) 2019-2021 Intel Corporation + + SPDX-License-Identifier: MIT + +""" +import argparse +import util +import generate_code +import os, sys +import time +import json + +""" + helper for adding mutually-exclusive boolean arguments "--name" and "--skip-name" +""" +def add_argument(parser, name, help, default=False): + group = parser.add_mutually_exclusive_group(required=False) + group.add_argument("--" + name, dest=name, help="Enable "+help, action="store_true") + group.add_argument("--skip-" + name, dest=name, help="Skip "+help, action="store_false") + parser.set_defaults(**{name:default}) + +if __name__ == '__main__': + parser = argparse.ArgumentParser() + add_argument(parser, "lib", "generation of lib files.", True) + add_argument(parser, "loader", "generation of loader files.", True) + add_argument(parser, "layers", "generation of layer files.", False) + add_argument(parser, "drivers", "generation of null driver files.", True) + parser.add_argument("--debug", action='store_true', help="dump intermediate data to disk.") + parser.add_argument("--sections", type=list, default=None, help="Optional list of sections for which to generate source, default is all") + parser.add_argument("--ver", type=str, default="1.0", help="specification version to generate.") + parser.add_argument('--api-json', nargs='?', type=argparse.FileType('r'), default=sys.stdin, help="JSON file containing the API specification, by default read from stdin") + parser.add_argument("out_dir", type=str, help="Root of the loader repository.") + args = parser.parse_args() + + input = json.loads(args.api_json.read()) + + start = time.time() + + srcpath = os.path.join(args.out_dir, "source") + + for idx, specs in enumerate(input['specs']): + config = input['configs'][idx] + if args.sections == None or config['name'] in args.sections: + if args.lib: + generate_code.generate_lib(srcpath, config['name'], config['namespace'], config['tags'], args.ver, specs, input['meta']) + if args.loader: + generate_code.generate_loader(srcpath, config['name'], config['namespace'], config['tags'], args.ver, specs, input['meta']) + #if args.layers: + # generate_code.generate_layers(srcpath, config['name'], config['namespace'], config['tags'], args.ver, specs, input['meta']) + if args.drivers: + generate_code.generate_drivers(srcpath, config['name'], config['namespace'], config['tags'], args.ver, specs, input['meta']) + + if args.debug: + util.makoFileListWrite("generated.json") + + print("\nCompleted in %.1f seconds!"%(time.time() - start)) diff --git a/scripts/run.py b/scripts/run.py old mode 100644 new mode 100755 index f09fd17eec..99fa61aa5c --- a/scripts/run.py +++ b/scripts/run.py @@ -99,6 +99,7 @@ def main(): add_argument(parser, "rst", "generation of reStructuredText files.", True) parser.add_argument("--update_spec", type=str, help="root of integrated spec directory to update") parser.add_argument("--ver", type=str, default="0.5", required=False, help="specification version to generate.") + parser.add_argument("--api-json", type=str, default="unified_runtime.json", required=False, help="json output file for the spec") args = vars(parser.parse_args()) args['rev'] = revision() @@ -124,10 +125,7 @@ def main(): specs, input['meta'], input['ref'] = parse_specs.parse(config['name'], args['ver'], config['tags'], input['meta'], input['ref']) input['specs'].append(specs) - if args['debug']: - util.jsonWrite("input.json", input) - - util.jsonWrite("level_zero.json", input['ref']) + util.jsonWrite(args['api_json'], input) # phase 3: generate files if args['clean']: diff --git a/scripts/templates/api.py.mako b/scripts/templates/api.py.mako index 5175c6d05f..477a290f0d 100644 --- a/scripts/templates/api.py.mako +++ b/scripts/templates/api.py.mako @@ -170,7 +170,7 @@ class ${N}_DDI: self.__dditable = ${n}_dditable_t() # initialize the UR - self.__dll.urInit(0, 0) + self.__dll.${x}Init(0, 0) %for tbl in tables: # call driver to get function pointers diff --git a/scripts/templates/helper.py b/scripts/templates/helper.py index 79087854a3..3c9fce3fbb 100644 --- a/scripts/templates/helper.py +++ b/scripts/templates/helper.py @@ -287,6 +287,7 @@ def find_enum_name(cls, name, meta): Extracts traits from a parameter object """ class param_traits: + RE_MBZ = r".*\[mbz\].*" RE_IN = r"^\[in\].*" RE_OUT = r"^\[out\].*" RE_INOUT = r"^\[in,out\].*" @@ -294,6 +295,13 @@ class param_traits: RE_RANGE = r".*\[range\((.+),\s*(.+)\)\][\S\s]*" RE_RELEASE = r".*\[release\].*" + @classmethod + def is_mbz(cls, item): + try: + return True if re.match(cls.RE_MBZ, item['desc']) else False + except: + return False + @classmethod def is_input(cls, item): try: @@ -942,7 +950,8 @@ def get_pfntables(specs, meta, namespace, tags): 'type': table, 'export': export, 'pfn': pfn, - 'functions': objs + 'functions': objs, + 'experimental': False }) if len(exp_objs) > 0: name = get_table_name(namespace, tags, exp_objs[0]) @@ -971,12 +980,29 @@ def get_pfntables(specs, meta, namespace, tags): 'type': table, 'export': export, 'pfn': pfn, - 'functions': exp_objs + 'functions': exp_objs, + 'experimental': True }) return tables +""" +Private: + returns the list of parameters, filtering based on desc tags +""" +def _filter_param_list(params, filters1=["[in]", "[in,out]", "[out]"], filters2=[""]): + lst = [] + for p in params: + for f1 in filters1: + if f1 in p['desc']: + for f2 in filters2: + if f2 in p['desc']: + lst.append(p) + break + break + return lst + """ Public: returns a list of dict of each pfntables needed @@ -996,4 +1022,84 @@ def get_pfncbtables(specs, meta, namespace, tags): }) return tables +""" +Public: + returns a list of dict for converting loader input parameters +""" +def get_loader_prologue(namespace, tags, obj, meta): + prologue = [] + + params = _filter_param_list(obj['params'], ["[in]"]) + for item in params: + if param_traits.is_mbz(item): + continue + if type_traits.is_class_handle(item['type'], meta): + name = subt(namespace, tags, item['name']) + tname = _remove_const_ptr(subt(namespace, tags, item['type'])) + + # e.g., "xe_device_handle_t" -> "xe_device_object_t" + obj_name = re.sub(r"(\w+)_handle_t", r"\1_object_t", tname) + fty_name = re.sub(r"(\w+)_handle_t", r"\1_factory", tname) + + if type_traits.is_pointer(item['type']): + range_start = param_traits.range_start(item) + range_end = param_traits.range_end(item) + prologue.append({ + 'name': name, + 'obj': obj_name, + 'range': (range_start, range_end), + 'type': tname, + 'factory': fty_name, + 'pointer' : "*" + }) + else: + prologue.append({ + 'name': name, + 'obj': obj_name, + 'optional': param_traits.is_optional(item), + 'pointer' : "" + }) + + return prologue + +""" +Public: + returns a list of dict for converting loader output parameters +""" +def get_loader_epilogue(namespace, tags, obj, meta): + epilogue = [] + + for i, item in enumerate(obj['params']): + if param_traits.is_mbz(item): + continue + if param_traits.is_release(item) or param_traits.is_output(item) or param_traits.is_inoutput(item): + if type_traits.is_class_handle(item['type'], meta): + name = subt(namespace, tags, item['name']) + tname = _remove_const_ptr(subt(namespace, tags, item['type'])) + + obj_name = re.sub(r"(\w+)_handle_t", r"\1_object_t", tname) + fty_name = re.sub(r"(\w+)_handle_t", r"\1_factory", tname) + + if param_traits.is_range(item): + range_start = param_traits.range_start(item) + range_end = param_traits.range_end(item) + epilogue.append({ + 'name': name, + 'type': tname, + 'obj': obj_name, + 'factory': fty_name, + 'release': param_traits.is_release(item), + 'range': (range_start, range_end) + }) + else: + epilogue.append({ + 'name': name, + 'type': tname, + 'obj': obj_name, + 'factory': fty_name, + 'release': param_traits.is_release(item), + 'optional': param_traits.is_optional(item) + }) + + return epilogue diff --git a/scripts/templates/ldrddi.cpp.mako b/scripts/templates/ldrddi.cpp.mako new file mode 100644 index 0000000000..00f0373768 --- /dev/null +++ b/scripts/templates/ldrddi.cpp.mako @@ -0,0 +1,292 @@ +<%! +import re +from templates import helper as th +%><% + n=namespace + N=n.upper() + + x=tags['$x'] + X=x.upper() +%>/* + * + * Copyright (C) 2022 Intel Corporation + * + * SPDX-License-Identifier: MIT + * + * @file ${name}.cpp + * + */ +#include "${x}_loader.h" + +namespace loader +{ + /////////////////////////////////////////////////////////////////////////////// + %for obj in th.extract_objs(specs, r"handle"): + %if 'class' in obj: + <% + _handle_t = th.subt(n, tags, obj['name']) + _factory_t = re.sub(r"(\w+)_handle_t", r"\1_factory_t", _handle_t) + _factory = re.sub(r"(\w+)_handle_t", r"\1_factory", _handle_t) + %>${th.append_ws(_factory_t, 35)} ${_factory}; + %endif + %endfor + + %for obj in th.extract_objs(specs, r"function"): + /////////////////////////////////////////////////////////////////////////////// + /// @brief Intercept function for ${th.make_func_name(n, tags, obj)} + %if 'condition' in obj: + #if ${th.subt(n, tags, obj['condition'])} + %endif + __${x}dlllocal ${x}_result_t ${X}_APICALL + ${th.make_func_name(n, tags, obj)}( + %for line in th.make_param_lines(n, tags, obj): + ${line} + %endfor + ) + { + ${x}_result_t result = ${X}_RESULT_SUCCESS;<% + add_local = False + arrays_to_delete = [] + %> + + %if re.match(r"Init", obj['name']): + bool atLeastOneplatformValid = false; + for( auto& platform : context->platforms ) + { + if(platform.initStatus != ${X}_RESULT_SUCCESS) + continue; + platform.initStatus = platform.dditable.${n}.${th.get_table_name(n, tags, obj)}.${th.make_pfn_name(n, tags, obj)}( ${", ".join(th.make_param_lines(n, tags, obj, format=["name"]))} ); + if(platform.initStatus == ${X}_RESULT_SUCCESS) + atLeastOneplatformValid = true; + } + + if(!atLeastOneplatformValid) + result=${X}_RESULT_ERROR_UNINITIALIZED; + + %elif re.match(r"\w+TearDown$", th.make_func_name(n, tags, obj)): + + for( auto& platform : context->platforms ) + { + platform.dditable.${n}.${th.get_table_name(n, tags, obj)}.${th.make_pfn_name(n, tags, obj)}( ${", ".join(th.make_param_lines(n, tags, obj, format=["name"]))} ); + } + + %elif re.match(r"\w+PlatformGet$", th.make_func_name(n, tags, obj)): + uint32_t total_platform_handle_count = 0; + + for( auto& platform : context->platforms ) + { + if(platform.initStatus != ${X}_RESULT_SUCCESS) + continue; + + if( ( 0 < ${obj['params'][0]['name']} ) && ( ${obj['params'][0]['name']} == total_platform_handle_count)) + break; + + uint32_t library_platform_handle_count = 0; + + result = platform.dditable.${n}.${th.get_table_name(n, tags, obj)}.${th.make_pfn_name(n, tags, obj)}( 0, nullptr, &library_platform_handle_count ); + if( ${X}_RESULT_SUCCESS != result ) break; + + if( nullptr != ${obj['params'][1]['name']} && ${obj['params'][0]['name']} !=0) + { + if( total_platform_handle_count + library_platform_handle_count > ${obj['params'][0]['name']}) { + library_platform_handle_count = ${obj['params'][0]['name']} - total_platform_handle_count; + } + result = platform.dditable.${n}.${th.get_table_name(n, tags, obj)}.${th.make_pfn_name(n, tags, obj)}( library_platform_handle_count, &${obj['params'][1]['name']}[ total_platform_handle_count ], nullptr ); + if( ${X}_RESULT_SUCCESS != result ) break; + + try + { + for( uint32_t i = 0; i < library_platform_handle_count; ++i ) { + uint32_t platform_index = total_platform_handle_count + i; + ${obj['params'][1]['name']}[ platform_index ] = reinterpret_cast<${n}_platform_handle_t>( + ${n}_platform_factory.getInstance( ${obj['params'][1]['name']}[ platform_index ], &platform.dditable ) ); + } + } + catch( std::bad_alloc& ) + { + result = ${X}_RESULT_ERROR_OUT_OF_HOST_MEMORY; + } + } + + total_platform_handle_count += library_platform_handle_count; + } + + if( ${X}_RESULT_SUCCESS == result && ${obj['params'][2]['name']} != nullptr ) + *${obj['params'][2]['name']} = total_platform_handle_count; + + %else: + %for i, item in enumerate(th.get_loader_prologue(n, tags, obj, meta)): + %if 0 == i: + // extract platform's function pointer table + auto dditable = reinterpret_cast<${item['obj']}*>( ${item['pointer']}${item['name']} )->dditable; + auto ${th.make_pfn_name(n, tags, obj)} = dditable->${n}.${th.get_table_name(n, tags, obj)}.${th.make_pfn_name(n, tags, obj)}; + if( nullptr == ${th.make_pfn_name(n, tags, obj)} ) + return ${X}_RESULT_ERROR_UNINITIALIZED; + + %endif + %if 'range' in item: + <% + add_local = True%>// convert loader handles to platform handles + auto ${item['name']}Local = new ${item['type']} [${item['range'][1]}]; + <% + arrays_to_delete.append(item['name']+ 'Local') + %>for( size_t i = ${item['range'][0]}; ( nullptr != ${item['name']} ) && ( i < ${item['range'][1]} ); ++i ) + ${item['name']}Local[ i ] = reinterpret_cast<${item['obj']}*>( ${item['name']}[ i ] )->handle; + %else: + // convert loader handle to platform handle + %if item['optional']: + ${item['name']} = ( ${item['name']} ) ? reinterpret_cast<${item['obj']}*>( ${item['name']} )->handle : nullptr; + %else: + ${item['name']} = reinterpret_cast<${item['obj']}*>( ${item['name']} )->handle; + %endif + %endif + + %endfor + // forward to device-platform + %if add_local: + result = ${th.make_pfn_name(n, tags, obj)}( ${", ".join(th.make_param_lines(n, tags, obj, format=["name", "local"]))} ); + %for array_name in arrays_to_delete: + delete []${array_name}; + %endfor + %else: + result = ${th.make_pfn_name(n, tags, obj)}( ${", ".join(th.make_param_lines(n, tags, obj, format=["name"]))} ); + %endif +<% + del arrays_to_delete + del add_local%> + %for i, item in enumerate(th.get_loader_epilogue(n, tags, obj, meta)): + %if 0 == i: + if( ${X}_RESULT_SUCCESS != result ) + return result; + + %endif + %if item['release']: + // release loader handle + ${item['factory']}.release( ${item['name']} ); + %else: + try + { + %if 'range' in item: + // convert platform handles to loader handles + for( size_t i = ${item['range'][0]}; ( nullptr != ${item['name']} ) && ( i < ${item['range'][1]} ); ++i ) + ${item['name']}[ i ] = reinterpret_cast<${item['type']}>( + ${item['factory']}.getInstance( ${item['name']}[ i ], dditable ) ); + %else: + // convert platform handle to loader handle + %if item['optional']: + if( nullptr != ${item['name']} ) + *${item['name']} = reinterpret_cast<${item['type']}>( + ${item['factory']}.getInstance( *${item['name']}, dditable ) ); + %else: + *${item['name']} = reinterpret_cast<${item['type']}>( + ${item['factory']}.getInstance( *${item['name']}, dditable ) ); + %endif + %endif + } + catch( std::bad_alloc& ) + { + result = ${X}_RESULT_ERROR_OUT_OF_HOST_MEMORY; + } + %endif + + %endfor + %endif + return result; + } + %if 'condition' in obj: + #endif // ${th.subt(n, tags, obj['condition'])} + %endif + + %endfor +} // namespace loader + +#if defined(__cplusplus) +extern "C" { +#endif + +%for tbl in th.get_pfntables(specs, meta, n, tags): +/////////////////////////////////////////////////////////////////////////////// +/// @brief Exported function for filling application's ${tbl['name']} table +/// with current process' addresses +/// +/// @returns +/// - ::${X}_RESULT_SUCCESS +/// - ::${X}_RESULT_ERROR_UNINITIALIZED +/// - ::${X}_RESULT_ERROR_INVALID_NULL_POINTER +/// - ::${X}_RESULT_ERROR_UNSUPPORTED_VERSION +${X}_DLLEXPORT ${x}_result_t ${X}_APICALL +${tbl['export']['name']}( + %for line in th.make_param_lines(n, tags, tbl['export']): + ${line} + %endfor + ) +{ + if( loader::context->platforms.size() < 1 ) + return ${X}_RESULT_ERROR_UNINITIALIZED; + + if( nullptr == pDdiTable ) + return ${X}_RESULT_ERROR_INVALID_NULL_POINTER; + + if( loader::context->version < version ) + return ${X}_RESULT_ERROR_UNSUPPORTED_VERSION; + + ${x}_result_t result = ${X}_RESULT_SUCCESS; + + bool atLeastOneplatformValid = false; + // Load the device-platform DDI tables + for( auto& platform : loader::context->platforms ) + { + if(platform.initStatus != ${X}_RESULT_SUCCESS) + continue; + auto getTable = reinterpret_cast<${tbl['pfn']}>( + GET_FUNCTION_PTR( platform.handle, "${tbl['export']['name']}") ); + if(!getTable) + continue; + auto getTableResult = getTable( version, &platform.dditable.${n}.${tbl['name']}); + if(getTableResult == ${X}_RESULT_SUCCESS) + atLeastOneplatformValid = true; + %if tbl['experimental'] is False: + else + platform.initStatus = getTableResult; + %endif + } + + %if tbl['experimental'] is False: #//Experimental Tables may not be implemented in platform + if(!atLeastOneplatformValid) + result = ${X}_RESULT_ERROR_UNINITIALIZED; + else + result = ${X}_RESULT_SUCCESS; + %endif + + if( ${X}_RESULT_SUCCESS == result ) + { + if( ( loader::context->platforms.size() > 1 ) || loader::context->forceIntercept ) + { + // return pointers to loader's DDIs + %for obj in tbl['functions']: + %if 'condition' in obj: + #if ${th.subt(n, tags, obj['condition'])} + %endif + pDdiTable->${th.append_ws(th.make_pfn_name(n, tags, obj), 43)} = loader::${th.make_func_name(n, tags, obj)}; + %if 'condition' in obj: + #else + pDdiTable->${th.append_ws(th.make_pfn_name(n, tags, obj), 43)} = nullptr; + #endif + %endif + %endfor + } + else + { + // return pointers directly to platform's DDIs + *pDdiTable = loader::context->platforms.front().dditable.${n}.${tbl['name']}; + } + } + + return result; +} + +%endfor + +#if defined(__cplusplus) +}; +#endif diff --git a/scripts/templates/ldrddi.h.mako b/scripts/templates/ldrddi.h.mako new file mode 100644 index 0000000000..09156bc3ce --- /dev/null +++ b/scripts/templates/ldrddi.h.mako @@ -0,0 +1,38 @@ +<%! +import re +from templates import helper as th +%><% + n=namespace + N=n.upper() + + x=tags['$x'] + X=x.upper() +%>/* + * + * Copyright (C) 2022 Intel Corporation + * + * SPDX-License-Identifier: MIT + * + * @file ${name}.h + * + */ +#ifndef UR_LOADER_LDRDDI_H +#define UR_LOADER_LDRDDI_H 1 + +namespace loader +{ + /////////////////////////////////////////////////////////////////////////////// + %for obj in th.extract_objs(specs, r"handle"): + %if 'class' in obj: + <% + _handle_t = th.subt(n, tags, obj['name']) + _object_t = re.sub(r"(\w+)_handle_t", r"\1_object_t", _handle_t) + _factory_t = re.sub(r"(\w+)_handle_t", r"\1_factory_t", _handle_t) + %>using ${th.append_ws(_object_t, 35)} = object_t < ${_handle_t} >; + using ${th.append_ws(_factory_t, 35)} = singleton_factory_t < ${_object_t}, ${_handle_t} >; + + %endif + %endfor +} + +#endif /* UR_LOADER_LDRDDI_H */ diff --git a/scripts/templates/libapi.cpp.mako b/scripts/templates/libapi.cpp.mako new file mode 100644 index 0000000000..299f0c8852 --- /dev/null +++ b/scripts/templates/libapi.cpp.mako @@ -0,0 +1,79 @@ +<%! +import re +from templates import helper as th + +def define_dbg(obj, tags): + if re.match("class", obj['type']): + return True + if 'class' not in obj or obj['class'] in tags: + return re.match("enum", obj['type']) or re.match("struct|union", obj['type']) + return False + +%><% + n=namespace + N=n.upper() + + x=tags['$x'] + X=x.upper() +%>/* + * + * Copyright (C) 2022 Intel Corporation + * + * SPDX-License-Identifier: MIT + * + * @file ${name}.cpp + * + * @brief C++ library for ${n} + * + */ +#include "${x}_lib.h" + +extern "C" { + +%for s in specs: +## FUNCTION ################################################################### +%for obj in th.filter_items(s['objects'], 'type', 'function'): +/////////////////////////////////////////////////////////////////////////////// +%if 'condition' in obj: +#if ${th.subt(n, tags, obj['condition'])} +%endif +%for line in th.make_desc_lines(n, tags, obj): +/// ${line} +%endfor +%for line in th.make_details_lines(n, tags, obj): +/// ${line} +%endfor +/// +%for line in th.make_returns_lines(n, tags, obj, meta=meta): +/// ${line} +%endfor +${x}_result_t ${X}_APICALL +${th.make_func_name(n, tags, obj)}( + %for line in th.make_param_lines(n, tags, obj): + ${line} + %endfor + ) +{ +%if re.match("Init", obj['name']): + static ${x}_result_t result = ${X}_RESULT_SUCCESS; + std::call_once(${x}_lib::context->initOnce, [platform_flags, device_flags]() { + result = ${x}_lib::context->Init(platform_flags, device_flags); + }); + + if( ${X}_RESULT_SUCCESS != result ) + return result; + +%endif + auto ${th.make_pfn_name(n, tags, obj)} = ${x}_lib::context->${n}DdiTable.${th.get_table_name(n, tags, obj)}.${th.make_pfn_name(n, tags, obj)}; + if( nullptr == ${th.make_pfn_name(n, tags, obj)} ) + return ${X}_RESULT_ERROR_UNINITIALIZED; + + return ${th.make_pfn_name(n, tags, obj)}( ${", ".join(th.make_param_lines(n, tags, obj, format=["name"]))} ); +} +%if 'condition' in obj: +#endif // ${th.subt(n, tags, obj['condition'])} +%endif + +%endfor +%endfor +} // extern "C" diff --git a/scripts/templates/libddi.cpp.mako b/scripts/templates/libddi.cpp.mako new file mode 100644 index 0000000000..6bf13f6f9f --- /dev/null +++ b/scripts/templates/libddi.cpp.mako @@ -0,0 +1,43 @@ +<%! +import re +from templates import helper as th +%><% + n=namespace + N=n.upper() + + x=tags['$x'] + X=x.upper() +%>/* + * + * Copyright (C) 2022 Intel Corporation + * + * SPDX-License-Identifier: MIT + * + * @file ${name}.cpp + * + */ +#include "${x}_lib.h" +#ifndef DYNAMIC_LOAD_LOADER +#include "${n}_ddi.h" +#endif + +namespace ${x}_lib +{ + /////////////////////////////////////////////////////////////////////////////// + + + __${x}dlllocal ${x}_result_t context_t::${n}Init() + { + ${x}_result_t result = ${X}_RESULT_SUCCESS; + + %for tbl in th.get_pfntables(specs, meta, n, tags): + if( ${X}_RESULT_SUCCESS == result ) + { + result = ${tbl['export']['name']}( ${X}_API_VERSION_0_9, &${n}DdiTable.${tbl['name']} ); + } + + %endfor + return result; + } + +} // namespace ${x}_lib diff --git a/scripts/templates/nullddi.cpp.mako b/scripts/templates/nullddi.cpp.mako new file mode 100644 index 0000000000..269e5997be --- /dev/null +++ b/scripts/templates/nullddi.cpp.mako @@ -0,0 +1,119 @@ +<%! +import re +from templates import helper as th +%><% + n=namespace + N=n.upper() + + x=tags['$x'] + X=x.upper() +%>/* + * + * Copyright (C) 2019-2022 Intel Corporation + * + * SPDX-License-Identifier: MIT + * + * @file ${name}.cpp + * + */ +#include "${x}_null.h" + +namespace driver +{ + %for obj in th.extract_objs(specs, r"function"): + /////////////////////////////////////////////////////////////////////////////// + <% + fname = th.make_func_name(n, tags, obj) + %>/// @brief Intercept function for ${fname} + %if 'condition' in obj: + #if ${th.subt(n, tags, obj['condition'])} + %endif + __${x}dlllocal ${x}_result_t ${X}_APICALL + ${fname}( + %for line in th.make_param_lines(n, tags, obj): + ${line} + %endfor + ) + { + ${x}_result_t result = ${X}_RESULT_SUCCESS; + + // if the driver has created a custom function, then call it instead of using the generic path + auto ${th.make_pfn_name(n, tags, obj)} = d_context.${n}DdiTable.${th.get_table_name(n, tags, obj)}.${th.make_pfn_name(n, tags, obj)}; + if( nullptr != ${th.make_pfn_name(n, tags, obj)} ) + { + result = ${th.make_pfn_name(n, tags, obj)}( ${", ".join(th.make_param_lines(n, tags, obj, format=["name"]))} ); + } + else + { + // generic implementation + %for item in th.get_loader_epilogue(n, tags, obj, meta): + %if 'range' in item: + for( size_t i = ${item['range'][0]}; ( nullptr != ${item['name']} ) && ( i < ${item['range'][1]} ); ++i ) + ${item['name']}[ i ] = reinterpret_cast<${item['type']}>( d_context.get() ); + %elif not item['release']: + %if item['optional']: + if( nullptr != ${item['name']} ) *${item['name']} = reinterpret_cast<${item['type']}>( d_context.get() ); + %else: + *${item['name']} = reinterpret_cast<${item['type']}>( d_context.get() ); + %endif + %endif + + %endfor + } + + return result; + } + %if 'condition' in obj: + #endif // ${th.subt(n, tags, obj['condition'])} + %endif + + %endfor +} // namespace driver + +#if defined(__cplusplus) +extern "C" { +#endif + +%for tbl in th.get_pfntables(specs, meta, n, tags): +/////////////////////////////////////////////////////////////////////////////// +/// @brief Exported function for filling application's ${tbl['name']} table +/// with current process' addresses +/// +/// @returns +/// - ::${X}_RESULT_SUCCESS +/// - ::${X}_RESULT_ERROR_INVALID_NULL_POINTER +/// - ::${X}_RESULT_ERROR_UNSUPPORTED_VERSION +${X}_DLLEXPORT ${x}_result_t ${X}_APICALL +${tbl['export']['name']}( + %for line in th.make_param_lines(n, tags, tbl['export']): + ${line} + %endfor + ) +{ + if( nullptr == pDdiTable ) + return ${X}_RESULT_ERROR_INVALID_NULL_POINTER; + + if( driver::d_context.version < version ) + return ${X}_RESULT_ERROR_UNSUPPORTED_VERSION; + + ${x}_result_t result = ${X}_RESULT_SUCCESS; + + %for obj in tbl['functions']: + %if 'condition' in obj: +#if ${th.subt(n, tags, obj['condition'])} + %endif + pDdiTable->${th.append_ws(th.make_pfn_name(n, tags, obj), 41)} = driver::${th.make_func_name(n, tags, obj)}; + %if 'condition' in obj: +#else + pDdiTable->${th.append_ws(th.make_pfn_name(n, tags, obj), 41)} = nullptr; +#endif + %endif + + %endfor + return result; +} + +%endfor +#if defined(__cplusplus) +}; +#endif diff --git a/source/CMakeLists.txt b/source/CMakeLists.txt index 5f0006211c..60ddb18aad 100644 --- a/source/CMakeLists.txt +++ b/source/CMakeLists.txt @@ -1,11 +1,9 @@ -set(TARGET_NAME ur_test) +# Copyright (C) 2022 Intel Corporation +# SPDX-License-Identifier: MIT -add_library(${TARGET_NAME} - STATIC - ${CMAKE_CURRENT_SOURCE_DIR}/ur_api.cpp -) +add_definitions(-DUR_VERSION="${PROJECT_VERSION_MAJOR}") +add_definitions(-DUR_VALIDATION_LAYER_SUPPORTED_VERSION="${PROJECT_VERSION_MAJOR}") -target_link_libraries(${TARGET_NAME} PRIVATE - ${PROJECT_NAME}::headers - ${CMAKE_DL_LIBS} -) +add_subdirectory(loader) +#add_subdirectory(layers) +add_subdirectory(drivers) diff --git a/source/common/ur_singleton.h b/source/common/ur_singleton.h new file mode 100644 index 0000000000..546377d33c --- /dev/null +++ b/source/common/ur_singleton.h @@ -0,0 +1,79 @@ +/* + * + * Copyright (C) 2022 Intel Corporation + * + * SPDX-License-Identifier: MIT + * + */ + +#ifndef UR_SINGLETON_H +#define UR_SINGLETON_H 1 + +#include +#include +#include + +////////////////////////////////////////////////////////////////////////// +/// a abstract factory for creation of singleton objects +template +class singleton_factory_t +{ +protected: + using singleton_t = singleton_tn; + using key_t = typename std::conditional::value, size_t, key_tn>::type; + + using ptr_t = std::unique_ptr < singleton_t >; + using map_t = std::unordered_map < key_t, ptr_t >; + + std::mutex mut; ///< lock for thread-safety + map_t map; ///< single instance of singleton for each unique key + + ////////////////////////////////////////////////////////////////////////// + /// extract the key from parameter list and if necessary, convert type + template + key_t getKey( key_tn key, Ts&&... params ) + { + return reinterpret_cast( key ); + } + +public: + ////////////////////////////////////////////////////////////////////////// + /// default ctor/dtor + singleton_factory_t() = default; + ~singleton_factory_t() = default; + + ////////////////////////////////////////////////////////////////////////// + /// gets a pointer to a unique instance of singleton + /// if no instance exists, then creates a new instance + /// the params are forwarded to the ctor of the singleton + /// the first parameter must be the unique identifier of the instance + template + singleton_tn* getInstance( Ts&&... params ) + { + auto key = getKey( std::forward( params )... ); + + if(key == 0) { // No zero keys allowed in map + return static_cast(0); + } + + std::lock_guard lk( mut ); + auto iter = map.find( key ); + + if( map.end() == iter ) + { + auto ptr = std::make_unique( std::forward( params )... ); + iter = map.emplace( key, std::move( ptr ) ).first; + } + return iter->second.get(); + } + + ////////////////////////////////////////////////////////////////////////// + /// once the key is no longer valid, release the singleton + void release( key_tn key ) + { + std::lock_guard lk( mut ); + map.erase( getKey( key ) ); + } +}; + +#endif /* UR_SINGLETON_H */ diff --git a/source/common/ur_util.h b/source/common/ur_util.h new file mode 100644 index 0000000000..94292e68e4 --- /dev/null +++ b/source/common/ur_util.h @@ -0,0 +1,114 @@ +/* + * + * Copyright (C) 2022 Intel Corporation + * + * SPDX-License-Identifier: MIT + * + */ + +#ifndef UR_UTIL_H +#define UR_UTIL_H 1 + +#include +#include +#include + +/////////////////////////////////////////////////////////////////////////////// +#if defined(_WIN32) +# include +# define MAKE_LIBRARY_NAME(NAME, VERSION) NAME".dll" +# define MAKE_LAYER_NAME(NAME) NAME".dll" +# define LOAD_DRIVER_LIBRARY(NAME) LoadLibraryExA(NAME, nullptr, LOAD_LIBRARY_SEARCH_SYSTEM32) +# define FREE_DRIVER_LIBRARY(LIB) if(LIB) FreeLibrary(LIB) +# define GET_FUNCTION_PTR(LIB, FUNC_NAME) GetProcAddress(LIB, FUNC_NAME) +# define string_copy_s strncpy_s +#else +# include +# define HMODULE void* +# define MAKE_LIBRARY_NAME(NAME, VERSION) "lib" NAME ".so." VERSION +# define MAKE_LAYER_NAME(NAME) "lib" NAME ".so." L0_VALIDATION_LAYER_SUPPORTED_VERSION +# define LOAD_DRIVER_LIBRARY(NAME) dlopen(NAME, RTLD_LAZY|RTLD_LOCAL|RTLD_DEEPBIND) +# define FREE_DRIVER_LIBRARY(LIB) if(LIB) dlclose(LIB) +# define GET_FUNCTION_PTR(LIB, FUNC_NAME) dlsym(LIB, FUNC_NAME) +# define string_copy_s strncpy +#endif + +inline std::string create_library_path(const char *name, const char *path){ + std::string library_path; + if (path && (strcmp("", path) != 0)) { + library_path.assign(path); +#ifdef _WIN32 + library_path.append("\\"); +#else + library_path.append("/"); +#endif + library_path.append(name); + } else { + library_path.assign(name); + } + return library_path; +} + +#ifdef _WIN32 +inline std::string readUnifiedRuntimeLoaderLibraryPath() { + std::string LoaderRegKeyPath = ""; + HKEY regKey = {}; + DWORD regValueType = {}; + DWORD pathSize = {}; + std::string loaderMajorVersionString = std::to_string(LOADER_VERSION_MAJOR); + std::string loaderRegistryKeyPath = "Software\\Intel\\oneAPI\\UnifiedRuntime\\"; + loaderRegistryKeyPath.append(loaderMajorVersionString); + static constexpr char unifiedRuntimeLoaderPathKey[] = "UnifiedRuntimeLoaderPath"; + + LSTATUS regOpenStatus = RegOpenKeyA(HKEY_LOCAL_MACHINE, loaderRegistryKeyPath.c_str(), ®Key); + + if (ERROR_SUCCESS != regOpenStatus) { + return LoaderRegKeyPath; + } + + LSTATUS regOpStatus = RegQueryValueExA(regKey, unifiedRuntimeLoaderPathKey, NULL, + ®ValueType, NULL, &pathSize); + + if ((ERROR_SUCCESS == regOpStatus) && (REG_SZ == regValueType)) { + LoaderRegKeyPath.resize(pathSize); + regOpStatus = RegQueryValueExA(regKey, unifiedRuntimeLoaderPathKey, NULL, + ®ValueType, (LPBYTE) & *LoaderRegKeyPath.begin(), + &pathSize); + if (ERROR_SUCCESS != regOpStatus) { + LoaderRegKeyPath.clear(); + LoaderRegKeyPath.assign(""); + } + } + + return LoaderRegKeyPath; +} +#endif + +////////////////////////////////////////////////////////////////////////// +#if !defined(_WIN32) && (__GNUC__ >= 4) +#define __urdlllocal __attribute__ ((visibility ("hidden"))) +#else +#define __urdlllocal +#endif + +/////////////////////////////////////////////////////////////////////////////// +inline bool getenv_tobool( const char* name ) +{ + const char* env = nullptr; + +#if defined(_WIN32) + char buffer[8]; + auto rc = GetEnvironmentVariable(name, buffer, 8); + if (0 != rc && rc <= 8) { + env = buffer; + } +#else + env = getenv(name); +#endif + + if( nullptr == env ) + return false; + return 0 == strcmp( "1", env ); +} + +#endif /* UR_UTIL_H */ diff --git a/source/drivers/CMakeLists.txt b/source/drivers/CMakeLists.txt new file mode 100644 index 0000000000..eabf618c54 --- /dev/null +++ b/source/drivers/CMakeLists.txt @@ -0,0 +1 @@ +add_subdirectory(null) diff --git a/source/drivers/null/CMakeLists.txt b/source/drivers/null/CMakeLists.txt new file mode 100644 index 0000000000..78ea91be19 --- /dev/null +++ b/source/drivers/null/CMakeLists.txt @@ -0,0 +1,25 @@ +set(TARGET_NAME ur_null) + +add_library(${TARGET_NAME} + SHARED + ${CMAKE_CURRENT_SOURCE_DIR}/ur_null.h + ${CMAKE_CURRENT_SOURCE_DIR}/ur_null.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/ur_nullddi.cpp +) + +set_target_properties(${TARGET_NAME} PROPERTIES + VERSION "${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}.${PROJECT_VERSION_PATCH}" + SOVERSION "${PROJECT_VERSION_MAJOR}" +) + +target_include_directories(${TARGET_NAME} + PUBLIC + ${CMAKE_CURRENT_SOURCE_DIR} + ${CMAKE_SOURCE_DIR}/include + ${CMAKE_SOURCE_DIR}/source/common +) + +if(UNIX) + set(GCC_COVERAGE_COMPILE_FLAGS "-fvisibility=hidden -fvisibility-inlines-hidden -fno-strict-aliasing") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${GCC_COVERAGE_COMPILE_FLAGS}") +endif() \ No newline at end of file diff --git a/source/drivers/null/ur_null.cpp b/source/drivers/null/ur_null.cpp new file mode 100644 index 0000000000..d8ad2f6923 --- /dev/null +++ b/source/drivers/null/ur_null.cpp @@ -0,0 +1,87 @@ +/* + * + * Copyright (C) 2019-2022 Intel Corporation + * + * SPDX-License-Identifier: MIT + * + * @file ur_null.cpp + * + */ +#include "ur_null.h" + +namespace driver +{ + ////////////////////////////////////////////////////////////////////////// + context_t d_context; + + ////////////////////////////////////////////////////////////////////////// + context_t::context_t() + { + ////////////////////////////////////////////////////////////////////////// + urDdiTable.Platform.pfnGet = []( + uint32_t NumEntries, + ur_platform_handle_t* phPlatforms, + uint32_t* pNumPlatforms) + { + if (phPlatforms != nullptr && NumEntries != 1) return UR_RESULT_ERROR_INVALID_SIZE; + if (pNumPlatforms != nullptr) *pNumPlatforms = 1; + if( nullptr != phPlatforms ) *reinterpret_cast( phPlatforms ) = d_context.get(); + return UR_RESULT_SUCCESS; + }; + + ////////////////////////////////////////////////////////////////////////// + urDdiTable.Device.pfnGet = []( + ur_platform_handle_t hPlatform, + ur_device_type_t DevicesType, + uint32_t NumEntries, + ur_device_handle_t* phDevices, + uint32_t* pNumDevices ) + { + (void)DevicesType; + if (phDevices != nullptr && NumEntries != 1) return UR_RESULT_ERROR_INVALID_SIZE; + if (pNumDevices != nullptr) *pNumDevices = 1; + if( nullptr != phDevices ) *reinterpret_cast( phDevices ) = d_context.get(); + return UR_RESULT_SUCCESS; + }; + + ////////////////////////////////////////////////////////////////////////// + urDdiTable.Device.pfnGetInfo = []( + ur_device_handle_t hDevice, + ur_device_info_t infoType, + size_t propSize, + void* pDeviceInfo, + size_t* pPropSizeRet) + { + switch (infoType) { + case UR_DEVICE_INFO_TYPE: + if (propSize != sizeof(ur_device_type_t)) return UR_RESULT_ERROR_INVALID_SIZE; + + if (pDeviceInfo != nullptr) { + *reinterpret_cast(pDeviceInfo) = UR_DEVICE_TYPE_GPU; + } + if (pPropSizeRet != nullptr) { + *pPropSizeRet = sizeof(ur_device_type_t); + } + break; + + case UR_DEVICE_INFO_NAME: + if (pDeviceInfo != nullptr) { +#if defined(_WIN32) + strncpy_s( reinterpret_cast(pDeviceInfo), "Null Device", propSize ); +#else + strncpy( reinterpret_cast(pDeviceInfo), "Null Device", propSize ); +#endif + } + if (pPropSizeRet != nullptr) { + *pPropSizeRet = sizeof(pDeviceInfo); + } + break; + + default: + return UR_RESULT_ERROR_INVALID_ARGUMENT; + } + return UR_RESULT_SUCCESS; + + }; + } +} // namespace driver diff --git a/source/drivers/null/ur_null.h b/source/drivers/null/ur_null.h new file mode 100644 index 0000000000..07eb876e8f --- /dev/null +++ b/source/drivers/null/ur_null.h @@ -0,0 +1,40 @@ +/* + * + * Copyright (C) 2019-2021 Intel Corporation + * + * SPDX-License-Identifier: MIT + * + * @file ur_null.h + * + */ +#ifndef UR_ADAPTER_NULL_H +#define UR_ADAPTER_NULL_H 1 + +#include +#include +#include "ur_ddi.h" +#include "ur_util.h" + +namespace driver +{ + /////////////////////////////////////////////////////////////////////////////// + class __urdlllocal context_t + { + public: + ur_api_version_t version = UR_API_VERSION_0_9; + + ur_dditable_t urDdiTable = {}; + context_t(); + ~context_t() = default; + + void* get() + { + static uint64_t count = 0x80800000; + return reinterpret_cast( ++count ); + } + }; + + extern context_t d_context; +} // namespace driver + +#endif /* UR_ADAPTER_NULL_H */ diff --git a/source/drivers/null/ur_nullddi.cpp b/source/drivers/null/ur_nullddi.cpp new file mode 100644 index 0000000000..49ba7cf5f1 --- /dev/null +++ b/source/drivers/null/ur_nullddi.cpp @@ -0,0 +1,3630 @@ +/* + * + * Copyright (C) 2019-2022 Intel Corporation + * + * SPDX-License-Identifier: MIT + * + * @file ur_nullddi.cpp + * + */ +#include "ur_null.h" + +namespace driver +{ + /////////////////////////////////////////////////////////////////////////////// + /// @brief Intercept function for urContextCreate + __urdlllocal ur_result_t UR_APICALL + urContextCreate( + uint32_t DeviceCount, ///< [in] the number of devices given in phDevices + ur_device_handle_t* phDevices, ///< [in][range(0, DeviceCount)] array of handle of devices. + ur_context_handle_t* phContext ///< [out] pointer to handle of context object created + ) + { + ur_result_t result = UR_RESULT_SUCCESS; + + // if the driver has created a custom function, then call it instead of using the generic path + auto pfnCreate = d_context.urDdiTable.Context.pfnCreate; + if( nullptr != pfnCreate ) + { + result = pfnCreate( DeviceCount, phDevices, phContext ); + } + else + { + // generic implementation + *phContext = reinterpret_cast( d_context.get() ); + + } + + return result; + } + + /////////////////////////////////////////////////////////////////////////////// + /// @brief Intercept function for urContextRetain + __urdlllocal ur_result_t UR_APICALL + urContextRetain( + ur_context_handle_t hContext ///< [in] handle of the context to get a reference of. + ) + { + ur_result_t result = UR_RESULT_SUCCESS; + + // if the driver has created a custom function, then call it instead of using the generic path + auto pfnRetain = d_context.urDdiTable.Context.pfnRetain; + if( nullptr != pfnRetain ) + { + result = pfnRetain( hContext ); + } + else + { + // generic implementation + } + + return result; + } + + /////////////////////////////////////////////////////////////////////////////// + /// @brief Intercept function for urContextRelease + __urdlllocal ur_result_t UR_APICALL + urContextRelease( + ur_context_handle_t hContext ///< [in] handle of the context to release. + ) + { + ur_result_t result = UR_RESULT_SUCCESS; + + // if the driver has created a custom function, then call it instead of using the generic path + auto pfnRelease = d_context.urDdiTable.Context.pfnRelease; + if( nullptr != pfnRelease ) + { + result = pfnRelease( hContext ); + } + else + { + // generic implementation + } + + return result; + } + + /////////////////////////////////////////////////////////////////////////////// + /// @brief Intercept function for urContextGetInfo + __urdlllocal ur_result_t UR_APICALL + urContextGetInfo( + ur_context_handle_t hContext, ///< [in] handle of the context + ur_context_info_t ContextInfoType, ///< [in] type of the info to retrieve + size_t propSize, ///< [in] the number of bytes of memory pointed to by pContextInfo. + void* pContextInfo, ///< [out][optional] 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 ::UR_RESULT_ERROR_INVALID_SIZE error is returned and + ///< pContextInfo is not used. + size_t* pPropSizeRet ///< [out][optional] pointer to the actual size in bytes of data queried by ContextInfoType. + ) + { + ur_result_t result = UR_RESULT_SUCCESS; + + // if the driver has created a custom function, then call it instead of using the generic path + auto pfnGetInfo = d_context.urDdiTable.Context.pfnGetInfo; + if( nullptr != pfnGetInfo ) + { + result = pfnGetInfo( hContext, ContextInfoType, propSize, pContextInfo, pPropSizeRet ); + } + else + { + // generic implementation + } + + return result; + } + + /////////////////////////////////////////////////////////////////////////////// + /// @brief Intercept function for urContextGetNativeHandle + __urdlllocal ur_result_t UR_APICALL + urContextGetNativeHandle( + ur_context_handle_t hContext, ///< [in] handle of the context. + ur_native_handle_t* phNativeContext ///< [out] a pointer to the native handle of the context. + ) + { + ur_result_t result = UR_RESULT_SUCCESS; + + // if the driver has created a custom function, then call it instead of using the generic path + auto pfnGetNativeHandle = d_context.urDdiTable.Context.pfnGetNativeHandle; + if( nullptr != pfnGetNativeHandle ) + { + result = pfnGetNativeHandle( hContext, phNativeContext ); + } + else + { + // generic implementation + *phNativeContext = reinterpret_cast( d_context.get() ); + + } + + return result; + } + + /////////////////////////////////////////////////////////////////////////////// + /// @brief Intercept function for urContextCreateWithNativeHandle + __urdlllocal ur_result_t UR_APICALL + urContextCreateWithNativeHandle( + ur_native_handle_t hNativeContext, ///< [in] the native handle of the context. + ur_context_handle_t* phContext ///< [out] pointer to the handle of the context object created. + ) + { + ur_result_t result = UR_RESULT_SUCCESS; + + // if the driver has created a custom function, then call it instead of using the generic path + auto pfnCreateWithNativeHandle = d_context.urDdiTable.Context.pfnCreateWithNativeHandle; + if( nullptr != pfnCreateWithNativeHandle ) + { + result = pfnCreateWithNativeHandle( hNativeContext, phContext ); + } + else + { + // generic implementation + *phContext = reinterpret_cast( d_context.get() ); + + } + + return result; + } + + /////////////////////////////////////////////////////////////////////////////// + /// @brief Intercept function for urContextSetExtendedDeleter + __urdlllocal ur_result_t UR_APICALL + urContextSetExtendedDeleter( + ur_context_handle_t hContext, ///< [in] handle of the context. + ur_context_extended_deleter_t pfnDeleter, ///< [in] Function pointer to extended deleter. + void* pUserData ///< [in][out] pointer to data to be passed to callback. + ) + { + ur_result_t result = UR_RESULT_SUCCESS; + + // if the driver has created a custom function, then call it instead of using the generic path + auto pfnSetExtendedDeleter = d_context.urDdiTable.Context.pfnSetExtendedDeleter; + if( nullptr != pfnSetExtendedDeleter ) + { + result = pfnSetExtendedDeleter( hContext, pfnDeleter, pUserData ); + } + else + { + // generic implementation + } + + return result; + } + + /////////////////////////////////////////////////////////////////////////////// + /// @brief Intercept function for urEnqueueKernelLaunch + __urdlllocal ur_result_t UR_APICALL + urEnqueueKernelLaunch( + ur_queue_handle_t hQueue, ///< [in] handle of the queue object + ur_kernel_handle_t hKernel, ///< [in] handle of the kernel object + uint32_t workDim, ///< [in] number of dimensions, from 1 to 3, to specify the global and + ///< work-group work-items + const size_t* pGlobalWorkOffset, ///< [in] pointer to an array of workDim unsigned values that specify the + ///< offset used to calculate the global ID of a work-item + const size_t* pGlobalWorkSize, ///< [in] pointer to an array of workDim unsigned values that specify the + ///< number of global work-items in workDim that will execute the kernel + ///< function + const size_t* pLocalWorkSize, ///< [in][optional] pointer to an array of workDim unsigned values that + ///< specify the number of local work-items forming a work-group that will + ///< execute the kernel function. + ///< If nullptr, the runtime implementation will choose the work-group + ///< size. + uint32_t numEventsInWaitList, ///< [in] size of the event wait list + const ur_event_handle_t* phEventWaitList, ///< [in][optional][range(0, numEventsInWaitList)] pointer to a list of + ///< events that must be complete before the kernel execution. + ///< If nullptr, the numEventsInWaitList must be 0, indicating that no wait + ///< event. + ur_event_handle_t* phEvent ///< [in,out] return an event object that identifies this particular kernel + ///< execution instance. + ///< Contrary to clEnqueueNDRangeKernel, its input can not be a nullptr. + ///< TODO: change to allow nullptr. + ) + { + ur_result_t result = UR_RESULT_SUCCESS; + + // if the driver has created a custom function, then call it instead of using the generic path + auto pfnKernelLaunch = d_context.urDdiTable.Enqueue.pfnKernelLaunch; + if( nullptr != pfnKernelLaunch ) + { + result = pfnKernelLaunch( hQueue, hKernel, workDim, pGlobalWorkOffset, pGlobalWorkSize, pLocalWorkSize, numEventsInWaitList, phEventWaitList, phEvent ); + } + else + { + // generic implementation + *phEvent = reinterpret_cast( d_context.get() ); + + } + + return result; + } + + /////////////////////////////////////////////////////////////////////////////// + /// @brief Intercept function for urEnqueueEventsWait + __urdlllocal ur_result_t UR_APICALL + urEnqueueEventsWait( + ur_queue_handle_t hQueue, ///< [in] handle of the queue object + uint32_t numEventsInWaitList, ///< [in] size of the event wait list + const ur_event_handle_t* phEventWaitList, ///< [in][optional][range(0, numEventsInWaitList)] pointer to a list of + ///< events that must be complete before this command can be executed. + ///< If nullptr, the numEventsInWaitList must be 0, indicating that all + ///< previously enqueued commands + ///< must be complete. + ur_event_handle_t* phEvent ///< [in,out] return an event object that identifies this particular + ///< command instance. + ///< Input can not be a nullptr. + ///< TODO: change to allow nullptr. + ) + { + ur_result_t result = UR_RESULT_SUCCESS; + + // if the driver has created a custom function, then call it instead of using the generic path + auto pfnEventsWait = d_context.urDdiTable.Enqueue.pfnEventsWait; + if( nullptr != pfnEventsWait ) + { + result = pfnEventsWait( hQueue, numEventsInWaitList, phEventWaitList, phEvent ); + } + else + { + // generic implementation + *phEvent = reinterpret_cast( d_context.get() ); + + } + + return result; + } + + /////////////////////////////////////////////////////////////////////////////// + /// @brief Intercept function for urEnqueueEventsWaitWithBarrier + __urdlllocal ur_result_t UR_APICALL + urEnqueueEventsWaitWithBarrier( + ur_queue_handle_t hQueue, ///< [in] handle of the queue object + uint32_t numEventsInWaitList, ///< [in] size of the event wait list + const ur_event_handle_t* phEventWaitList, ///< [in][optional][range(0, numEventsInWaitList)] pointer to a list of + ///< events that must be complete before this command can be executed. + ///< If nullptr, the numEventsInWaitList must be 0, indicating that all + ///< previously enqueued commands + ///< must be complete. + ur_event_handle_t* phEvent ///< [in,out] return an event object that identifies this particular + ///< command instance. + ///< Input can not be a nullptr. + ///< TODO: change to allow nullptr. + ) + { + ur_result_t result = UR_RESULT_SUCCESS; + + // if the driver has created a custom function, then call it instead of using the generic path + auto pfnEventsWaitWithBarrier = d_context.urDdiTable.Enqueue.pfnEventsWaitWithBarrier; + if( nullptr != pfnEventsWaitWithBarrier ) + { + result = pfnEventsWaitWithBarrier( hQueue, numEventsInWaitList, phEventWaitList, phEvent ); + } + else + { + // generic implementation + *phEvent = reinterpret_cast( d_context.get() ); + + } + + return result; + } + + /////////////////////////////////////////////////////////////////////////////// + /// @brief Intercept function for urEnqueueMemBufferRead + __urdlllocal ur_result_t UR_APICALL + urEnqueueMemBufferRead( + ur_queue_handle_t hQueue, ///< [in] handle of the queue object + ur_mem_handle_t hBuffer, ///< [in] handle of the buffer object + bool blockingRead, ///< [in] indicates blocking (true), non-blocking (false) + size_t offset, ///< [in] offset in bytes in the buffer object + size_t size, ///< [in] size in bytes of data being read + void* pDst, ///< [in] pointer to host memory where data is to be read into + uint32_t numEventsInWaitList, ///< [in] size of the event wait list + const ur_event_handle_t* phEventWaitList, ///< [in][optional][range(0, numEventsInWaitList)] pointer to a list of + ///< events that must be complete before this command can be executed. + ///< If nullptr, the numEventsInWaitList must be 0, indicating that this + ///< command does not wait on any event to complete. + ur_event_handle_t* phEvent ///< [in,out] return an event object that identifies this particular + ///< command instance. + ///< Input can not be a nullptr. + ///< TODO: change to allow nullptr. + ) + { + ur_result_t result = UR_RESULT_SUCCESS; + + // if the driver has created a custom function, then call it instead of using the generic path + auto pfnMemBufferRead = d_context.urDdiTable.Enqueue.pfnMemBufferRead; + if( nullptr != pfnMemBufferRead ) + { + result = pfnMemBufferRead( hQueue, hBuffer, blockingRead, offset, size, pDst, numEventsInWaitList, phEventWaitList, phEvent ); + } + else + { + // generic implementation + *phEvent = reinterpret_cast( d_context.get() ); + + } + + return result; + } + + /////////////////////////////////////////////////////////////////////////////// + /// @brief Intercept function for urEnqueueMemBufferWrite + __urdlllocal ur_result_t UR_APICALL + urEnqueueMemBufferWrite( + ur_queue_handle_t hQueue, ///< [in] handle of the queue object + ur_mem_handle_t hBuffer, ///< [in] handle of the buffer object + bool blockingWrite, ///< [in] indicates blocking (true), non-blocking (false) + size_t offset, ///< [in] offset in bytes in the buffer object + size_t size, ///< [in] size in bytes of data being written + const void* pSrc, ///< [in] pointer to host memory where data is to be written from + uint32_t numEventsInWaitList, ///< [in] size of the event wait list + const ur_event_handle_t* phEventWaitList, ///< [in][optional][range(0, numEventsInWaitList)] pointer to a list of + ///< events that must be complete before this command can be executed. + ///< If nullptr, the numEventsInWaitList must be 0, indicating that this + ///< command does not wait on any event to complete. + ur_event_handle_t* phEvent ///< [in,out] return an event object that identifies this particular + ///< command instance. + ///< Input can not be a nullptr. + ///< TODO: change to allow nullptr. + ) + { + ur_result_t result = UR_RESULT_SUCCESS; + + // if the driver has created a custom function, then call it instead of using the generic path + auto pfnMemBufferWrite = d_context.urDdiTable.Enqueue.pfnMemBufferWrite; + if( nullptr != pfnMemBufferWrite ) + { + result = pfnMemBufferWrite( hQueue, hBuffer, blockingWrite, offset, size, pSrc, numEventsInWaitList, phEventWaitList, phEvent ); + } + else + { + // generic implementation + *phEvent = reinterpret_cast( d_context.get() ); + + } + + return result; + } + + /////////////////////////////////////////////////////////////////////////////// + /// @brief Intercept function for urEnqueueMemBufferReadRect + __urdlllocal ur_result_t UR_APICALL + urEnqueueMemBufferReadRect( + ur_queue_handle_t hQueue, ///< [in] handle of the queue object + ur_mem_handle_t hBuffer, ///< [in] handle of the buffer object + bool blockingRead, ///< [in] indicates blocking (true), non-blocking (false) + ur_rect_offset_t bufferOffset, ///< [in] 3D offset in the buffer + ur_rect_offset_t hostOffset, ///< [in] 3D offset in the host region + ur_rect_region_t region, ///< [in] 3D rectangular region descriptor: width, height, depth + size_t bufferRowPitch, ///< [in] length of each row in bytes in the buffer object + size_t bufferSlicePitch, ///< [in] length of each 2D slice in bytes in the buffer object being read + size_t hostRowPitch, ///< [in] length of each row in bytes in the host memory region pointed by + ///< dst + size_t hostSlicePitch, ///< [in] length of each 2D slice in bytes in the host memory region + ///< pointed by dst + void* pDst, ///< [in] pointer to host memory where data is to be read into + uint32_t numEventsInWaitList, ///< [in] size of the event wait list + const ur_event_handle_t* phEventWaitList, ///< [in][optional][range(0, numEventsInWaitList)] pointer to a list of + ///< events that must be complete before this command can be executed. + ///< If nullptr, the numEventsInWaitList must be 0, indicating that this + ///< command does not wait on any event to complete. + ur_event_handle_t* phEvent ///< [in,out] return an event object that identifies this particular + ///< command instance. + ///< Input can not be a nullptr. + ///< TODO: change to allow nullptr. + ) + { + ur_result_t result = UR_RESULT_SUCCESS; + + // if the driver has created a custom function, then call it instead of using the generic path + auto pfnMemBufferReadRect = d_context.urDdiTable.Enqueue.pfnMemBufferReadRect; + if( nullptr != pfnMemBufferReadRect ) + { + result = pfnMemBufferReadRect( hQueue, hBuffer, blockingRead, bufferOffset, hostOffset, region, bufferRowPitch, bufferSlicePitch, hostRowPitch, hostSlicePitch, pDst, numEventsInWaitList, phEventWaitList, phEvent ); + } + else + { + // generic implementation + *phEvent = reinterpret_cast( d_context.get() ); + + } + + return result; + } + + /////////////////////////////////////////////////////////////////////////////// + /// @brief Intercept function for urEnqueueMemBufferWriteRect + __urdlllocal ur_result_t UR_APICALL + urEnqueueMemBufferWriteRect( + ur_queue_handle_t hQueue, ///< [in] handle of the queue object + ur_mem_handle_t hBuffer, ///< [in] handle of the buffer object + bool blockingWrite, ///< [in] indicates blocking (true), non-blocking (false) + ur_rect_offset_t bufferOffset, ///< [in] 3D offset in the buffer + ur_rect_offset_t hostOffset, ///< [in] 3D offset in the host region + ur_rect_region_t region, ///< [in] 3D rectangular region descriptor: width, height, depth + size_t bufferRowPitch, ///< [in] length of each row in bytes in the buffer object + size_t bufferSlicePitch, ///< [in] length of each 2D slice in bytes in the buffer object being + ///< written + size_t hostRowPitch, ///< [in] length of each row in bytes in the host memory region pointed by + ///< src + size_t hostSlicePitch, ///< [in] length of each 2D slice in bytes in the host memory region + ///< pointed by src + void* pSrc, ///< [in] pointer to host memory where data is to be written from + uint32_t numEventsInWaitList, ///< [in] size of the event wait list + const ur_event_handle_t* phEventWaitList, ///< [in][optional][range(0, numEventsInWaitList)] points to a list of + ///< events that must be complete before this command can be executed. + ///< If nullptr, the numEventsInWaitList must be 0, indicating that this + ///< command does not wait on any event to complete. + ur_event_handle_t* phEvent ///< [in,out] return an event object that identifies this particular + ///< command instance. + ///< Input can not be a nullptr. + ///< TODO: change to allow nullptr. + ) + { + ur_result_t result = UR_RESULT_SUCCESS; + + // if the driver has created a custom function, then call it instead of using the generic path + auto pfnMemBufferWriteRect = d_context.urDdiTable.Enqueue.pfnMemBufferWriteRect; + if( nullptr != pfnMemBufferWriteRect ) + { + result = pfnMemBufferWriteRect( hQueue, hBuffer, blockingWrite, bufferOffset, hostOffset, region, bufferRowPitch, bufferSlicePitch, hostRowPitch, hostSlicePitch, pSrc, numEventsInWaitList, phEventWaitList, phEvent ); + } + else + { + // generic implementation + *phEvent = reinterpret_cast( d_context.get() ); + + } + + return result; + } + + /////////////////////////////////////////////////////////////////////////////// + /// @brief Intercept function for urEnqueueMemBufferCopy + __urdlllocal ur_result_t UR_APICALL + urEnqueueMemBufferCopy( + ur_queue_handle_t hQueue, ///< [in] handle of the queue object + ur_mem_handle_t hBufferSrc, ///< [in] handle of the src buffer object + ur_mem_handle_t hBufferDst, ///< [in] handle of the dest buffer object + size_t size, ///< [in] size in bytes of data being copied + uint32_t numEventsInWaitList, ///< [in] size of the event wait list + const ur_event_handle_t* phEventWaitList, ///< [in][optional][range(0, numEventsInWaitList)] pointer to a list of + ///< events that must be complete before this command can be executed. + ///< If nullptr, the numEventsInWaitList must be 0, indicating that this + ///< command does not wait on any event to complete. + ur_event_handle_t* phEvent ///< [in,out] return an event object that identifies this particular + ///< command instance. + ///< Input can not be a nullptr. + ///< TODO: change to allow nullptr. + ) + { + ur_result_t result = UR_RESULT_SUCCESS; + + // if the driver has created a custom function, then call it instead of using the generic path + auto pfnMemBufferCopy = d_context.urDdiTable.Enqueue.pfnMemBufferCopy; + if( nullptr != pfnMemBufferCopy ) + { + result = pfnMemBufferCopy( hQueue, hBufferSrc, hBufferDst, size, numEventsInWaitList, phEventWaitList, phEvent ); + } + else + { + // generic implementation + *phEvent = reinterpret_cast( d_context.get() ); + + } + + return result; + } + + /////////////////////////////////////////////////////////////////////////////// + /// @brief Intercept function for urEnqueueMemBufferCopyRect + __urdlllocal ur_result_t UR_APICALL + urEnqueueMemBufferCopyRect( + ur_queue_handle_t hQueue, ///< [in] handle of the queue object + ur_mem_handle_t hBufferSrc, ///< [in] handle of the source buffer object + ur_mem_handle_t hBufferDst, ///< [in] handle of the dest buffer object + ur_rect_offset_t srcOrigin, ///< [in] 3D offset in the source buffer + ur_rect_offset_t dstOrigin, ///< [in] 3D offset in the destination buffer + ur_rect_region_t srcRegion, ///< [in] source 3D rectangular region descriptor: width, height, depth + size_t srcRowPitch, ///< [in] length of each row in bytes in the source buffer object + size_t srcSlicePitch, ///< [in] length of each 2D slice in bytes in the source buffer object + size_t dstRowPitch, ///< [in] length of each row in bytes in the destination buffer object + size_t dstSlicePitch, ///< [in] length of each 2D slice in bytes in the destination buffer object + uint32_t numEventsInWaitList, ///< [in] size of the event wait list + const ur_event_handle_t* phEventWaitList, ///< [in][optional][range(0, numEventsInWaitList)] pointer to a list of + ///< events that must be complete before this command can be executed. + ///< If nullptr, the numEventsInWaitList must be 0, indicating that this + ///< command does not wait on any event to complete. + ur_event_handle_t* phEvent ///< [in,out] return an event object that identifies this particular + ///< command instance. + ///< Input can not be a nullptr. + ///< TODO: change to allow nullptr. + ) + { + ur_result_t result = UR_RESULT_SUCCESS; + + // if the driver has created a custom function, then call it instead of using the generic path + auto pfnMemBufferCopyRect = d_context.urDdiTable.Enqueue.pfnMemBufferCopyRect; + if( nullptr != pfnMemBufferCopyRect ) + { + result = pfnMemBufferCopyRect( hQueue, hBufferSrc, hBufferDst, srcOrigin, dstOrigin, srcRegion, srcRowPitch, srcSlicePitch, dstRowPitch, dstSlicePitch, numEventsInWaitList, phEventWaitList, phEvent ); + } + else + { + // generic implementation + *phEvent = reinterpret_cast( d_context.get() ); + + } + + return result; + } + + /////////////////////////////////////////////////////////////////////////////// + /// @brief Intercept function for urEnqueueMemBufferFill + __urdlllocal ur_result_t UR_APICALL + urEnqueueMemBufferFill( + ur_queue_handle_t hQueue, ///< [in] handle of the queue object + ur_mem_handle_t hBuffer, ///< [in] handle of the buffer object + const void* pPattern, ///< [in] pointer to the fill pattern + size_t patternSize, ///< [in] size in bytes of the pattern + size_t offset, ///< [in] offset into the buffer + size_t size, ///< [in] fill size in bytes, must be a multiple of patternSize + uint32_t numEventsInWaitList, ///< [in] size of the event wait list + const ur_event_handle_t* phEventWaitList, ///< [in][optional][range(0, numEventsInWaitList)] pointer to a list of + ///< events that must be complete before this command can be executed. + ///< If nullptr, the numEventsInWaitList must be 0, indicating that this + ///< command does not wait on any event to complete. + ur_event_handle_t* phEvent ///< [in,out] return an event object that identifies this particular + ///< command instance. + ///< Input can not be a nullptr. + ///< TODO: change to allow nullptr. + ) + { + ur_result_t result = UR_RESULT_SUCCESS; + + // if the driver has created a custom function, then call it instead of using the generic path + auto pfnMemBufferFill = d_context.urDdiTable.Enqueue.pfnMemBufferFill; + if( nullptr != pfnMemBufferFill ) + { + result = pfnMemBufferFill( hQueue, hBuffer, pPattern, patternSize, offset, size, numEventsInWaitList, phEventWaitList, phEvent ); + } + else + { + // generic implementation + *phEvent = reinterpret_cast( d_context.get() ); + + } + + return result; + } + + /////////////////////////////////////////////////////////////////////////////// + /// @brief Intercept function for urEnqueueMemImageRead + __urdlllocal ur_result_t UR_APICALL + urEnqueueMemImageRead( + ur_queue_handle_t hQueue, ///< [in] handle of the queue object + ur_mem_handle_t hImage, ///< [in] handle of the image object + bool blockingRead, ///< [in] indicates blocking (true), non-blocking (false) + ur_rect_offset_t origin, ///< [in] defines the (x,y,z) offset in pixels in the 1D, 2D, or 3D image + ur_rect_region_t region, ///< [in] defines the (width, height, depth) in pixels of the 1D, 2D, or 3D + ///< image + size_t rowPitch, ///< [in] length of each row in bytes + size_t slicePitch, ///< [in] length of each 2D slice of the 3D image + void* pDst, ///< [in] pointer to host memory where image is to be read into + uint32_t numEventsInWaitList, ///< [in] size of the event wait list + const ur_event_handle_t* phEventWaitList, ///< [in][optional][range(0, numEventsInWaitList)] pointer to a list of + ///< events that must be complete before this command can be executed. + ///< If nullptr, the numEventsInWaitList must be 0, indicating that this + ///< command does not wait on any event to complete. + ur_event_handle_t* phEvent ///< [in,out] return an event object that identifies this particular + ///< command instance. + ///< Input can not be a nullptr. + ///< TODO: change to allow nullptr. + ) + { + ur_result_t result = UR_RESULT_SUCCESS; + + // if the driver has created a custom function, then call it instead of using the generic path + auto pfnMemImageRead = d_context.urDdiTable.Enqueue.pfnMemImageRead; + if( nullptr != pfnMemImageRead ) + { + result = pfnMemImageRead( hQueue, hImage, blockingRead, origin, region, rowPitch, slicePitch, pDst, numEventsInWaitList, phEventWaitList, phEvent ); + } + else + { + // generic implementation + *phEvent = reinterpret_cast( d_context.get() ); + + } + + return result; + } + + /////////////////////////////////////////////////////////////////////////////// + /// @brief Intercept function for urEnqueueMemImageWrite + __urdlllocal ur_result_t UR_APICALL + urEnqueueMemImageWrite( + ur_queue_handle_t hQueue, ///< [in] handle of the queue object + ur_mem_handle_t hImage, ///< [in] handle of the image object + bool blockingWrite, ///< [in] indicates blocking (true), non-blocking (false) + ur_rect_offset_t origin, ///< [in] defines the (x,y,z) offset in pixels in the 1D, 2D, or 3D image + ur_rect_region_t region, ///< [in] defines the (width, height, depth) in pixels of the 1D, 2D, or 3D + ///< image + size_t inputRowPitch, ///< [in] length of each row in bytes + size_t inputSlicePitch, ///< [in] length of each 2D slice of the 3D image + void* pSrc, ///< [in] pointer to host memory where image is to be read into + uint32_t numEventsInWaitList, ///< [in] size of the event wait list + const ur_event_handle_t* phEventWaitList, ///< [in][optional][range(0, numEventsInWaitList)] pointer to a list of + ///< events that must be complete before this command can be executed. + ///< If nullptr, the numEventsInWaitList must be 0, indicating that this + ///< command does not wait on any event to complete. + ur_event_handle_t* phEvent ///< [in,out] return an event object that identifies this particular + ///< command instance. + ///< Input can not be a nullptr. + ///< TODO: change to allow nullptr. + ) + { + ur_result_t result = UR_RESULT_SUCCESS; + + // if the driver has created a custom function, then call it instead of using the generic path + auto pfnMemImageWrite = d_context.urDdiTable.Enqueue.pfnMemImageWrite; + if( nullptr != pfnMemImageWrite ) + { + result = pfnMemImageWrite( hQueue, hImage, blockingWrite, origin, region, inputRowPitch, inputSlicePitch, pSrc, numEventsInWaitList, phEventWaitList, phEvent ); + } + else + { + // generic implementation + *phEvent = reinterpret_cast( d_context.get() ); + + } + + return result; + } + + /////////////////////////////////////////////////////////////////////////////// + /// @brief Intercept function for urEnqueueMemImageCopy + __urdlllocal ur_result_t UR_APICALL + urEnqueueMemImageCopy( + ur_queue_handle_t hQueue, ///< [in] handle of the queue object + ur_mem_handle_t hImageSrc, ///< [in] handle of the src image object + ur_mem_handle_t hImageDst, ///< [in] handle of the dest image object + ur_rect_offset_t srcOrigin, ///< [in] defines the (x,y,z) offset in pixels in the source 1D, 2D, or 3D + ///< image + ur_rect_offset_t dstOrigin, ///< [in] defines the (x,y,z) offset in pixels in the destination 1D, 2D, + ///< or 3D image + ur_rect_region_t region, ///< [in] defines the (width, height, depth) in pixels of the 1D, 2D, or 3D + ///< image + uint32_t numEventsInWaitList, ///< [in] size of the event wait list + const ur_event_handle_t* phEventWaitList, ///< [in][optional][range(0, numEventsInWaitList)] pointer to a list of + ///< events that must be complete before this command can be executed. + ///< If nullptr, the numEventsInWaitList must be 0, indicating that this + ///< command does not wait on any event to complete. + ur_event_handle_t* phEvent ///< [in,out] return an event object that identifies this particular + ///< command instance. + ///< Input can not be a nullptr. + ///< TODO: change to allow nullptr. + ) + { + ur_result_t result = UR_RESULT_SUCCESS; + + // if the driver has created a custom function, then call it instead of using the generic path + auto pfnMemImageCopy = d_context.urDdiTable.Enqueue.pfnMemImageCopy; + if( nullptr != pfnMemImageCopy ) + { + result = pfnMemImageCopy( hQueue, hImageSrc, hImageDst, srcOrigin, dstOrigin, region, numEventsInWaitList, phEventWaitList, phEvent ); + } + else + { + // generic implementation + *phEvent = reinterpret_cast( d_context.get() ); + + } + + return result; + } + + /////////////////////////////////////////////////////////////////////////////// + /// @brief Intercept function for urEnqueueMemBufferMap + __urdlllocal ur_result_t UR_APICALL + urEnqueueMemBufferMap( + ur_queue_handle_t hQueue, ///< [in] handle of the queue object + ur_mem_handle_t hBuffer, ///< [in] handle of the buffer object + bool blockingMap, ///< [in] indicates blocking (true), non-blocking (false) + ur_map_flags_t mapFlags, ///< [in] flags for read, write, readwrite mapping + size_t offset, ///< [in] offset in bytes of the buffer region being mapped + size_t size, ///< [in] size in bytes of the buffer region being mapped + uint32_t numEventsInWaitList, ///< [in] size of the event wait list + const ur_event_handle_t* phEventWaitList, ///< [in][optional][range(0, numEventsInWaitList)] pointer to a list of + ///< events that must be complete before this command can be executed. + ///< If nullptr, the numEventsInWaitList must be 0, indicating that this + ///< command does not wait on any event to complete. + ur_event_handle_t* phEvent, ///< [in,out] return an event object that identifies this particular + ///< command instance. + ///< Input can not be a nullptr. + ///< TODO: change to allow nullptr. + void** ppRetMap ///< [in,out] return mapped pointer. TODO: move it before + ///< numEventsInWaitList? + ) + { + ur_result_t result = UR_RESULT_SUCCESS; + + // if the driver has created a custom function, then call it instead of using the generic path + auto pfnMemBufferMap = d_context.urDdiTable.Enqueue.pfnMemBufferMap; + if( nullptr != pfnMemBufferMap ) + { + result = pfnMemBufferMap( hQueue, hBuffer, blockingMap, mapFlags, offset, size, numEventsInWaitList, phEventWaitList, phEvent, ppRetMap ); + } + else + { + // generic implementation + *phEvent = reinterpret_cast( d_context.get() ); + + } + + return result; + } + + /////////////////////////////////////////////////////////////////////////////// + /// @brief Intercept function for urEnqueueMemUnmap + __urdlllocal ur_result_t UR_APICALL + urEnqueueMemUnmap( + ur_queue_handle_t hQueue, ///< [in] handle of the queue object + ur_mem_handle_t hMem, ///< [in] handle of the memory (buffer or image) object + void* pMappedPtr, ///< [in] mapped host address + uint32_t numEventsInWaitList, ///< [in] size of the event wait list + const ur_event_handle_t* phEventWaitList, ///< [in][optional][range(0, numEventsInWaitList)] pointer to a list of + ///< events that must be complete before this command can be executed. + ///< If nullptr, the numEventsInWaitList must be 0, indicating that this + ///< command does not wait on any event to complete. + ur_event_handle_t* phEvent ///< [in,out] return an event object that identifies this particular + ///< command instance. + ///< Input can not be a nullptr. + ///< TODO: change to allow nullptr. + ) + { + ur_result_t result = UR_RESULT_SUCCESS; + + // if the driver has created a custom function, then call it instead of using the generic path + auto pfnMemUnmap = d_context.urDdiTable.Enqueue.pfnMemUnmap; + if( nullptr != pfnMemUnmap ) + { + result = pfnMemUnmap( hQueue, hMem, pMappedPtr, numEventsInWaitList, phEventWaitList, phEvent ); + } + else + { + // generic implementation + *phEvent = reinterpret_cast( d_context.get() ); + + } + + return result; + } + + /////////////////////////////////////////////////////////////////////////////// + /// @brief Intercept function for urEnqueueUSMMemset + __urdlllocal ur_result_t UR_APICALL + urEnqueueUSMMemset( + ur_queue_handle_t hQueue, ///< [in] handle of the queue object + void* ptr, ///< [in] pointer to USM memory object + int8_t byteValue, ///< [in] byte value to fill + size_t count, ///< [in] size in bytes to be set + uint32_t numEventsInWaitList, ///< [in] size of the event wait list + const ur_event_handle_t* phEventWaitList, ///< [in][optional][range(0, numEventsInWaitList)] pointer to a list of + ///< events that must be complete before this command can be executed. + ///< If nullptr, the numEventsInWaitList must be 0, indicating that this + ///< command does not wait on any event to complete. + ur_event_handle_t* phEvent ///< [in,out] return an event object that identifies this particular + ///< command instance. + ///< Input can not be a nullptr. + ///< TODO: change to allow nullptr. + ) + { + ur_result_t result = UR_RESULT_SUCCESS; + + // if the driver has created a custom function, then call it instead of using the generic path + auto pfnUSMMemset = d_context.urDdiTable.Enqueue.pfnUSMMemset; + if( nullptr != pfnUSMMemset ) + { + result = pfnUSMMemset( hQueue, ptr, byteValue, count, numEventsInWaitList, phEventWaitList, phEvent ); + } + else + { + // generic implementation + *phEvent = reinterpret_cast( d_context.get() ); + + } + + return result; + } + + /////////////////////////////////////////////////////////////////////////////// + /// @brief Intercept function for urEnqueueUSMMemcpy + __urdlllocal ur_result_t UR_APICALL + urEnqueueUSMMemcpy( + ur_queue_handle_t hQueue, ///< [in] handle of the queue object + bool blocking, ///< [in] blocking or non-blocking copy + void* pDst, ///< [in] pointer to the destination USM memory object + const void* pSrc, ///< [in] pointer to the source USM memory object + size_t size, ///< [in] size in bytes to be copied + uint32_t numEventsInWaitList, ///< [in] size of the event wait list + const ur_event_handle_t* phEventWaitList, ///< [in][optional][range(0, numEventsInWaitList)] pointer to a list of + ///< events that must be complete before this command can be executed. + ///< If nullptr, the numEventsInWaitList must be 0, indicating that this + ///< command does not wait on any event to complete. + ur_event_handle_t* phEvent ///< [in,out] return an event object that identifies this particular + ///< command instance. + ///< Input can not be a nullptr. + ///< TODO: change to allow nullptr. + ) + { + ur_result_t result = UR_RESULT_SUCCESS; + + // if the driver has created a custom function, then call it instead of using the generic path + auto pfnUSMMemcpy = d_context.urDdiTable.Enqueue.pfnUSMMemcpy; + if( nullptr != pfnUSMMemcpy ) + { + result = pfnUSMMemcpy( hQueue, blocking, pDst, pSrc, size, numEventsInWaitList, phEventWaitList, phEvent ); + } + else + { + // generic implementation + *phEvent = reinterpret_cast( d_context.get() ); + + } + + return result; + } + + /////////////////////////////////////////////////////////////////////////////// + /// @brief Intercept function for urEnqueueUSMPrefetch + __urdlllocal ur_result_t UR_APICALL + urEnqueueUSMPrefetch( + ur_queue_handle_t hQueue, ///< [in] handle of the queue object + const void* pMem, ///< [in] pointer to the USM memory object + size_t size, ///< [in] size in bytes to be fetched + ur_usm_migration_flags_t flags, ///< [in] USM prefetch flags + uint32_t numEventsInWaitList, ///< [in] size of the event wait list + const ur_event_handle_t* phEventWaitList, ///< [in][optional][range(0, numEventsInWaitList)] pointer to a list of + ///< events that must be complete before this command can be executed. + ///< If nullptr, the numEventsInWaitList must be 0, indicating that this + ///< command does not wait on any event to complete. + ur_event_handle_t* phEvent ///< [in,out] return an event object that identifies this particular + ///< command instance. + ///< Input can not be a nullptr. + ///< TODO: change to allow nullptr. + ) + { + ur_result_t result = UR_RESULT_SUCCESS; + + // if the driver has created a custom function, then call it instead of using the generic path + auto pfnUSMPrefetch = d_context.urDdiTable.Enqueue.pfnUSMPrefetch; + if( nullptr != pfnUSMPrefetch ) + { + result = pfnUSMPrefetch( hQueue, pMem, size, flags, numEventsInWaitList, phEventWaitList, phEvent ); + } + else + { + // generic implementation + *phEvent = reinterpret_cast( d_context.get() ); + + } + + return result; + } + + /////////////////////////////////////////////////////////////////////////////// + /// @brief Intercept function for urEnqueueUSMMemAdvice + __urdlllocal ur_result_t UR_APICALL + urEnqueueUSMMemAdvice( + ur_queue_handle_t hQueue, ///< [in] handle of the queue object + const void* pMem, ///< [in] pointer to the USM memory object + size_t size, ///< [in] size in bytes to be adviced + ur_mem_advice_t advice, ///< [in] USM memory advice + ur_event_handle_t* phEvent ///< [in,out] return an event object that identifies this particular + ///< command instance. + ///< Input can not be a nullptr. + ///< TODO: change to allow nullptr. + ) + { + ur_result_t result = UR_RESULT_SUCCESS; + + // if the driver has created a custom function, then call it instead of using the generic path + auto pfnUSMMemAdvice = d_context.urDdiTable.Enqueue.pfnUSMMemAdvice; + if( nullptr != pfnUSMMemAdvice ) + { + result = pfnUSMMemAdvice( hQueue, pMem, size, advice, phEvent ); + } + else + { + // generic implementation + *phEvent = reinterpret_cast( d_context.get() ); + + } + + return result; + } + + /////////////////////////////////////////////////////////////////////////////// + /// @brief Intercept function for urEventGetInfo + __urdlllocal ur_result_t UR_APICALL + urEventGetInfo( + ur_event_handle_t hEvent, ///< [in] handle of the event object + ur_event_info_t propName, ///< [in] the name of the event property to query + size_t propValueSize, ///< [in] size in bytes of the event property value + void* pPropValue, ///< [out] value of the event property + size_t* pPropValueSizeRet ///< [out] bytes returned in event property + ) + { + ur_result_t result = UR_RESULT_SUCCESS; + + // if the driver has created a custom function, then call it instead of using the generic path + auto pfnGetInfo = d_context.urDdiTable.Event.pfnGetInfo; + if( nullptr != pfnGetInfo ) + { + result = pfnGetInfo( hEvent, propName, propValueSize, pPropValue, pPropValueSizeRet ); + } + else + { + // generic implementation + } + + return result; + } + + /////////////////////////////////////////////////////////////////////////////// + /// @brief Intercept function for urEventGetProfilingInfo + __urdlllocal ur_result_t UR_APICALL + urEventGetProfilingInfo( + ur_event_handle_t hEvent, ///< [in] handle of the event object + ur_profiling_info_t propName, ///< [in] the name of the profiling property to query + size_t propValueSize, ///< [in] size in bytes of the profiling property value + void* pPropValue, ///< [out][optional] value of the profiling property + size_t* pPropValueSizeRet ///< [out][optional] pointer to the actual size in bytes returned in + ///< propValue + ) + { + ur_result_t result = UR_RESULT_SUCCESS; + + // if the driver has created a custom function, then call it instead of using the generic path + auto pfnGetProfilingInfo = d_context.urDdiTable.Event.pfnGetProfilingInfo; + if( nullptr != pfnGetProfilingInfo ) + { + result = pfnGetProfilingInfo( hEvent, propName, propValueSize, pPropValue, pPropValueSizeRet ); + } + else + { + // generic implementation + } + + return result; + } + + /////////////////////////////////////////////////////////////////////////////// + /// @brief Intercept function for urEventWait + __urdlllocal ur_result_t UR_APICALL + urEventWait( + uint32_t numEvents, ///< [in] number of events in the event list + const ur_event_handle_t* phEventWaitList ///< [in][range(0, numEvents)] pointer to a list of events to wait for + ///< completion + ) + { + ur_result_t result = UR_RESULT_SUCCESS; + + // if the driver has created a custom function, then call it instead of using the generic path + auto pfnWait = d_context.urDdiTable.Event.pfnWait; + if( nullptr != pfnWait ) + { + result = pfnWait( numEvents, phEventWaitList ); + } + else + { + // generic implementation + } + + return result; + } + + /////////////////////////////////////////////////////////////////////////////// + /// @brief Intercept function for urEventRetain + __urdlllocal ur_result_t UR_APICALL + urEventRetain( + ur_event_handle_t hEvent ///< [in] handle of the event object + ) + { + ur_result_t result = UR_RESULT_SUCCESS; + + // if the driver has created a custom function, then call it instead of using the generic path + auto pfnRetain = d_context.urDdiTable.Event.pfnRetain; + if( nullptr != pfnRetain ) + { + result = pfnRetain( hEvent ); + } + else + { + // generic implementation + } + + return result; + } + + /////////////////////////////////////////////////////////////////////////////// + /// @brief Intercept function for urEventRelease + __urdlllocal ur_result_t UR_APICALL + urEventRelease( + ur_event_handle_t hEvent ///< [in] handle of the event object + ) + { + ur_result_t result = UR_RESULT_SUCCESS; + + // if the driver has created a custom function, then call it instead of using the generic path + auto pfnRelease = d_context.urDdiTable.Event.pfnRelease; + if( nullptr != pfnRelease ) + { + result = pfnRelease( hEvent ); + } + else + { + // generic implementation + } + + return result; + } + + /////////////////////////////////////////////////////////////////////////////// + /// @brief Intercept function for urEventGetNativeHandle + __urdlllocal ur_result_t UR_APICALL + urEventGetNativeHandle( + ur_event_handle_t hEvent, ///< [in] handle of the event. + ur_native_handle_t* phNativeEvent ///< [out] a pointer to the native handle of the event. + ) + { + ur_result_t result = UR_RESULT_SUCCESS; + + // if the driver has created a custom function, then call it instead of using the generic path + auto pfnGetNativeHandle = d_context.urDdiTable.Event.pfnGetNativeHandle; + if( nullptr != pfnGetNativeHandle ) + { + result = pfnGetNativeHandle( hEvent, phNativeEvent ); + } + else + { + // generic implementation + *phNativeEvent = reinterpret_cast( d_context.get() ); + + } + + return result; + } + + /////////////////////////////////////////////////////////////////////////////// + /// @brief Intercept function for urEventCreateWithNativeHandle + __urdlllocal ur_result_t UR_APICALL + urEventCreateWithNativeHandle( + ur_native_handle_t hNativeEvent, ///< [in] the native handle of the event. + ur_context_handle_t hContext, ///< [in] handle of the context object + ur_event_handle_t* phEvent ///< [out] pointer to the handle of the event object created. + ) + { + ur_result_t result = UR_RESULT_SUCCESS; + + // if the driver has created a custom function, then call it instead of using the generic path + auto pfnCreateWithNativeHandle = d_context.urDdiTable.Event.pfnCreateWithNativeHandle; + if( nullptr != pfnCreateWithNativeHandle ) + { + result = pfnCreateWithNativeHandle( hNativeEvent, hContext, phEvent ); + } + else + { + // generic implementation + *phEvent = reinterpret_cast( d_context.get() ); + + } + + return result; + } + + /////////////////////////////////////////////////////////////////////////////// + /// @brief Intercept function for urEventSetCallback + __urdlllocal ur_result_t UR_APICALL + urEventSetCallback( + ur_event_handle_t hEvent, ///< [in] handle of the event object + ur_execution_info_t execStatus, ///< [in] execution status of the event + ur_event_callback_t pfnNotify, ///< [in] execution status of the event + void* pUserData ///< [in][out][optional] pointer to data to be passed to callback. + ) + { + ur_result_t result = UR_RESULT_SUCCESS; + + // if the driver has created a custom function, then call it instead of using the generic path + auto pfnSetCallback = d_context.urDdiTable.Event.pfnSetCallback; + if( nullptr != pfnSetCallback ) + { + result = pfnSetCallback( hEvent, execStatus, pfnNotify, pUserData ); + } + else + { + // generic implementation + } + + return result; + } + + /////////////////////////////////////////////////////////////////////////////// + /// @brief Intercept function for urMemImageCreate + __urdlllocal ur_result_t UR_APICALL + urMemImageCreate( + ur_context_handle_t hContext, ///< [in] handle of the context object + ur_mem_flags_t flags, ///< [in] allocation and usage information flags + const ur_image_format_t* pImageFormat, ///< [in] pointer to image format specification + const ur_image_desc_t* pImageDesc, ///< [in] pointer to image description + void* pHost, ///< [in] pointer to the buffer data + ur_mem_handle_t* phMem ///< [out] pointer to handle of image object created + ) + { + ur_result_t result = UR_RESULT_SUCCESS; + + // if the driver has created a custom function, then call it instead of using the generic path + auto pfnImageCreate = d_context.urDdiTable.Mem.pfnImageCreate; + if( nullptr != pfnImageCreate ) + { + result = pfnImageCreate( hContext, flags, pImageFormat, pImageDesc, pHost, phMem ); + } + else + { + // generic implementation + *phMem = reinterpret_cast( d_context.get() ); + + } + + return result; + } + + /////////////////////////////////////////////////////////////////////////////// + /// @brief Intercept function for urMemBufferCreate + __urdlllocal ur_result_t UR_APICALL + urMemBufferCreate( + ur_context_handle_t hContext, ///< [in] handle of the context object + ur_mem_flags_t flags, ///< [in] allocation and usage information flags + size_t size, ///< [in] size in bytes of the memory object to be allocated + void* pHost, ///< [in] pointer to the buffer data + ur_mem_handle_t* phBuffer ///< [out] pointer to handle of the memory buffer created + ) + { + ur_result_t result = UR_RESULT_SUCCESS; + + // if the driver has created a custom function, then call it instead of using the generic path + auto pfnBufferCreate = d_context.urDdiTable.Mem.pfnBufferCreate; + if( nullptr != pfnBufferCreate ) + { + result = pfnBufferCreate( hContext, flags, size, pHost, phBuffer ); + } + else + { + // generic implementation + *phBuffer = reinterpret_cast( d_context.get() ); + + } + + return result; + } + + /////////////////////////////////////////////////////////////////////////////// + /// @brief Intercept function for urMemRetain + __urdlllocal ur_result_t UR_APICALL + urMemRetain( + ur_mem_handle_t hMem ///< [in] handle of the memory object to get access + ) + { + ur_result_t result = UR_RESULT_SUCCESS; + + // if the driver has created a custom function, then call it instead of using the generic path + auto pfnRetain = d_context.urDdiTable.Mem.pfnRetain; + if( nullptr != pfnRetain ) + { + result = pfnRetain( hMem ); + } + else + { + // generic implementation + } + + return result; + } + + /////////////////////////////////////////////////////////////////////////////// + /// @brief Intercept function for urMemRelease + __urdlllocal ur_result_t UR_APICALL + urMemRelease( + ur_mem_handle_t hMem ///< [in] handle of the memory object to release + ) + { + ur_result_t result = UR_RESULT_SUCCESS; + + // if the driver has created a custom function, then call it instead of using the generic path + auto pfnRelease = d_context.urDdiTable.Mem.pfnRelease; + if( nullptr != pfnRelease ) + { + result = pfnRelease( hMem ); + } + else + { + // generic implementation + } + + return result; + } + + /////////////////////////////////////////////////////////////////////////////// + /// @brief Intercept function for urMemBufferPartition + __urdlllocal ur_result_t UR_APICALL + urMemBufferPartition( + ur_mem_handle_t hBuffer, ///< [in] handle of the buffer object to allocate from + ur_mem_flags_t flags, ///< [in] allocation and usage information flags + ur_buffer_create_type_t bufferCreateType, ///< [in] buffer creation type + ur_buffer_region_t* pBufferCreateInfo, ///< [in] pointer to buffer create region information + ur_mem_handle_t* phMem ///< [out] pointer to the handle of sub buffer created + ) + { + ur_result_t result = UR_RESULT_SUCCESS; + + // if the driver has created a custom function, then call it instead of using the generic path + auto pfnBufferPartition = d_context.urDdiTable.Mem.pfnBufferPartition; + if( nullptr != pfnBufferPartition ) + { + result = pfnBufferPartition( hBuffer, flags, bufferCreateType, pBufferCreateInfo, phMem ); + } + else + { + // generic implementation + *phMem = reinterpret_cast( d_context.get() ); + + } + + return result; + } + + /////////////////////////////////////////////////////////////////////////////// + /// @brief Intercept function for urMemGetNativeHandle + __urdlllocal ur_result_t UR_APICALL + urMemGetNativeHandle( + ur_mem_handle_t hMem, ///< [in] handle of the mem. + ur_native_handle_t* phNativeMem ///< [out] a pointer to the native handle of the mem. + ) + { + ur_result_t result = UR_RESULT_SUCCESS; + + // if the driver has created a custom function, then call it instead of using the generic path + auto pfnGetNativeHandle = d_context.urDdiTable.Mem.pfnGetNativeHandle; + if( nullptr != pfnGetNativeHandle ) + { + result = pfnGetNativeHandle( hMem, phNativeMem ); + } + else + { + // generic implementation + *phNativeMem = reinterpret_cast( d_context.get() ); + + } + + return result; + } + + /////////////////////////////////////////////////////////////////////////////// + /// @brief Intercept function for urMemCreateWithNativeHandle + __urdlllocal ur_result_t UR_APICALL + urMemCreateWithNativeHandle( + ur_native_handle_t hNativeMem, ///< [in] the native handle of the mem. + ur_context_handle_t hContext, ///< [in] handle of the context object + ur_mem_handle_t* phMem ///< [out] pointer to the handle of the mem object created. + ) + { + ur_result_t result = UR_RESULT_SUCCESS; + + // if the driver has created a custom function, then call it instead of using the generic path + auto pfnCreateWithNativeHandle = d_context.urDdiTable.Mem.pfnCreateWithNativeHandle; + if( nullptr != pfnCreateWithNativeHandle ) + { + result = pfnCreateWithNativeHandle( hNativeMem, hContext, phMem ); + } + else + { + // generic implementation + *phMem = reinterpret_cast( d_context.get() ); + + } + + return result; + } + + /////////////////////////////////////////////////////////////////////////////// + /// @brief Intercept function for urMemGetInfo + __urdlllocal ur_result_t UR_APICALL + urMemGetInfo( + ur_mem_handle_t hMemory, ///< [in] handle to the memory object being queried. + ur_mem_info_t MemInfoType, ///< [in] type of the info to retrieve. + size_t propSize, ///< [in] the number of bytes of memory pointed to by pMemInfo. + void* pMemInfo, ///< [out][optional] array of bytes holding the info. + ///< If propSize is less than the real number of bytes needed to return + ///< the info then the ::UR_RESULT_ERROR_INVALID_SIZE error is returned and + ///< pMemInfo is not used. + size_t* pPropSizeRet ///< [out][optional] pointer to the actual size in bytes of data queried by pMemInfo. + ) + { + ur_result_t result = UR_RESULT_SUCCESS; + + // if the driver has created a custom function, then call it instead of using the generic path + auto pfnGetInfo = d_context.urDdiTable.Mem.pfnGetInfo; + if( nullptr != pfnGetInfo ) + { + result = pfnGetInfo( hMemory, MemInfoType, propSize, pMemInfo, pPropSizeRet ); + } + else + { + // generic implementation + } + + return result; + } + + /////////////////////////////////////////////////////////////////////////////// + /// @brief Intercept function for urMemImageGetInfo + __urdlllocal ur_result_t UR_APICALL + urMemImageGetInfo( + ur_mem_handle_t hMemory, ///< [in] handle to the image object being queried. + ur_image_info_t ImgInfoType, ///< [in] type of image info to retrieve. + size_t propSize, ///< [in] the number of bytes of memory pointer to by pImgInfo. + void* pImgInfo, ///< [out][optional] array of bytes holding the info. + ///< If propSize is less than the real number of bytes needed to return + ///< the info then the ::UR_RESULT_ERROR_INVALID_SIZE error is returned and + ///< pImgInfo is not used. + size_t* pPropSizeRet ///< [out][optional] pointer to the actual size in bytes of data queried by pImgInfo. + ) + { + ur_result_t result = UR_RESULT_SUCCESS; + + // if the driver has created a custom function, then call it instead of using the generic path + auto pfnImageGetInfo = d_context.urDdiTable.Mem.pfnImageGetInfo; + if( nullptr != pfnImageGetInfo ) + { + result = pfnImageGetInfo( hMemory, ImgInfoType, propSize, pImgInfo, pPropSizeRet ); + } + else + { + // generic implementation + } + + return result; + } + + /////////////////////////////////////////////////////////////////////////////// + /// @brief Intercept function for urTearDown + __urdlllocal ur_result_t UR_APICALL + urTearDown( + void* pParams ///< [in] pointer to tear down parameters + ) + { + ur_result_t result = UR_RESULT_SUCCESS; + + // if the driver has created a custom function, then call it instead of using the generic path + auto pfnTearDown = d_context.urDdiTable.Global.pfnTearDown; + if( nullptr != pfnTearDown ) + { + result = pfnTearDown( pParams ); + } + else + { + // generic implementation + } + + return result; + } + + /////////////////////////////////////////////////////////////////////////////// + /// @brief Intercept function for urQueueGetInfo + __urdlllocal ur_result_t UR_APICALL + urQueueGetInfo( + ur_queue_handle_t hQueue, ///< [in] handle of the queue object + ur_queue_info_t propName, ///< [in] name of the queue property to query + size_t propValueSize, ///< [in] size in bytes of the queue property value provided + void* pPropValue, ///< [out] value of the queue property + size_t* pPropSizeRet ///< [out] size in bytes returned in queue property value + ) + { + ur_result_t result = UR_RESULT_SUCCESS; + + // if the driver has created a custom function, then call it instead of using the generic path + auto pfnGetInfo = d_context.urDdiTable.Queue.pfnGetInfo; + if( nullptr != pfnGetInfo ) + { + result = pfnGetInfo( hQueue, propName, propValueSize, pPropValue, pPropSizeRet ); + } + else + { + // generic implementation + } + + return result; + } + + /////////////////////////////////////////////////////////////////////////////// + /// @brief Intercept function for urQueueCreate + __urdlllocal ur_result_t UR_APICALL + urQueueCreate( + ur_context_handle_t hContext, ///< [in] handle of the context object + ur_device_handle_t hDevice, ///< [in] handle of the device object + ur_queue_flags_t props, ///< [in] initialization properties. + ///< must be 0 (default) or a combination of ::ur_queue_flags_t. + ur_queue_handle_t* phQueue ///< [out] pointer to handle of queue object created + ) + { + ur_result_t result = UR_RESULT_SUCCESS; + + // if the driver has created a custom function, then call it instead of using the generic path + auto pfnCreate = d_context.urDdiTable.Queue.pfnCreate; + if( nullptr != pfnCreate ) + { + result = pfnCreate( hContext, hDevice, props, phQueue ); + } + else + { + // generic implementation + *phQueue = reinterpret_cast( d_context.get() ); + + } + + return result; + } + + /////////////////////////////////////////////////////////////////////////////// + /// @brief Intercept function for urQueueRetain + __urdlllocal ur_result_t UR_APICALL + urQueueRetain( + ur_queue_handle_t hQueue ///< [in] handle of the queue object to get access + ) + { + ur_result_t result = UR_RESULT_SUCCESS; + + // if the driver has created a custom function, then call it instead of using the generic path + auto pfnRetain = d_context.urDdiTable.Queue.pfnRetain; + if( nullptr != pfnRetain ) + { + result = pfnRetain( hQueue ); + } + else + { + // generic implementation + } + + return result; + } + + /////////////////////////////////////////////////////////////////////////////// + /// @brief Intercept function for urQueueRelease + __urdlllocal ur_result_t UR_APICALL + urQueueRelease( + ur_queue_handle_t hQueue ///< [in] handle of the queue object to release + ) + { + ur_result_t result = UR_RESULT_SUCCESS; + + // if the driver has created a custom function, then call it instead of using the generic path + auto pfnRelease = d_context.urDdiTable.Queue.pfnRelease; + if( nullptr != pfnRelease ) + { + result = pfnRelease( hQueue ); + } + else + { + // generic implementation + } + + return result; + } + + /////////////////////////////////////////////////////////////////////////////// + /// @brief Intercept function for urQueueGetNativeHandle + __urdlllocal ur_result_t UR_APICALL + urQueueGetNativeHandle( + ur_queue_handle_t hQueue, ///< [in] handle of the queue. + ur_native_handle_t* phNativeQueue ///< [out] a pointer to the native handle of the queue. + ) + { + ur_result_t result = UR_RESULT_SUCCESS; + + // if the driver has created a custom function, then call it instead of using the generic path + auto pfnGetNativeHandle = d_context.urDdiTable.Queue.pfnGetNativeHandle; + if( nullptr != pfnGetNativeHandle ) + { + result = pfnGetNativeHandle( hQueue, phNativeQueue ); + } + else + { + // generic implementation + *phNativeQueue = reinterpret_cast( d_context.get() ); + + } + + return result; + } + + /////////////////////////////////////////////////////////////////////////////// + /// @brief Intercept function for urQueueCreateWithNativeHandle + __urdlllocal ur_result_t UR_APICALL + urQueueCreateWithNativeHandle( + ur_native_handle_t hNativeQueue, ///< [in] the native handle of the queue. + ur_context_handle_t hContext, ///< [in] handle of the context object + ur_queue_handle_t* phQueue ///< [out] pointer to the handle of the queue object created. + ) + { + ur_result_t result = UR_RESULT_SUCCESS; + + // if the driver has created a custom function, then call it instead of using the generic path + auto pfnCreateWithNativeHandle = d_context.urDdiTable.Queue.pfnCreateWithNativeHandle; + if( nullptr != pfnCreateWithNativeHandle ) + { + result = pfnCreateWithNativeHandle( hNativeQueue, hContext, phQueue ); + } + else + { + // generic implementation + *phQueue = reinterpret_cast( d_context.get() ); + + } + + return result; + } + + /////////////////////////////////////////////////////////////////////////////// + /// @brief Intercept function for urQueueFinish + __urdlllocal ur_result_t UR_APICALL + urQueueFinish( + ur_queue_handle_t hQueue ///< [in] handle of the queue to be finished. + ) + { + ur_result_t result = UR_RESULT_SUCCESS; + + // if the driver has created a custom function, then call it instead of using the generic path + auto pfnFinish = d_context.urDdiTable.Queue.pfnFinish; + if( nullptr != pfnFinish ) + { + result = pfnFinish( hQueue ); + } + else + { + // generic implementation + } + + return result; + } + + /////////////////////////////////////////////////////////////////////////////// + /// @brief Intercept function for urQueueFlush + __urdlllocal ur_result_t UR_APICALL + urQueueFlush( + ur_queue_handle_t hQueue ///< [in] handle of the queue to be flushed. + ) + { + ur_result_t result = UR_RESULT_SUCCESS; + + // if the driver has created a custom function, then call it instead of using the generic path + auto pfnFlush = d_context.urDdiTable.Queue.pfnFlush; + if( nullptr != pfnFlush ) + { + result = pfnFlush( hQueue ); + } + else + { + // generic implementation + } + + return result; + } + + /////////////////////////////////////////////////////////////////////////////// + /// @brief Intercept function for urSamplerCreate + __urdlllocal ur_result_t UR_APICALL + urSamplerCreate( + ur_context_handle_t hContext, ///< [in] handle of the context object + const ur_sampler_property_value_t* pProps, ///< [in] specifies a list of sampler property names and their + ///< corresponding values. + ur_sampler_handle_t* phSampler ///< [out] pointer to handle of sampler object created + ) + { + ur_result_t result = UR_RESULT_SUCCESS; + + // if the driver has created a custom function, then call it instead of using the generic path + auto pfnCreate = d_context.urDdiTable.Sampler.pfnCreate; + if( nullptr != pfnCreate ) + { + result = pfnCreate( hContext, pProps, phSampler ); + } + else + { + // generic implementation + *phSampler = reinterpret_cast( d_context.get() ); + + } + + return result; + } + + /////////////////////////////////////////////////////////////////////////////// + /// @brief Intercept function for urSamplerRetain + __urdlllocal ur_result_t UR_APICALL + urSamplerRetain( + ur_sampler_handle_t hSampler ///< [in] handle of the sampler object to get access + ) + { + ur_result_t result = UR_RESULT_SUCCESS; + + // if the driver has created a custom function, then call it instead of using the generic path + auto pfnRetain = d_context.urDdiTable.Sampler.pfnRetain; + if( nullptr != pfnRetain ) + { + result = pfnRetain( hSampler ); + } + else + { + // generic implementation + } + + return result; + } + + /////////////////////////////////////////////////////////////////////////////// + /// @brief Intercept function for urSamplerRelease + __urdlllocal ur_result_t UR_APICALL + urSamplerRelease( + ur_sampler_handle_t hSampler ///< [in] handle of the sampler object to release + ) + { + ur_result_t result = UR_RESULT_SUCCESS; + + // if the driver has created a custom function, then call it instead of using the generic path + auto pfnRelease = d_context.urDdiTable.Sampler.pfnRelease; + if( nullptr != pfnRelease ) + { + result = pfnRelease( hSampler ); + } + else + { + // generic implementation + } + + return result; + } + + /////////////////////////////////////////////////////////////////////////////// + /// @brief Intercept function for urSamplerGetInfo + __urdlllocal ur_result_t UR_APICALL + urSamplerGetInfo( + ur_sampler_handle_t hSampler, ///< [in] handle of the sampler object + ur_sampler_info_t propName, ///< [in] name of the sampler property to query + size_t propValueSize, ///< [in] size in bytes of the sampler property value provided + void* pPropValue, ///< [out] value of the sampler property + size_t* pPropSizeRet ///< [out] size in bytes returned in sampler property value + ) + { + ur_result_t result = UR_RESULT_SUCCESS; + + // if the driver has created a custom function, then call it instead of using the generic path + auto pfnGetInfo = d_context.urDdiTable.Sampler.pfnGetInfo; + if( nullptr != pfnGetInfo ) + { + result = pfnGetInfo( hSampler, propName, propValueSize, pPropValue, pPropSizeRet ); + } + else + { + // generic implementation + } + + return result; + } + + /////////////////////////////////////////////////////////////////////////////// + /// @brief Intercept function for urSamplerGetNativeHandle + __urdlllocal ur_result_t UR_APICALL + urSamplerGetNativeHandle( + ur_sampler_handle_t hSampler, ///< [in] handle of the sampler. + ur_native_handle_t* phNativeSampler ///< [out] a pointer to the native handle of the sampler. + ) + { + ur_result_t result = UR_RESULT_SUCCESS; + + // if the driver has created a custom function, then call it instead of using the generic path + auto pfnGetNativeHandle = d_context.urDdiTable.Sampler.pfnGetNativeHandle; + if( nullptr != pfnGetNativeHandle ) + { + result = pfnGetNativeHandle( hSampler, phNativeSampler ); + } + else + { + // generic implementation + *phNativeSampler = reinterpret_cast( d_context.get() ); + + } + + return result; + } + + /////////////////////////////////////////////////////////////////////////////// + /// @brief Intercept function for urSamplerCreateWithNativeHandle + __urdlllocal ur_result_t UR_APICALL + urSamplerCreateWithNativeHandle( + ur_native_handle_t hNativeSampler, ///< [in] the native handle of the sampler. + ur_context_handle_t hContext, ///< [in] handle of the context object + ur_sampler_handle_t* phSampler ///< [out] pointer to the handle of the sampler object created. + ) + { + ur_result_t result = UR_RESULT_SUCCESS; + + // if the driver has created a custom function, then call it instead of using the generic path + auto pfnCreateWithNativeHandle = d_context.urDdiTable.Sampler.pfnCreateWithNativeHandle; + if( nullptr != pfnCreateWithNativeHandle ) + { + result = pfnCreateWithNativeHandle( hNativeSampler, hContext, phSampler ); + } + else + { + // generic implementation + *phSampler = reinterpret_cast( d_context.get() ); + + } + + return result; + } + + /////////////////////////////////////////////////////////////////////////////// + /// @brief Intercept function for urUSMHostAlloc + __urdlllocal ur_result_t UR_APICALL + urUSMHostAlloc( + ur_context_handle_t hContext, ///< [in] handle of the context object + ur_usm_mem_flags_t* pUSMFlag, ///< [in] USM memory allocation flags + size_t size, ///< [in] size in bytes of the USM memory object to be allocated + uint32_t align, ///< [in] alignment of the USM memory object + void** ppMem ///< [out] pointer to USM host memory object + ) + { + ur_result_t result = UR_RESULT_SUCCESS; + + // if the driver has created a custom function, then call it instead of using the generic path + auto pfnHostAlloc = d_context.urDdiTable.USM.pfnHostAlloc; + if( nullptr != pfnHostAlloc ) + { + result = pfnHostAlloc( hContext, pUSMFlag, size, align, ppMem ); + } + else + { + // generic implementation + } + + return result; + } + + /////////////////////////////////////////////////////////////////////////////// + /// @brief Intercept function for urUSMDeviceAlloc + __urdlllocal ur_result_t UR_APICALL + urUSMDeviceAlloc( + ur_context_handle_t hContext, ///< [in] handle of the context object + ur_device_handle_t hDevice, ///< [in] handle of the device object + ur_usm_mem_flags_t* pUSMProp, ///< [in] USM memory properties + size_t size, ///< [in] size in bytes of the USM memory object to be allocated + uint32_t align, ///< [in] alignment of the USM memory object + void** ppMem ///< [out] pointer to USM device memory object + ) + { + ur_result_t result = UR_RESULT_SUCCESS; + + // if the driver has created a custom function, then call it instead of using the generic path + auto pfnDeviceAlloc = d_context.urDdiTable.USM.pfnDeviceAlloc; + if( nullptr != pfnDeviceAlloc ) + { + result = pfnDeviceAlloc( hContext, hDevice, pUSMProp, size, align, ppMem ); + } + else + { + // generic implementation + } + + return result; + } + + /////////////////////////////////////////////////////////////////////////////// + /// @brief Intercept function for urUSMSharedAlloc + __urdlllocal ur_result_t UR_APICALL + urUSMSharedAlloc( + ur_context_handle_t hContext, ///< [in] handle of the context object + ur_device_handle_t hDevice, ///< [in] handle of the device object + ur_usm_mem_flags_t* pUSMProp, ///< [in] USM memory properties + size_t size, ///< [in] size in bytes of the USM memory object to be allocated + uint32_t align, ///< [in] alignment of the USM memory object + void** ppMem ///< [out] pointer to USM shared memory object + ) + { + ur_result_t result = UR_RESULT_SUCCESS; + + // if the driver has created a custom function, then call it instead of using the generic path + auto pfnSharedAlloc = d_context.urDdiTable.USM.pfnSharedAlloc; + if( nullptr != pfnSharedAlloc ) + { + result = pfnSharedAlloc( hContext, hDevice, pUSMProp, size, align, ppMem ); + } + else + { + // generic implementation + } + + return result; + } + + /////////////////////////////////////////////////////////////////////////////// + /// @brief Intercept function for urMemFree + __urdlllocal ur_result_t UR_APICALL + urMemFree( + ur_context_handle_t hContext, ///< [in] handle of the context object + void* pMem ///< [in] pointer to USM memory object + ) + { + ur_result_t result = UR_RESULT_SUCCESS; + + // if the driver has created a custom function, then call it instead of using the generic path + auto pfnFree = d_context.urDdiTable.Mem.pfnFree; + if( nullptr != pfnFree ) + { + result = pfnFree( hContext, pMem ); + } + else + { + // generic implementation + } + + return result; + } + + /////////////////////////////////////////////////////////////////////////////// + /// @brief Intercept function for urMemGetMemAllocInfo + __urdlllocal ur_result_t UR_APICALL + urMemGetMemAllocInfo( + ur_context_handle_t hContext, ///< [in] handle of the context object + const void* pMem, ///< [in] pointer to USM memory object + ur_mem_alloc_info_t propName, ///< [in] the name of the USM allocation property to query + size_t propValueSize, ///< [in] size in bytes of the USM allocation property value + void* pPropValue, ///< [out] value of the USM allocation property + size_t* pPropValueSizeRet ///< [out] bytes returned in USM allocation property + ) + { + ur_result_t result = UR_RESULT_SUCCESS; + + // if the driver has created a custom function, then call it instead of using the generic path + auto pfnGetMemAllocInfo = d_context.urDdiTable.Mem.pfnGetMemAllocInfo; + if( nullptr != pfnGetMemAllocInfo ) + { + result = pfnGetMemAllocInfo( hContext, pMem, propName, propValueSize, pPropValue, pPropValueSizeRet ); + } + else + { + // generic implementation + } + + return result; + } + + /////////////////////////////////////////////////////////////////////////////// + /// @brief Intercept function for urDeviceGet + __urdlllocal ur_result_t UR_APICALL + urDeviceGet( + ur_platform_handle_t hPlatform, ///< [in] handle of the platform instance + ur_device_type_t DeviceType, ///< [in] the type of the devices. + uint32_t NumEntries, ///< [in] the number of devices to be added to phDevices. + ///< If phDevices in not NULL then NumEntries should be greater than zero, + ///< otherwise ::UR_RESULT_ERROR_INVALID_SIZE, + ///< will be returned. + ur_device_handle_t* phDevices, ///< [out][optional][range(0, NumEntries)] array of handle of devices. + ///< If NumEntries is less than the number of devices available, then + ///< platform shall only retrieve that number of devices. + uint32_t* pNumDevices ///< [out][optional] pointer to the number of devices. + ///< pNumDevices will be updated with the total number of devices available. + ) + { + ur_result_t result = UR_RESULT_SUCCESS; + + // if the driver has created a custom function, then call it instead of using the generic path + auto pfnGet = d_context.urDdiTable.Device.pfnGet; + if( nullptr != pfnGet ) + { + result = pfnGet( hPlatform, DeviceType, NumEntries, phDevices, pNumDevices ); + } + else + { + // generic implementation + for( size_t i = 0; ( nullptr != phDevices ) && ( i < NumEntries ); ++i ) + phDevices[ i ] = reinterpret_cast( d_context.get() ); + + } + + return result; + } + + /////////////////////////////////////////////////////////////////////////////// + /// @brief Intercept function for urDeviceGetInfo + __urdlllocal ur_result_t UR_APICALL + urDeviceGetInfo( + ur_device_handle_t hDevice, ///< [in] handle of the device instance + ur_device_info_t infoType, ///< [in] type of the info to retrieve + size_t propSize, ///< [in] the number of bytes pointed to by pDeviceInfo. + void* pDeviceInfo, ///< [out][optional] 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 ::UR_RESULT_ERROR_INVALID_SIZE error is returned and + ///< pDeviceInfo is not used. + size_t* pPropSizeRet ///< [out][optional] pointer to the actual size in bytes of the queried infoType. + ) + { + ur_result_t result = UR_RESULT_SUCCESS; + + // if the driver has created a custom function, then call it instead of using the generic path + auto pfnGetInfo = d_context.urDdiTable.Device.pfnGetInfo; + if( nullptr != pfnGetInfo ) + { + result = pfnGetInfo( hDevice, infoType, propSize, pDeviceInfo, pPropSizeRet ); + } + else + { + // generic implementation + } + + return result; + } + + /////////////////////////////////////////////////////////////////////////////// + /// @brief Intercept function for urDeviceRetain + __urdlllocal ur_result_t UR_APICALL + urDeviceRetain( + ur_device_handle_t hDevice ///< [in] handle of the device to get a reference of. + ) + { + ur_result_t result = UR_RESULT_SUCCESS; + + // if the driver has created a custom function, then call it instead of using the generic path + auto pfnRetain = d_context.urDdiTable.Device.pfnRetain; + if( nullptr != pfnRetain ) + { + result = pfnRetain( hDevice ); + } + else + { + // generic implementation + } + + return result; + } + + /////////////////////////////////////////////////////////////////////////////// + /// @brief Intercept function for urDeviceRelease + __urdlllocal ur_result_t UR_APICALL + urDeviceRelease( + ur_device_handle_t hDevice ///< [in] handle of the device to release. + ) + { + ur_result_t result = UR_RESULT_SUCCESS; + + // if the driver has created a custom function, then call it instead of using the generic path + auto pfnRelease = d_context.urDdiTable.Device.pfnRelease; + if( nullptr != pfnRelease ) + { + result = pfnRelease( hDevice ); + } + else + { + // generic implementation + } + + return result; + } + + /////////////////////////////////////////////////////////////////////////////// + /// @brief Intercept function for urDevicePartition + __urdlllocal ur_result_t UR_APICALL + urDevicePartition( + ur_device_handle_t hDevice, ///< [in] handle of the device to partition. + ur_device_partition_property_value_t* Properties, ///< [in] null-terminated array of pair of the requested partitioning. + uint32_t NumDevices, ///< [in] the number of sub-devices. + ur_device_handle_t* phSubDevices, ///< [out][optional][range(0, NumDevices)] array of handle of devices. + ///< If NumDevices is less than the number of sub-devices available, then + ///< the function shall only retrieve that number of sub-devices. + uint32_t* pNumDevicesRet ///< [out][optional] pointer to the number of sub-devices the device can be + ///< partitioned into according to the partitioning property. + ) + { + ur_result_t result = UR_RESULT_SUCCESS; + + // if the driver has created a custom function, then call it instead of using the generic path + auto pfnPartition = d_context.urDdiTable.Device.pfnPartition; + if( nullptr != pfnPartition ) + { + result = pfnPartition( hDevice, Properties, NumDevices, phSubDevices, pNumDevicesRet ); + } + else + { + // generic implementation + for( size_t i = 0; ( nullptr != phSubDevices ) && ( i < NumDevices ); ++i ) + phSubDevices[ i ] = reinterpret_cast( d_context.get() ); + + } + + return result; + } + + /////////////////////////////////////////////////////////////////////////////// + /// @brief Intercept function for urDeviceSelectBinary + __urdlllocal ur_result_t UR_APICALL + urDeviceSelectBinary( + ur_device_handle_t hDevice, ///< [in] handle of the device to select binary for. + const uint8_t** ppBinaries, ///< [in] the array of binaries to select from. + uint32_t NumBinaries, ///< [in] the number of binaries passed in ppBinaries. Must greater than or + ///< equal to zero. + uint32_t* pSelectedBinary ///< [out] the index of the selected binary in the input array of binaries. + ///< If a suitable binary was not found the function returns ${X}_INVALID_BINARY. + ) + { + ur_result_t result = UR_RESULT_SUCCESS; + + // if the driver has created a custom function, then call it instead of using the generic path + auto pfnSelectBinary = d_context.urDdiTable.Device.pfnSelectBinary; + if( nullptr != pfnSelectBinary ) + { + result = pfnSelectBinary( hDevice, ppBinaries, NumBinaries, pSelectedBinary ); + } + else + { + // generic implementation + } + + return result; + } + + /////////////////////////////////////////////////////////////////////////////// + /// @brief Intercept function for urDeviceGetNativeHandle + __urdlllocal ur_result_t UR_APICALL + urDeviceGetNativeHandle( + ur_device_handle_t hDevice, ///< [in] handle of the device. + ur_native_handle_t* phNativeDevice ///< [out] a pointer to the native handle of the device. + ) + { + ur_result_t result = UR_RESULT_SUCCESS; + + // if the driver has created a custom function, then call it instead of using the generic path + auto pfnGetNativeHandle = d_context.urDdiTable.Device.pfnGetNativeHandle; + if( nullptr != pfnGetNativeHandle ) + { + result = pfnGetNativeHandle( hDevice, phNativeDevice ); + } + else + { + // generic implementation + *phNativeDevice = reinterpret_cast( d_context.get() ); + + } + + return result; + } + + /////////////////////////////////////////////////////////////////////////////// + /// @brief Intercept function for urDeviceCreateWithNativeHandle + __urdlllocal ur_result_t UR_APICALL + urDeviceCreateWithNativeHandle( + ur_native_handle_t hNativeDevice, ///< [in] the native handle of the device. + ur_platform_handle_t hPlatform, ///< [in] handle of the platform instance + ur_device_handle_t* phDevice ///< [out] pointer to the handle of the device object created. + ) + { + ur_result_t result = UR_RESULT_SUCCESS; + + // if the driver has created a custom function, then call it instead of using the generic path + auto pfnCreateWithNativeHandle = d_context.urDdiTable.Device.pfnCreateWithNativeHandle; + if( nullptr != pfnCreateWithNativeHandle ) + { + result = pfnCreateWithNativeHandle( hNativeDevice, hPlatform, phDevice ); + } + else + { + // generic implementation + *phDevice = reinterpret_cast( d_context.get() ); + + } + + return result; + } + + /////////////////////////////////////////////////////////////////////////////// + /// @brief Intercept function for urKernelCreate + __urdlllocal ur_result_t UR_APICALL + urKernelCreate( + ur_program_handle_t hProgram, ///< [in] handle of the program instance + const char* pKernelName, ///< [in] pointer to null-terminated string. + ur_kernel_handle_t* phKernel ///< [out] pointer to handle of kernel object created. + ) + { + ur_result_t result = UR_RESULT_SUCCESS; + + // if the driver has created a custom function, then call it instead of using the generic path + auto pfnCreate = d_context.urDdiTable.Kernel.pfnCreate; + if( nullptr != pfnCreate ) + { + result = pfnCreate( hProgram, pKernelName, phKernel ); + } + else + { + // generic implementation + *phKernel = reinterpret_cast( d_context.get() ); + + } + + return result; + } + + /////////////////////////////////////////////////////////////////////////////// + /// @brief Intercept function for urKernelSetArg + __urdlllocal ur_result_t UR_APICALL + urKernelSetArg( + ur_kernel_handle_t hKernel, ///< [in] handle of the kernel object + uint32_t argIndex, ///< [in] argument index in range [0, num args - 1] + size_t argSize, ///< [in] size of argument type + const void* pArgValue ///< [in][optional] argument value represented as matching arg type. If + ///< null then argument value is considered null. + ) + { + ur_result_t result = UR_RESULT_SUCCESS; + + // if the driver has created a custom function, then call it instead of using the generic path + auto pfnSetArg = d_context.urDdiTable.Kernel.pfnSetArg; + if( nullptr != pfnSetArg ) + { + result = pfnSetArg( hKernel, argIndex, argSize, pArgValue ); + } + else + { + // generic implementation + } + + return result; + } + + /////////////////////////////////////////////////////////////////////////////// + /// @brief Intercept function for urKernelGetInfo + __urdlllocal ur_result_t UR_APICALL + urKernelGetInfo( + ur_kernel_handle_t hKernel, ///< [in] handle of the Kernel object + ur_kernel_info_t propName, ///< [in] name of the Kernel property to query + size_t propSize, ///< [in] the size of the Kernel property value. + void* pKernelInfo, ///< [in,out][optional] array of bytes holding the kernel info property. + ///< If propSize is not equal to or greater than the real number of bytes + ///< needed to return + ///< the info then the ::UR_RESULT_ERROR_INVALID_SIZE error is returned and + ///< pKernelInfo is not used. + size_t* pPropSizeRet ///< [out][optional] pointer to the actual size in bytes of data being + ///< queried by propName. + ) + { + ur_result_t result = UR_RESULT_SUCCESS; + + // if the driver has created a custom function, then call it instead of using the generic path + auto pfnGetInfo = d_context.urDdiTable.Kernel.pfnGetInfo; + if( nullptr != pfnGetInfo ) + { + result = pfnGetInfo( hKernel, propName, propSize, pKernelInfo, pPropSizeRet ); + } + else + { + // generic implementation + } + + return result; + } + + /////////////////////////////////////////////////////////////////////////////// + /// @brief Intercept function for urKernelGetGroupInfo + __urdlllocal ur_result_t UR_APICALL + urKernelGetGroupInfo( + ur_kernel_handle_t hKernel, ///< [in] handle of the Kernel object + ur_device_handle_t hDevice, ///< [in] handle of the Device object + ur_kernel_group_info_t propName, ///< [in] name of the work Group property to query + size_t propSize, ///< [in] size of the Kernel Work Group property value + void* pPropValue, ///< [in,out][optional][range(0, propSize)] value of the Kernel Work Group + ///< property. + size_t* pPropSizeRet ///< [out][optional] pointer to the actual size in bytes of data being + ///< queried by propName. + ) + { + ur_result_t result = UR_RESULT_SUCCESS; + + // if the driver has created a custom function, then call it instead of using the generic path + auto pfnGetGroupInfo = d_context.urDdiTable.Kernel.pfnGetGroupInfo; + if( nullptr != pfnGetGroupInfo ) + { + result = pfnGetGroupInfo( hKernel, hDevice, propName, propSize, pPropValue, pPropSizeRet ); + } + else + { + // generic implementation + } + + return result; + } + + /////////////////////////////////////////////////////////////////////////////// + /// @brief Intercept function for urKernelGetSubGroupInfo + __urdlllocal ur_result_t UR_APICALL + urKernelGetSubGroupInfo( + ur_kernel_handle_t hKernel, ///< [in] handle of the Kernel object + ur_device_handle_t hDevice, ///< [in] handle of the Device object + ur_kernel_sub_group_info_t propName, ///< [in] name of the SubGroup property to query + size_t propSize, ///< [in] size of the Kernel SubGroup property value + void* pPropValue, ///< [in,out][range(0, propSize)][optional] value of the Kernel SubGroup + ///< property. + size_t* pPropSizeRet ///< [out][optional] pointer to the actual size in bytes of data being + ///< queried by propName. + ) + { + ur_result_t result = UR_RESULT_SUCCESS; + + // if the driver has created a custom function, then call it instead of using the generic path + auto pfnGetSubGroupInfo = d_context.urDdiTable.Kernel.pfnGetSubGroupInfo; + if( nullptr != pfnGetSubGroupInfo ) + { + result = pfnGetSubGroupInfo( hKernel, hDevice, propName, propSize, pPropValue, pPropSizeRet ); + } + else + { + // generic implementation + } + + return result; + } + + /////////////////////////////////////////////////////////////////////////////// + /// @brief Intercept function for urKernelRetain + __urdlllocal ur_result_t UR_APICALL + urKernelRetain( + ur_kernel_handle_t hKernel ///< [in] handle for the Kernel to retain + ) + { + ur_result_t result = UR_RESULT_SUCCESS; + + // if the driver has created a custom function, then call it instead of using the generic path + auto pfnRetain = d_context.urDdiTable.Kernel.pfnRetain; + if( nullptr != pfnRetain ) + { + result = pfnRetain( hKernel ); + } + else + { + // generic implementation + } + + return result; + } + + /////////////////////////////////////////////////////////////////////////////// + /// @brief Intercept function for urKernelRelease + __urdlllocal ur_result_t UR_APICALL + urKernelRelease( + ur_kernel_handle_t hKernel ///< [in] handle for the Kernel to release + ) + { + ur_result_t result = UR_RESULT_SUCCESS; + + // if the driver has created a custom function, then call it instead of using the generic path + auto pfnRelease = d_context.urDdiTable.Kernel.pfnRelease; + if( nullptr != pfnRelease ) + { + result = pfnRelease( hKernel ); + } + else + { + // generic implementation + } + + return result; + } + + /////////////////////////////////////////////////////////////////////////////// + /// @brief Intercept function for urKernelSetArgPointer + __urdlllocal ur_result_t UR_APICALL + urKernelSetArgPointer( + ur_kernel_handle_t hKernel, ///< [in] handle of the kernel object + uint32_t argIndex, ///< [in] argument index in range [0, num args - 1] + size_t argSize, ///< [in] size of argument type + const void* pArgValue ///< [in][optional] SVM pointer to memory location holding the argument + ///< value. If null then argument value is considered null. + ) + { + ur_result_t result = UR_RESULT_SUCCESS; + + // if the driver has created a custom function, then call it instead of using the generic path + auto pfnSetArgPointer = d_context.urDdiTable.Kernel.pfnSetArgPointer; + if( nullptr != pfnSetArgPointer ) + { + result = pfnSetArgPointer( hKernel, argIndex, argSize, pArgValue ); + } + else + { + // generic implementation + } + + return result; + } + + /////////////////////////////////////////////////////////////////////////////// + /// @brief Intercept function for urKernelSetExecInfo + __urdlllocal ur_result_t UR_APICALL + urKernelSetExecInfo( + ur_kernel_handle_t hKernel, ///< [in] handle of the kernel object + ur_kernel_exec_info_t propName, ///< [in] name of the execution attribute + size_t propSize, ///< [in] size in byte the attribute value + const void* pPropValue ///< [in][range(0, propSize)] pointer to memory location holding the + ///< property value. + ) + { + ur_result_t result = UR_RESULT_SUCCESS; + + // if the driver has created a custom function, then call it instead of using the generic path + auto pfnSetExecInfo = d_context.urDdiTable.Kernel.pfnSetExecInfo; + if( nullptr != pfnSetExecInfo ) + { + result = pfnSetExecInfo( hKernel, propName, propSize, pPropValue ); + } + else + { + // generic implementation + } + + return result; + } + + /////////////////////////////////////////////////////////////////////////////// + /// @brief Intercept function for urKernelSetArgSampler + __urdlllocal ur_result_t UR_APICALL + urKernelSetArgSampler( + ur_kernel_handle_t hKernel, ///< [in] handle of the kernel object + uint32_t argIndex, ///< [in] argument index in range [0, num args - 1] + ur_sampler_handle_t hArgValue ///< [in] handle of Sampler object. + ) + { + ur_result_t result = UR_RESULT_SUCCESS; + + // if the driver has created a custom function, then call it instead of using the generic path + auto pfnSetArgSampler = d_context.urDdiTable.Kernel.pfnSetArgSampler; + if( nullptr != pfnSetArgSampler ) + { + result = pfnSetArgSampler( hKernel, argIndex, hArgValue ); + } + else + { + // generic implementation + } + + return result; + } + + /////////////////////////////////////////////////////////////////////////////// + /// @brief Intercept function for urKernelSetArgMemObj + __urdlllocal ur_result_t UR_APICALL + urKernelSetArgMemObj( + ur_kernel_handle_t hKernel, ///< [in] handle of the kernel object + uint32_t argIndex, ///< [in] argument index in range [0, num args - 1] + ur_mem_handle_t hArgValue ///< [in] handle of Memory object. + ) + { + ur_result_t result = UR_RESULT_SUCCESS; + + // if the driver has created a custom function, then call it instead of using the generic path + auto pfnSetArgMemObj = d_context.urDdiTable.Kernel.pfnSetArgMemObj; + if( nullptr != pfnSetArgMemObj ) + { + result = pfnSetArgMemObj( hKernel, argIndex, hArgValue ); + } + else + { + // generic implementation + } + + return result; + } + + /////////////////////////////////////////////////////////////////////////////// + /// @brief Intercept function for urKernelGetNativeHandle + __urdlllocal ur_result_t UR_APICALL + urKernelGetNativeHandle( + ur_kernel_handle_t hKernel, ///< [in] handle of the kernel. + ur_native_handle_t* phNativeKernel ///< [out] a pointer to the native handle of the kernel. + ) + { + ur_result_t result = UR_RESULT_SUCCESS; + + // if the driver has created a custom function, then call it instead of using the generic path + auto pfnGetNativeHandle = d_context.urDdiTable.Kernel.pfnGetNativeHandle; + if( nullptr != pfnGetNativeHandle ) + { + result = pfnGetNativeHandle( hKernel, phNativeKernel ); + } + else + { + // generic implementation + *phNativeKernel = reinterpret_cast( d_context.get() ); + + } + + return result; + } + + /////////////////////////////////////////////////////////////////////////////// + /// @brief Intercept function for urKernelCreateWithNativeHandle + __urdlllocal ur_result_t UR_APICALL + urKernelCreateWithNativeHandle( + ur_native_handle_t hNativeKernel, ///< [in] the native handle of the kernel. + ur_context_handle_t hContext, ///< [in] handle of the context object + ur_kernel_handle_t* phKernel ///< [out] pointer to the handle of the kernel object created. + ) + { + ur_result_t result = UR_RESULT_SUCCESS; + + // if the driver has created a custom function, then call it instead of using the generic path + auto pfnCreateWithNativeHandle = d_context.urDdiTable.Kernel.pfnCreateWithNativeHandle; + if( nullptr != pfnCreateWithNativeHandle ) + { + result = pfnCreateWithNativeHandle( hNativeKernel, hContext, phKernel ); + } + else + { + // generic implementation + *phKernel = reinterpret_cast( d_context.get() ); + + } + + return result; + } + + /////////////////////////////////////////////////////////////////////////////// + /// @brief Intercept function for urModuleCreate + __urdlllocal ur_result_t UR_APICALL + urModuleCreate( + ur_context_handle_t hContext, ///< [in] handle of the context instance. + const void* pIL, ///< [in] pointer to IL string. + size_t length, ///< [in] length of IL in bytes. + const char* pOptions, ///< [in] pointer to compiler options null-terminated string. + ur_modulecreate_callback_t pfnNotify, ///< [in][optional] A function pointer to a notification routine that is + ///< called when program compilation is complete. + void* pUserData, ///< [in][optional] Passed as an argument when pfnNotify is called. + ur_module_handle_t* phModule ///< [out] pointer to handle of Module object created. + ) + { + ur_result_t result = UR_RESULT_SUCCESS; + + // if the driver has created a custom function, then call it instead of using the generic path + auto pfnCreate = d_context.urDdiTable.Module.pfnCreate; + if( nullptr != pfnCreate ) + { + result = pfnCreate( hContext, pIL, length, pOptions, pfnNotify, pUserData, phModule ); + } + else + { + // generic implementation + *phModule = reinterpret_cast( d_context.get() ); + + } + + return result; + } + + /////////////////////////////////////////////////////////////////////////////// + /// @brief Intercept function for urModuleRetain + __urdlllocal ur_result_t UR_APICALL + urModuleRetain( + ur_module_handle_t hModule ///< [in] handle for the Module to retain + ) + { + ur_result_t result = UR_RESULT_SUCCESS; + + // if the driver has created a custom function, then call it instead of using the generic path + auto pfnRetain = d_context.urDdiTable.Module.pfnRetain; + if( nullptr != pfnRetain ) + { + result = pfnRetain( hModule ); + } + else + { + // generic implementation + } + + return result; + } + + /////////////////////////////////////////////////////////////////////////////// + /// @brief Intercept function for urModuleRelease + __urdlllocal ur_result_t UR_APICALL + urModuleRelease( + ur_module_handle_t hModule ///< [in] handle for the Module to release + ) + { + ur_result_t result = UR_RESULT_SUCCESS; + + // if the driver has created a custom function, then call it instead of using the generic path + auto pfnRelease = d_context.urDdiTable.Module.pfnRelease; + if( nullptr != pfnRelease ) + { + result = pfnRelease( hModule ); + } + else + { + // generic implementation + } + + return result; + } + + /////////////////////////////////////////////////////////////////////////////// + /// @brief Intercept function for urModuleGetNativeHandle + __urdlllocal ur_result_t UR_APICALL + urModuleGetNativeHandle( + ur_module_handle_t hModule, ///< [in] handle of the module. + ur_native_handle_t* phNativeModule ///< [out] a pointer to the native handle of the module. + ) + { + ur_result_t result = UR_RESULT_SUCCESS; + + // if the driver has created a custom function, then call it instead of using the generic path + auto pfnGetNativeHandle = d_context.urDdiTable.Module.pfnGetNativeHandle; + if( nullptr != pfnGetNativeHandle ) + { + result = pfnGetNativeHandle( hModule, phNativeModule ); + } + else + { + // generic implementation + *phNativeModule = reinterpret_cast( d_context.get() ); + + } + + return result; + } + + /////////////////////////////////////////////////////////////////////////////// + /// @brief Intercept function for urModuleCreateWithNativeHandle + __urdlllocal ur_result_t UR_APICALL + urModuleCreateWithNativeHandle( + ur_native_handle_t hNativeModule, ///< [in] the native handle of the module. + ur_context_handle_t hContext, ///< [in] handle of the context instance. + ur_module_handle_t* phModule ///< [out] pointer to the handle of the module object created. + ) + { + ur_result_t result = UR_RESULT_SUCCESS; + + // if the driver has created a custom function, then call it instead of using the generic path + auto pfnCreateWithNativeHandle = d_context.urDdiTable.Module.pfnCreateWithNativeHandle; + if( nullptr != pfnCreateWithNativeHandle ) + { + result = pfnCreateWithNativeHandle( hNativeModule, hContext, phModule ); + } + else + { + // generic implementation + *phModule = reinterpret_cast( d_context.get() ); + + } + + return result; + } + + /////////////////////////////////////////////////////////////////////////////// + /// @brief Intercept function for urPlatformGet + __urdlllocal ur_result_t UR_APICALL + urPlatformGet( + uint32_t NumEntries, ///< [in] the number of platforms to be added to phPlatforms. + ///< If phPlatforms is not NULL, then NumEntries should be greater than + ///< zero, otherwise ::UR_RESULT_ERROR_INVALID_SIZE, + ///< will be returned. + ur_platform_handle_t* phPlatforms, ///< [out][optional][range(0, NumEntries)] array of handle of platforms. + ///< If NumEntries is less than the number of platforms available, then + ///< ::urPlatformGet shall only retrieve that number of platforms. + uint32_t* pNumPlatforms ///< [out][optional] returns the total number of platforms available. + ) + { + ur_result_t result = UR_RESULT_SUCCESS; + + // if the driver has created a custom function, then call it instead of using the generic path + auto pfnGet = d_context.urDdiTable.Platform.pfnGet; + if( nullptr != pfnGet ) + { + result = pfnGet( NumEntries, phPlatforms, pNumPlatforms ); + } + else + { + // generic implementation + for( size_t i = 0; ( nullptr != phPlatforms ) && ( i < NumEntries ); ++i ) + phPlatforms[ i ] = reinterpret_cast( d_context.get() ); + + } + + return result; + } + + /////////////////////////////////////////////////////////////////////////////// + /// @brief Intercept function for urPlatformGetInfo + __urdlllocal ur_result_t UR_APICALL + urPlatformGetInfo( + ur_platform_handle_t hPlatform, ///< [in] handle of the platform + ur_platform_info_t PlatformInfoType, ///< [in] type of the info to retrieve + size_t Size, ///< [in] the number of bytes pointed to by pPlatformInfo. + void* pPlatformInfo, ///< [out][optional] 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 ::UR_RESULT_ERROR_INVALID_SIZE error is + ///< returned and pPlatformInfo is not used. + size_t* pSizeRet ///< [out][optional] pointer to the actual number of bytes being queried by pPlatformInfo. + ) + { + ur_result_t result = UR_RESULT_SUCCESS; + + // if the driver has created a custom function, then call it instead of using the generic path + auto pfnGetInfo = d_context.urDdiTable.Platform.pfnGetInfo; + if( nullptr != pfnGetInfo ) + { + result = pfnGetInfo( hPlatform, PlatformInfoType, Size, pPlatformInfo, pSizeRet ); + } + else + { + // generic implementation + } + + return result; + } + + /////////////////////////////////////////////////////////////////////////////// + /// @brief Intercept function for urPlatformGetApiVersion + __urdlllocal ur_result_t UR_APICALL + urPlatformGetApiVersion( + ur_platform_handle_t hDriver, ///< [in] handle of the platform + ur_api_version_t* pVersion ///< [out] api version + ) + { + ur_result_t result = UR_RESULT_SUCCESS; + + // if the driver has created a custom function, then call it instead of using the generic path + auto pfnGetApiVersion = d_context.urDdiTable.Platform.pfnGetApiVersion; + if( nullptr != pfnGetApiVersion ) + { + result = pfnGetApiVersion( hDriver, pVersion ); + } + else + { + // generic implementation + } + + return result; + } + + /////////////////////////////////////////////////////////////////////////////// + /// @brief Intercept function for urPlatformGetNativeHandle + __urdlllocal ur_result_t UR_APICALL + urPlatformGetNativeHandle( + ur_platform_handle_t hPlatform, ///< [in] handle of the platform. + ur_native_handle_t* phNativePlatform ///< [out] a pointer to the native handle of the platform. + ) + { + ur_result_t result = UR_RESULT_SUCCESS; + + // if the driver has created a custom function, then call it instead of using the generic path + auto pfnGetNativeHandle = d_context.urDdiTable.Platform.pfnGetNativeHandle; + if( nullptr != pfnGetNativeHandle ) + { + result = pfnGetNativeHandle( hPlatform, phNativePlatform ); + } + else + { + // generic implementation + *phNativePlatform = reinterpret_cast( d_context.get() ); + + } + + return result; + } + + /////////////////////////////////////////////////////////////////////////////// + /// @brief Intercept function for urPlatformCreateWithNativeHandle + __urdlllocal ur_result_t UR_APICALL + urPlatformCreateWithNativeHandle( + ur_native_handle_t hNativePlatform, ///< [in] the native handle of the platform. + ur_platform_handle_t* phPlatform ///< [out] pointer to the handle of the platform object created. + ) + { + ur_result_t result = UR_RESULT_SUCCESS; + + // if the driver has created a custom function, then call it instead of using the generic path + auto pfnCreateWithNativeHandle = d_context.urDdiTable.Platform.pfnCreateWithNativeHandle; + if( nullptr != pfnCreateWithNativeHandle ) + { + result = pfnCreateWithNativeHandle( hNativePlatform, phPlatform ); + } + else + { + // generic implementation + *phPlatform = reinterpret_cast( d_context.get() ); + + } + + return result; + } + + /////////////////////////////////////////////////////////////////////////////// + /// @brief Intercept function for urGetLastResult + __urdlllocal ur_result_t UR_APICALL + urGetLastResult( + ur_platform_handle_t hPlatform, ///< [in] handle of the platform instance + const char** ppMessage ///< [out] pointer to a string containing adapter specific result in string + ///< representation. + ) + { + ur_result_t result = UR_RESULT_SUCCESS; + + // if the driver has created a custom function, then call it instead of using the generic path + auto pfnGetLastResult = d_context.urDdiTable.Global.pfnGetLastResult; + if( nullptr != pfnGetLastResult ) + { + result = pfnGetLastResult( hPlatform, ppMessage ); + } + else + { + // generic implementation + } + + return result; + } + + /////////////////////////////////////////////////////////////////////////////// + /// @brief Intercept function for urProgramCreate + __urdlllocal ur_result_t UR_APICALL + urProgramCreate( + ur_context_handle_t hContext, ///< [in] handle of the context instance + uint32_t count, ///< [in] number of module handles in module list. + const ur_module_handle_t* phModules, ///< [in][range(0, count)] pointer to array of modules. + const char* pOptions, ///< [in][optional] pointer to linker options null-terminated string. + ur_program_handle_t* phProgram ///< [out] pointer to handle of program object created. + ) + { + ur_result_t result = UR_RESULT_SUCCESS; + + // if the driver has created a custom function, then call it instead of using the generic path + auto pfnCreate = d_context.urDdiTable.Program.pfnCreate; + if( nullptr != pfnCreate ) + { + result = pfnCreate( hContext, count, phModules, pOptions, phProgram ); + } + else + { + // generic implementation + *phProgram = reinterpret_cast( d_context.get() ); + + } + + return result; + } + + /////////////////////////////////////////////////////////////////////////////// + /// @brief Intercept function for urProgramCreateWithBinary + __urdlllocal ur_result_t UR_APICALL + urProgramCreateWithBinary( + ur_context_handle_t hContext, ///< [in] handle of the context instance + ur_device_handle_t hDevice, ///< [in] handle to device associated with binary. + size_t size, ///< [in] size in bytes. + const uint8_t* pBinary, ///< [in] pointer to binary. + ur_program_handle_t* phProgram ///< [out] pointer to handle of Program object created. + ) + { + ur_result_t result = UR_RESULT_SUCCESS; + + // if the driver has created a custom function, then call it instead of using the generic path + auto pfnCreateWithBinary = d_context.urDdiTable.Program.pfnCreateWithBinary; + if( nullptr != pfnCreateWithBinary ) + { + result = pfnCreateWithBinary( hContext, hDevice, size, pBinary, phProgram ); + } + else + { + // generic implementation + *phProgram = reinterpret_cast( d_context.get() ); + + } + + return result; + } + + /////////////////////////////////////////////////////////////////////////////// + /// @brief Intercept function for urProgramRetain + __urdlllocal ur_result_t UR_APICALL + urProgramRetain( + ur_program_handle_t hProgram ///< [in] handle for the Program to retain + ) + { + ur_result_t result = UR_RESULT_SUCCESS; + + // if the driver has created a custom function, then call it instead of using the generic path + auto pfnRetain = d_context.urDdiTable.Program.pfnRetain; + if( nullptr != pfnRetain ) + { + result = pfnRetain( hProgram ); + } + else + { + // generic implementation + } + + return result; + } + + /////////////////////////////////////////////////////////////////////////////// + /// @brief Intercept function for urProgramRelease + __urdlllocal ur_result_t UR_APICALL + urProgramRelease( + ur_program_handle_t hProgram ///< [in] handle for the Program to release + ) + { + ur_result_t result = UR_RESULT_SUCCESS; + + // if the driver has created a custom function, then call it instead of using the generic path + auto pfnRelease = d_context.urDdiTable.Program.pfnRelease; + if( nullptr != pfnRelease ) + { + result = pfnRelease( hProgram ); + } + else + { + // generic implementation + } + + return result; + } + + /////////////////////////////////////////////////////////////////////////////// + /// @brief Intercept function for urProgramGetFunctionPointer + __urdlllocal ur_result_t UR_APICALL + urProgramGetFunctionPointer( + ur_device_handle_t hDevice, ///< [in] handle of the device to retrieve pointer for. + ur_program_handle_t hProgram, ///< [in] handle of the program to search for function in. + ///< The program must already be built to the specified device, or + ///< otherwise ::UR_RESULT_ERROR_INVALID_PROGRAM_EXECUTABLE is returned. + const char* pFunctionName, ///< [in] A null-terminates string denoting the mangled function name. + void** ppFunctionPointer ///< [out] Returns the pointer to the function if it is found in the program. + ) + { + ur_result_t result = UR_RESULT_SUCCESS; + + // if the driver has created a custom function, then call it instead of using the generic path + auto pfnGetFunctionPointer = d_context.urDdiTable.Program.pfnGetFunctionPointer; + if( nullptr != pfnGetFunctionPointer ) + { + result = pfnGetFunctionPointer( hDevice, hProgram, pFunctionName, ppFunctionPointer ); + } + else + { + // generic implementation + } + + return result; + } + + /////////////////////////////////////////////////////////////////////////////// + /// @brief Intercept function for urProgramGetInfo + __urdlllocal ur_result_t UR_APICALL + urProgramGetInfo( + ur_program_handle_t hProgram, ///< [in] handle of the Program object + ur_program_info_t propName, ///< [in] name of the Program property to query + size_t propSize, ///< [in] the size of the Program property. + void* pProgramInfo, ///< [in,out][optional] array of bytes of holding the program info property. + ///< If propSize is not equal to or greater than the real number of bytes + ///< needed to return + ///< the info then the ::UR_RESULT_ERROR_INVALID_SIZE error is returned and + ///< pProgramInfo is not used. + size_t* pPropSizeRet ///< [out][optional] pointer to the actual size in bytes of data copied to propName. + ) + { + ur_result_t result = UR_RESULT_SUCCESS; + + // if the driver has created a custom function, then call it instead of using the generic path + auto pfnGetInfo = d_context.urDdiTable.Program.pfnGetInfo; + if( nullptr != pfnGetInfo ) + { + result = pfnGetInfo( hProgram, propName, propSize, pProgramInfo, pPropSizeRet ); + } + else + { + // generic implementation + } + + return result; + } + + /////////////////////////////////////////////////////////////////////////////// + /// @brief Intercept function for urProgramGetBuildInfo + __urdlllocal ur_result_t UR_APICALL + urProgramGetBuildInfo( + ur_program_handle_t hProgram, ///< [in] handle of the Program object + ur_device_handle_t hDevice, ///< [in] handle of the Device object + ur_program_build_info_t propName, ///< [in] name of the Program build info to query + size_t propSize, ///< [in] size of the Program build info property. + void* pPropValue, ///< [in,out][optional] value of the Program build property. + ///< If propSize is not equal to or greater than the real number of bytes + ///< needed to return the info then the ::UR_RESULT_ERROR_INVALID_SIZE + ///< error is returned and pKernelInfo is not used. + size_t* pPropSizeRet ///< [out][optional] pointer to the actual size in bytes of data being + ///< queried by propName. + ) + { + ur_result_t result = UR_RESULT_SUCCESS; + + // if the driver has created a custom function, then call it instead of using the generic path + auto pfnGetBuildInfo = d_context.urDdiTable.Program.pfnGetBuildInfo; + if( nullptr != pfnGetBuildInfo ) + { + result = pfnGetBuildInfo( hProgram, hDevice, propName, propSize, pPropValue, pPropSizeRet ); + } + else + { + // generic implementation + } + + return result; + } + + /////////////////////////////////////////////////////////////////////////////// + /// @brief Intercept function for urProgramSetSpecializationConstant + __urdlllocal ur_result_t UR_APICALL + urProgramSetSpecializationConstant( + ur_program_handle_t hProgram, ///< [in] handle of the Program object + uint32_t specId, ///< [in] specification constant Id + size_t specSize, ///< [in] size of the specialization constant value + const void* pSpecValue ///< [in] pointer to the specialization value bytes + ) + { + ur_result_t result = UR_RESULT_SUCCESS; + + // if the driver has created a custom function, then call it instead of using the generic path + auto pfnSetSpecializationConstant = d_context.urDdiTable.Program.pfnSetSpecializationConstant; + if( nullptr != pfnSetSpecializationConstant ) + { + result = pfnSetSpecializationConstant( hProgram, specId, specSize, pSpecValue ); + } + else + { + // generic implementation + } + + return result; + } + + /////////////////////////////////////////////////////////////////////////////// + /// @brief Intercept function for urProgramGetNativeHandle + __urdlllocal ur_result_t UR_APICALL + urProgramGetNativeHandle( + ur_program_handle_t hProgram, ///< [in] handle of the program. + ur_native_handle_t* phNativeProgram ///< [out] a pointer to the native handle of the program. + ) + { + ur_result_t result = UR_RESULT_SUCCESS; + + // if the driver has created a custom function, then call it instead of using the generic path + auto pfnGetNativeHandle = d_context.urDdiTable.Program.pfnGetNativeHandle; + if( nullptr != pfnGetNativeHandle ) + { + result = pfnGetNativeHandle( hProgram, phNativeProgram ); + } + else + { + // generic implementation + *phNativeProgram = reinterpret_cast( d_context.get() ); + + } + + return result; + } + + /////////////////////////////////////////////////////////////////////////////// + /// @brief Intercept function for urProgramCreateWithNativeHandle + __urdlllocal ur_result_t UR_APICALL + urProgramCreateWithNativeHandle( + ur_native_handle_t hNativeProgram, ///< [in] the native handle of the program. + ur_context_handle_t hContext, ///< [in] handle of the context instance + ur_program_handle_t* phProgram ///< [out] pointer to the handle of the program object created. + ) + { + ur_result_t result = UR_RESULT_SUCCESS; + + // if the driver has created a custom function, then call it instead of using the generic path + auto pfnCreateWithNativeHandle = d_context.urDdiTable.Program.pfnCreateWithNativeHandle; + if( nullptr != pfnCreateWithNativeHandle ) + { + result = pfnCreateWithNativeHandle( hNativeProgram, hContext, phProgram ); + } + else + { + // generic implementation + *phProgram = reinterpret_cast( d_context.get() ); + + } + + return result; + } + + /////////////////////////////////////////////////////////////////////////////// + /// @brief Intercept function for urInit + __urdlllocal ur_result_t UR_APICALL + urInit( + ur_platform_init_flags_t platform_flags, ///< [in] platform initialization flags. + ///< must be 0 (default) or a combination of ::ur_platform_init_flag_t. + ur_device_init_flags_t device_flags ///< [in] device initialization flags. + ///< must be 0 (default) or a combination of ::ur_device_init_flag_t. + ) + { + ur_result_t result = UR_RESULT_SUCCESS; + + // if the driver has created a custom function, then call it instead of using the generic path + auto pfnInit = d_context.urDdiTable.Global.pfnInit; + if( nullptr != pfnInit ) + { + result = pfnInit( platform_flags, device_flags ); + } + else + { + // generic implementation + } + + return result; + } + +} // namespace driver + +#if defined(__cplusplus) +extern "C" { +#endif + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Exported function for filling application's Global table +/// with current process' addresses +/// +/// @returns +/// - ::UR_RESULT_SUCCESS +/// - ::UR_RESULT_ERROR_INVALID_NULL_POINTER +/// - ::UR_RESULT_ERROR_UNSUPPORTED_VERSION +UR_DLLEXPORT ur_result_t UR_APICALL +urGetGlobalProcAddrTable( + ur_api_version_t version, ///< [in] API version requested + ur_global_dditable_t* pDdiTable ///< [in,out] pointer to table of DDI function pointers + ) +{ + if( nullptr == pDdiTable ) + return UR_RESULT_ERROR_INVALID_NULL_POINTER; + + if( driver::d_context.version < version ) + return UR_RESULT_ERROR_UNSUPPORTED_VERSION; + + ur_result_t result = UR_RESULT_SUCCESS; + + pDdiTable->pfnTearDown = driver::urTearDown; + + pDdiTable->pfnGetLastResult = driver::urGetLastResult; + + pDdiTable->pfnInit = driver::urInit; + + return result; +} + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Exported function for filling application's Context table +/// with current process' addresses +/// +/// @returns +/// - ::UR_RESULT_SUCCESS +/// - ::UR_RESULT_ERROR_INVALID_NULL_POINTER +/// - ::UR_RESULT_ERROR_UNSUPPORTED_VERSION +UR_DLLEXPORT ur_result_t UR_APICALL +urGetContextProcAddrTable( + ur_api_version_t version, ///< [in] API version requested + ur_context_dditable_t* pDdiTable ///< [in,out] pointer to table of DDI function pointers + ) +{ + if( nullptr == pDdiTable ) + return UR_RESULT_ERROR_INVALID_NULL_POINTER; + + if( driver::d_context.version < version ) + return UR_RESULT_ERROR_UNSUPPORTED_VERSION; + + ur_result_t result = UR_RESULT_SUCCESS; + + pDdiTable->pfnCreate = driver::urContextCreate; + + pDdiTable->pfnRetain = driver::urContextRetain; + + pDdiTable->pfnRelease = driver::urContextRelease; + + pDdiTable->pfnGetInfo = driver::urContextGetInfo; + + pDdiTable->pfnGetNativeHandle = driver::urContextGetNativeHandle; + + pDdiTable->pfnCreateWithNativeHandle = driver::urContextCreateWithNativeHandle; + + pDdiTable->pfnSetExtendedDeleter = driver::urContextSetExtendedDeleter; + + return result; +} + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Exported function for filling application's Enqueue table +/// with current process' addresses +/// +/// @returns +/// - ::UR_RESULT_SUCCESS +/// - ::UR_RESULT_ERROR_INVALID_NULL_POINTER +/// - ::UR_RESULT_ERROR_UNSUPPORTED_VERSION +UR_DLLEXPORT ur_result_t UR_APICALL +urGetEnqueueProcAddrTable( + ur_api_version_t version, ///< [in] API version requested + ur_enqueue_dditable_t* pDdiTable ///< [in,out] pointer to table of DDI function pointers + ) +{ + if( nullptr == pDdiTable ) + return UR_RESULT_ERROR_INVALID_NULL_POINTER; + + if( driver::d_context.version < version ) + return UR_RESULT_ERROR_UNSUPPORTED_VERSION; + + ur_result_t result = UR_RESULT_SUCCESS; + + pDdiTable->pfnKernelLaunch = driver::urEnqueueKernelLaunch; + + pDdiTable->pfnEventsWait = driver::urEnqueueEventsWait; + + pDdiTable->pfnEventsWaitWithBarrier = driver::urEnqueueEventsWaitWithBarrier; + + pDdiTable->pfnMemBufferRead = driver::urEnqueueMemBufferRead; + + pDdiTable->pfnMemBufferWrite = driver::urEnqueueMemBufferWrite; + + pDdiTable->pfnMemBufferReadRect = driver::urEnqueueMemBufferReadRect; + + pDdiTable->pfnMemBufferWriteRect = driver::urEnqueueMemBufferWriteRect; + + pDdiTable->pfnMemBufferCopy = driver::urEnqueueMemBufferCopy; + + pDdiTable->pfnMemBufferCopyRect = driver::urEnqueueMemBufferCopyRect; + + pDdiTable->pfnMemBufferFill = driver::urEnqueueMemBufferFill; + + pDdiTable->pfnMemImageRead = driver::urEnqueueMemImageRead; + + pDdiTable->pfnMemImageWrite = driver::urEnqueueMemImageWrite; + + pDdiTable->pfnMemImageCopy = driver::urEnqueueMemImageCopy; + + pDdiTable->pfnMemBufferMap = driver::urEnqueueMemBufferMap; + + pDdiTable->pfnMemUnmap = driver::urEnqueueMemUnmap; + + pDdiTable->pfnUSMMemset = driver::urEnqueueUSMMemset; + + pDdiTable->pfnUSMMemcpy = driver::urEnqueueUSMMemcpy; + + pDdiTable->pfnUSMPrefetch = driver::urEnqueueUSMPrefetch; + + pDdiTable->pfnUSMMemAdvice = driver::urEnqueueUSMMemAdvice; + + return result; +} + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Exported function for filling application's Event table +/// with current process' addresses +/// +/// @returns +/// - ::UR_RESULT_SUCCESS +/// - ::UR_RESULT_ERROR_INVALID_NULL_POINTER +/// - ::UR_RESULT_ERROR_UNSUPPORTED_VERSION +UR_DLLEXPORT ur_result_t UR_APICALL +urGetEventProcAddrTable( + ur_api_version_t version, ///< [in] API version requested + ur_event_dditable_t* pDdiTable ///< [in,out] pointer to table of DDI function pointers + ) +{ + if( nullptr == pDdiTable ) + return UR_RESULT_ERROR_INVALID_NULL_POINTER; + + if( driver::d_context.version < version ) + return UR_RESULT_ERROR_UNSUPPORTED_VERSION; + + ur_result_t result = UR_RESULT_SUCCESS; + + pDdiTable->pfnGetInfo = driver::urEventGetInfo; + + pDdiTable->pfnGetProfilingInfo = driver::urEventGetProfilingInfo; + + pDdiTable->pfnWait = driver::urEventWait; + + pDdiTable->pfnRetain = driver::urEventRetain; + + pDdiTable->pfnRelease = driver::urEventRelease; + + pDdiTable->pfnGetNativeHandle = driver::urEventGetNativeHandle; + + pDdiTable->pfnCreateWithNativeHandle = driver::urEventCreateWithNativeHandle; + + pDdiTable->pfnSetCallback = driver::urEventSetCallback; + + return result; +} + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Exported function for filling application's Kernel table +/// with current process' addresses +/// +/// @returns +/// - ::UR_RESULT_SUCCESS +/// - ::UR_RESULT_ERROR_INVALID_NULL_POINTER +/// - ::UR_RESULT_ERROR_UNSUPPORTED_VERSION +UR_DLLEXPORT ur_result_t UR_APICALL +urGetKernelProcAddrTable( + ur_api_version_t version, ///< [in] API version requested + ur_kernel_dditable_t* pDdiTable ///< [in,out] pointer to table of DDI function pointers + ) +{ + if( nullptr == pDdiTable ) + return UR_RESULT_ERROR_INVALID_NULL_POINTER; + + if( driver::d_context.version < version ) + return UR_RESULT_ERROR_UNSUPPORTED_VERSION; + + ur_result_t result = UR_RESULT_SUCCESS; + + pDdiTable->pfnCreate = driver::urKernelCreate; + + pDdiTable->pfnGetInfo = driver::urKernelGetInfo; + + pDdiTable->pfnGetGroupInfo = driver::urKernelGetGroupInfo; + + pDdiTable->pfnGetSubGroupInfo = driver::urKernelGetSubGroupInfo; + + pDdiTable->pfnRetain = driver::urKernelRetain; + + pDdiTable->pfnRelease = driver::urKernelRelease; + + pDdiTable->pfnGetNativeHandle = driver::urKernelGetNativeHandle; + + pDdiTable->pfnCreateWithNativeHandle = driver::urKernelCreateWithNativeHandle; + + pDdiTable->pfnSetArg = driver::urKernelSetArg; + + pDdiTable->pfnSetArgPointer = driver::urKernelSetArgPointer; + + pDdiTable->pfnSetExecInfo = driver::urKernelSetExecInfo; + + pDdiTable->pfnSetArgSampler = driver::urKernelSetArgSampler; + + pDdiTable->pfnSetArgMemObj = driver::urKernelSetArgMemObj; + + return result; +} + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Exported function for filling application's Mem table +/// with current process' addresses +/// +/// @returns +/// - ::UR_RESULT_SUCCESS +/// - ::UR_RESULT_ERROR_INVALID_NULL_POINTER +/// - ::UR_RESULT_ERROR_UNSUPPORTED_VERSION +UR_DLLEXPORT ur_result_t UR_APICALL +urGetMemProcAddrTable( + ur_api_version_t version, ///< [in] API version requested + ur_mem_dditable_t* pDdiTable ///< [in,out] pointer to table of DDI function pointers + ) +{ + if( nullptr == pDdiTable ) + return UR_RESULT_ERROR_INVALID_NULL_POINTER; + + if( driver::d_context.version < version ) + return UR_RESULT_ERROR_UNSUPPORTED_VERSION; + + ur_result_t result = UR_RESULT_SUCCESS; + + pDdiTable->pfnImageCreate = driver::urMemImageCreate; + + pDdiTable->pfnBufferCreate = driver::urMemBufferCreate; + + pDdiTable->pfnRetain = driver::urMemRetain; + + pDdiTable->pfnRelease = driver::urMemRelease; + + pDdiTable->pfnBufferPartition = driver::urMemBufferPartition; + + pDdiTable->pfnGetNativeHandle = driver::urMemGetNativeHandle; + + pDdiTable->pfnCreateWithNativeHandle = driver::urMemCreateWithNativeHandle; + + pDdiTable->pfnGetInfo = driver::urMemGetInfo; + + pDdiTable->pfnImageGetInfo = driver::urMemImageGetInfo; + + pDdiTable->pfnFree = driver::urMemFree; + + pDdiTable->pfnGetMemAllocInfo = driver::urMemGetMemAllocInfo; + + return result; +} + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Exported function for filling application's Module table +/// with current process' addresses +/// +/// @returns +/// - ::UR_RESULT_SUCCESS +/// - ::UR_RESULT_ERROR_INVALID_NULL_POINTER +/// - ::UR_RESULT_ERROR_UNSUPPORTED_VERSION +UR_DLLEXPORT ur_result_t UR_APICALL +urGetModuleProcAddrTable( + ur_api_version_t version, ///< [in] API version requested + ur_module_dditable_t* pDdiTable ///< [in,out] pointer to table of DDI function pointers + ) +{ + if( nullptr == pDdiTable ) + return UR_RESULT_ERROR_INVALID_NULL_POINTER; + + if( driver::d_context.version < version ) + return UR_RESULT_ERROR_UNSUPPORTED_VERSION; + + ur_result_t result = UR_RESULT_SUCCESS; + + pDdiTable->pfnCreate = driver::urModuleCreate; + + pDdiTable->pfnRetain = driver::urModuleRetain; + + pDdiTable->pfnRelease = driver::urModuleRelease; + + pDdiTable->pfnGetNativeHandle = driver::urModuleGetNativeHandle; + + pDdiTable->pfnCreateWithNativeHandle = driver::urModuleCreateWithNativeHandle; + + return result; +} + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Exported function for filling application's Platform table +/// with current process' addresses +/// +/// @returns +/// - ::UR_RESULT_SUCCESS +/// - ::UR_RESULT_ERROR_INVALID_NULL_POINTER +/// - ::UR_RESULT_ERROR_UNSUPPORTED_VERSION +UR_DLLEXPORT ur_result_t UR_APICALL +urGetPlatformProcAddrTable( + ur_api_version_t version, ///< [in] API version requested + ur_platform_dditable_t* pDdiTable ///< [in,out] pointer to table of DDI function pointers + ) +{ + if( nullptr == pDdiTable ) + return UR_RESULT_ERROR_INVALID_NULL_POINTER; + + if( driver::d_context.version < version ) + return UR_RESULT_ERROR_UNSUPPORTED_VERSION; + + ur_result_t result = UR_RESULT_SUCCESS; + + pDdiTable->pfnGet = driver::urPlatformGet; + + pDdiTable->pfnGetInfo = driver::urPlatformGetInfo; + + pDdiTable->pfnGetNativeHandle = driver::urPlatformGetNativeHandle; + + pDdiTable->pfnCreateWithNativeHandle = driver::urPlatformCreateWithNativeHandle; + + pDdiTable->pfnGetApiVersion = driver::urPlatformGetApiVersion; + + return result; +} + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Exported function for filling application's Program table +/// with current process' addresses +/// +/// @returns +/// - ::UR_RESULT_SUCCESS +/// - ::UR_RESULT_ERROR_INVALID_NULL_POINTER +/// - ::UR_RESULT_ERROR_UNSUPPORTED_VERSION +UR_DLLEXPORT ur_result_t UR_APICALL +urGetProgramProcAddrTable( + ur_api_version_t version, ///< [in] API version requested + ur_program_dditable_t* pDdiTable ///< [in,out] pointer to table of DDI function pointers + ) +{ + if( nullptr == pDdiTable ) + return UR_RESULT_ERROR_INVALID_NULL_POINTER; + + if( driver::d_context.version < version ) + return UR_RESULT_ERROR_UNSUPPORTED_VERSION; + + ur_result_t result = UR_RESULT_SUCCESS; + + pDdiTable->pfnCreate = driver::urProgramCreate; + + pDdiTable->pfnCreateWithBinary = driver::urProgramCreateWithBinary; + + pDdiTable->pfnRetain = driver::urProgramRetain; + + pDdiTable->pfnRelease = driver::urProgramRelease; + + pDdiTable->pfnGetFunctionPointer = driver::urProgramGetFunctionPointer; + + pDdiTable->pfnGetInfo = driver::urProgramGetInfo; + + pDdiTable->pfnGetBuildInfo = driver::urProgramGetBuildInfo; + + pDdiTable->pfnSetSpecializationConstant = driver::urProgramSetSpecializationConstant; + + pDdiTable->pfnGetNativeHandle = driver::urProgramGetNativeHandle; + + pDdiTable->pfnCreateWithNativeHandle = driver::urProgramCreateWithNativeHandle; + + return result; +} + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Exported function for filling application's Queue table +/// with current process' addresses +/// +/// @returns +/// - ::UR_RESULT_SUCCESS +/// - ::UR_RESULT_ERROR_INVALID_NULL_POINTER +/// - ::UR_RESULT_ERROR_UNSUPPORTED_VERSION +UR_DLLEXPORT ur_result_t UR_APICALL +urGetQueueProcAddrTable( + ur_api_version_t version, ///< [in] API version requested + ur_queue_dditable_t* pDdiTable ///< [in,out] pointer to table of DDI function pointers + ) +{ + if( nullptr == pDdiTable ) + return UR_RESULT_ERROR_INVALID_NULL_POINTER; + + if( driver::d_context.version < version ) + return UR_RESULT_ERROR_UNSUPPORTED_VERSION; + + ur_result_t result = UR_RESULT_SUCCESS; + + pDdiTable->pfnGetInfo = driver::urQueueGetInfo; + + pDdiTable->pfnCreate = driver::urQueueCreate; + + pDdiTable->pfnRetain = driver::urQueueRetain; + + pDdiTable->pfnRelease = driver::urQueueRelease; + + pDdiTable->pfnGetNativeHandle = driver::urQueueGetNativeHandle; + + pDdiTable->pfnCreateWithNativeHandle = driver::urQueueCreateWithNativeHandle; + + pDdiTable->pfnFinish = driver::urQueueFinish; + + pDdiTable->pfnFlush = driver::urQueueFlush; + + return result; +} + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Exported function for filling application's Sampler table +/// with current process' addresses +/// +/// @returns +/// - ::UR_RESULT_SUCCESS +/// - ::UR_RESULT_ERROR_INVALID_NULL_POINTER +/// - ::UR_RESULT_ERROR_UNSUPPORTED_VERSION +UR_DLLEXPORT ur_result_t UR_APICALL +urGetSamplerProcAddrTable( + ur_api_version_t version, ///< [in] API version requested + ur_sampler_dditable_t* pDdiTable ///< [in,out] pointer to table of DDI function pointers + ) +{ + if( nullptr == pDdiTable ) + return UR_RESULT_ERROR_INVALID_NULL_POINTER; + + if( driver::d_context.version < version ) + return UR_RESULT_ERROR_UNSUPPORTED_VERSION; + + ur_result_t result = UR_RESULT_SUCCESS; + + pDdiTable->pfnCreate = driver::urSamplerCreate; + + pDdiTable->pfnRetain = driver::urSamplerRetain; + + pDdiTable->pfnRelease = driver::urSamplerRelease; + + pDdiTable->pfnGetInfo = driver::urSamplerGetInfo; + + pDdiTable->pfnGetNativeHandle = driver::urSamplerGetNativeHandle; + + pDdiTable->pfnCreateWithNativeHandle = driver::urSamplerCreateWithNativeHandle; + + return result; +} + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Exported function for filling application's USM table +/// with current process' addresses +/// +/// @returns +/// - ::UR_RESULT_SUCCESS +/// - ::UR_RESULT_ERROR_INVALID_NULL_POINTER +/// - ::UR_RESULT_ERROR_UNSUPPORTED_VERSION +UR_DLLEXPORT ur_result_t UR_APICALL +urGetUSMProcAddrTable( + ur_api_version_t version, ///< [in] API version requested + ur_usm_dditable_t* pDdiTable ///< [in,out] pointer to table of DDI function pointers + ) +{ + if( nullptr == pDdiTable ) + return UR_RESULT_ERROR_INVALID_NULL_POINTER; + + if( driver::d_context.version < version ) + return UR_RESULT_ERROR_UNSUPPORTED_VERSION; + + ur_result_t result = UR_RESULT_SUCCESS; + + pDdiTable->pfnHostAlloc = driver::urUSMHostAlloc; + + pDdiTable->pfnDeviceAlloc = driver::urUSMDeviceAlloc; + + pDdiTable->pfnSharedAlloc = driver::urUSMSharedAlloc; + + return result; +} + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Exported function for filling application's Device table +/// with current process' addresses +/// +/// @returns +/// - ::UR_RESULT_SUCCESS +/// - ::UR_RESULT_ERROR_INVALID_NULL_POINTER +/// - ::UR_RESULT_ERROR_UNSUPPORTED_VERSION +UR_DLLEXPORT ur_result_t UR_APICALL +urGetDeviceProcAddrTable( + ur_api_version_t version, ///< [in] API version requested + ur_device_dditable_t* pDdiTable ///< [in,out] pointer to table of DDI function pointers + ) +{ + if( nullptr == pDdiTable ) + return UR_RESULT_ERROR_INVALID_NULL_POINTER; + + if( driver::d_context.version < version ) + return UR_RESULT_ERROR_UNSUPPORTED_VERSION; + + ur_result_t result = UR_RESULT_SUCCESS; + + pDdiTable->pfnGet = driver::urDeviceGet; + + pDdiTable->pfnGetInfo = driver::urDeviceGetInfo; + + pDdiTable->pfnRetain = driver::urDeviceRetain; + + pDdiTable->pfnRelease = driver::urDeviceRelease; + + pDdiTable->pfnPartition = driver::urDevicePartition; + + pDdiTable->pfnSelectBinary = driver::urDeviceSelectBinary; + + pDdiTable->pfnGetNativeHandle = driver::urDeviceGetNativeHandle; + + pDdiTable->pfnCreateWithNativeHandle = driver::urDeviceCreateWithNativeHandle; + + return result; +} + +#if defined(__cplusplus) +}; +#endif diff --git a/source/loader/CMakeLists.txt b/source/loader/CMakeLists.txt new file mode 100644 index 0000000000..2d3abeba3a --- /dev/null +++ b/source/loader/CMakeLists.txt @@ -0,0 +1,90 @@ +# Copyright (C) 2022 Intel Corporation +# SPDX-License-Identifier: MIT + +configure_file( + ${CMAKE_CURRENT_SOURCE_DIR}/UrLoaderVersion.rc.in + ${CMAKE_CURRENT_BINARY_DIR}/UrLoaderVersion.rc + @ONLY) + +add_library(loader + SHARED + "" + ${CMAKE_CURRENT_BINARY_DIR}/UrLoaderVersion.rc +) + +set_target_properties(loader PROPERTIES + LIBRARY_OUTPUT_NAME ur_loader +) + +add_library(${PROJECT_NAME}::loader ALIAS loader) + +target_include_directories(loader PRIVATE + ${CMAKE_SOURCE_DIR} + ${CMAKE_SOURCE_DIR}/source/common + ${CMAKE_SOURCE_DIR}/source/loader +) + +set_target_properties(loader PROPERTIES + VERSION "${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}.${PROJECT_VERSION_PATCH}" + SOVERSION "${PROJECT_VERSION_MAJOR}" +) + +target_link_libraries(loader + ${PROJECT_NAME}::headers + ${CMAKE_DL_LIBS} +) + +if (UNIX) + set(CMAKE_THREAD_PREFER_PTHREAD TRUE) + set(THREADS_PREFER_PTHREAD_FLAG TRUE) + find_package(Threads REQUIRED) + target_link_libraries(loader Threads::Threads) +endif() + +if(WIN32) + target_link_libraries(loader cfgmgr32.lib) +endif() + +if(UNIX) + configure_file( + ${CMAKE_CURRENT_SOURCE_DIR}/libur_loader.pc.in + ${CMAKE_CURRENT_BINARY_DIR}/libur_loader.pc + @ONLY) + install(FILES "${CMAKE_CURRENT_BINARY_DIR}/libur_loader.pc" DESTINATION "${CMAKE_INSTALL_FULL_LIBDIR}/pkgconfig" COMPONENT unified-runtime) +endif() + +install(TARGETS loader + EXPORT ${PROJECT_NAME}-targets + ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} + RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} + LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} +) + +target_sources(loader + PRIVATE + ${CMAKE_CURRENT_SOURCE_DIR}/ur_object.h + ${CMAKE_CURRENT_SOURCE_DIR}/ur_loader.h + ${CMAKE_CURRENT_SOURCE_DIR}/ur_loader.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/ur_ldrddi.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/ur_ldrddi.h + ${CMAKE_CURRENT_SOURCE_DIR}/ur_libapi.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/ur_libddi.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/ur_lib.h + ${CMAKE_CURRENT_SOURCE_DIR}/ur_lib.cpp +) + +if(WIN32) + target_sources(loader + PRIVATE + ${CMAKE_CURRENT_SOURCE_DIR}/windows/lib_init.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/windows/platform_discovery_win.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/windows/loader_init.cpp + ) +else() + target_sources(loader + PRIVATE + ${CMAKE_CURRENT_SOURCE_DIR}/linux/lib_init.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/linux/platform_discovery_lin.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/linux/loader_init.cpp + ) +endif() diff --git a/source/loader/UrLoaderVersion.rc.in b/source/loader/UrLoaderVersion.rc.in new file mode 100644 index 0000000000..dd9327ba83 --- /dev/null +++ b/source/loader/UrLoaderVersion.rc.in @@ -0,0 +1,33 @@ +#define VER_FILEVERSION @PROJECT_VERSION_MAJOR@,@PROJECT_VERSION_MINOR@,@PROJECT_VERSION_PATCH@ +#define VER_FILEVERSION_STR "@PROJECT_VERSION_MAJOR@.@PROJECT_VERSION_MINOR@.@PROJECT_VERSION_PATCH@\0" + +#define VER_PRODUCTVERSION @PROJECT_VERSION_MAJOR@,@PROJECT_VERSION_MINOR@,@PROJECT_VERSION_PATCH@ +#define VER_PRODUCTVERSION_STR "@PROJECT_VERSION_MAJOR@.@PROJECT_VERSION_MINOR@.@PROJECT_VERSION_PATCH@\0" + +#define VER_FILEDESCRIPTION_STR "oneAPI Unified Runtime Loader for Windows(R) Unified Runtime Drivers" + +#define VER_PRODUCT_NAME_STR "oneAPI Unified Runtime Zero Loader for Windows(R)" + +#define VER_LEGALCOPYRIGHT_STR "Copyright (C) 2022 Intel Corporation" + +1 VERSIONINFO +FILEVERSION VER_FILEVERSION +PRODUCTVERSION VER_PRODUCTVERSION +BEGIN + BLOCK "StringFileInfo" + BEGIN + BLOCK "040904E4" + BEGIN + VALUE "FileDescription", VER_FILEDESCRIPTION_STR + VALUE "FileVersion", VER_FILEVERSION_STR + VALUE "ProductVersion", VER_PRODUCTVERSION_STR + VALUE "ProductName", VER_PRODUCT_NAME_STR + VALUE "LegalCopyright", VER_LEGALCOPYRIGHT_STR + END + END + + BLOCK "VarFileInfo" + BEGIN + VALUE "Translation", 0x409, 1252 + END +END \ No newline at end of file diff --git a/source/loader/libur_loader.pc.in b/source/loader/libur_loader.pc.in new file mode 100644 index 0000000000..d79c3a9da8 --- /dev/null +++ b/source/loader/libur_loader.pc.in @@ -0,0 +1,14 @@ +prefix=@CMAKE_INSTALL_PREFIX@ +includedir=${prefix}/include +libdir=${prefix}/lib + + +Name: Unified Runtime Loader +Description: Unified Runtime Library Loader for Unified Runtime +URL: TBD +Version: @PROJECT_VERSION_MAJOR@.@PROJECT_VERSION_MINOR@.@PROJECT_VERSION_PATCH@ +Requires: +Libs: -L${libdir} -lur_loader +CFlags: -I${includedir} + + diff --git a/source/loader/linux/lib_init.cpp b/source/loader/linux/lib_init.cpp new file mode 100644 index 0000000000..85b30c59fb --- /dev/null +++ b/source/loader/linux/lib_init.cpp @@ -0,0 +1,22 @@ +/* + * + * Copyright (C) 2022 Intel Corporation + * + * SPDX-License-Identifier: MIT + * + */ + +#include "ur_lib.h" + +namespace ur_lib +{ + + void __attribute__((constructor)) createLibContext() { + context = new context_t; + } + + void __attribute__((destructor)) deleteLibContext() { + delete context; + } + +} diff --git a/source/loader/linux/loader_init.cpp b/source/loader/linux/loader_init.cpp new file mode 100644 index 0000000000..6bb9735ce7 --- /dev/null +++ b/source/loader/linux/loader_init.cpp @@ -0,0 +1,22 @@ +/* + * + * Copyright (C) 2022 Intel Corporation + * + * SPDX-License-Identifier: MIT + * + */ + +#include "ur_loader.h" + +namespace loader +{ + + void __attribute__((constructor)) createLoaderContext() { + context = new context_t; + } + + void __attribute__((destructor)) deleteLoaderContext() { + delete context; + } + +} diff --git a/source/loader/linux/platform_discovery_lin.cpp b/source/loader/linux/platform_discovery_lin.cpp new file mode 100644 index 0000000000..d28f8b9f8b --- /dev/null +++ b/source/loader/linux/platform_discovery_lin.cpp @@ -0,0 +1,43 @@ +/* + * + * Copyright (C) 2022 Intel Corporation + * + * SPDX-License-Identifier: MIT + * + */ + +#include "source/loader/platform_discovery.h" + +#include "ur_util.h" +#include +#include +#include + +namespace loader { + +static const char *knownPlatformNames[] = { + MAKE_LIBRARY_NAME("ur_null", UR_VERSION), +}; + +std::vector discoverEnabledPlatforms() { + std::vector enabledPlatforms; + const char *altPlatforms = nullptr; + + // UR_ENABLE_ALT_DRIVERS is for development/debug only + altPlatforms = getenv("UR_ENABLE_ALT_DRIVERS"); + if (altPlatforms == nullptr) { + for (auto path : knownPlatformNames) { + enabledPlatforms.emplace_back(path); + } + } else { + std::stringstream ss(altPlatforms); + while (ss.good()) { + std::string substr; + getline(ss, substr, ','); + enabledPlatforms.emplace_back(substr); + } + } + return enabledPlatforms; +} + +} // namespace loader diff --git a/source/loader/platform_discovery.h b/source/loader/platform_discovery.h new file mode 100644 index 0000000000..24e6eed5b6 --- /dev/null +++ b/source/loader/platform_discovery.h @@ -0,0 +1,23 @@ +/* + * + * Copyright (C) 2022 Intel Corporation + * + * SPDX-License-Identifier: MIT + * + */ + +#ifndef UR_LOADER_PLATFORM_DISCOVERY_H +#define UR_LOADER_PLATFORM_DISCOVERY_H 1 + +#include +#include + +namespace loader { + +using PlatformLibraryPath = std::string; + +std::vector discoverEnabledPlatforms(); + +} // namespace loader + +#endif /* UR_LOADER_PLATFORM_DISCOVERY_H */ diff --git a/source/loader/ur_ldrddi.cpp b/source/loader/ur_ldrddi.cpp new file mode 100644 index 0000000000..ac248b8b83 --- /dev/null +++ b/source/loader/ur_ldrddi.cpp @@ -0,0 +1,5008 @@ +/* + * + * Copyright (C) 2022 Intel Corporation + * + * SPDX-License-Identifier: MIT + * + * @file ur_ldrddi.cpp + * + */ +#include "ur_loader.h" + +namespace loader +{ + /////////////////////////////////////////////////////////////////////////////// + ur_platform_factory_t ur_platform_factory; + ur_device_factory_t ur_device_factory; + ur_context_factory_t ur_context_factory; + ur_event_factory_t ur_event_factory; + ur_program_factory_t ur_program_factory; + ur_module_factory_t ur_module_factory; + ur_kernel_factory_t ur_kernel_factory; + ur_queue_factory_t ur_queue_factory; + ur_native_factory_t ur_native_factory; + ur_sampler_factory_t ur_sampler_factory; + ur_mem_factory_t ur_mem_factory; + + /////////////////////////////////////////////////////////////////////////////// + /// @brief Intercept function for urContextCreate + __urdlllocal ur_result_t UR_APICALL + urContextCreate( + uint32_t DeviceCount, ///< [in] the number of devices given in phDevices + ur_device_handle_t* phDevices, ///< [in][range(0, DeviceCount)] array of handle of devices. + ur_context_handle_t* phContext ///< [out] pointer to handle of context object created + ) + { + ur_result_t result = UR_RESULT_SUCCESS; + + // extract platform's function pointer table + auto dditable = reinterpret_cast( *phDevices )->dditable; + auto pfnCreate = dditable->ur.Context.pfnCreate; + if( nullptr == pfnCreate ) + return UR_RESULT_ERROR_UNINITIALIZED; + + // convert loader handles to platform handles + auto phDevicesLocal = new ur_device_handle_t [DeviceCount]; + for( size_t i = 0; ( nullptr != phDevices ) && ( i < DeviceCount ); ++i ) + phDevicesLocal[ i ] = reinterpret_cast( phDevices[ i ] )->handle; + + // forward to device-platform + result = pfnCreate( DeviceCount, phDevices, phContext ); + delete []phDevicesLocal; + + if( UR_RESULT_SUCCESS != result ) + return result; + + try + { + // convert platform handle to loader handle + *phContext = reinterpret_cast( + ur_context_factory.getInstance( *phContext, dditable ) ); + } + catch( std::bad_alloc& ) + { + result = UR_RESULT_ERROR_OUT_OF_HOST_MEMORY; + } + + return result; + } + + /////////////////////////////////////////////////////////////////////////////// + /// @brief Intercept function for urContextRetain + __urdlllocal ur_result_t UR_APICALL + urContextRetain( + ur_context_handle_t hContext ///< [in] handle of the context to get a reference of. + ) + { + ur_result_t result = UR_RESULT_SUCCESS; + + // extract platform's function pointer table + auto dditable = reinterpret_cast( hContext )->dditable; + auto pfnRetain = dditable->ur.Context.pfnRetain; + if( nullptr == pfnRetain ) + return UR_RESULT_ERROR_UNINITIALIZED; + + // convert loader handle to platform handle + hContext = reinterpret_cast( hContext )->handle; + + // forward to device-platform + result = pfnRetain( hContext ); + + return result; + } + + /////////////////////////////////////////////////////////////////////////////// + /// @brief Intercept function for urContextRelease + __urdlllocal ur_result_t UR_APICALL + urContextRelease( + ur_context_handle_t hContext ///< [in] handle of the context to release. + ) + { + ur_result_t result = UR_RESULT_SUCCESS; + + // extract platform's function pointer table + auto dditable = reinterpret_cast( hContext )->dditable; + auto pfnRelease = dditable->ur.Context.pfnRelease; + if( nullptr == pfnRelease ) + return UR_RESULT_ERROR_UNINITIALIZED; + + // convert loader handle to platform handle + hContext = reinterpret_cast( hContext )->handle; + + // forward to device-platform + result = pfnRelease( hContext ); + + return result; + } + + /////////////////////////////////////////////////////////////////////////////// + /// @brief Intercept function for urContextGetInfo + __urdlllocal ur_result_t UR_APICALL + urContextGetInfo( + ur_context_handle_t hContext, ///< [in] handle of the context + ur_context_info_t ContextInfoType, ///< [in] type of the info to retrieve + size_t propSize, ///< [in] the number of bytes of memory pointed to by pContextInfo. + void* pContextInfo, ///< [out][optional] 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 ::UR_RESULT_ERROR_INVALID_SIZE error is returned and + ///< pContextInfo is not used. + size_t* pPropSizeRet ///< [out][optional] pointer to the actual size in bytes of data queried by ContextInfoType. + ) + { + ur_result_t result = UR_RESULT_SUCCESS; + + // extract platform's function pointer table + auto dditable = reinterpret_cast( hContext )->dditable; + auto pfnGetInfo = dditable->ur.Context.pfnGetInfo; + if( nullptr == pfnGetInfo ) + return UR_RESULT_ERROR_UNINITIALIZED; + + // convert loader handle to platform handle + hContext = reinterpret_cast( hContext )->handle; + + // forward to device-platform + result = pfnGetInfo( hContext, ContextInfoType, propSize, pContextInfo, pPropSizeRet ); + + return result; + } + + /////////////////////////////////////////////////////////////////////////////// + /// @brief Intercept function for urContextGetNativeHandle + __urdlllocal ur_result_t UR_APICALL + urContextGetNativeHandle( + ur_context_handle_t hContext, ///< [in] handle of the context. + ur_native_handle_t* phNativeContext ///< [out] a pointer to the native handle of the context. + ) + { + ur_result_t result = UR_RESULT_SUCCESS; + + // extract platform's function pointer table + auto dditable = reinterpret_cast( hContext )->dditable; + auto pfnGetNativeHandle = dditable->ur.Context.pfnGetNativeHandle; + if( nullptr == pfnGetNativeHandle ) + return UR_RESULT_ERROR_UNINITIALIZED; + + // convert loader handle to platform handle + hContext = reinterpret_cast( hContext )->handle; + + // forward to device-platform + result = pfnGetNativeHandle( hContext, phNativeContext ); + + if( UR_RESULT_SUCCESS != result ) + return result; + + try + { + // convert platform handle to loader handle + *phNativeContext = reinterpret_cast( + ur_native_factory.getInstance( *phNativeContext, dditable ) ); + } + catch( std::bad_alloc& ) + { + result = UR_RESULT_ERROR_OUT_OF_HOST_MEMORY; + } + + return result; + } + + /////////////////////////////////////////////////////////////////////////////// + /// @brief Intercept function for urContextCreateWithNativeHandle + __urdlllocal ur_result_t UR_APICALL + urContextCreateWithNativeHandle( + ur_native_handle_t hNativeContext, ///< [in] the native handle of the context. + ur_context_handle_t* phContext ///< [out] pointer to the handle of the context object created. + ) + { + ur_result_t result = UR_RESULT_SUCCESS; + + // extract platform's function pointer table + auto dditable = reinterpret_cast( hNativeContext )->dditable; + auto pfnCreateWithNativeHandle = dditable->ur.Context.pfnCreateWithNativeHandle; + if( nullptr == pfnCreateWithNativeHandle ) + return UR_RESULT_ERROR_UNINITIALIZED; + + // convert loader handle to platform handle + hNativeContext = reinterpret_cast( hNativeContext )->handle; + + // forward to device-platform + result = pfnCreateWithNativeHandle( hNativeContext, phContext ); + + if( UR_RESULT_SUCCESS != result ) + return result; + + try + { + // convert platform handle to loader handle + *phContext = reinterpret_cast( + ur_context_factory.getInstance( *phContext, dditable ) ); + } + catch( std::bad_alloc& ) + { + result = UR_RESULT_ERROR_OUT_OF_HOST_MEMORY; + } + + return result; + } + + /////////////////////////////////////////////////////////////////////////////// + /// @brief Intercept function for urContextSetExtendedDeleter + __urdlllocal ur_result_t UR_APICALL + urContextSetExtendedDeleter( + ur_context_handle_t hContext, ///< [in] handle of the context. + ur_context_extended_deleter_t pfnDeleter, ///< [in] Function pointer to extended deleter. + void* pUserData ///< [in][out] pointer to data to be passed to callback. + ) + { + ur_result_t result = UR_RESULT_SUCCESS; + + // extract platform's function pointer table + auto dditable = reinterpret_cast( hContext )->dditable; + auto pfnSetExtendedDeleter = dditable->ur.Context.pfnSetExtendedDeleter; + if( nullptr == pfnSetExtendedDeleter ) + return UR_RESULT_ERROR_UNINITIALIZED; + + // convert loader handle to platform handle + hContext = reinterpret_cast( hContext )->handle; + + // forward to device-platform + result = pfnSetExtendedDeleter( hContext, pfnDeleter, pUserData ); + + return result; + } + + /////////////////////////////////////////////////////////////////////////////// + /// @brief Intercept function for urEnqueueKernelLaunch + __urdlllocal ur_result_t UR_APICALL + urEnqueueKernelLaunch( + ur_queue_handle_t hQueue, ///< [in] handle of the queue object + ur_kernel_handle_t hKernel, ///< [in] handle of the kernel object + uint32_t workDim, ///< [in] number of dimensions, from 1 to 3, to specify the global and + ///< work-group work-items + const size_t* pGlobalWorkOffset, ///< [in] pointer to an array of workDim unsigned values that specify the + ///< offset used to calculate the global ID of a work-item + const size_t* pGlobalWorkSize, ///< [in] pointer to an array of workDim unsigned values that specify the + ///< number of global work-items in workDim that will execute the kernel + ///< function + const size_t* pLocalWorkSize, ///< [in][optional] pointer to an array of workDim unsigned values that + ///< specify the number of local work-items forming a work-group that will + ///< execute the kernel function. + ///< If nullptr, the runtime implementation will choose the work-group + ///< size. + uint32_t numEventsInWaitList, ///< [in] size of the event wait list + const ur_event_handle_t* phEventWaitList, ///< [in][optional][range(0, numEventsInWaitList)] pointer to a list of + ///< events that must be complete before the kernel execution. + ///< If nullptr, the numEventsInWaitList must be 0, indicating that no wait + ///< event. + ur_event_handle_t* phEvent ///< [in,out] return an event object that identifies this particular kernel + ///< execution instance. + ///< Contrary to clEnqueueNDRangeKernel, its input can not be a nullptr. + ///< TODO: change to allow nullptr. + ) + { + ur_result_t result = UR_RESULT_SUCCESS; + + // extract platform's function pointer table + auto dditable = reinterpret_cast( hQueue )->dditable; + auto pfnKernelLaunch = dditable->ur.Enqueue.pfnKernelLaunch; + if( nullptr == pfnKernelLaunch ) + return UR_RESULT_ERROR_UNINITIALIZED; + + // convert loader handle to platform handle + hQueue = reinterpret_cast( hQueue )->handle; + + // convert loader handle to platform handle + hKernel = reinterpret_cast( hKernel )->handle; + + // convert loader handles to platform handles + auto phEventWaitListLocal = new ur_event_handle_t [numEventsInWaitList]; + for( size_t i = 0; ( nullptr != phEventWaitList ) && ( i < numEventsInWaitList ); ++i ) + phEventWaitListLocal[ i ] = reinterpret_cast( phEventWaitList[ i ] )->handle; + + // forward to device-platform + result = pfnKernelLaunch( hQueue, hKernel, workDim, pGlobalWorkOffset, pGlobalWorkSize, pLocalWorkSize, numEventsInWaitList, phEventWaitList, phEvent ); + delete []phEventWaitListLocal; + + if( UR_RESULT_SUCCESS != result ) + return result; + + try + { + // convert platform handle to loader handle + *phEvent = reinterpret_cast( + ur_event_factory.getInstance( *phEvent, dditable ) ); + } + catch( std::bad_alloc& ) + { + result = UR_RESULT_ERROR_OUT_OF_HOST_MEMORY; + } + + return result; + } + + /////////////////////////////////////////////////////////////////////////////// + /// @brief Intercept function for urEnqueueEventsWait + __urdlllocal ur_result_t UR_APICALL + urEnqueueEventsWait( + ur_queue_handle_t hQueue, ///< [in] handle of the queue object + uint32_t numEventsInWaitList, ///< [in] size of the event wait list + const ur_event_handle_t* phEventWaitList, ///< [in][optional][range(0, numEventsInWaitList)] pointer to a list of + ///< events that must be complete before this command can be executed. + ///< If nullptr, the numEventsInWaitList must be 0, indicating that all + ///< previously enqueued commands + ///< must be complete. + ur_event_handle_t* phEvent ///< [in,out] return an event object that identifies this particular + ///< command instance. + ///< Input can not be a nullptr. + ///< TODO: change to allow nullptr. + ) + { + ur_result_t result = UR_RESULT_SUCCESS; + + // extract platform's function pointer table + auto dditable = reinterpret_cast( hQueue )->dditable; + auto pfnEventsWait = dditable->ur.Enqueue.pfnEventsWait; + if( nullptr == pfnEventsWait ) + return UR_RESULT_ERROR_UNINITIALIZED; + + // convert loader handle to platform handle + hQueue = reinterpret_cast( hQueue )->handle; + + // convert loader handles to platform handles + auto phEventWaitListLocal = new ur_event_handle_t [numEventsInWaitList]; + for( size_t i = 0; ( nullptr != phEventWaitList ) && ( i < numEventsInWaitList ); ++i ) + phEventWaitListLocal[ i ] = reinterpret_cast( phEventWaitList[ i ] )->handle; + + // forward to device-platform + result = pfnEventsWait( hQueue, numEventsInWaitList, phEventWaitList, phEvent ); + delete []phEventWaitListLocal; + + if( UR_RESULT_SUCCESS != result ) + return result; + + try + { + // convert platform handle to loader handle + *phEvent = reinterpret_cast( + ur_event_factory.getInstance( *phEvent, dditable ) ); + } + catch( std::bad_alloc& ) + { + result = UR_RESULT_ERROR_OUT_OF_HOST_MEMORY; + } + + return result; + } + + /////////////////////////////////////////////////////////////////////////////// + /// @brief Intercept function for urEnqueueEventsWaitWithBarrier + __urdlllocal ur_result_t UR_APICALL + urEnqueueEventsWaitWithBarrier( + ur_queue_handle_t hQueue, ///< [in] handle of the queue object + uint32_t numEventsInWaitList, ///< [in] size of the event wait list + const ur_event_handle_t* phEventWaitList, ///< [in][optional][range(0, numEventsInWaitList)] pointer to a list of + ///< events that must be complete before this command can be executed. + ///< If nullptr, the numEventsInWaitList must be 0, indicating that all + ///< previously enqueued commands + ///< must be complete. + ur_event_handle_t* phEvent ///< [in,out] return an event object that identifies this particular + ///< command instance. + ///< Input can not be a nullptr. + ///< TODO: change to allow nullptr. + ) + { + ur_result_t result = UR_RESULT_SUCCESS; + + // extract platform's function pointer table + auto dditable = reinterpret_cast( hQueue )->dditable; + auto pfnEventsWaitWithBarrier = dditable->ur.Enqueue.pfnEventsWaitWithBarrier; + if( nullptr == pfnEventsWaitWithBarrier ) + return UR_RESULT_ERROR_UNINITIALIZED; + + // convert loader handle to platform handle + hQueue = reinterpret_cast( hQueue )->handle; + + // convert loader handles to platform handles + auto phEventWaitListLocal = new ur_event_handle_t [numEventsInWaitList]; + for( size_t i = 0; ( nullptr != phEventWaitList ) && ( i < numEventsInWaitList ); ++i ) + phEventWaitListLocal[ i ] = reinterpret_cast( phEventWaitList[ i ] )->handle; + + // forward to device-platform + result = pfnEventsWaitWithBarrier( hQueue, numEventsInWaitList, phEventWaitList, phEvent ); + delete []phEventWaitListLocal; + + if( UR_RESULT_SUCCESS != result ) + return result; + + try + { + // convert platform handle to loader handle + *phEvent = reinterpret_cast( + ur_event_factory.getInstance( *phEvent, dditable ) ); + } + catch( std::bad_alloc& ) + { + result = UR_RESULT_ERROR_OUT_OF_HOST_MEMORY; + } + + return result; + } + + /////////////////////////////////////////////////////////////////////////////// + /// @brief Intercept function for urEnqueueMemBufferRead + __urdlllocal ur_result_t UR_APICALL + urEnqueueMemBufferRead( + ur_queue_handle_t hQueue, ///< [in] handle of the queue object + ur_mem_handle_t hBuffer, ///< [in] handle of the buffer object + bool blockingRead, ///< [in] indicates blocking (true), non-blocking (false) + size_t offset, ///< [in] offset in bytes in the buffer object + size_t size, ///< [in] size in bytes of data being read + void* pDst, ///< [in] pointer to host memory where data is to be read into + uint32_t numEventsInWaitList, ///< [in] size of the event wait list + const ur_event_handle_t* phEventWaitList, ///< [in][optional][range(0, numEventsInWaitList)] pointer to a list of + ///< events that must be complete before this command can be executed. + ///< If nullptr, the numEventsInWaitList must be 0, indicating that this + ///< command does not wait on any event to complete. + ur_event_handle_t* phEvent ///< [in,out] return an event object that identifies this particular + ///< command instance. + ///< Input can not be a nullptr. + ///< TODO: change to allow nullptr. + ) + { + ur_result_t result = UR_RESULT_SUCCESS; + + // extract platform's function pointer table + auto dditable = reinterpret_cast( hQueue )->dditable; + auto pfnMemBufferRead = dditable->ur.Enqueue.pfnMemBufferRead; + if( nullptr == pfnMemBufferRead ) + return UR_RESULT_ERROR_UNINITIALIZED; + + // convert loader handle to platform handle + hQueue = reinterpret_cast( hQueue )->handle; + + // convert loader handle to platform handle + hBuffer = reinterpret_cast( hBuffer )->handle; + + // convert loader handles to platform handles + auto phEventWaitListLocal = new ur_event_handle_t [numEventsInWaitList]; + for( size_t i = 0; ( nullptr != phEventWaitList ) && ( i < numEventsInWaitList ); ++i ) + phEventWaitListLocal[ i ] = reinterpret_cast( phEventWaitList[ i ] )->handle; + + // forward to device-platform + result = pfnMemBufferRead( hQueue, hBuffer, blockingRead, offset, size, pDst, numEventsInWaitList, phEventWaitList, phEvent ); + delete []phEventWaitListLocal; + + if( UR_RESULT_SUCCESS != result ) + return result; + + try + { + // convert platform handle to loader handle + *phEvent = reinterpret_cast( + ur_event_factory.getInstance( *phEvent, dditable ) ); + } + catch( std::bad_alloc& ) + { + result = UR_RESULT_ERROR_OUT_OF_HOST_MEMORY; + } + + return result; + } + + /////////////////////////////////////////////////////////////////////////////// + /// @brief Intercept function for urEnqueueMemBufferWrite + __urdlllocal ur_result_t UR_APICALL + urEnqueueMemBufferWrite( + ur_queue_handle_t hQueue, ///< [in] handle of the queue object + ur_mem_handle_t hBuffer, ///< [in] handle of the buffer object + bool blockingWrite, ///< [in] indicates blocking (true), non-blocking (false) + size_t offset, ///< [in] offset in bytes in the buffer object + size_t size, ///< [in] size in bytes of data being written + const void* pSrc, ///< [in] pointer to host memory where data is to be written from + uint32_t numEventsInWaitList, ///< [in] size of the event wait list + const ur_event_handle_t* phEventWaitList, ///< [in][optional][range(0, numEventsInWaitList)] pointer to a list of + ///< events that must be complete before this command can be executed. + ///< If nullptr, the numEventsInWaitList must be 0, indicating that this + ///< command does not wait on any event to complete. + ur_event_handle_t* phEvent ///< [in,out] return an event object that identifies this particular + ///< command instance. + ///< Input can not be a nullptr. + ///< TODO: change to allow nullptr. + ) + { + ur_result_t result = UR_RESULT_SUCCESS; + + // extract platform's function pointer table + auto dditable = reinterpret_cast( hQueue )->dditable; + auto pfnMemBufferWrite = dditable->ur.Enqueue.pfnMemBufferWrite; + if( nullptr == pfnMemBufferWrite ) + return UR_RESULT_ERROR_UNINITIALIZED; + + // convert loader handle to platform handle + hQueue = reinterpret_cast( hQueue )->handle; + + // convert loader handle to platform handle + hBuffer = reinterpret_cast( hBuffer )->handle; + + // convert loader handles to platform handles + auto phEventWaitListLocal = new ur_event_handle_t [numEventsInWaitList]; + for( size_t i = 0; ( nullptr != phEventWaitList ) && ( i < numEventsInWaitList ); ++i ) + phEventWaitListLocal[ i ] = reinterpret_cast( phEventWaitList[ i ] )->handle; + + // forward to device-platform + result = pfnMemBufferWrite( hQueue, hBuffer, blockingWrite, offset, size, pSrc, numEventsInWaitList, phEventWaitList, phEvent ); + delete []phEventWaitListLocal; + + if( UR_RESULT_SUCCESS != result ) + return result; + + try + { + // convert platform handle to loader handle + *phEvent = reinterpret_cast( + ur_event_factory.getInstance( *phEvent, dditable ) ); + } + catch( std::bad_alloc& ) + { + result = UR_RESULT_ERROR_OUT_OF_HOST_MEMORY; + } + + return result; + } + + /////////////////////////////////////////////////////////////////////////////// + /// @brief Intercept function for urEnqueueMemBufferReadRect + __urdlllocal ur_result_t UR_APICALL + urEnqueueMemBufferReadRect( + ur_queue_handle_t hQueue, ///< [in] handle of the queue object + ur_mem_handle_t hBuffer, ///< [in] handle of the buffer object + bool blockingRead, ///< [in] indicates blocking (true), non-blocking (false) + ur_rect_offset_t bufferOffset, ///< [in] 3D offset in the buffer + ur_rect_offset_t hostOffset, ///< [in] 3D offset in the host region + ur_rect_region_t region, ///< [in] 3D rectangular region descriptor: width, height, depth + size_t bufferRowPitch, ///< [in] length of each row in bytes in the buffer object + size_t bufferSlicePitch, ///< [in] length of each 2D slice in bytes in the buffer object being read + size_t hostRowPitch, ///< [in] length of each row in bytes in the host memory region pointed by + ///< dst + size_t hostSlicePitch, ///< [in] length of each 2D slice in bytes in the host memory region + ///< pointed by dst + void* pDst, ///< [in] pointer to host memory where data is to be read into + uint32_t numEventsInWaitList, ///< [in] size of the event wait list + const ur_event_handle_t* phEventWaitList, ///< [in][optional][range(0, numEventsInWaitList)] pointer to a list of + ///< events that must be complete before this command can be executed. + ///< If nullptr, the numEventsInWaitList must be 0, indicating that this + ///< command does not wait on any event to complete. + ur_event_handle_t* phEvent ///< [in,out] return an event object that identifies this particular + ///< command instance. + ///< Input can not be a nullptr. + ///< TODO: change to allow nullptr. + ) + { + ur_result_t result = UR_RESULT_SUCCESS; + + // extract platform's function pointer table + auto dditable = reinterpret_cast( hQueue )->dditable; + auto pfnMemBufferReadRect = dditable->ur.Enqueue.pfnMemBufferReadRect; + if( nullptr == pfnMemBufferReadRect ) + return UR_RESULT_ERROR_UNINITIALIZED; + + // convert loader handle to platform handle + hQueue = reinterpret_cast( hQueue )->handle; + + // convert loader handle to platform handle + hBuffer = reinterpret_cast( hBuffer )->handle; + + // convert loader handles to platform handles + auto phEventWaitListLocal = new ur_event_handle_t [numEventsInWaitList]; + for( size_t i = 0; ( nullptr != phEventWaitList ) && ( i < numEventsInWaitList ); ++i ) + phEventWaitListLocal[ i ] = reinterpret_cast( phEventWaitList[ i ] )->handle; + + // forward to device-platform + result = pfnMemBufferReadRect( hQueue, hBuffer, blockingRead, bufferOffset, hostOffset, region, bufferRowPitch, bufferSlicePitch, hostRowPitch, hostSlicePitch, pDst, numEventsInWaitList, phEventWaitList, phEvent ); + delete []phEventWaitListLocal; + + if( UR_RESULT_SUCCESS != result ) + return result; + + try + { + // convert platform handle to loader handle + *phEvent = reinterpret_cast( + ur_event_factory.getInstance( *phEvent, dditable ) ); + } + catch( std::bad_alloc& ) + { + result = UR_RESULT_ERROR_OUT_OF_HOST_MEMORY; + } + + return result; + } + + /////////////////////////////////////////////////////////////////////////////// + /// @brief Intercept function for urEnqueueMemBufferWriteRect + __urdlllocal ur_result_t UR_APICALL + urEnqueueMemBufferWriteRect( + ur_queue_handle_t hQueue, ///< [in] handle of the queue object + ur_mem_handle_t hBuffer, ///< [in] handle of the buffer object + bool blockingWrite, ///< [in] indicates blocking (true), non-blocking (false) + ur_rect_offset_t bufferOffset, ///< [in] 3D offset in the buffer + ur_rect_offset_t hostOffset, ///< [in] 3D offset in the host region + ur_rect_region_t region, ///< [in] 3D rectangular region descriptor: width, height, depth + size_t bufferRowPitch, ///< [in] length of each row in bytes in the buffer object + size_t bufferSlicePitch, ///< [in] length of each 2D slice in bytes in the buffer object being + ///< written + size_t hostRowPitch, ///< [in] length of each row in bytes in the host memory region pointed by + ///< src + size_t hostSlicePitch, ///< [in] length of each 2D slice in bytes in the host memory region + ///< pointed by src + void* pSrc, ///< [in] pointer to host memory where data is to be written from + uint32_t numEventsInWaitList, ///< [in] size of the event wait list + const ur_event_handle_t* phEventWaitList, ///< [in][optional][range(0, numEventsInWaitList)] points to a list of + ///< events that must be complete before this command can be executed. + ///< If nullptr, the numEventsInWaitList must be 0, indicating that this + ///< command does not wait on any event to complete. + ur_event_handle_t* phEvent ///< [in,out] return an event object that identifies this particular + ///< command instance. + ///< Input can not be a nullptr. + ///< TODO: change to allow nullptr. + ) + { + ur_result_t result = UR_RESULT_SUCCESS; + + // extract platform's function pointer table + auto dditable = reinterpret_cast( hQueue )->dditable; + auto pfnMemBufferWriteRect = dditable->ur.Enqueue.pfnMemBufferWriteRect; + if( nullptr == pfnMemBufferWriteRect ) + return UR_RESULT_ERROR_UNINITIALIZED; + + // convert loader handle to platform handle + hQueue = reinterpret_cast( hQueue )->handle; + + // convert loader handle to platform handle + hBuffer = reinterpret_cast( hBuffer )->handle; + + // convert loader handles to platform handles + auto phEventWaitListLocal = new ur_event_handle_t [numEventsInWaitList]; + for( size_t i = 0; ( nullptr != phEventWaitList ) && ( i < numEventsInWaitList ); ++i ) + phEventWaitListLocal[ i ] = reinterpret_cast( phEventWaitList[ i ] )->handle; + + // forward to device-platform + result = pfnMemBufferWriteRect( hQueue, hBuffer, blockingWrite, bufferOffset, hostOffset, region, bufferRowPitch, bufferSlicePitch, hostRowPitch, hostSlicePitch, pSrc, numEventsInWaitList, phEventWaitList, phEvent ); + delete []phEventWaitListLocal; + + if( UR_RESULT_SUCCESS != result ) + return result; + + try + { + // convert platform handle to loader handle + *phEvent = reinterpret_cast( + ur_event_factory.getInstance( *phEvent, dditable ) ); + } + catch( std::bad_alloc& ) + { + result = UR_RESULT_ERROR_OUT_OF_HOST_MEMORY; + } + + return result; + } + + /////////////////////////////////////////////////////////////////////////////// + /// @brief Intercept function for urEnqueueMemBufferCopy + __urdlllocal ur_result_t UR_APICALL + urEnqueueMemBufferCopy( + ur_queue_handle_t hQueue, ///< [in] handle of the queue object + ur_mem_handle_t hBufferSrc, ///< [in] handle of the src buffer object + ur_mem_handle_t hBufferDst, ///< [in] handle of the dest buffer object + size_t size, ///< [in] size in bytes of data being copied + uint32_t numEventsInWaitList, ///< [in] size of the event wait list + const ur_event_handle_t* phEventWaitList, ///< [in][optional][range(0, numEventsInWaitList)] pointer to a list of + ///< events that must be complete before this command can be executed. + ///< If nullptr, the numEventsInWaitList must be 0, indicating that this + ///< command does not wait on any event to complete. + ur_event_handle_t* phEvent ///< [in,out] return an event object that identifies this particular + ///< command instance. + ///< Input can not be a nullptr. + ///< TODO: change to allow nullptr. + ) + { + ur_result_t result = UR_RESULT_SUCCESS; + + // extract platform's function pointer table + auto dditable = reinterpret_cast( hQueue )->dditable; + auto pfnMemBufferCopy = dditable->ur.Enqueue.pfnMemBufferCopy; + if( nullptr == pfnMemBufferCopy ) + return UR_RESULT_ERROR_UNINITIALIZED; + + // convert loader handle to platform handle + hQueue = reinterpret_cast( hQueue )->handle; + + // convert loader handle to platform handle + hBufferSrc = reinterpret_cast( hBufferSrc )->handle; + + // convert loader handle to platform handle + hBufferDst = reinterpret_cast( hBufferDst )->handle; + + // convert loader handles to platform handles + auto phEventWaitListLocal = new ur_event_handle_t [numEventsInWaitList]; + for( size_t i = 0; ( nullptr != phEventWaitList ) && ( i < numEventsInWaitList ); ++i ) + phEventWaitListLocal[ i ] = reinterpret_cast( phEventWaitList[ i ] )->handle; + + // forward to device-platform + result = pfnMemBufferCopy( hQueue, hBufferSrc, hBufferDst, size, numEventsInWaitList, phEventWaitList, phEvent ); + delete []phEventWaitListLocal; + + if( UR_RESULT_SUCCESS != result ) + return result; + + try + { + // convert platform handle to loader handle + *phEvent = reinterpret_cast( + ur_event_factory.getInstance( *phEvent, dditable ) ); + } + catch( std::bad_alloc& ) + { + result = UR_RESULT_ERROR_OUT_OF_HOST_MEMORY; + } + + return result; + } + + /////////////////////////////////////////////////////////////////////////////// + /// @brief Intercept function for urEnqueueMemBufferCopyRect + __urdlllocal ur_result_t UR_APICALL + urEnqueueMemBufferCopyRect( + ur_queue_handle_t hQueue, ///< [in] handle of the queue object + ur_mem_handle_t hBufferSrc, ///< [in] handle of the source buffer object + ur_mem_handle_t hBufferDst, ///< [in] handle of the dest buffer object + ur_rect_offset_t srcOrigin, ///< [in] 3D offset in the source buffer + ur_rect_offset_t dstOrigin, ///< [in] 3D offset in the destination buffer + ur_rect_region_t srcRegion, ///< [in] source 3D rectangular region descriptor: width, height, depth + size_t srcRowPitch, ///< [in] length of each row in bytes in the source buffer object + size_t srcSlicePitch, ///< [in] length of each 2D slice in bytes in the source buffer object + size_t dstRowPitch, ///< [in] length of each row in bytes in the destination buffer object + size_t dstSlicePitch, ///< [in] length of each 2D slice in bytes in the destination buffer object + uint32_t numEventsInWaitList, ///< [in] size of the event wait list + const ur_event_handle_t* phEventWaitList, ///< [in][optional][range(0, numEventsInWaitList)] pointer to a list of + ///< events that must be complete before this command can be executed. + ///< If nullptr, the numEventsInWaitList must be 0, indicating that this + ///< command does not wait on any event to complete. + ur_event_handle_t* phEvent ///< [in,out] return an event object that identifies this particular + ///< command instance. + ///< Input can not be a nullptr. + ///< TODO: change to allow nullptr. + ) + { + ur_result_t result = UR_RESULT_SUCCESS; + + // extract platform's function pointer table + auto dditable = reinterpret_cast( hQueue )->dditable; + auto pfnMemBufferCopyRect = dditable->ur.Enqueue.pfnMemBufferCopyRect; + if( nullptr == pfnMemBufferCopyRect ) + return UR_RESULT_ERROR_UNINITIALIZED; + + // convert loader handle to platform handle + hQueue = reinterpret_cast( hQueue )->handle; + + // convert loader handle to platform handle + hBufferSrc = reinterpret_cast( hBufferSrc )->handle; + + // convert loader handle to platform handle + hBufferDst = reinterpret_cast( hBufferDst )->handle; + + // convert loader handles to platform handles + auto phEventWaitListLocal = new ur_event_handle_t [numEventsInWaitList]; + for( size_t i = 0; ( nullptr != phEventWaitList ) && ( i < numEventsInWaitList ); ++i ) + phEventWaitListLocal[ i ] = reinterpret_cast( phEventWaitList[ i ] )->handle; + + // forward to device-platform + result = pfnMemBufferCopyRect( hQueue, hBufferSrc, hBufferDst, srcOrigin, dstOrigin, srcRegion, srcRowPitch, srcSlicePitch, dstRowPitch, dstSlicePitch, numEventsInWaitList, phEventWaitList, phEvent ); + delete []phEventWaitListLocal; + + if( UR_RESULT_SUCCESS != result ) + return result; + + try + { + // convert platform handle to loader handle + *phEvent = reinterpret_cast( + ur_event_factory.getInstance( *phEvent, dditable ) ); + } + catch( std::bad_alloc& ) + { + result = UR_RESULT_ERROR_OUT_OF_HOST_MEMORY; + } + + return result; + } + + /////////////////////////////////////////////////////////////////////////////// + /// @brief Intercept function for urEnqueueMemBufferFill + __urdlllocal ur_result_t UR_APICALL + urEnqueueMemBufferFill( + ur_queue_handle_t hQueue, ///< [in] handle of the queue object + ur_mem_handle_t hBuffer, ///< [in] handle of the buffer object + const void* pPattern, ///< [in] pointer to the fill pattern + size_t patternSize, ///< [in] size in bytes of the pattern + size_t offset, ///< [in] offset into the buffer + size_t size, ///< [in] fill size in bytes, must be a multiple of patternSize + uint32_t numEventsInWaitList, ///< [in] size of the event wait list + const ur_event_handle_t* phEventWaitList, ///< [in][optional][range(0, numEventsInWaitList)] pointer to a list of + ///< events that must be complete before this command can be executed. + ///< If nullptr, the numEventsInWaitList must be 0, indicating that this + ///< command does not wait on any event to complete. + ur_event_handle_t* phEvent ///< [in,out] return an event object that identifies this particular + ///< command instance. + ///< Input can not be a nullptr. + ///< TODO: change to allow nullptr. + ) + { + ur_result_t result = UR_RESULT_SUCCESS; + + // extract platform's function pointer table + auto dditable = reinterpret_cast( hQueue )->dditable; + auto pfnMemBufferFill = dditable->ur.Enqueue.pfnMemBufferFill; + if( nullptr == pfnMemBufferFill ) + return UR_RESULT_ERROR_UNINITIALIZED; + + // convert loader handle to platform handle + hQueue = reinterpret_cast( hQueue )->handle; + + // convert loader handle to platform handle + hBuffer = reinterpret_cast( hBuffer )->handle; + + // convert loader handles to platform handles + auto phEventWaitListLocal = new ur_event_handle_t [numEventsInWaitList]; + for( size_t i = 0; ( nullptr != phEventWaitList ) && ( i < numEventsInWaitList ); ++i ) + phEventWaitListLocal[ i ] = reinterpret_cast( phEventWaitList[ i ] )->handle; + + // forward to device-platform + result = pfnMemBufferFill( hQueue, hBuffer, pPattern, patternSize, offset, size, numEventsInWaitList, phEventWaitList, phEvent ); + delete []phEventWaitListLocal; + + if( UR_RESULT_SUCCESS != result ) + return result; + + try + { + // convert platform handle to loader handle + *phEvent = reinterpret_cast( + ur_event_factory.getInstance( *phEvent, dditable ) ); + } + catch( std::bad_alloc& ) + { + result = UR_RESULT_ERROR_OUT_OF_HOST_MEMORY; + } + + return result; + } + + /////////////////////////////////////////////////////////////////////////////// + /// @brief Intercept function for urEnqueueMemImageRead + __urdlllocal ur_result_t UR_APICALL + urEnqueueMemImageRead( + ur_queue_handle_t hQueue, ///< [in] handle of the queue object + ur_mem_handle_t hImage, ///< [in] handle of the image object + bool blockingRead, ///< [in] indicates blocking (true), non-blocking (false) + ur_rect_offset_t origin, ///< [in] defines the (x,y,z) offset in pixels in the 1D, 2D, or 3D image + ur_rect_region_t region, ///< [in] defines the (width, height, depth) in pixels of the 1D, 2D, or 3D + ///< image + size_t rowPitch, ///< [in] length of each row in bytes + size_t slicePitch, ///< [in] length of each 2D slice of the 3D image + void* pDst, ///< [in] pointer to host memory where image is to be read into + uint32_t numEventsInWaitList, ///< [in] size of the event wait list + const ur_event_handle_t* phEventWaitList, ///< [in][optional][range(0, numEventsInWaitList)] pointer to a list of + ///< events that must be complete before this command can be executed. + ///< If nullptr, the numEventsInWaitList must be 0, indicating that this + ///< command does not wait on any event to complete. + ur_event_handle_t* phEvent ///< [in,out] return an event object that identifies this particular + ///< command instance. + ///< Input can not be a nullptr. + ///< TODO: change to allow nullptr. + ) + { + ur_result_t result = UR_RESULT_SUCCESS; + + // extract platform's function pointer table + auto dditable = reinterpret_cast( hQueue )->dditable; + auto pfnMemImageRead = dditable->ur.Enqueue.pfnMemImageRead; + if( nullptr == pfnMemImageRead ) + return UR_RESULT_ERROR_UNINITIALIZED; + + // convert loader handle to platform handle + hQueue = reinterpret_cast( hQueue )->handle; + + // convert loader handle to platform handle + hImage = reinterpret_cast( hImage )->handle; + + // convert loader handles to platform handles + auto phEventWaitListLocal = new ur_event_handle_t [numEventsInWaitList]; + for( size_t i = 0; ( nullptr != phEventWaitList ) && ( i < numEventsInWaitList ); ++i ) + phEventWaitListLocal[ i ] = reinterpret_cast( phEventWaitList[ i ] )->handle; + + // forward to device-platform + result = pfnMemImageRead( hQueue, hImage, blockingRead, origin, region, rowPitch, slicePitch, pDst, numEventsInWaitList, phEventWaitList, phEvent ); + delete []phEventWaitListLocal; + + if( UR_RESULT_SUCCESS != result ) + return result; + + try + { + // convert platform handle to loader handle + *phEvent = reinterpret_cast( + ur_event_factory.getInstance( *phEvent, dditable ) ); + } + catch( std::bad_alloc& ) + { + result = UR_RESULT_ERROR_OUT_OF_HOST_MEMORY; + } + + return result; + } + + /////////////////////////////////////////////////////////////////////////////// + /// @brief Intercept function for urEnqueueMemImageWrite + __urdlllocal ur_result_t UR_APICALL + urEnqueueMemImageWrite( + ur_queue_handle_t hQueue, ///< [in] handle of the queue object + ur_mem_handle_t hImage, ///< [in] handle of the image object + bool blockingWrite, ///< [in] indicates blocking (true), non-blocking (false) + ur_rect_offset_t origin, ///< [in] defines the (x,y,z) offset in pixels in the 1D, 2D, or 3D image + ur_rect_region_t region, ///< [in] defines the (width, height, depth) in pixels of the 1D, 2D, or 3D + ///< image + size_t inputRowPitch, ///< [in] length of each row in bytes + size_t inputSlicePitch, ///< [in] length of each 2D slice of the 3D image + void* pSrc, ///< [in] pointer to host memory where image is to be read into + uint32_t numEventsInWaitList, ///< [in] size of the event wait list + const ur_event_handle_t* phEventWaitList, ///< [in][optional][range(0, numEventsInWaitList)] pointer to a list of + ///< events that must be complete before this command can be executed. + ///< If nullptr, the numEventsInWaitList must be 0, indicating that this + ///< command does not wait on any event to complete. + ur_event_handle_t* phEvent ///< [in,out] return an event object that identifies this particular + ///< command instance. + ///< Input can not be a nullptr. + ///< TODO: change to allow nullptr. + ) + { + ur_result_t result = UR_RESULT_SUCCESS; + + // extract platform's function pointer table + auto dditable = reinterpret_cast( hQueue )->dditable; + auto pfnMemImageWrite = dditable->ur.Enqueue.pfnMemImageWrite; + if( nullptr == pfnMemImageWrite ) + return UR_RESULT_ERROR_UNINITIALIZED; + + // convert loader handle to platform handle + hQueue = reinterpret_cast( hQueue )->handle; + + // convert loader handle to platform handle + hImage = reinterpret_cast( hImage )->handle; + + // convert loader handles to platform handles + auto phEventWaitListLocal = new ur_event_handle_t [numEventsInWaitList]; + for( size_t i = 0; ( nullptr != phEventWaitList ) && ( i < numEventsInWaitList ); ++i ) + phEventWaitListLocal[ i ] = reinterpret_cast( phEventWaitList[ i ] )->handle; + + // forward to device-platform + result = pfnMemImageWrite( hQueue, hImage, blockingWrite, origin, region, inputRowPitch, inputSlicePitch, pSrc, numEventsInWaitList, phEventWaitList, phEvent ); + delete []phEventWaitListLocal; + + if( UR_RESULT_SUCCESS != result ) + return result; + + try + { + // convert platform handle to loader handle + *phEvent = reinterpret_cast( + ur_event_factory.getInstance( *phEvent, dditable ) ); + } + catch( std::bad_alloc& ) + { + result = UR_RESULT_ERROR_OUT_OF_HOST_MEMORY; + } + + return result; + } + + /////////////////////////////////////////////////////////////////////////////// + /// @brief Intercept function for urEnqueueMemImageCopy + __urdlllocal ur_result_t UR_APICALL + urEnqueueMemImageCopy( + ur_queue_handle_t hQueue, ///< [in] handle of the queue object + ur_mem_handle_t hImageSrc, ///< [in] handle of the src image object + ur_mem_handle_t hImageDst, ///< [in] handle of the dest image object + ur_rect_offset_t srcOrigin, ///< [in] defines the (x,y,z) offset in pixels in the source 1D, 2D, or 3D + ///< image + ur_rect_offset_t dstOrigin, ///< [in] defines the (x,y,z) offset in pixels in the destination 1D, 2D, + ///< or 3D image + ur_rect_region_t region, ///< [in] defines the (width, height, depth) in pixels of the 1D, 2D, or 3D + ///< image + uint32_t numEventsInWaitList, ///< [in] size of the event wait list + const ur_event_handle_t* phEventWaitList, ///< [in][optional][range(0, numEventsInWaitList)] pointer to a list of + ///< events that must be complete before this command can be executed. + ///< If nullptr, the numEventsInWaitList must be 0, indicating that this + ///< command does not wait on any event to complete. + ur_event_handle_t* phEvent ///< [in,out] return an event object that identifies this particular + ///< command instance. + ///< Input can not be a nullptr. + ///< TODO: change to allow nullptr. + ) + { + ur_result_t result = UR_RESULT_SUCCESS; + + // extract platform's function pointer table + auto dditable = reinterpret_cast( hQueue )->dditable; + auto pfnMemImageCopy = dditable->ur.Enqueue.pfnMemImageCopy; + if( nullptr == pfnMemImageCopy ) + return UR_RESULT_ERROR_UNINITIALIZED; + + // convert loader handle to platform handle + hQueue = reinterpret_cast( hQueue )->handle; + + // convert loader handle to platform handle + hImageSrc = reinterpret_cast( hImageSrc )->handle; + + // convert loader handle to platform handle + hImageDst = reinterpret_cast( hImageDst )->handle; + + // convert loader handles to platform handles + auto phEventWaitListLocal = new ur_event_handle_t [numEventsInWaitList]; + for( size_t i = 0; ( nullptr != phEventWaitList ) && ( i < numEventsInWaitList ); ++i ) + phEventWaitListLocal[ i ] = reinterpret_cast( phEventWaitList[ i ] )->handle; + + // forward to device-platform + result = pfnMemImageCopy( hQueue, hImageSrc, hImageDst, srcOrigin, dstOrigin, region, numEventsInWaitList, phEventWaitList, phEvent ); + delete []phEventWaitListLocal; + + if( UR_RESULT_SUCCESS != result ) + return result; + + try + { + // convert platform handle to loader handle + *phEvent = reinterpret_cast( + ur_event_factory.getInstance( *phEvent, dditable ) ); + } + catch( std::bad_alloc& ) + { + result = UR_RESULT_ERROR_OUT_OF_HOST_MEMORY; + } + + return result; + } + + /////////////////////////////////////////////////////////////////////////////// + /// @brief Intercept function for urEnqueueMemBufferMap + __urdlllocal ur_result_t UR_APICALL + urEnqueueMemBufferMap( + ur_queue_handle_t hQueue, ///< [in] handle of the queue object + ur_mem_handle_t hBuffer, ///< [in] handle of the buffer object + bool blockingMap, ///< [in] indicates blocking (true), non-blocking (false) + ur_map_flags_t mapFlags, ///< [in] flags for read, write, readwrite mapping + size_t offset, ///< [in] offset in bytes of the buffer region being mapped + size_t size, ///< [in] size in bytes of the buffer region being mapped + uint32_t numEventsInWaitList, ///< [in] size of the event wait list + const ur_event_handle_t* phEventWaitList, ///< [in][optional][range(0, numEventsInWaitList)] pointer to a list of + ///< events that must be complete before this command can be executed. + ///< If nullptr, the numEventsInWaitList must be 0, indicating that this + ///< command does not wait on any event to complete. + ur_event_handle_t* phEvent, ///< [in,out] return an event object that identifies this particular + ///< command instance. + ///< Input can not be a nullptr. + ///< TODO: change to allow nullptr. + void** ppRetMap ///< [in,out] return mapped pointer. TODO: move it before + ///< numEventsInWaitList? + ) + { + ur_result_t result = UR_RESULT_SUCCESS; + + // extract platform's function pointer table + auto dditable = reinterpret_cast( hQueue )->dditable; + auto pfnMemBufferMap = dditable->ur.Enqueue.pfnMemBufferMap; + if( nullptr == pfnMemBufferMap ) + return UR_RESULT_ERROR_UNINITIALIZED; + + // convert loader handle to platform handle + hQueue = reinterpret_cast( hQueue )->handle; + + // convert loader handle to platform handle + hBuffer = reinterpret_cast( hBuffer )->handle; + + // convert loader handles to platform handles + auto phEventWaitListLocal = new ur_event_handle_t [numEventsInWaitList]; + for( size_t i = 0; ( nullptr != phEventWaitList ) && ( i < numEventsInWaitList ); ++i ) + phEventWaitListLocal[ i ] = reinterpret_cast( phEventWaitList[ i ] )->handle; + + // forward to device-platform + result = pfnMemBufferMap( hQueue, hBuffer, blockingMap, mapFlags, offset, size, numEventsInWaitList, phEventWaitList, phEvent, ppRetMap ); + delete []phEventWaitListLocal; + + if( UR_RESULT_SUCCESS != result ) + return result; + + try + { + // convert platform handle to loader handle + *phEvent = reinterpret_cast( + ur_event_factory.getInstance( *phEvent, dditable ) ); + } + catch( std::bad_alloc& ) + { + result = UR_RESULT_ERROR_OUT_OF_HOST_MEMORY; + } + + return result; + } + + /////////////////////////////////////////////////////////////////////////////// + /// @brief Intercept function for urEnqueueMemUnmap + __urdlllocal ur_result_t UR_APICALL + urEnqueueMemUnmap( + ur_queue_handle_t hQueue, ///< [in] handle of the queue object + ur_mem_handle_t hMem, ///< [in] handle of the memory (buffer or image) object + void* pMappedPtr, ///< [in] mapped host address + uint32_t numEventsInWaitList, ///< [in] size of the event wait list + const ur_event_handle_t* phEventWaitList, ///< [in][optional][range(0, numEventsInWaitList)] pointer to a list of + ///< events that must be complete before this command can be executed. + ///< If nullptr, the numEventsInWaitList must be 0, indicating that this + ///< command does not wait on any event to complete. + ur_event_handle_t* phEvent ///< [in,out] return an event object that identifies this particular + ///< command instance. + ///< Input can not be a nullptr. + ///< TODO: change to allow nullptr. + ) + { + ur_result_t result = UR_RESULT_SUCCESS; + + // extract platform's function pointer table + auto dditable = reinterpret_cast( hQueue )->dditable; + auto pfnMemUnmap = dditable->ur.Enqueue.pfnMemUnmap; + if( nullptr == pfnMemUnmap ) + return UR_RESULT_ERROR_UNINITIALIZED; + + // convert loader handle to platform handle + hQueue = reinterpret_cast( hQueue )->handle; + + // convert loader handle to platform handle + hMem = reinterpret_cast( hMem )->handle; + + // convert loader handles to platform handles + auto phEventWaitListLocal = new ur_event_handle_t [numEventsInWaitList]; + for( size_t i = 0; ( nullptr != phEventWaitList ) && ( i < numEventsInWaitList ); ++i ) + phEventWaitListLocal[ i ] = reinterpret_cast( phEventWaitList[ i ] )->handle; + + // forward to device-platform + result = pfnMemUnmap( hQueue, hMem, pMappedPtr, numEventsInWaitList, phEventWaitList, phEvent ); + delete []phEventWaitListLocal; + + if( UR_RESULT_SUCCESS != result ) + return result; + + try + { + // convert platform handle to loader handle + *phEvent = reinterpret_cast( + ur_event_factory.getInstance( *phEvent, dditable ) ); + } + catch( std::bad_alloc& ) + { + result = UR_RESULT_ERROR_OUT_OF_HOST_MEMORY; + } + + return result; + } + + /////////////////////////////////////////////////////////////////////////////// + /// @brief Intercept function for urEnqueueUSMMemset + __urdlllocal ur_result_t UR_APICALL + urEnqueueUSMMemset( + ur_queue_handle_t hQueue, ///< [in] handle of the queue object + void* ptr, ///< [in] pointer to USM memory object + int8_t byteValue, ///< [in] byte value to fill + size_t count, ///< [in] size in bytes to be set + uint32_t numEventsInWaitList, ///< [in] size of the event wait list + const ur_event_handle_t* phEventWaitList, ///< [in][optional][range(0, numEventsInWaitList)] pointer to a list of + ///< events that must be complete before this command can be executed. + ///< If nullptr, the numEventsInWaitList must be 0, indicating that this + ///< command does not wait on any event to complete. + ur_event_handle_t* phEvent ///< [in,out] return an event object that identifies this particular + ///< command instance. + ///< Input can not be a nullptr. + ///< TODO: change to allow nullptr. + ) + { + ur_result_t result = UR_RESULT_SUCCESS; + + // extract platform's function pointer table + auto dditable = reinterpret_cast( hQueue )->dditable; + auto pfnUSMMemset = dditable->ur.Enqueue.pfnUSMMemset; + if( nullptr == pfnUSMMemset ) + return UR_RESULT_ERROR_UNINITIALIZED; + + // convert loader handle to platform handle + hQueue = reinterpret_cast( hQueue )->handle; + + // convert loader handles to platform handles + auto phEventWaitListLocal = new ur_event_handle_t [numEventsInWaitList]; + for( size_t i = 0; ( nullptr != phEventWaitList ) && ( i < numEventsInWaitList ); ++i ) + phEventWaitListLocal[ i ] = reinterpret_cast( phEventWaitList[ i ] )->handle; + + // forward to device-platform + result = pfnUSMMemset( hQueue, ptr, byteValue, count, numEventsInWaitList, phEventWaitList, phEvent ); + delete []phEventWaitListLocal; + + if( UR_RESULT_SUCCESS != result ) + return result; + + try + { + // convert platform handle to loader handle + *phEvent = reinterpret_cast( + ur_event_factory.getInstance( *phEvent, dditable ) ); + } + catch( std::bad_alloc& ) + { + result = UR_RESULT_ERROR_OUT_OF_HOST_MEMORY; + } + + return result; + } + + /////////////////////////////////////////////////////////////////////////////// + /// @brief Intercept function for urEnqueueUSMMemcpy + __urdlllocal ur_result_t UR_APICALL + urEnqueueUSMMemcpy( + ur_queue_handle_t hQueue, ///< [in] handle of the queue object + bool blocking, ///< [in] blocking or non-blocking copy + void* pDst, ///< [in] pointer to the destination USM memory object + const void* pSrc, ///< [in] pointer to the source USM memory object + size_t size, ///< [in] size in bytes to be copied + uint32_t numEventsInWaitList, ///< [in] size of the event wait list + const ur_event_handle_t* phEventWaitList, ///< [in][optional][range(0, numEventsInWaitList)] pointer to a list of + ///< events that must be complete before this command can be executed. + ///< If nullptr, the numEventsInWaitList must be 0, indicating that this + ///< command does not wait on any event to complete. + ur_event_handle_t* phEvent ///< [in,out] return an event object that identifies this particular + ///< command instance. + ///< Input can not be a nullptr. + ///< TODO: change to allow nullptr. + ) + { + ur_result_t result = UR_RESULT_SUCCESS; + + // extract platform's function pointer table + auto dditable = reinterpret_cast( hQueue )->dditable; + auto pfnUSMMemcpy = dditable->ur.Enqueue.pfnUSMMemcpy; + if( nullptr == pfnUSMMemcpy ) + return UR_RESULT_ERROR_UNINITIALIZED; + + // convert loader handle to platform handle + hQueue = reinterpret_cast( hQueue )->handle; + + // convert loader handles to platform handles + auto phEventWaitListLocal = new ur_event_handle_t [numEventsInWaitList]; + for( size_t i = 0; ( nullptr != phEventWaitList ) && ( i < numEventsInWaitList ); ++i ) + phEventWaitListLocal[ i ] = reinterpret_cast( phEventWaitList[ i ] )->handle; + + // forward to device-platform + result = pfnUSMMemcpy( hQueue, blocking, pDst, pSrc, size, numEventsInWaitList, phEventWaitList, phEvent ); + delete []phEventWaitListLocal; + + if( UR_RESULT_SUCCESS != result ) + return result; + + try + { + // convert platform handle to loader handle + *phEvent = reinterpret_cast( + ur_event_factory.getInstance( *phEvent, dditable ) ); + } + catch( std::bad_alloc& ) + { + result = UR_RESULT_ERROR_OUT_OF_HOST_MEMORY; + } + + return result; + } + + /////////////////////////////////////////////////////////////////////////////// + /// @brief Intercept function for urEnqueueUSMPrefetch + __urdlllocal ur_result_t UR_APICALL + urEnqueueUSMPrefetch( + ur_queue_handle_t hQueue, ///< [in] handle of the queue object + const void* pMem, ///< [in] pointer to the USM memory object + size_t size, ///< [in] size in bytes to be fetched + ur_usm_migration_flags_t flags, ///< [in] USM prefetch flags + uint32_t numEventsInWaitList, ///< [in] size of the event wait list + const ur_event_handle_t* phEventWaitList, ///< [in][optional][range(0, numEventsInWaitList)] pointer to a list of + ///< events that must be complete before this command can be executed. + ///< If nullptr, the numEventsInWaitList must be 0, indicating that this + ///< command does not wait on any event to complete. + ur_event_handle_t* phEvent ///< [in,out] return an event object that identifies this particular + ///< command instance. + ///< Input can not be a nullptr. + ///< TODO: change to allow nullptr. + ) + { + ur_result_t result = UR_RESULT_SUCCESS; + + // extract platform's function pointer table + auto dditable = reinterpret_cast( hQueue )->dditable; + auto pfnUSMPrefetch = dditable->ur.Enqueue.pfnUSMPrefetch; + if( nullptr == pfnUSMPrefetch ) + return UR_RESULT_ERROR_UNINITIALIZED; + + // convert loader handle to platform handle + hQueue = reinterpret_cast( hQueue )->handle; + + // convert loader handles to platform handles + auto phEventWaitListLocal = new ur_event_handle_t [numEventsInWaitList]; + for( size_t i = 0; ( nullptr != phEventWaitList ) && ( i < numEventsInWaitList ); ++i ) + phEventWaitListLocal[ i ] = reinterpret_cast( phEventWaitList[ i ] )->handle; + + // forward to device-platform + result = pfnUSMPrefetch( hQueue, pMem, size, flags, numEventsInWaitList, phEventWaitList, phEvent ); + delete []phEventWaitListLocal; + + if( UR_RESULT_SUCCESS != result ) + return result; + + try + { + // convert platform handle to loader handle + *phEvent = reinterpret_cast( + ur_event_factory.getInstance( *phEvent, dditable ) ); + } + catch( std::bad_alloc& ) + { + result = UR_RESULT_ERROR_OUT_OF_HOST_MEMORY; + } + + return result; + } + + /////////////////////////////////////////////////////////////////////////////// + /// @brief Intercept function for urEnqueueUSMMemAdvice + __urdlllocal ur_result_t UR_APICALL + urEnqueueUSMMemAdvice( + ur_queue_handle_t hQueue, ///< [in] handle of the queue object + const void* pMem, ///< [in] pointer to the USM memory object + size_t size, ///< [in] size in bytes to be adviced + ur_mem_advice_t advice, ///< [in] USM memory advice + ur_event_handle_t* phEvent ///< [in,out] return an event object that identifies this particular + ///< command instance. + ///< Input can not be a nullptr. + ///< TODO: change to allow nullptr. + ) + { + ur_result_t result = UR_RESULT_SUCCESS; + + // extract platform's function pointer table + auto dditable = reinterpret_cast( hQueue )->dditable; + auto pfnUSMMemAdvice = dditable->ur.Enqueue.pfnUSMMemAdvice; + if( nullptr == pfnUSMMemAdvice ) + return UR_RESULT_ERROR_UNINITIALIZED; + + // convert loader handle to platform handle + hQueue = reinterpret_cast( hQueue )->handle; + + // forward to device-platform + result = pfnUSMMemAdvice( hQueue, pMem, size, advice, phEvent ); + + if( UR_RESULT_SUCCESS != result ) + return result; + + try + { + // convert platform handle to loader handle + *phEvent = reinterpret_cast( + ur_event_factory.getInstance( *phEvent, dditable ) ); + } + catch( std::bad_alloc& ) + { + result = UR_RESULT_ERROR_OUT_OF_HOST_MEMORY; + } + + return result; + } + + /////////////////////////////////////////////////////////////////////////////// + /// @brief Intercept function for urEventGetInfo + __urdlllocal ur_result_t UR_APICALL + urEventGetInfo( + ur_event_handle_t hEvent, ///< [in] handle of the event object + ur_event_info_t propName, ///< [in] the name of the event property to query + size_t propValueSize, ///< [in] size in bytes of the event property value + void* pPropValue, ///< [out] value of the event property + size_t* pPropValueSizeRet ///< [out] bytes returned in event property + ) + { + ur_result_t result = UR_RESULT_SUCCESS; + + // extract platform's function pointer table + auto dditable = reinterpret_cast( hEvent )->dditable; + auto pfnGetInfo = dditable->ur.Event.pfnGetInfo; + if( nullptr == pfnGetInfo ) + return UR_RESULT_ERROR_UNINITIALIZED; + + // convert loader handle to platform handle + hEvent = reinterpret_cast( hEvent )->handle; + + // forward to device-platform + result = pfnGetInfo( hEvent, propName, propValueSize, pPropValue, pPropValueSizeRet ); + + return result; + } + + /////////////////////////////////////////////////////////////////////////////// + /// @brief Intercept function for urEventGetProfilingInfo + __urdlllocal ur_result_t UR_APICALL + urEventGetProfilingInfo( + ur_event_handle_t hEvent, ///< [in] handle of the event object + ur_profiling_info_t propName, ///< [in] the name of the profiling property to query + size_t propValueSize, ///< [in] size in bytes of the profiling property value + void* pPropValue, ///< [out][optional] value of the profiling property + size_t* pPropValueSizeRet ///< [out][optional] pointer to the actual size in bytes returned in + ///< propValue + ) + { + ur_result_t result = UR_RESULT_SUCCESS; + + // extract platform's function pointer table + auto dditable = reinterpret_cast( hEvent )->dditable; + auto pfnGetProfilingInfo = dditable->ur.Event.pfnGetProfilingInfo; + if( nullptr == pfnGetProfilingInfo ) + return UR_RESULT_ERROR_UNINITIALIZED; + + // convert loader handle to platform handle + hEvent = reinterpret_cast( hEvent )->handle; + + // forward to device-platform + result = pfnGetProfilingInfo( hEvent, propName, propValueSize, pPropValue, pPropValueSizeRet ); + + return result; + } + + /////////////////////////////////////////////////////////////////////////////// + /// @brief Intercept function for urEventWait + __urdlllocal ur_result_t UR_APICALL + urEventWait( + uint32_t numEvents, ///< [in] number of events in the event list + const ur_event_handle_t* phEventWaitList ///< [in][range(0, numEvents)] pointer to a list of events to wait for + ///< completion + ) + { + ur_result_t result = UR_RESULT_SUCCESS; + + // extract platform's function pointer table + auto dditable = reinterpret_cast( *phEventWaitList )->dditable; + auto pfnWait = dditable->ur.Event.pfnWait; + if( nullptr == pfnWait ) + return UR_RESULT_ERROR_UNINITIALIZED; + + // convert loader handles to platform handles + auto phEventWaitListLocal = new ur_event_handle_t [numEvents]; + for( size_t i = 0; ( nullptr != phEventWaitList ) && ( i < numEvents ); ++i ) + phEventWaitListLocal[ i ] = reinterpret_cast( phEventWaitList[ i ] )->handle; + + // forward to device-platform + result = pfnWait( numEvents, phEventWaitList ); + delete []phEventWaitListLocal; + + return result; + } + + /////////////////////////////////////////////////////////////////////////////// + /// @brief Intercept function for urEventRetain + __urdlllocal ur_result_t UR_APICALL + urEventRetain( + ur_event_handle_t hEvent ///< [in] handle of the event object + ) + { + ur_result_t result = UR_RESULT_SUCCESS; + + // extract platform's function pointer table + auto dditable = reinterpret_cast( hEvent )->dditable; + auto pfnRetain = dditable->ur.Event.pfnRetain; + if( nullptr == pfnRetain ) + return UR_RESULT_ERROR_UNINITIALIZED; + + // convert loader handle to platform handle + hEvent = reinterpret_cast( hEvent )->handle; + + // forward to device-platform + result = pfnRetain( hEvent ); + + return result; + } + + /////////////////////////////////////////////////////////////////////////////// + /// @brief Intercept function for urEventRelease + __urdlllocal ur_result_t UR_APICALL + urEventRelease( + ur_event_handle_t hEvent ///< [in] handle of the event object + ) + { + ur_result_t result = UR_RESULT_SUCCESS; + + // extract platform's function pointer table + auto dditable = reinterpret_cast( hEvent )->dditable; + auto pfnRelease = dditable->ur.Event.pfnRelease; + if( nullptr == pfnRelease ) + return UR_RESULT_ERROR_UNINITIALIZED; + + // convert loader handle to platform handle + hEvent = reinterpret_cast( hEvent )->handle; + + // forward to device-platform + result = pfnRelease( hEvent ); + + return result; + } + + /////////////////////////////////////////////////////////////////////////////// + /// @brief Intercept function for urEventGetNativeHandle + __urdlllocal ur_result_t UR_APICALL + urEventGetNativeHandle( + ur_event_handle_t hEvent, ///< [in] handle of the event. + ur_native_handle_t* phNativeEvent ///< [out] a pointer to the native handle of the event. + ) + { + ur_result_t result = UR_RESULT_SUCCESS; + + // extract platform's function pointer table + auto dditable = reinterpret_cast( hEvent )->dditable; + auto pfnGetNativeHandle = dditable->ur.Event.pfnGetNativeHandle; + if( nullptr == pfnGetNativeHandle ) + return UR_RESULT_ERROR_UNINITIALIZED; + + // convert loader handle to platform handle + hEvent = reinterpret_cast( hEvent )->handle; + + // forward to device-platform + result = pfnGetNativeHandle( hEvent, phNativeEvent ); + + if( UR_RESULT_SUCCESS != result ) + return result; + + try + { + // convert platform handle to loader handle + *phNativeEvent = reinterpret_cast( + ur_native_factory.getInstance( *phNativeEvent, dditable ) ); + } + catch( std::bad_alloc& ) + { + result = UR_RESULT_ERROR_OUT_OF_HOST_MEMORY; + } + + return result; + } + + /////////////////////////////////////////////////////////////////////////////// + /// @brief Intercept function for urEventCreateWithNativeHandle + __urdlllocal ur_result_t UR_APICALL + urEventCreateWithNativeHandle( + ur_native_handle_t hNativeEvent, ///< [in] the native handle of the event. + ur_context_handle_t hContext, ///< [in] handle of the context object + ur_event_handle_t* phEvent ///< [out] pointer to the handle of the event object created. + ) + { + ur_result_t result = UR_RESULT_SUCCESS; + + // extract platform's function pointer table + auto dditable = reinterpret_cast( hNativeEvent )->dditable; + auto pfnCreateWithNativeHandle = dditable->ur.Event.pfnCreateWithNativeHandle; + if( nullptr == pfnCreateWithNativeHandle ) + return UR_RESULT_ERROR_UNINITIALIZED; + + // convert loader handle to platform handle + hNativeEvent = reinterpret_cast( hNativeEvent )->handle; + + // convert loader handle to platform handle + hContext = reinterpret_cast( hContext )->handle; + + // forward to device-platform + result = pfnCreateWithNativeHandle( hNativeEvent, hContext, phEvent ); + + if( UR_RESULT_SUCCESS != result ) + return result; + + try + { + // convert platform handle to loader handle + *phEvent = reinterpret_cast( + ur_event_factory.getInstance( *phEvent, dditable ) ); + } + catch( std::bad_alloc& ) + { + result = UR_RESULT_ERROR_OUT_OF_HOST_MEMORY; + } + + return result; + } + + /////////////////////////////////////////////////////////////////////////////// + /// @brief Intercept function for urEventSetCallback + __urdlllocal ur_result_t UR_APICALL + urEventSetCallback( + ur_event_handle_t hEvent, ///< [in] handle of the event object + ur_execution_info_t execStatus, ///< [in] execution status of the event + ur_event_callback_t pfnNotify, ///< [in] execution status of the event + void* pUserData ///< [in][out][optional] pointer to data to be passed to callback. + ) + { + ur_result_t result = UR_RESULT_SUCCESS; + + // extract platform's function pointer table + auto dditable = reinterpret_cast( hEvent )->dditable; + auto pfnSetCallback = dditable->ur.Event.pfnSetCallback; + if( nullptr == pfnSetCallback ) + return UR_RESULT_ERROR_UNINITIALIZED; + + // convert loader handle to platform handle + hEvent = reinterpret_cast( hEvent )->handle; + + // forward to device-platform + result = pfnSetCallback( hEvent, execStatus, pfnNotify, pUserData ); + + return result; + } + + /////////////////////////////////////////////////////////////////////////////// + /// @brief Intercept function for urMemImageCreate + __urdlllocal ur_result_t UR_APICALL + urMemImageCreate( + ur_context_handle_t hContext, ///< [in] handle of the context object + ur_mem_flags_t flags, ///< [in] allocation and usage information flags + const ur_image_format_t* pImageFormat, ///< [in] pointer to image format specification + const ur_image_desc_t* pImageDesc, ///< [in] pointer to image description + void* pHost, ///< [in] pointer to the buffer data + ur_mem_handle_t* phMem ///< [out] pointer to handle of image object created + ) + { + ur_result_t result = UR_RESULT_SUCCESS; + + // extract platform's function pointer table + auto dditable = reinterpret_cast( hContext )->dditable; + auto pfnImageCreate = dditable->ur.Mem.pfnImageCreate; + if( nullptr == pfnImageCreate ) + return UR_RESULT_ERROR_UNINITIALIZED; + + // convert loader handle to platform handle + hContext = reinterpret_cast( hContext )->handle; + + // forward to device-platform + result = pfnImageCreate( hContext, flags, pImageFormat, pImageDesc, pHost, phMem ); + + if( UR_RESULT_SUCCESS != result ) + return result; + + try + { + // convert platform handle to loader handle + *phMem = reinterpret_cast( + ur_mem_factory.getInstance( *phMem, dditable ) ); + } + catch( std::bad_alloc& ) + { + result = UR_RESULT_ERROR_OUT_OF_HOST_MEMORY; + } + + return result; + } + + /////////////////////////////////////////////////////////////////////////////// + /// @brief Intercept function for urMemBufferCreate + __urdlllocal ur_result_t UR_APICALL + urMemBufferCreate( + ur_context_handle_t hContext, ///< [in] handle of the context object + ur_mem_flags_t flags, ///< [in] allocation and usage information flags + size_t size, ///< [in] size in bytes of the memory object to be allocated + void* pHost, ///< [in] pointer to the buffer data + ur_mem_handle_t* phBuffer ///< [out] pointer to handle of the memory buffer created + ) + { + ur_result_t result = UR_RESULT_SUCCESS; + + // extract platform's function pointer table + auto dditable = reinterpret_cast( hContext )->dditable; + auto pfnBufferCreate = dditable->ur.Mem.pfnBufferCreate; + if( nullptr == pfnBufferCreate ) + return UR_RESULT_ERROR_UNINITIALIZED; + + // convert loader handle to platform handle + hContext = reinterpret_cast( hContext )->handle; + + // forward to device-platform + result = pfnBufferCreate( hContext, flags, size, pHost, phBuffer ); + + if( UR_RESULT_SUCCESS != result ) + return result; + + try + { + // convert platform handle to loader handle + *phBuffer = reinterpret_cast( + ur_mem_factory.getInstance( *phBuffer, dditable ) ); + } + catch( std::bad_alloc& ) + { + result = UR_RESULT_ERROR_OUT_OF_HOST_MEMORY; + } + + return result; + } + + /////////////////////////////////////////////////////////////////////////////// + /// @brief Intercept function for urMemRetain + __urdlllocal ur_result_t UR_APICALL + urMemRetain( + ur_mem_handle_t hMem ///< [in] handle of the memory object to get access + ) + { + ur_result_t result = UR_RESULT_SUCCESS; + + // extract platform's function pointer table + auto dditable = reinterpret_cast( hMem )->dditable; + auto pfnRetain = dditable->ur.Mem.pfnRetain; + if( nullptr == pfnRetain ) + return UR_RESULT_ERROR_UNINITIALIZED; + + // convert loader handle to platform handle + hMem = reinterpret_cast( hMem )->handle; + + // forward to device-platform + result = pfnRetain( hMem ); + + return result; + } + + /////////////////////////////////////////////////////////////////////////////// + /// @brief Intercept function for urMemRelease + __urdlllocal ur_result_t UR_APICALL + urMemRelease( + ur_mem_handle_t hMem ///< [in] handle of the memory object to release + ) + { + ur_result_t result = UR_RESULT_SUCCESS; + + // extract platform's function pointer table + auto dditable = reinterpret_cast( hMem )->dditable; + auto pfnRelease = dditable->ur.Mem.pfnRelease; + if( nullptr == pfnRelease ) + return UR_RESULT_ERROR_UNINITIALIZED; + + // convert loader handle to platform handle + hMem = reinterpret_cast( hMem )->handle; + + // forward to device-platform + result = pfnRelease( hMem ); + + return result; + } + + /////////////////////////////////////////////////////////////////////////////// + /// @brief Intercept function for urMemBufferPartition + __urdlllocal ur_result_t UR_APICALL + urMemBufferPartition( + ur_mem_handle_t hBuffer, ///< [in] handle of the buffer object to allocate from + ur_mem_flags_t flags, ///< [in] allocation and usage information flags + ur_buffer_create_type_t bufferCreateType, ///< [in] buffer creation type + ur_buffer_region_t* pBufferCreateInfo, ///< [in] pointer to buffer create region information + ur_mem_handle_t* phMem ///< [out] pointer to the handle of sub buffer created + ) + { + ur_result_t result = UR_RESULT_SUCCESS; + + // extract platform's function pointer table + auto dditable = reinterpret_cast( hBuffer )->dditable; + auto pfnBufferPartition = dditable->ur.Mem.pfnBufferPartition; + if( nullptr == pfnBufferPartition ) + return UR_RESULT_ERROR_UNINITIALIZED; + + // convert loader handle to platform handle + hBuffer = reinterpret_cast( hBuffer )->handle; + + // forward to device-platform + result = pfnBufferPartition( hBuffer, flags, bufferCreateType, pBufferCreateInfo, phMem ); + + if( UR_RESULT_SUCCESS != result ) + return result; + + try + { + // convert platform handle to loader handle + *phMem = reinterpret_cast( + ur_mem_factory.getInstance( *phMem, dditable ) ); + } + catch( std::bad_alloc& ) + { + result = UR_RESULT_ERROR_OUT_OF_HOST_MEMORY; + } + + return result; + } + + /////////////////////////////////////////////////////////////////////////////// + /// @brief Intercept function for urMemGetNativeHandle + __urdlllocal ur_result_t UR_APICALL + urMemGetNativeHandle( + ur_mem_handle_t hMem, ///< [in] handle of the mem. + ur_native_handle_t* phNativeMem ///< [out] a pointer to the native handle of the mem. + ) + { + ur_result_t result = UR_RESULT_SUCCESS; + + // extract platform's function pointer table + auto dditable = reinterpret_cast( hMem )->dditable; + auto pfnGetNativeHandle = dditable->ur.Mem.pfnGetNativeHandle; + if( nullptr == pfnGetNativeHandle ) + return UR_RESULT_ERROR_UNINITIALIZED; + + // convert loader handle to platform handle + hMem = reinterpret_cast( hMem )->handle; + + // forward to device-platform + result = pfnGetNativeHandle( hMem, phNativeMem ); + + if( UR_RESULT_SUCCESS != result ) + return result; + + try + { + // convert platform handle to loader handle + *phNativeMem = reinterpret_cast( + ur_native_factory.getInstance( *phNativeMem, dditable ) ); + } + catch( std::bad_alloc& ) + { + result = UR_RESULT_ERROR_OUT_OF_HOST_MEMORY; + } + + return result; + } + + /////////////////////////////////////////////////////////////////////////////// + /// @brief Intercept function for urMemCreateWithNativeHandle + __urdlllocal ur_result_t UR_APICALL + urMemCreateWithNativeHandle( + ur_native_handle_t hNativeMem, ///< [in] the native handle of the mem. + ur_context_handle_t hContext, ///< [in] handle of the context object + ur_mem_handle_t* phMem ///< [out] pointer to the handle of the mem object created. + ) + { + ur_result_t result = UR_RESULT_SUCCESS; + + // extract platform's function pointer table + auto dditable = reinterpret_cast( hNativeMem )->dditable; + auto pfnCreateWithNativeHandle = dditable->ur.Mem.pfnCreateWithNativeHandle; + if( nullptr == pfnCreateWithNativeHandle ) + return UR_RESULT_ERROR_UNINITIALIZED; + + // convert loader handle to platform handle + hNativeMem = reinterpret_cast( hNativeMem )->handle; + + // convert loader handle to platform handle + hContext = reinterpret_cast( hContext )->handle; + + // forward to device-platform + result = pfnCreateWithNativeHandle( hNativeMem, hContext, phMem ); + + if( UR_RESULT_SUCCESS != result ) + return result; + + try + { + // convert platform handle to loader handle + *phMem = reinterpret_cast( + ur_mem_factory.getInstance( *phMem, dditable ) ); + } + catch( std::bad_alloc& ) + { + result = UR_RESULT_ERROR_OUT_OF_HOST_MEMORY; + } + + return result; + } + + /////////////////////////////////////////////////////////////////////////////// + /// @brief Intercept function for urMemGetInfo + __urdlllocal ur_result_t UR_APICALL + urMemGetInfo( + ur_mem_handle_t hMemory, ///< [in] handle to the memory object being queried. + ur_mem_info_t MemInfoType, ///< [in] type of the info to retrieve. + size_t propSize, ///< [in] the number of bytes of memory pointed to by pMemInfo. + void* pMemInfo, ///< [out][optional] array of bytes holding the info. + ///< If propSize is less than the real number of bytes needed to return + ///< the info then the ::UR_RESULT_ERROR_INVALID_SIZE error is returned and + ///< pMemInfo is not used. + size_t* pPropSizeRet ///< [out][optional] pointer to the actual size in bytes of data queried by pMemInfo. + ) + { + ur_result_t result = UR_RESULT_SUCCESS; + + // extract platform's function pointer table + auto dditable = reinterpret_cast( hMemory )->dditable; + auto pfnGetInfo = dditable->ur.Mem.pfnGetInfo; + if( nullptr == pfnGetInfo ) + return UR_RESULT_ERROR_UNINITIALIZED; + + // convert loader handle to platform handle + hMemory = reinterpret_cast( hMemory )->handle; + + // forward to device-platform + result = pfnGetInfo( hMemory, MemInfoType, propSize, pMemInfo, pPropSizeRet ); + + return result; + } + + /////////////////////////////////////////////////////////////////////////////// + /// @brief Intercept function for urMemImageGetInfo + __urdlllocal ur_result_t UR_APICALL + urMemImageGetInfo( + ur_mem_handle_t hMemory, ///< [in] handle to the image object being queried. + ur_image_info_t ImgInfoType, ///< [in] type of image info to retrieve. + size_t propSize, ///< [in] the number of bytes of memory pointer to by pImgInfo. + void* pImgInfo, ///< [out][optional] array of bytes holding the info. + ///< If propSize is less than the real number of bytes needed to return + ///< the info then the ::UR_RESULT_ERROR_INVALID_SIZE error is returned and + ///< pImgInfo is not used. + size_t* pPropSizeRet ///< [out][optional] pointer to the actual size in bytes of data queried by pImgInfo. + ) + { + ur_result_t result = UR_RESULT_SUCCESS; + + // extract platform's function pointer table + auto dditable = reinterpret_cast( hMemory )->dditable; + auto pfnImageGetInfo = dditable->ur.Mem.pfnImageGetInfo; + if( nullptr == pfnImageGetInfo ) + return UR_RESULT_ERROR_UNINITIALIZED; + + // convert loader handle to platform handle + hMemory = reinterpret_cast( hMemory )->handle; + + // forward to device-platform + result = pfnImageGetInfo( hMemory, ImgInfoType, propSize, pImgInfo, pPropSizeRet ); + + return result; + } + + /////////////////////////////////////////////////////////////////////////////// + /// @brief Intercept function for urTearDown + __urdlllocal ur_result_t UR_APICALL + urTearDown( + void* pParams ///< [in] pointer to tear down parameters + ) + { + ur_result_t result = UR_RESULT_SUCCESS; + + + for( auto& platform : context->platforms ) + { + platform.dditable.ur.Global.pfnTearDown( pParams ); + } + + return result; + } + + /////////////////////////////////////////////////////////////////////////////// + /// @brief Intercept function for urQueueGetInfo + __urdlllocal ur_result_t UR_APICALL + urQueueGetInfo( + ur_queue_handle_t hQueue, ///< [in] handle of the queue object + ur_queue_info_t propName, ///< [in] name of the queue property to query + size_t propValueSize, ///< [in] size in bytes of the queue property value provided + void* pPropValue, ///< [out] value of the queue property + size_t* pPropSizeRet ///< [out] size in bytes returned in queue property value + ) + { + ur_result_t result = UR_RESULT_SUCCESS; + + // extract platform's function pointer table + auto dditable = reinterpret_cast( hQueue )->dditable; + auto pfnGetInfo = dditable->ur.Queue.pfnGetInfo; + if( nullptr == pfnGetInfo ) + return UR_RESULT_ERROR_UNINITIALIZED; + + // convert loader handle to platform handle + hQueue = reinterpret_cast( hQueue )->handle; + + // forward to device-platform + result = pfnGetInfo( hQueue, propName, propValueSize, pPropValue, pPropSizeRet ); + + return result; + } + + /////////////////////////////////////////////////////////////////////////////// + /// @brief Intercept function for urQueueCreate + __urdlllocal ur_result_t UR_APICALL + urQueueCreate( + ur_context_handle_t hContext, ///< [in] handle of the context object + ur_device_handle_t hDevice, ///< [in] handle of the device object + ur_queue_flags_t props, ///< [in] initialization properties. + ///< must be 0 (default) or a combination of ::ur_queue_flags_t. + ur_queue_handle_t* phQueue ///< [out] pointer to handle of queue object created + ) + { + ur_result_t result = UR_RESULT_SUCCESS; + + // extract platform's function pointer table + auto dditable = reinterpret_cast( hContext )->dditable; + auto pfnCreate = dditable->ur.Queue.pfnCreate; + if( nullptr == pfnCreate ) + return UR_RESULT_ERROR_UNINITIALIZED; + + // convert loader handle to platform handle + hContext = reinterpret_cast( hContext )->handle; + + // convert loader handle to platform handle + hDevice = reinterpret_cast( hDevice )->handle; + + // forward to device-platform + result = pfnCreate( hContext, hDevice, props, phQueue ); + + if( UR_RESULT_SUCCESS != result ) + return result; + + try + { + // convert platform handle to loader handle + *phQueue = reinterpret_cast( + ur_queue_factory.getInstance( *phQueue, dditable ) ); + } + catch( std::bad_alloc& ) + { + result = UR_RESULT_ERROR_OUT_OF_HOST_MEMORY; + } + + return result; + } + + /////////////////////////////////////////////////////////////////////////////// + /// @brief Intercept function for urQueueRetain + __urdlllocal ur_result_t UR_APICALL + urQueueRetain( + ur_queue_handle_t hQueue ///< [in] handle of the queue object to get access + ) + { + ur_result_t result = UR_RESULT_SUCCESS; + + // extract platform's function pointer table + auto dditable = reinterpret_cast( hQueue )->dditable; + auto pfnRetain = dditable->ur.Queue.pfnRetain; + if( nullptr == pfnRetain ) + return UR_RESULT_ERROR_UNINITIALIZED; + + // convert loader handle to platform handle + hQueue = reinterpret_cast( hQueue )->handle; + + // forward to device-platform + result = pfnRetain( hQueue ); + + return result; + } + + /////////////////////////////////////////////////////////////////////////////// + /// @brief Intercept function for urQueueRelease + __urdlllocal ur_result_t UR_APICALL + urQueueRelease( + ur_queue_handle_t hQueue ///< [in] handle of the queue object to release + ) + { + ur_result_t result = UR_RESULT_SUCCESS; + + // extract platform's function pointer table + auto dditable = reinterpret_cast( hQueue )->dditable; + auto pfnRelease = dditable->ur.Queue.pfnRelease; + if( nullptr == pfnRelease ) + return UR_RESULT_ERROR_UNINITIALIZED; + + // convert loader handle to platform handle + hQueue = reinterpret_cast( hQueue )->handle; + + // forward to device-platform + result = pfnRelease( hQueue ); + + return result; + } + + /////////////////////////////////////////////////////////////////////////////// + /// @brief Intercept function for urQueueGetNativeHandle + __urdlllocal ur_result_t UR_APICALL + urQueueGetNativeHandle( + ur_queue_handle_t hQueue, ///< [in] handle of the queue. + ur_native_handle_t* phNativeQueue ///< [out] a pointer to the native handle of the queue. + ) + { + ur_result_t result = UR_RESULT_SUCCESS; + + // extract platform's function pointer table + auto dditable = reinterpret_cast( hQueue )->dditable; + auto pfnGetNativeHandle = dditable->ur.Queue.pfnGetNativeHandle; + if( nullptr == pfnGetNativeHandle ) + return UR_RESULT_ERROR_UNINITIALIZED; + + // convert loader handle to platform handle + hQueue = reinterpret_cast( hQueue )->handle; + + // forward to device-platform + result = pfnGetNativeHandle( hQueue, phNativeQueue ); + + if( UR_RESULT_SUCCESS != result ) + return result; + + try + { + // convert platform handle to loader handle + *phNativeQueue = reinterpret_cast( + ur_native_factory.getInstance( *phNativeQueue, dditable ) ); + } + catch( std::bad_alloc& ) + { + result = UR_RESULT_ERROR_OUT_OF_HOST_MEMORY; + } + + return result; + } + + /////////////////////////////////////////////////////////////////////////////// + /// @brief Intercept function for urQueueCreateWithNativeHandle + __urdlllocal ur_result_t UR_APICALL + urQueueCreateWithNativeHandle( + ur_native_handle_t hNativeQueue, ///< [in] the native handle of the queue. + ur_context_handle_t hContext, ///< [in] handle of the context object + ur_queue_handle_t* phQueue ///< [out] pointer to the handle of the queue object created. + ) + { + ur_result_t result = UR_RESULT_SUCCESS; + + // extract platform's function pointer table + auto dditable = reinterpret_cast( hNativeQueue )->dditable; + auto pfnCreateWithNativeHandle = dditable->ur.Queue.pfnCreateWithNativeHandle; + if( nullptr == pfnCreateWithNativeHandle ) + return UR_RESULT_ERROR_UNINITIALIZED; + + // convert loader handle to platform handle + hNativeQueue = reinterpret_cast( hNativeQueue )->handle; + + // convert loader handle to platform handle + hContext = reinterpret_cast( hContext )->handle; + + // forward to device-platform + result = pfnCreateWithNativeHandle( hNativeQueue, hContext, phQueue ); + + if( UR_RESULT_SUCCESS != result ) + return result; + + try + { + // convert platform handle to loader handle + *phQueue = reinterpret_cast( + ur_queue_factory.getInstance( *phQueue, dditable ) ); + } + catch( std::bad_alloc& ) + { + result = UR_RESULT_ERROR_OUT_OF_HOST_MEMORY; + } + + return result; + } + + /////////////////////////////////////////////////////////////////////////////// + /// @brief Intercept function for urQueueFinish + __urdlllocal ur_result_t UR_APICALL + urQueueFinish( + ur_queue_handle_t hQueue ///< [in] handle of the queue to be finished. + ) + { + ur_result_t result = UR_RESULT_SUCCESS; + + // extract platform's function pointer table + auto dditable = reinterpret_cast( hQueue )->dditable; + auto pfnFinish = dditable->ur.Queue.pfnFinish; + if( nullptr == pfnFinish ) + return UR_RESULT_ERROR_UNINITIALIZED; + + // convert loader handle to platform handle + hQueue = reinterpret_cast( hQueue )->handle; + + // forward to device-platform + result = pfnFinish( hQueue ); + + return result; + } + + /////////////////////////////////////////////////////////////////////////////// + /// @brief Intercept function for urQueueFlush + __urdlllocal ur_result_t UR_APICALL + urQueueFlush( + ur_queue_handle_t hQueue ///< [in] handle of the queue to be flushed. + ) + { + ur_result_t result = UR_RESULT_SUCCESS; + + // extract platform's function pointer table + auto dditable = reinterpret_cast( hQueue )->dditable; + auto pfnFlush = dditable->ur.Queue.pfnFlush; + if( nullptr == pfnFlush ) + return UR_RESULT_ERROR_UNINITIALIZED; + + // convert loader handle to platform handle + hQueue = reinterpret_cast( hQueue )->handle; + + // forward to device-platform + result = pfnFlush( hQueue ); + + return result; + } + + /////////////////////////////////////////////////////////////////////////////// + /// @brief Intercept function for urSamplerCreate + __urdlllocal ur_result_t UR_APICALL + urSamplerCreate( + ur_context_handle_t hContext, ///< [in] handle of the context object + const ur_sampler_property_value_t* pProps, ///< [in] specifies a list of sampler property names and their + ///< corresponding values. + ur_sampler_handle_t* phSampler ///< [out] pointer to handle of sampler object created + ) + { + ur_result_t result = UR_RESULT_SUCCESS; + + // extract platform's function pointer table + auto dditable = reinterpret_cast( hContext )->dditable; + auto pfnCreate = dditable->ur.Sampler.pfnCreate; + if( nullptr == pfnCreate ) + return UR_RESULT_ERROR_UNINITIALIZED; + + // convert loader handle to platform handle + hContext = reinterpret_cast( hContext )->handle; + + // forward to device-platform + result = pfnCreate( hContext, pProps, phSampler ); + + if( UR_RESULT_SUCCESS != result ) + return result; + + try + { + // convert platform handle to loader handle + *phSampler = reinterpret_cast( + ur_sampler_factory.getInstance( *phSampler, dditable ) ); + } + catch( std::bad_alloc& ) + { + result = UR_RESULT_ERROR_OUT_OF_HOST_MEMORY; + } + + return result; + } + + /////////////////////////////////////////////////////////////////////////////// + /// @brief Intercept function for urSamplerRetain + __urdlllocal ur_result_t UR_APICALL + urSamplerRetain( + ur_sampler_handle_t hSampler ///< [in] handle of the sampler object to get access + ) + { + ur_result_t result = UR_RESULT_SUCCESS; + + // extract platform's function pointer table + auto dditable = reinterpret_cast( hSampler )->dditable; + auto pfnRetain = dditable->ur.Sampler.pfnRetain; + if( nullptr == pfnRetain ) + return UR_RESULT_ERROR_UNINITIALIZED; + + // convert loader handle to platform handle + hSampler = reinterpret_cast( hSampler )->handle; + + // forward to device-platform + result = pfnRetain( hSampler ); + + return result; + } + + /////////////////////////////////////////////////////////////////////////////// + /// @brief Intercept function for urSamplerRelease + __urdlllocal ur_result_t UR_APICALL + urSamplerRelease( + ur_sampler_handle_t hSampler ///< [in] handle of the sampler object to release + ) + { + ur_result_t result = UR_RESULT_SUCCESS; + + // extract platform's function pointer table + auto dditable = reinterpret_cast( hSampler )->dditable; + auto pfnRelease = dditable->ur.Sampler.pfnRelease; + if( nullptr == pfnRelease ) + return UR_RESULT_ERROR_UNINITIALIZED; + + // convert loader handle to platform handle + hSampler = reinterpret_cast( hSampler )->handle; + + // forward to device-platform + result = pfnRelease( hSampler ); + + return result; + } + + /////////////////////////////////////////////////////////////////////////////// + /// @brief Intercept function for urSamplerGetInfo + __urdlllocal ur_result_t UR_APICALL + urSamplerGetInfo( + ur_sampler_handle_t hSampler, ///< [in] handle of the sampler object + ur_sampler_info_t propName, ///< [in] name of the sampler property to query + size_t propValueSize, ///< [in] size in bytes of the sampler property value provided + void* pPropValue, ///< [out] value of the sampler property + size_t* pPropSizeRet ///< [out] size in bytes returned in sampler property value + ) + { + ur_result_t result = UR_RESULT_SUCCESS; + + // extract platform's function pointer table + auto dditable = reinterpret_cast( hSampler )->dditable; + auto pfnGetInfo = dditable->ur.Sampler.pfnGetInfo; + if( nullptr == pfnGetInfo ) + return UR_RESULT_ERROR_UNINITIALIZED; + + // convert loader handle to platform handle + hSampler = reinterpret_cast( hSampler )->handle; + + // forward to device-platform + result = pfnGetInfo( hSampler, propName, propValueSize, pPropValue, pPropSizeRet ); + + return result; + } + + /////////////////////////////////////////////////////////////////////////////// + /// @brief Intercept function for urSamplerGetNativeHandle + __urdlllocal ur_result_t UR_APICALL + urSamplerGetNativeHandle( + ur_sampler_handle_t hSampler, ///< [in] handle of the sampler. + ur_native_handle_t* phNativeSampler ///< [out] a pointer to the native handle of the sampler. + ) + { + ur_result_t result = UR_RESULT_SUCCESS; + + // extract platform's function pointer table + auto dditable = reinterpret_cast( hSampler )->dditable; + auto pfnGetNativeHandle = dditable->ur.Sampler.pfnGetNativeHandle; + if( nullptr == pfnGetNativeHandle ) + return UR_RESULT_ERROR_UNINITIALIZED; + + // convert loader handle to platform handle + hSampler = reinterpret_cast( hSampler )->handle; + + // forward to device-platform + result = pfnGetNativeHandle( hSampler, phNativeSampler ); + + if( UR_RESULT_SUCCESS != result ) + return result; + + try + { + // convert platform handle to loader handle + *phNativeSampler = reinterpret_cast( + ur_native_factory.getInstance( *phNativeSampler, dditable ) ); + } + catch( std::bad_alloc& ) + { + result = UR_RESULT_ERROR_OUT_OF_HOST_MEMORY; + } + + return result; + } + + /////////////////////////////////////////////////////////////////////////////// + /// @brief Intercept function for urSamplerCreateWithNativeHandle + __urdlllocal ur_result_t UR_APICALL + urSamplerCreateWithNativeHandle( + ur_native_handle_t hNativeSampler, ///< [in] the native handle of the sampler. + ur_context_handle_t hContext, ///< [in] handle of the context object + ur_sampler_handle_t* phSampler ///< [out] pointer to the handle of the sampler object created. + ) + { + ur_result_t result = UR_RESULT_SUCCESS; + + // extract platform's function pointer table + auto dditable = reinterpret_cast( hNativeSampler )->dditable; + auto pfnCreateWithNativeHandle = dditable->ur.Sampler.pfnCreateWithNativeHandle; + if( nullptr == pfnCreateWithNativeHandle ) + return UR_RESULT_ERROR_UNINITIALIZED; + + // convert loader handle to platform handle + hNativeSampler = reinterpret_cast( hNativeSampler )->handle; + + // convert loader handle to platform handle + hContext = reinterpret_cast( hContext )->handle; + + // forward to device-platform + result = pfnCreateWithNativeHandle( hNativeSampler, hContext, phSampler ); + + if( UR_RESULT_SUCCESS != result ) + return result; + + try + { + // convert platform handle to loader handle + *phSampler = reinterpret_cast( + ur_sampler_factory.getInstance( *phSampler, dditable ) ); + } + catch( std::bad_alloc& ) + { + result = UR_RESULT_ERROR_OUT_OF_HOST_MEMORY; + } + + return result; + } + + /////////////////////////////////////////////////////////////////////////////// + /// @brief Intercept function for urUSMHostAlloc + __urdlllocal ur_result_t UR_APICALL + urUSMHostAlloc( + ur_context_handle_t hContext, ///< [in] handle of the context object + ur_usm_mem_flags_t* pUSMFlag, ///< [in] USM memory allocation flags + size_t size, ///< [in] size in bytes of the USM memory object to be allocated + uint32_t align, ///< [in] alignment of the USM memory object + void** ppMem ///< [out] pointer to USM host memory object + ) + { + ur_result_t result = UR_RESULT_SUCCESS; + + // extract platform's function pointer table + auto dditable = reinterpret_cast( hContext )->dditable; + auto pfnHostAlloc = dditable->ur.USM.pfnHostAlloc; + if( nullptr == pfnHostAlloc ) + return UR_RESULT_ERROR_UNINITIALIZED; + + // convert loader handle to platform handle + hContext = reinterpret_cast( hContext )->handle; + + // forward to device-platform + result = pfnHostAlloc( hContext, pUSMFlag, size, align, ppMem ); + + return result; + } + + /////////////////////////////////////////////////////////////////////////////// + /// @brief Intercept function for urUSMDeviceAlloc + __urdlllocal ur_result_t UR_APICALL + urUSMDeviceAlloc( + ur_context_handle_t hContext, ///< [in] handle of the context object + ur_device_handle_t hDevice, ///< [in] handle of the device object + ur_usm_mem_flags_t* pUSMProp, ///< [in] USM memory properties + size_t size, ///< [in] size in bytes of the USM memory object to be allocated + uint32_t align, ///< [in] alignment of the USM memory object + void** ppMem ///< [out] pointer to USM device memory object + ) + { + ur_result_t result = UR_RESULT_SUCCESS; + + // extract platform's function pointer table + auto dditable = reinterpret_cast( hContext )->dditable; + auto pfnDeviceAlloc = dditable->ur.USM.pfnDeviceAlloc; + if( nullptr == pfnDeviceAlloc ) + return UR_RESULT_ERROR_UNINITIALIZED; + + // convert loader handle to platform handle + hContext = reinterpret_cast( hContext )->handle; + + // convert loader handle to platform handle + hDevice = reinterpret_cast( hDevice )->handle; + + // forward to device-platform + result = pfnDeviceAlloc( hContext, hDevice, pUSMProp, size, align, ppMem ); + + return result; + } + + /////////////////////////////////////////////////////////////////////////////// + /// @brief Intercept function for urUSMSharedAlloc + __urdlllocal ur_result_t UR_APICALL + urUSMSharedAlloc( + ur_context_handle_t hContext, ///< [in] handle of the context object + ur_device_handle_t hDevice, ///< [in] handle of the device object + ur_usm_mem_flags_t* pUSMProp, ///< [in] USM memory properties + size_t size, ///< [in] size in bytes of the USM memory object to be allocated + uint32_t align, ///< [in] alignment of the USM memory object + void** ppMem ///< [out] pointer to USM shared memory object + ) + { + ur_result_t result = UR_RESULT_SUCCESS; + + // extract platform's function pointer table + auto dditable = reinterpret_cast( hContext )->dditable; + auto pfnSharedAlloc = dditable->ur.USM.pfnSharedAlloc; + if( nullptr == pfnSharedAlloc ) + return UR_RESULT_ERROR_UNINITIALIZED; + + // convert loader handle to platform handle + hContext = reinterpret_cast( hContext )->handle; + + // convert loader handle to platform handle + hDevice = reinterpret_cast( hDevice )->handle; + + // forward to device-platform + result = pfnSharedAlloc( hContext, hDevice, pUSMProp, size, align, ppMem ); + + return result; + } + + /////////////////////////////////////////////////////////////////////////////// + /// @brief Intercept function for urMemFree + __urdlllocal ur_result_t UR_APICALL + urMemFree( + ur_context_handle_t hContext, ///< [in] handle of the context object + void* pMem ///< [in] pointer to USM memory object + ) + { + ur_result_t result = UR_RESULT_SUCCESS; + + // extract platform's function pointer table + auto dditable = reinterpret_cast( hContext )->dditable; + auto pfnFree = dditable->ur.Mem.pfnFree; + if( nullptr == pfnFree ) + return UR_RESULT_ERROR_UNINITIALIZED; + + // convert loader handle to platform handle + hContext = reinterpret_cast( hContext )->handle; + + // forward to device-platform + result = pfnFree( hContext, pMem ); + + return result; + } + + /////////////////////////////////////////////////////////////////////////////// + /// @brief Intercept function for urMemGetMemAllocInfo + __urdlllocal ur_result_t UR_APICALL + urMemGetMemAllocInfo( + ur_context_handle_t hContext, ///< [in] handle of the context object + const void* pMem, ///< [in] pointer to USM memory object + ur_mem_alloc_info_t propName, ///< [in] the name of the USM allocation property to query + size_t propValueSize, ///< [in] size in bytes of the USM allocation property value + void* pPropValue, ///< [out] value of the USM allocation property + size_t* pPropValueSizeRet ///< [out] bytes returned in USM allocation property + ) + { + ur_result_t result = UR_RESULT_SUCCESS; + + // extract platform's function pointer table + auto dditable = reinterpret_cast( hContext )->dditable; + auto pfnGetMemAllocInfo = dditable->ur.Mem.pfnGetMemAllocInfo; + if( nullptr == pfnGetMemAllocInfo ) + return UR_RESULT_ERROR_UNINITIALIZED; + + // convert loader handle to platform handle + hContext = reinterpret_cast( hContext )->handle; + + // forward to device-platform + result = pfnGetMemAllocInfo( hContext, pMem, propName, propValueSize, pPropValue, pPropValueSizeRet ); + + return result; + } + + /////////////////////////////////////////////////////////////////////////////// + /// @brief Intercept function for urDeviceGet + __urdlllocal ur_result_t UR_APICALL + urDeviceGet( + ur_platform_handle_t hPlatform, ///< [in] handle of the platform instance + ur_device_type_t DeviceType, ///< [in] the type of the devices. + uint32_t NumEntries, ///< [in] the number of devices to be added to phDevices. + ///< If phDevices in not NULL then NumEntries should be greater than zero, + ///< otherwise ::UR_RESULT_ERROR_INVALID_SIZE, + ///< will be returned. + ur_device_handle_t* phDevices, ///< [out][optional][range(0, NumEntries)] array of handle of devices. + ///< If NumEntries is less than the number of devices available, then + ///< platform shall only retrieve that number of devices. + uint32_t* pNumDevices ///< [out][optional] pointer to the number of devices. + ///< pNumDevices will be updated with the total number of devices available. + ) + { + ur_result_t result = UR_RESULT_SUCCESS; + + // extract platform's function pointer table + auto dditable = reinterpret_cast( hPlatform )->dditable; + auto pfnGet = dditable->ur.Device.pfnGet; + if( nullptr == pfnGet ) + return UR_RESULT_ERROR_UNINITIALIZED; + + // convert loader handle to platform handle + hPlatform = reinterpret_cast( hPlatform )->handle; + + // forward to device-platform + result = pfnGet( hPlatform, DeviceType, NumEntries, phDevices, pNumDevices ); + + if( UR_RESULT_SUCCESS != result ) + return result; + + try + { + // convert platform handles to loader handles + for( size_t i = 0; ( nullptr != phDevices ) && ( i < NumEntries ); ++i ) + phDevices[ i ] = reinterpret_cast( + ur_device_factory.getInstance( phDevices[ i ], dditable ) ); + } + catch( std::bad_alloc& ) + { + result = UR_RESULT_ERROR_OUT_OF_HOST_MEMORY; + } + + return result; + } + + /////////////////////////////////////////////////////////////////////////////// + /// @brief Intercept function for urDeviceGetInfo + __urdlllocal ur_result_t UR_APICALL + urDeviceGetInfo( + ur_device_handle_t hDevice, ///< [in] handle of the device instance + ur_device_info_t infoType, ///< [in] type of the info to retrieve + size_t propSize, ///< [in] the number of bytes pointed to by pDeviceInfo. + void* pDeviceInfo, ///< [out][optional] 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 ::UR_RESULT_ERROR_INVALID_SIZE error is returned and + ///< pDeviceInfo is not used. + size_t* pPropSizeRet ///< [out][optional] pointer to the actual size in bytes of the queried infoType. + ) + { + ur_result_t result = UR_RESULT_SUCCESS; + + // extract platform's function pointer table + auto dditable = reinterpret_cast( hDevice )->dditable; + auto pfnGetInfo = dditable->ur.Device.pfnGetInfo; + if( nullptr == pfnGetInfo ) + return UR_RESULT_ERROR_UNINITIALIZED; + + // convert loader handle to platform handle + hDevice = reinterpret_cast( hDevice )->handle; + + // forward to device-platform + result = pfnGetInfo( hDevice, infoType, propSize, pDeviceInfo, pPropSizeRet ); + + return result; + } + + /////////////////////////////////////////////////////////////////////////////// + /// @brief Intercept function for urDeviceRetain + __urdlllocal ur_result_t UR_APICALL + urDeviceRetain( + ur_device_handle_t hDevice ///< [in] handle of the device to get a reference of. + ) + { + ur_result_t result = UR_RESULT_SUCCESS; + + // extract platform's function pointer table + auto dditable = reinterpret_cast( hDevice )->dditable; + auto pfnRetain = dditable->ur.Device.pfnRetain; + if( nullptr == pfnRetain ) + return UR_RESULT_ERROR_UNINITIALIZED; + + // convert loader handle to platform handle + hDevice = reinterpret_cast( hDevice )->handle; + + // forward to device-platform + result = pfnRetain( hDevice ); + + return result; + } + + /////////////////////////////////////////////////////////////////////////////// + /// @brief Intercept function for urDeviceRelease + __urdlllocal ur_result_t UR_APICALL + urDeviceRelease( + ur_device_handle_t hDevice ///< [in] handle of the device to release. + ) + { + ur_result_t result = UR_RESULT_SUCCESS; + + // extract platform's function pointer table + auto dditable = reinterpret_cast( hDevice )->dditable; + auto pfnRelease = dditable->ur.Device.pfnRelease; + if( nullptr == pfnRelease ) + return UR_RESULT_ERROR_UNINITIALIZED; + + // convert loader handle to platform handle + hDevice = reinterpret_cast( hDevice )->handle; + + // forward to device-platform + result = pfnRelease( hDevice ); + + return result; + } + + /////////////////////////////////////////////////////////////////////////////// + /// @brief Intercept function for urDevicePartition + __urdlllocal ur_result_t UR_APICALL + urDevicePartition( + ur_device_handle_t hDevice, ///< [in] handle of the device to partition. + ur_device_partition_property_value_t* Properties, ///< [in] null-terminated array of pair of the requested partitioning. + uint32_t NumDevices, ///< [in] the number of sub-devices. + ur_device_handle_t* phSubDevices, ///< [out][optional][range(0, NumDevices)] array of handle of devices. + ///< If NumDevices is less than the number of sub-devices available, then + ///< the function shall only retrieve that number of sub-devices. + uint32_t* pNumDevicesRet ///< [out][optional] pointer to the number of sub-devices the device can be + ///< partitioned into according to the partitioning property. + ) + { + ur_result_t result = UR_RESULT_SUCCESS; + + // extract platform's function pointer table + auto dditable = reinterpret_cast( hDevice )->dditable; + auto pfnPartition = dditable->ur.Device.pfnPartition; + if( nullptr == pfnPartition ) + return UR_RESULT_ERROR_UNINITIALIZED; + + // convert loader handle to platform handle + hDevice = reinterpret_cast( hDevice )->handle; + + // forward to device-platform + result = pfnPartition( hDevice, Properties, NumDevices, phSubDevices, pNumDevicesRet ); + + if( UR_RESULT_SUCCESS != result ) + return result; + + try + { + // convert platform handles to loader handles + for( size_t i = 0; ( nullptr != phSubDevices ) && ( i < NumDevices ); ++i ) + phSubDevices[ i ] = reinterpret_cast( + ur_device_factory.getInstance( phSubDevices[ i ], dditable ) ); + } + catch( std::bad_alloc& ) + { + result = UR_RESULT_ERROR_OUT_OF_HOST_MEMORY; + } + + return result; + } + + /////////////////////////////////////////////////////////////////////////////// + /// @brief Intercept function for urDeviceSelectBinary + __urdlllocal ur_result_t UR_APICALL + urDeviceSelectBinary( + ur_device_handle_t hDevice, ///< [in] handle of the device to select binary for. + const uint8_t** ppBinaries, ///< [in] the array of binaries to select from. + uint32_t NumBinaries, ///< [in] the number of binaries passed in ppBinaries. Must greater than or + ///< equal to zero. + uint32_t* pSelectedBinary ///< [out] the index of the selected binary in the input array of binaries. + ///< If a suitable binary was not found the function returns ${X}_INVALID_BINARY. + ) + { + ur_result_t result = UR_RESULT_SUCCESS; + + // extract platform's function pointer table + auto dditable = reinterpret_cast( hDevice )->dditable; + auto pfnSelectBinary = dditable->ur.Device.pfnSelectBinary; + if( nullptr == pfnSelectBinary ) + return UR_RESULT_ERROR_UNINITIALIZED; + + // convert loader handle to platform handle + hDevice = reinterpret_cast( hDevice )->handle; + + // forward to device-platform + result = pfnSelectBinary( hDevice, ppBinaries, NumBinaries, pSelectedBinary ); + + return result; + } + + /////////////////////////////////////////////////////////////////////////////// + /// @brief Intercept function for urDeviceGetNativeHandle + __urdlllocal ur_result_t UR_APICALL + urDeviceGetNativeHandle( + ur_device_handle_t hDevice, ///< [in] handle of the device. + ur_native_handle_t* phNativeDevice ///< [out] a pointer to the native handle of the device. + ) + { + ur_result_t result = UR_RESULT_SUCCESS; + + // extract platform's function pointer table + auto dditable = reinterpret_cast( hDevice )->dditable; + auto pfnGetNativeHandle = dditable->ur.Device.pfnGetNativeHandle; + if( nullptr == pfnGetNativeHandle ) + return UR_RESULT_ERROR_UNINITIALIZED; + + // convert loader handle to platform handle + hDevice = reinterpret_cast( hDevice )->handle; + + // forward to device-platform + result = pfnGetNativeHandle( hDevice, phNativeDevice ); + + if( UR_RESULT_SUCCESS != result ) + return result; + + try + { + // convert platform handle to loader handle + *phNativeDevice = reinterpret_cast( + ur_native_factory.getInstance( *phNativeDevice, dditable ) ); + } + catch( std::bad_alloc& ) + { + result = UR_RESULT_ERROR_OUT_OF_HOST_MEMORY; + } + + return result; + } + + /////////////////////////////////////////////////////////////////////////////// + /// @brief Intercept function for urDeviceCreateWithNativeHandle + __urdlllocal ur_result_t UR_APICALL + urDeviceCreateWithNativeHandle( + ur_native_handle_t hNativeDevice, ///< [in] the native handle of the device. + ur_platform_handle_t hPlatform, ///< [in] handle of the platform instance + ur_device_handle_t* phDevice ///< [out] pointer to the handle of the device object created. + ) + { + ur_result_t result = UR_RESULT_SUCCESS; + + // extract platform's function pointer table + auto dditable = reinterpret_cast( hNativeDevice )->dditable; + auto pfnCreateWithNativeHandle = dditable->ur.Device.pfnCreateWithNativeHandle; + if( nullptr == pfnCreateWithNativeHandle ) + return UR_RESULT_ERROR_UNINITIALIZED; + + // convert loader handle to platform handle + hNativeDevice = reinterpret_cast( hNativeDevice )->handle; + + // convert loader handle to platform handle + hPlatform = reinterpret_cast( hPlatform )->handle; + + // forward to device-platform + result = pfnCreateWithNativeHandle( hNativeDevice, hPlatform, phDevice ); + + if( UR_RESULT_SUCCESS != result ) + return result; + + try + { + // convert platform handle to loader handle + *phDevice = reinterpret_cast( + ur_device_factory.getInstance( *phDevice, dditable ) ); + } + catch( std::bad_alloc& ) + { + result = UR_RESULT_ERROR_OUT_OF_HOST_MEMORY; + } + + return result; + } + + /////////////////////////////////////////////////////////////////////////////// + /// @brief Intercept function for urKernelCreate + __urdlllocal ur_result_t UR_APICALL + urKernelCreate( + ur_program_handle_t hProgram, ///< [in] handle of the program instance + const char* pKernelName, ///< [in] pointer to null-terminated string. + ur_kernel_handle_t* phKernel ///< [out] pointer to handle of kernel object created. + ) + { + ur_result_t result = UR_RESULT_SUCCESS; + + // extract platform's function pointer table + auto dditable = reinterpret_cast( hProgram )->dditable; + auto pfnCreate = dditable->ur.Kernel.pfnCreate; + if( nullptr == pfnCreate ) + return UR_RESULT_ERROR_UNINITIALIZED; + + // convert loader handle to platform handle + hProgram = reinterpret_cast( hProgram )->handle; + + // forward to device-platform + result = pfnCreate( hProgram, pKernelName, phKernel ); + + if( UR_RESULT_SUCCESS != result ) + return result; + + try + { + // convert platform handle to loader handle + *phKernel = reinterpret_cast( + ur_kernel_factory.getInstance( *phKernel, dditable ) ); + } + catch( std::bad_alloc& ) + { + result = UR_RESULT_ERROR_OUT_OF_HOST_MEMORY; + } + + return result; + } + + /////////////////////////////////////////////////////////////////////////////// + /// @brief Intercept function for urKernelSetArg + __urdlllocal ur_result_t UR_APICALL + urKernelSetArg( + ur_kernel_handle_t hKernel, ///< [in] handle of the kernel object + uint32_t argIndex, ///< [in] argument index in range [0, num args - 1] + size_t argSize, ///< [in] size of argument type + const void* pArgValue ///< [in][optional] argument value represented as matching arg type. If + ///< null then argument value is considered null. + ) + { + ur_result_t result = UR_RESULT_SUCCESS; + + // extract platform's function pointer table + auto dditable = reinterpret_cast( hKernel )->dditable; + auto pfnSetArg = dditable->ur.Kernel.pfnSetArg; + if( nullptr == pfnSetArg ) + return UR_RESULT_ERROR_UNINITIALIZED; + + // convert loader handle to platform handle + hKernel = reinterpret_cast( hKernel )->handle; + + // forward to device-platform + result = pfnSetArg( hKernel, argIndex, argSize, pArgValue ); + + return result; + } + + /////////////////////////////////////////////////////////////////////////////// + /// @brief Intercept function for urKernelGetInfo + __urdlllocal ur_result_t UR_APICALL + urKernelGetInfo( + ur_kernel_handle_t hKernel, ///< [in] handle of the Kernel object + ur_kernel_info_t propName, ///< [in] name of the Kernel property to query + size_t propSize, ///< [in] the size of the Kernel property value. + void* pKernelInfo, ///< [in,out][optional] array of bytes holding the kernel info property. + ///< If propSize is not equal to or greater than the real number of bytes + ///< needed to return + ///< the info then the ::UR_RESULT_ERROR_INVALID_SIZE error is returned and + ///< pKernelInfo is not used. + size_t* pPropSizeRet ///< [out][optional] pointer to the actual size in bytes of data being + ///< queried by propName. + ) + { + ur_result_t result = UR_RESULT_SUCCESS; + + // extract platform's function pointer table + auto dditable = reinterpret_cast( hKernel )->dditable; + auto pfnGetInfo = dditable->ur.Kernel.pfnGetInfo; + if( nullptr == pfnGetInfo ) + return UR_RESULT_ERROR_UNINITIALIZED; + + // convert loader handle to platform handle + hKernel = reinterpret_cast( hKernel )->handle; + + // forward to device-platform + result = pfnGetInfo( hKernel, propName, propSize, pKernelInfo, pPropSizeRet ); + + return result; + } + + /////////////////////////////////////////////////////////////////////////////// + /// @brief Intercept function for urKernelGetGroupInfo + __urdlllocal ur_result_t UR_APICALL + urKernelGetGroupInfo( + ur_kernel_handle_t hKernel, ///< [in] handle of the Kernel object + ur_device_handle_t hDevice, ///< [in] handle of the Device object + ur_kernel_group_info_t propName, ///< [in] name of the work Group property to query + size_t propSize, ///< [in] size of the Kernel Work Group property value + void* pPropValue, ///< [in,out][optional][range(0, propSize)] value of the Kernel Work Group + ///< property. + size_t* pPropSizeRet ///< [out][optional] pointer to the actual size in bytes of data being + ///< queried by propName. + ) + { + ur_result_t result = UR_RESULT_SUCCESS; + + // extract platform's function pointer table + auto dditable = reinterpret_cast( hKernel )->dditable; + auto pfnGetGroupInfo = dditable->ur.Kernel.pfnGetGroupInfo; + if( nullptr == pfnGetGroupInfo ) + return UR_RESULT_ERROR_UNINITIALIZED; + + // convert loader handle to platform handle + hKernel = reinterpret_cast( hKernel )->handle; + + // convert loader handle to platform handle + hDevice = reinterpret_cast( hDevice )->handle; + + // forward to device-platform + result = pfnGetGroupInfo( hKernel, hDevice, propName, propSize, pPropValue, pPropSizeRet ); + + return result; + } + + /////////////////////////////////////////////////////////////////////////////// + /// @brief Intercept function for urKernelGetSubGroupInfo + __urdlllocal ur_result_t UR_APICALL + urKernelGetSubGroupInfo( + ur_kernel_handle_t hKernel, ///< [in] handle of the Kernel object + ur_device_handle_t hDevice, ///< [in] handle of the Device object + ur_kernel_sub_group_info_t propName, ///< [in] name of the SubGroup property to query + size_t propSize, ///< [in] size of the Kernel SubGroup property value + void* pPropValue, ///< [in,out][range(0, propSize)][optional] value of the Kernel SubGroup + ///< property. + size_t* pPropSizeRet ///< [out][optional] pointer to the actual size in bytes of data being + ///< queried by propName. + ) + { + ur_result_t result = UR_RESULT_SUCCESS; + + // extract platform's function pointer table + auto dditable = reinterpret_cast( hKernel )->dditable; + auto pfnGetSubGroupInfo = dditable->ur.Kernel.pfnGetSubGroupInfo; + if( nullptr == pfnGetSubGroupInfo ) + return UR_RESULT_ERROR_UNINITIALIZED; + + // convert loader handle to platform handle + hKernel = reinterpret_cast( hKernel )->handle; + + // convert loader handle to platform handle + hDevice = reinterpret_cast( hDevice )->handle; + + // forward to device-platform + result = pfnGetSubGroupInfo( hKernel, hDevice, propName, propSize, pPropValue, pPropSizeRet ); + + return result; + } + + /////////////////////////////////////////////////////////////////////////////// + /// @brief Intercept function for urKernelRetain + __urdlllocal ur_result_t UR_APICALL + urKernelRetain( + ur_kernel_handle_t hKernel ///< [in] handle for the Kernel to retain + ) + { + ur_result_t result = UR_RESULT_SUCCESS; + + // extract platform's function pointer table + auto dditable = reinterpret_cast( hKernel )->dditable; + auto pfnRetain = dditable->ur.Kernel.pfnRetain; + if( nullptr == pfnRetain ) + return UR_RESULT_ERROR_UNINITIALIZED; + + // convert loader handle to platform handle + hKernel = reinterpret_cast( hKernel )->handle; + + // forward to device-platform + result = pfnRetain( hKernel ); + + return result; + } + + /////////////////////////////////////////////////////////////////////////////// + /// @brief Intercept function for urKernelRelease + __urdlllocal ur_result_t UR_APICALL + urKernelRelease( + ur_kernel_handle_t hKernel ///< [in] handle for the Kernel to release + ) + { + ur_result_t result = UR_RESULT_SUCCESS; + + // extract platform's function pointer table + auto dditable = reinterpret_cast( hKernel )->dditable; + auto pfnRelease = dditable->ur.Kernel.pfnRelease; + if( nullptr == pfnRelease ) + return UR_RESULT_ERROR_UNINITIALIZED; + + // convert loader handle to platform handle + hKernel = reinterpret_cast( hKernel )->handle; + + // forward to device-platform + result = pfnRelease( hKernel ); + + return result; + } + + /////////////////////////////////////////////////////////////////////////////// + /// @brief Intercept function for urKernelSetArgPointer + __urdlllocal ur_result_t UR_APICALL + urKernelSetArgPointer( + ur_kernel_handle_t hKernel, ///< [in] handle of the kernel object + uint32_t argIndex, ///< [in] argument index in range [0, num args - 1] + size_t argSize, ///< [in] size of argument type + const void* pArgValue ///< [in][optional] SVM pointer to memory location holding the argument + ///< value. If null then argument value is considered null. + ) + { + ur_result_t result = UR_RESULT_SUCCESS; + + // extract platform's function pointer table + auto dditable = reinterpret_cast( hKernel )->dditable; + auto pfnSetArgPointer = dditable->ur.Kernel.pfnSetArgPointer; + if( nullptr == pfnSetArgPointer ) + return UR_RESULT_ERROR_UNINITIALIZED; + + // convert loader handle to platform handle + hKernel = reinterpret_cast( hKernel )->handle; + + // forward to device-platform + result = pfnSetArgPointer( hKernel, argIndex, argSize, pArgValue ); + + return result; + } + + /////////////////////////////////////////////////////////////////////////////// + /// @brief Intercept function for urKernelSetExecInfo + __urdlllocal ur_result_t UR_APICALL + urKernelSetExecInfo( + ur_kernel_handle_t hKernel, ///< [in] handle of the kernel object + ur_kernel_exec_info_t propName, ///< [in] name of the execution attribute + size_t propSize, ///< [in] size in byte the attribute value + const void* pPropValue ///< [in][range(0, propSize)] pointer to memory location holding the + ///< property value. + ) + { + ur_result_t result = UR_RESULT_SUCCESS; + + // extract platform's function pointer table + auto dditable = reinterpret_cast( hKernel )->dditable; + auto pfnSetExecInfo = dditable->ur.Kernel.pfnSetExecInfo; + if( nullptr == pfnSetExecInfo ) + return UR_RESULT_ERROR_UNINITIALIZED; + + // convert loader handle to platform handle + hKernel = reinterpret_cast( hKernel )->handle; + + // forward to device-platform + result = pfnSetExecInfo( hKernel, propName, propSize, pPropValue ); + + return result; + } + + /////////////////////////////////////////////////////////////////////////////// + /// @brief Intercept function for urKernelSetArgSampler + __urdlllocal ur_result_t UR_APICALL + urKernelSetArgSampler( + ur_kernel_handle_t hKernel, ///< [in] handle of the kernel object + uint32_t argIndex, ///< [in] argument index in range [0, num args - 1] + ur_sampler_handle_t hArgValue ///< [in] handle of Sampler object. + ) + { + ur_result_t result = UR_RESULT_SUCCESS; + + // extract platform's function pointer table + auto dditable = reinterpret_cast( hKernel )->dditable; + auto pfnSetArgSampler = dditable->ur.Kernel.pfnSetArgSampler; + if( nullptr == pfnSetArgSampler ) + return UR_RESULT_ERROR_UNINITIALIZED; + + // convert loader handle to platform handle + hKernel = reinterpret_cast( hKernel )->handle; + + // convert loader handle to platform handle + hArgValue = reinterpret_cast( hArgValue )->handle; + + // forward to device-platform + result = pfnSetArgSampler( hKernel, argIndex, hArgValue ); + + return result; + } + + /////////////////////////////////////////////////////////////////////////////// + /// @brief Intercept function for urKernelSetArgMemObj + __urdlllocal ur_result_t UR_APICALL + urKernelSetArgMemObj( + ur_kernel_handle_t hKernel, ///< [in] handle of the kernel object + uint32_t argIndex, ///< [in] argument index in range [0, num args - 1] + ur_mem_handle_t hArgValue ///< [in] handle of Memory object. + ) + { + ur_result_t result = UR_RESULT_SUCCESS; + + // extract platform's function pointer table + auto dditable = reinterpret_cast( hKernel )->dditable; + auto pfnSetArgMemObj = dditable->ur.Kernel.pfnSetArgMemObj; + if( nullptr == pfnSetArgMemObj ) + return UR_RESULT_ERROR_UNINITIALIZED; + + // convert loader handle to platform handle + hKernel = reinterpret_cast( hKernel )->handle; + + // convert loader handle to platform handle + hArgValue = reinterpret_cast( hArgValue )->handle; + + // forward to device-platform + result = pfnSetArgMemObj( hKernel, argIndex, hArgValue ); + + return result; + } + + /////////////////////////////////////////////////////////////////////////////// + /// @brief Intercept function for urKernelGetNativeHandle + __urdlllocal ur_result_t UR_APICALL + urKernelGetNativeHandle( + ur_kernel_handle_t hKernel, ///< [in] handle of the kernel. + ur_native_handle_t* phNativeKernel ///< [out] a pointer to the native handle of the kernel. + ) + { + ur_result_t result = UR_RESULT_SUCCESS; + + // extract platform's function pointer table + auto dditable = reinterpret_cast( hKernel )->dditable; + auto pfnGetNativeHandle = dditable->ur.Kernel.pfnGetNativeHandle; + if( nullptr == pfnGetNativeHandle ) + return UR_RESULT_ERROR_UNINITIALIZED; + + // convert loader handle to platform handle + hKernel = reinterpret_cast( hKernel )->handle; + + // forward to device-platform + result = pfnGetNativeHandle( hKernel, phNativeKernel ); + + if( UR_RESULT_SUCCESS != result ) + return result; + + try + { + // convert platform handle to loader handle + *phNativeKernel = reinterpret_cast( + ur_native_factory.getInstance( *phNativeKernel, dditable ) ); + } + catch( std::bad_alloc& ) + { + result = UR_RESULT_ERROR_OUT_OF_HOST_MEMORY; + } + + return result; + } + + /////////////////////////////////////////////////////////////////////////////// + /// @brief Intercept function for urKernelCreateWithNativeHandle + __urdlllocal ur_result_t UR_APICALL + urKernelCreateWithNativeHandle( + ur_native_handle_t hNativeKernel, ///< [in] the native handle of the kernel. + ur_context_handle_t hContext, ///< [in] handle of the context object + ur_kernel_handle_t* phKernel ///< [out] pointer to the handle of the kernel object created. + ) + { + ur_result_t result = UR_RESULT_SUCCESS; + + // extract platform's function pointer table + auto dditable = reinterpret_cast( hNativeKernel )->dditable; + auto pfnCreateWithNativeHandle = dditable->ur.Kernel.pfnCreateWithNativeHandle; + if( nullptr == pfnCreateWithNativeHandle ) + return UR_RESULT_ERROR_UNINITIALIZED; + + // convert loader handle to platform handle + hNativeKernel = reinterpret_cast( hNativeKernel )->handle; + + // convert loader handle to platform handle + hContext = reinterpret_cast( hContext )->handle; + + // forward to device-platform + result = pfnCreateWithNativeHandle( hNativeKernel, hContext, phKernel ); + + if( UR_RESULT_SUCCESS != result ) + return result; + + try + { + // convert platform handle to loader handle + *phKernel = reinterpret_cast( + ur_kernel_factory.getInstance( *phKernel, dditable ) ); + } + catch( std::bad_alloc& ) + { + result = UR_RESULT_ERROR_OUT_OF_HOST_MEMORY; + } + + return result; + } + + /////////////////////////////////////////////////////////////////////////////// + /// @brief Intercept function for urModuleCreate + __urdlllocal ur_result_t UR_APICALL + urModuleCreate( + ur_context_handle_t hContext, ///< [in] handle of the context instance. + const void* pIL, ///< [in] pointer to IL string. + size_t length, ///< [in] length of IL in bytes. + const char* pOptions, ///< [in] pointer to compiler options null-terminated string. + ur_modulecreate_callback_t pfnNotify, ///< [in][optional] A function pointer to a notification routine that is + ///< called when program compilation is complete. + void* pUserData, ///< [in][optional] Passed as an argument when pfnNotify is called. + ur_module_handle_t* phModule ///< [out] pointer to handle of Module object created. + ) + { + ur_result_t result = UR_RESULT_SUCCESS; + + // extract platform's function pointer table + auto dditable = reinterpret_cast( hContext )->dditable; + auto pfnCreate = dditable->ur.Module.pfnCreate; + if( nullptr == pfnCreate ) + return UR_RESULT_ERROR_UNINITIALIZED; + + // convert loader handle to platform handle + hContext = reinterpret_cast( hContext )->handle; + + // forward to device-platform + result = pfnCreate( hContext, pIL, length, pOptions, pfnNotify, pUserData, phModule ); + + if( UR_RESULT_SUCCESS != result ) + return result; + + try + { + // convert platform handle to loader handle + *phModule = reinterpret_cast( + ur_module_factory.getInstance( *phModule, dditable ) ); + } + catch( std::bad_alloc& ) + { + result = UR_RESULT_ERROR_OUT_OF_HOST_MEMORY; + } + + return result; + } + + /////////////////////////////////////////////////////////////////////////////// + /// @brief Intercept function for urModuleRetain + __urdlllocal ur_result_t UR_APICALL + urModuleRetain( + ur_module_handle_t hModule ///< [in] handle for the Module to retain + ) + { + ur_result_t result = UR_RESULT_SUCCESS; + + // extract platform's function pointer table + auto dditable = reinterpret_cast( hModule )->dditable; + auto pfnRetain = dditable->ur.Module.pfnRetain; + if( nullptr == pfnRetain ) + return UR_RESULT_ERROR_UNINITIALIZED; + + // convert loader handle to platform handle + hModule = reinterpret_cast( hModule )->handle; + + // forward to device-platform + result = pfnRetain( hModule ); + + return result; + } + + /////////////////////////////////////////////////////////////////////////////// + /// @brief Intercept function for urModuleRelease + __urdlllocal ur_result_t UR_APICALL + urModuleRelease( + ur_module_handle_t hModule ///< [in] handle for the Module to release + ) + { + ur_result_t result = UR_RESULT_SUCCESS; + + // extract platform's function pointer table + auto dditable = reinterpret_cast( hModule )->dditable; + auto pfnRelease = dditable->ur.Module.pfnRelease; + if( nullptr == pfnRelease ) + return UR_RESULT_ERROR_UNINITIALIZED; + + // convert loader handle to platform handle + hModule = reinterpret_cast( hModule )->handle; + + // forward to device-platform + result = pfnRelease( hModule ); + + return result; + } + + /////////////////////////////////////////////////////////////////////////////// + /// @brief Intercept function for urModuleGetNativeHandle + __urdlllocal ur_result_t UR_APICALL + urModuleGetNativeHandle( + ur_module_handle_t hModule, ///< [in] handle of the module. + ur_native_handle_t* phNativeModule ///< [out] a pointer to the native handle of the module. + ) + { + ur_result_t result = UR_RESULT_SUCCESS; + + // extract platform's function pointer table + auto dditable = reinterpret_cast( hModule )->dditable; + auto pfnGetNativeHandle = dditable->ur.Module.pfnGetNativeHandle; + if( nullptr == pfnGetNativeHandle ) + return UR_RESULT_ERROR_UNINITIALIZED; + + // convert loader handle to platform handle + hModule = reinterpret_cast( hModule )->handle; + + // forward to device-platform + result = pfnGetNativeHandle( hModule, phNativeModule ); + + if( UR_RESULT_SUCCESS != result ) + return result; + + try + { + // convert platform handle to loader handle + *phNativeModule = reinterpret_cast( + ur_native_factory.getInstance( *phNativeModule, dditable ) ); + } + catch( std::bad_alloc& ) + { + result = UR_RESULT_ERROR_OUT_OF_HOST_MEMORY; + } + + return result; + } + + /////////////////////////////////////////////////////////////////////////////// + /// @brief Intercept function for urModuleCreateWithNativeHandle + __urdlllocal ur_result_t UR_APICALL + urModuleCreateWithNativeHandle( + ur_native_handle_t hNativeModule, ///< [in] the native handle of the module. + ur_context_handle_t hContext, ///< [in] handle of the context instance. + ur_module_handle_t* phModule ///< [out] pointer to the handle of the module object created. + ) + { + ur_result_t result = UR_RESULT_SUCCESS; + + // extract platform's function pointer table + auto dditable = reinterpret_cast( hNativeModule )->dditable; + auto pfnCreateWithNativeHandle = dditable->ur.Module.pfnCreateWithNativeHandle; + if( nullptr == pfnCreateWithNativeHandle ) + return UR_RESULT_ERROR_UNINITIALIZED; + + // convert loader handle to platform handle + hNativeModule = reinterpret_cast( hNativeModule )->handle; + + // convert loader handle to platform handle + hContext = reinterpret_cast( hContext )->handle; + + // forward to device-platform + result = pfnCreateWithNativeHandle( hNativeModule, hContext, phModule ); + + if( UR_RESULT_SUCCESS != result ) + return result; + + try + { + // convert platform handle to loader handle + *phModule = reinterpret_cast( + ur_module_factory.getInstance( *phModule, dditable ) ); + } + catch( std::bad_alloc& ) + { + result = UR_RESULT_ERROR_OUT_OF_HOST_MEMORY; + } + + return result; + } + + /////////////////////////////////////////////////////////////////////////////// + /// @brief Intercept function for urPlatformGet + __urdlllocal ur_result_t UR_APICALL + urPlatformGet( + uint32_t NumEntries, ///< [in] the number of platforms to be added to phPlatforms. + ///< If phPlatforms is not NULL, then NumEntries should be greater than + ///< zero, otherwise ::UR_RESULT_ERROR_INVALID_SIZE, + ///< will be returned. + ur_platform_handle_t* phPlatforms, ///< [out][optional][range(0, NumEntries)] array of handle of platforms. + ///< If NumEntries is less than the number of platforms available, then + ///< ::urPlatformGet shall only retrieve that number of platforms. + uint32_t* pNumPlatforms ///< [out][optional] returns the total number of platforms available. + ) + { + ur_result_t result = UR_RESULT_SUCCESS; + + uint32_t total_platform_handle_count = 0; + + for( auto& platform : context->platforms ) + { + if(platform.initStatus != UR_RESULT_SUCCESS) + continue; + + if( ( 0 < NumEntries ) && ( NumEntries == total_platform_handle_count)) + break; + + uint32_t library_platform_handle_count = 0; + + result = platform.dditable.ur.Platform.pfnGet( 0, nullptr, &library_platform_handle_count ); + if( UR_RESULT_SUCCESS != result ) break; + + if( nullptr != phPlatforms && NumEntries !=0) + { + if( total_platform_handle_count + library_platform_handle_count > NumEntries) { + library_platform_handle_count = NumEntries - total_platform_handle_count; + } + result = platform.dditable.ur.Platform.pfnGet( library_platform_handle_count, &phPlatforms[ total_platform_handle_count ], nullptr ); + if( UR_RESULT_SUCCESS != result ) break; + + try + { + for( uint32_t i = 0; i < library_platform_handle_count; ++i ) { + uint32_t platform_index = total_platform_handle_count + i; + phPlatforms[ platform_index ] = reinterpret_cast( + ur_platform_factory.getInstance( phPlatforms[ platform_index ], &platform.dditable ) ); + } + } + catch( std::bad_alloc& ) + { + result = UR_RESULT_ERROR_OUT_OF_HOST_MEMORY; + } + } + + total_platform_handle_count += library_platform_handle_count; + } + + if( UR_RESULT_SUCCESS == result && pNumPlatforms != nullptr ) + *pNumPlatforms = total_platform_handle_count; + + return result; + } + + /////////////////////////////////////////////////////////////////////////////// + /// @brief Intercept function for urPlatformGetInfo + __urdlllocal ur_result_t UR_APICALL + urPlatformGetInfo( + ur_platform_handle_t hPlatform, ///< [in] handle of the platform + ur_platform_info_t PlatformInfoType, ///< [in] type of the info to retrieve + size_t Size, ///< [in] the number of bytes pointed to by pPlatformInfo. + void* pPlatformInfo, ///< [out][optional] 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 ::UR_RESULT_ERROR_INVALID_SIZE error is + ///< returned and pPlatformInfo is not used. + size_t* pSizeRet ///< [out][optional] pointer to the actual number of bytes being queried by pPlatformInfo. + ) + { + ur_result_t result = UR_RESULT_SUCCESS; + + // extract platform's function pointer table + auto dditable = reinterpret_cast( hPlatform )->dditable; + auto pfnGetInfo = dditable->ur.Platform.pfnGetInfo; + if( nullptr == pfnGetInfo ) + return UR_RESULT_ERROR_UNINITIALIZED; + + // convert loader handle to platform handle + hPlatform = reinterpret_cast( hPlatform )->handle; + + // forward to device-platform + result = pfnGetInfo( hPlatform, PlatformInfoType, Size, pPlatformInfo, pSizeRet ); + + return result; + } + + /////////////////////////////////////////////////////////////////////////////// + /// @brief Intercept function for urPlatformGetApiVersion + __urdlllocal ur_result_t UR_APICALL + urPlatformGetApiVersion( + ur_platform_handle_t hDriver, ///< [in] handle of the platform + ur_api_version_t* pVersion ///< [out] api version + ) + { + ur_result_t result = UR_RESULT_SUCCESS; + + // extract platform's function pointer table + auto dditable = reinterpret_cast( hDriver )->dditable; + auto pfnGetApiVersion = dditable->ur.Platform.pfnGetApiVersion; + if( nullptr == pfnGetApiVersion ) + return UR_RESULT_ERROR_UNINITIALIZED; + + // convert loader handle to platform handle + hDriver = reinterpret_cast( hDriver )->handle; + + // forward to device-platform + result = pfnGetApiVersion( hDriver, pVersion ); + + return result; + } + + /////////////////////////////////////////////////////////////////////////////// + /// @brief Intercept function for urPlatformGetNativeHandle + __urdlllocal ur_result_t UR_APICALL + urPlatformGetNativeHandle( + ur_platform_handle_t hPlatform, ///< [in] handle of the platform. + ur_native_handle_t* phNativePlatform ///< [out] a pointer to the native handle of the platform. + ) + { + ur_result_t result = UR_RESULT_SUCCESS; + + // extract platform's function pointer table + auto dditable = reinterpret_cast( hPlatform )->dditable; + auto pfnGetNativeHandle = dditable->ur.Platform.pfnGetNativeHandle; + if( nullptr == pfnGetNativeHandle ) + return UR_RESULT_ERROR_UNINITIALIZED; + + // convert loader handle to platform handle + hPlatform = reinterpret_cast( hPlatform )->handle; + + // forward to device-platform + result = pfnGetNativeHandle( hPlatform, phNativePlatform ); + + if( UR_RESULT_SUCCESS != result ) + return result; + + try + { + // convert platform handle to loader handle + *phNativePlatform = reinterpret_cast( + ur_native_factory.getInstance( *phNativePlatform, dditable ) ); + } + catch( std::bad_alloc& ) + { + result = UR_RESULT_ERROR_OUT_OF_HOST_MEMORY; + } + + return result; + } + + /////////////////////////////////////////////////////////////////////////////// + /// @brief Intercept function for urPlatformCreateWithNativeHandle + __urdlllocal ur_result_t UR_APICALL + urPlatformCreateWithNativeHandle( + ur_native_handle_t hNativePlatform, ///< [in] the native handle of the platform. + ur_platform_handle_t* phPlatform ///< [out] pointer to the handle of the platform object created. + ) + { + ur_result_t result = UR_RESULT_SUCCESS; + + // extract platform's function pointer table + auto dditable = reinterpret_cast( hNativePlatform )->dditable; + auto pfnCreateWithNativeHandle = dditable->ur.Platform.pfnCreateWithNativeHandle; + if( nullptr == pfnCreateWithNativeHandle ) + return UR_RESULT_ERROR_UNINITIALIZED; + + // convert loader handle to platform handle + hNativePlatform = reinterpret_cast( hNativePlatform )->handle; + + // forward to device-platform + result = pfnCreateWithNativeHandle( hNativePlatform, phPlatform ); + + if( UR_RESULT_SUCCESS != result ) + return result; + + try + { + // convert platform handle to loader handle + *phPlatform = reinterpret_cast( + ur_platform_factory.getInstance( *phPlatform, dditable ) ); + } + catch( std::bad_alloc& ) + { + result = UR_RESULT_ERROR_OUT_OF_HOST_MEMORY; + } + + return result; + } + + /////////////////////////////////////////////////////////////////////////////// + /// @brief Intercept function for urGetLastResult + __urdlllocal ur_result_t UR_APICALL + urGetLastResult( + ur_platform_handle_t hPlatform, ///< [in] handle of the platform instance + const char** ppMessage ///< [out] pointer to a string containing adapter specific result in string + ///< representation. + ) + { + ur_result_t result = UR_RESULT_SUCCESS; + + // extract platform's function pointer table + auto dditable = reinterpret_cast( hPlatform )->dditable; + auto pfnGetLastResult = dditable->ur.Global.pfnGetLastResult; + if( nullptr == pfnGetLastResult ) + return UR_RESULT_ERROR_UNINITIALIZED; + + // convert loader handle to platform handle + hPlatform = reinterpret_cast( hPlatform )->handle; + + // forward to device-platform + result = pfnGetLastResult( hPlatform, ppMessage ); + + return result; + } + + /////////////////////////////////////////////////////////////////////////////// + /// @brief Intercept function for urProgramCreate + __urdlllocal ur_result_t UR_APICALL + urProgramCreate( + ur_context_handle_t hContext, ///< [in] handle of the context instance + uint32_t count, ///< [in] number of module handles in module list. + const ur_module_handle_t* phModules, ///< [in][range(0, count)] pointer to array of modules. + const char* pOptions, ///< [in][optional] pointer to linker options null-terminated string. + ur_program_handle_t* phProgram ///< [out] pointer to handle of program object created. + ) + { + ur_result_t result = UR_RESULT_SUCCESS; + + // extract platform's function pointer table + auto dditable = reinterpret_cast( hContext )->dditable; + auto pfnCreate = dditable->ur.Program.pfnCreate; + if( nullptr == pfnCreate ) + return UR_RESULT_ERROR_UNINITIALIZED; + + // convert loader handle to platform handle + hContext = reinterpret_cast( hContext )->handle; + + // convert loader handles to platform handles + auto phModulesLocal = new ur_module_handle_t [count]; + for( size_t i = 0; ( nullptr != phModules ) && ( i < count ); ++i ) + phModulesLocal[ i ] = reinterpret_cast( phModules[ i ] )->handle; + + // forward to device-platform + result = pfnCreate( hContext, count, phModules, pOptions, phProgram ); + delete []phModulesLocal; + + if( UR_RESULT_SUCCESS != result ) + return result; + + try + { + // convert platform handle to loader handle + *phProgram = reinterpret_cast( + ur_program_factory.getInstance( *phProgram, dditable ) ); + } + catch( std::bad_alloc& ) + { + result = UR_RESULT_ERROR_OUT_OF_HOST_MEMORY; + } + + return result; + } + + /////////////////////////////////////////////////////////////////////////////// + /// @brief Intercept function for urProgramCreateWithBinary + __urdlllocal ur_result_t UR_APICALL + urProgramCreateWithBinary( + ur_context_handle_t hContext, ///< [in] handle of the context instance + ur_device_handle_t hDevice, ///< [in] handle to device associated with binary. + size_t size, ///< [in] size in bytes. + const uint8_t* pBinary, ///< [in] pointer to binary. + ur_program_handle_t* phProgram ///< [out] pointer to handle of Program object created. + ) + { + ur_result_t result = UR_RESULT_SUCCESS; + + // extract platform's function pointer table + auto dditable = reinterpret_cast( hContext )->dditable; + auto pfnCreateWithBinary = dditable->ur.Program.pfnCreateWithBinary; + if( nullptr == pfnCreateWithBinary ) + return UR_RESULT_ERROR_UNINITIALIZED; + + // convert loader handle to platform handle + hContext = reinterpret_cast( hContext )->handle; + + // convert loader handle to platform handle + hDevice = reinterpret_cast( hDevice )->handle; + + // forward to device-platform + result = pfnCreateWithBinary( hContext, hDevice, size, pBinary, phProgram ); + + if( UR_RESULT_SUCCESS != result ) + return result; + + try + { + // convert platform handle to loader handle + *phProgram = reinterpret_cast( + ur_program_factory.getInstance( *phProgram, dditable ) ); + } + catch( std::bad_alloc& ) + { + result = UR_RESULT_ERROR_OUT_OF_HOST_MEMORY; + } + + return result; + } + + /////////////////////////////////////////////////////////////////////////////// + /// @brief Intercept function for urProgramRetain + __urdlllocal ur_result_t UR_APICALL + urProgramRetain( + ur_program_handle_t hProgram ///< [in] handle for the Program to retain + ) + { + ur_result_t result = UR_RESULT_SUCCESS; + + // extract platform's function pointer table + auto dditable = reinterpret_cast( hProgram )->dditable; + auto pfnRetain = dditable->ur.Program.pfnRetain; + if( nullptr == pfnRetain ) + return UR_RESULT_ERROR_UNINITIALIZED; + + // convert loader handle to platform handle + hProgram = reinterpret_cast( hProgram )->handle; + + // forward to device-platform + result = pfnRetain( hProgram ); + + return result; + } + + /////////////////////////////////////////////////////////////////////////////// + /// @brief Intercept function for urProgramRelease + __urdlllocal ur_result_t UR_APICALL + urProgramRelease( + ur_program_handle_t hProgram ///< [in] handle for the Program to release + ) + { + ur_result_t result = UR_RESULT_SUCCESS; + + // extract platform's function pointer table + auto dditable = reinterpret_cast( hProgram )->dditable; + auto pfnRelease = dditable->ur.Program.pfnRelease; + if( nullptr == pfnRelease ) + return UR_RESULT_ERROR_UNINITIALIZED; + + // convert loader handle to platform handle + hProgram = reinterpret_cast( hProgram )->handle; + + // forward to device-platform + result = pfnRelease( hProgram ); + + return result; + } + + /////////////////////////////////////////////////////////////////////////////// + /// @brief Intercept function for urProgramGetFunctionPointer + __urdlllocal ur_result_t UR_APICALL + urProgramGetFunctionPointer( + ur_device_handle_t hDevice, ///< [in] handle of the device to retrieve pointer for. + ur_program_handle_t hProgram, ///< [in] handle of the program to search for function in. + ///< The program must already be built to the specified device, or + ///< otherwise ::UR_RESULT_ERROR_INVALID_PROGRAM_EXECUTABLE is returned. + const char* pFunctionName, ///< [in] A null-terminates string denoting the mangled function name. + void** ppFunctionPointer ///< [out] Returns the pointer to the function if it is found in the program. + ) + { + ur_result_t result = UR_RESULT_SUCCESS; + + // extract platform's function pointer table + auto dditable = reinterpret_cast( hDevice )->dditable; + auto pfnGetFunctionPointer = dditable->ur.Program.pfnGetFunctionPointer; + if( nullptr == pfnGetFunctionPointer ) + return UR_RESULT_ERROR_UNINITIALIZED; + + // convert loader handle to platform handle + hDevice = reinterpret_cast( hDevice )->handle; + + // convert loader handle to platform handle + hProgram = reinterpret_cast( hProgram )->handle; + + // forward to device-platform + result = pfnGetFunctionPointer( hDevice, hProgram, pFunctionName, ppFunctionPointer ); + + return result; + } + + /////////////////////////////////////////////////////////////////////////////// + /// @brief Intercept function for urProgramGetInfo + __urdlllocal ur_result_t UR_APICALL + urProgramGetInfo( + ur_program_handle_t hProgram, ///< [in] handle of the Program object + ur_program_info_t propName, ///< [in] name of the Program property to query + size_t propSize, ///< [in] the size of the Program property. + void* pProgramInfo, ///< [in,out][optional] array of bytes of holding the program info property. + ///< If propSize is not equal to or greater than the real number of bytes + ///< needed to return + ///< the info then the ::UR_RESULT_ERROR_INVALID_SIZE error is returned and + ///< pProgramInfo is not used. + size_t* pPropSizeRet ///< [out][optional] pointer to the actual size in bytes of data copied to propName. + ) + { + ur_result_t result = UR_RESULT_SUCCESS; + + // extract platform's function pointer table + auto dditable = reinterpret_cast( hProgram )->dditable; + auto pfnGetInfo = dditable->ur.Program.pfnGetInfo; + if( nullptr == pfnGetInfo ) + return UR_RESULT_ERROR_UNINITIALIZED; + + // convert loader handle to platform handle + hProgram = reinterpret_cast( hProgram )->handle; + + // forward to device-platform + result = pfnGetInfo( hProgram, propName, propSize, pProgramInfo, pPropSizeRet ); + + return result; + } + + /////////////////////////////////////////////////////////////////////////////// + /// @brief Intercept function for urProgramGetBuildInfo + __urdlllocal ur_result_t UR_APICALL + urProgramGetBuildInfo( + ur_program_handle_t hProgram, ///< [in] handle of the Program object + ur_device_handle_t hDevice, ///< [in] handle of the Device object + ur_program_build_info_t propName, ///< [in] name of the Program build info to query + size_t propSize, ///< [in] size of the Program build info property. + void* pPropValue, ///< [in,out][optional] value of the Program build property. + ///< If propSize is not equal to or greater than the real number of bytes + ///< needed to return the info then the ::UR_RESULT_ERROR_INVALID_SIZE + ///< error is returned and pKernelInfo is not used. + size_t* pPropSizeRet ///< [out][optional] pointer to the actual size in bytes of data being + ///< queried by propName. + ) + { + ur_result_t result = UR_RESULT_SUCCESS; + + // extract platform's function pointer table + auto dditable = reinterpret_cast( hProgram )->dditable; + auto pfnGetBuildInfo = dditable->ur.Program.pfnGetBuildInfo; + if( nullptr == pfnGetBuildInfo ) + return UR_RESULT_ERROR_UNINITIALIZED; + + // convert loader handle to platform handle + hProgram = reinterpret_cast( hProgram )->handle; + + // convert loader handle to platform handle + hDevice = reinterpret_cast( hDevice )->handle; + + // forward to device-platform + result = pfnGetBuildInfo( hProgram, hDevice, propName, propSize, pPropValue, pPropSizeRet ); + + return result; + } + + /////////////////////////////////////////////////////////////////////////////// + /// @brief Intercept function for urProgramSetSpecializationConstant + __urdlllocal ur_result_t UR_APICALL + urProgramSetSpecializationConstant( + ur_program_handle_t hProgram, ///< [in] handle of the Program object + uint32_t specId, ///< [in] specification constant Id + size_t specSize, ///< [in] size of the specialization constant value + const void* pSpecValue ///< [in] pointer to the specialization value bytes + ) + { + ur_result_t result = UR_RESULT_SUCCESS; + + // extract platform's function pointer table + auto dditable = reinterpret_cast( hProgram )->dditable; + auto pfnSetSpecializationConstant = dditable->ur.Program.pfnSetSpecializationConstant; + if( nullptr == pfnSetSpecializationConstant ) + return UR_RESULT_ERROR_UNINITIALIZED; + + // convert loader handle to platform handle + hProgram = reinterpret_cast( hProgram )->handle; + + // forward to device-platform + result = pfnSetSpecializationConstant( hProgram, specId, specSize, pSpecValue ); + + return result; + } + + /////////////////////////////////////////////////////////////////////////////// + /// @brief Intercept function for urProgramGetNativeHandle + __urdlllocal ur_result_t UR_APICALL + urProgramGetNativeHandle( + ur_program_handle_t hProgram, ///< [in] handle of the program. + ur_native_handle_t* phNativeProgram ///< [out] a pointer to the native handle of the program. + ) + { + ur_result_t result = UR_RESULT_SUCCESS; + + // extract platform's function pointer table + auto dditable = reinterpret_cast( hProgram )->dditable; + auto pfnGetNativeHandle = dditable->ur.Program.pfnGetNativeHandle; + if( nullptr == pfnGetNativeHandle ) + return UR_RESULT_ERROR_UNINITIALIZED; + + // convert loader handle to platform handle + hProgram = reinterpret_cast( hProgram )->handle; + + // forward to device-platform + result = pfnGetNativeHandle( hProgram, phNativeProgram ); + + if( UR_RESULT_SUCCESS != result ) + return result; + + try + { + // convert platform handle to loader handle + *phNativeProgram = reinterpret_cast( + ur_native_factory.getInstance( *phNativeProgram, dditable ) ); + } + catch( std::bad_alloc& ) + { + result = UR_RESULT_ERROR_OUT_OF_HOST_MEMORY; + } + + return result; + } + + /////////////////////////////////////////////////////////////////////////////// + /// @brief Intercept function for urProgramCreateWithNativeHandle + __urdlllocal ur_result_t UR_APICALL + urProgramCreateWithNativeHandle( + ur_native_handle_t hNativeProgram, ///< [in] the native handle of the program. + ur_context_handle_t hContext, ///< [in] handle of the context instance + ur_program_handle_t* phProgram ///< [out] pointer to the handle of the program object created. + ) + { + ur_result_t result = UR_RESULT_SUCCESS; + + // extract platform's function pointer table + auto dditable = reinterpret_cast( hNativeProgram )->dditable; + auto pfnCreateWithNativeHandle = dditable->ur.Program.pfnCreateWithNativeHandle; + if( nullptr == pfnCreateWithNativeHandle ) + return UR_RESULT_ERROR_UNINITIALIZED; + + // convert loader handle to platform handle + hNativeProgram = reinterpret_cast( hNativeProgram )->handle; + + // convert loader handle to platform handle + hContext = reinterpret_cast( hContext )->handle; + + // forward to device-platform + result = pfnCreateWithNativeHandle( hNativeProgram, hContext, phProgram ); + + if( UR_RESULT_SUCCESS != result ) + return result; + + try + { + // convert platform handle to loader handle + *phProgram = reinterpret_cast( + ur_program_factory.getInstance( *phProgram, dditable ) ); + } + catch( std::bad_alloc& ) + { + result = UR_RESULT_ERROR_OUT_OF_HOST_MEMORY; + } + + return result; + } + + /////////////////////////////////////////////////////////////////////////////// + /// @brief Intercept function for urInit + __urdlllocal ur_result_t UR_APICALL + urInit( + ur_platform_init_flags_t platform_flags, ///< [in] platform initialization flags. + ///< must be 0 (default) or a combination of ::ur_platform_init_flag_t. + ur_device_init_flags_t device_flags ///< [in] device initialization flags. + ///< must be 0 (default) or a combination of ::ur_device_init_flag_t. + ) + { + ur_result_t result = UR_RESULT_SUCCESS; + + bool atLeastOneplatformValid = false; + for( auto& platform : context->platforms ) + { + if(platform.initStatus != UR_RESULT_SUCCESS) + continue; + platform.initStatus = platform.dditable.ur.Global.pfnInit( platform_flags, device_flags ); + if(platform.initStatus == UR_RESULT_SUCCESS) + atLeastOneplatformValid = true; + } + + if(!atLeastOneplatformValid) + result=UR_RESULT_ERROR_UNINITIALIZED; + + return result; + } + +} // namespace loader + +#if defined(__cplusplus) +extern "C" { +#endif + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Exported function for filling application's Global table +/// with current process' addresses +/// +/// @returns +/// - ::UR_RESULT_SUCCESS +/// - ::UR_RESULT_ERROR_UNINITIALIZED +/// - ::UR_RESULT_ERROR_INVALID_NULL_POINTER +/// - ::UR_RESULT_ERROR_UNSUPPORTED_VERSION +UR_DLLEXPORT ur_result_t UR_APICALL +urGetGlobalProcAddrTable( + ur_api_version_t version, ///< [in] API version requested + ur_global_dditable_t* pDdiTable ///< [in,out] pointer to table of DDI function pointers + ) +{ + if( loader::context->platforms.size() < 1 ) + return UR_RESULT_ERROR_UNINITIALIZED; + + if( nullptr == pDdiTable ) + return UR_RESULT_ERROR_INVALID_NULL_POINTER; + + if( loader::context->version < version ) + return UR_RESULT_ERROR_UNSUPPORTED_VERSION; + + ur_result_t result = UR_RESULT_SUCCESS; + + bool atLeastOneplatformValid = false; + // Load the device-platform DDI tables + for( auto& platform : loader::context->platforms ) + { + if(platform.initStatus != UR_RESULT_SUCCESS) + continue; + auto getTable = reinterpret_cast( + GET_FUNCTION_PTR( platform.handle, "urGetGlobalProcAddrTable") ); + if(!getTable) + continue; + auto getTableResult = getTable( version, &platform.dditable.ur.Global); + if(getTableResult == UR_RESULT_SUCCESS) + atLeastOneplatformValid = true; + else + platform.initStatus = getTableResult; + } + + if(!atLeastOneplatformValid) + result = UR_RESULT_ERROR_UNINITIALIZED; + else + result = UR_RESULT_SUCCESS; + + if( UR_RESULT_SUCCESS == result ) + { + if( ( loader::context->platforms.size() > 1 ) || loader::context->forceIntercept ) + { + // return pointers to loader's DDIs + pDdiTable->pfnTearDown = loader::urTearDown; + pDdiTable->pfnGetLastResult = loader::urGetLastResult; + pDdiTable->pfnInit = loader::urInit; + } + else + { + // return pointers directly to platform's DDIs + *pDdiTable = loader::context->platforms.front().dditable.ur.Global; + } + } + + return result; +} + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Exported function for filling application's Context table +/// with current process' addresses +/// +/// @returns +/// - ::UR_RESULT_SUCCESS +/// - ::UR_RESULT_ERROR_UNINITIALIZED +/// - ::UR_RESULT_ERROR_INVALID_NULL_POINTER +/// - ::UR_RESULT_ERROR_UNSUPPORTED_VERSION +UR_DLLEXPORT ur_result_t UR_APICALL +urGetContextProcAddrTable( + ur_api_version_t version, ///< [in] API version requested + ur_context_dditable_t* pDdiTable ///< [in,out] pointer to table of DDI function pointers + ) +{ + if( loader::context->platforms.size() < 1 ) + return UR_RESULT_ERROR_UNINITIALIZED; + + if( nullptr == pDdiTable ) + return UR_RESULT_ERROR_INVALID_NULL_POINTER; + + if( loader::context->version < version ) + return UR_RESULT_ERROR_UNSUPPORTED_VERSION; + + ur_result_t result = UR_RESULT_SUCCESS; + + bool atLeastOneplatformValid = false; + // Load the device-platform DDI tables + for( auto& platform : loader::context->platforms ) + { + if(platform.initStatus != UR_RESULT_SUCCESS) + continue; + auto getTable = reinterpret_cast( + GET_FUNCTION_PTR( platform.handle, "urGetContextProcAddrTable") ); + if(!getTable) + continue; + auto getTableResult = getTable( version, &platform.dditable.ur.Context); + if(getTableResult == UR_RESULT_SUCCESS) + atLeastOneplatformValid = true; + else + platform.initStatus = getTableResult; + } + + if(!atLeastOneplatformValid) + result = UR_RESULT_ERROR_UNINITIALIZED; + else + result = UR_RESULT_SUCCESS; + + if( UR_RESULT_SUCCESS == result ) + { + if( ( loader::context->platforms.size() > 1 ) || loader::context->forceIntercept ) + { + // return pointers to loader's DDIs + pDdiTable->pfnCreate = loader::urContextCreate; + pDdiTable->pfnRetain = loader::urContextRetain; + pDdiTable->pfnRelease = loader::urContextRelease; + pDdiTable->pfnGetInfo = loader::urContextGetInfo; + pDdiTable->pfnGetNativeHandle = loader::urContextGetNativeHandle; + pDdiTable->pfnCreateWithNativeHandle = loader::urContextCreateWithNativeHandle; + pDdiTable->pfnSetExtendedDeleter = loader::urContextSetExtendedDeleter; + } + else + { + // return pointers directly to platform's DDIs + *pDdiTable = loader::context->platforms.front().dditable.ur.Context; + } + } + + return result; +} + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Exported function for filling application's Enqueue table +/// with current process' addresses +/// +/// @returns +/// - ::UR_RESULT_SUCCESS +/// - ::UR_RESULT_ERROR_UNINITIALIZED +/// - ::UR_RESULT_ERROR_INVALID_NULL_POINTER +/// - ::UR_RESULT_ERROR_UNSUPPORTED_VERSION +UR_DLLEXPORT ur_result_t UR_APICALL +urGetEnqueueProcAddrTable( + ur_api_version_t version, ///< [in] API version requested + ur_enqueue_dditable_t* pDdiTable ///< [in,out] pointer to table of DDI function pointers + ) +{ + if( loader::context->platforms.size() < 1 ) + return UR_RESULT_ERROR_UNINITIALIZED; + + if( nullptr == pDdiTable ) + return UR_RESULT_ERROR_INVALID_NULL_POINTER; + + if( loader::context->version < version ) + return UR_RESULT_ERROR_UNSUPPORTED_VERSION; + + ur_result_t result = UR_RESULT_SUCCESS; + + bool atLeastOneplatformValid = false; + // Load the device-platform DDI tables + for( auto& platform : loader::context->platforms ) + { + if(platform.initStatus != UR_RESULT_SUCCESS) + continue; + auto getTable = reinterpret_cast( + GET_FUNCTION_PTR( platform.handle, "urGetEnqueueProcAddrTable") ); + if(!getTable) + continue; + auto getTableResult = getTable( version, &platform.dditable.ur.Enqueue); + if(getTableResult == UR_RESULT_SUCCESS) + atLeastOneplatformValid = true; + else + platform.initStatus = getTableResult; + } + + if(!atLeastOneplatformValid) + result = UR_RESULT_ERROR_UNINITIALIZED; + else + result = UR_RESULT_SUCCESS; + + if( UR_RESULT_SUCCESS == result ) + { + if( ( loader::context->platforms.size() > 1 ) || loader::context->forceIntercept ) + { + // return pointers to loader's DDIs + pDdiTable->pfnKernelLaunch = loader::urEnqueueKernelLaunch; + pDdiTable->pfnEventsWait = loader::urEnqueueEventsWait; + pDdiTable->pfnEventsWaitWithBarrier = loader::urEnqueueEventsWaitWithBarrier; + pDdiTable->pfnMemBufferRead = loader::urEnqueueMemBufferRead; + pDdiTable->pfnMemBufferWrite = loader::urEnqueueMemBufferWrite; + pDdiTable->pfnMemBufferReadRect = loader::urEnqueueMemBufferReadRect; + pDdiTable->pfnMemBufferWriteRect = loader::urEnqueueMemBufferWriteRect; + pDdiTable->pfnMemBufferCopy = loader::urEnqueueMemBufferCopy; + pDdiTable->pfnMemBufferCopyRect = loader::urEnqueueMemBufferCopyRect; + pDdiTable->pfnMemBufferFill = loader::urEnqueueMemBufferFill; + pDdiTable->pfnMemImageRead = loader::urEnqueueMemImageRead; + pDdiTable->pfnMemImageWrite = loader::urEnqueueMemImageWrite; + pDdiTable->pfnMemImageCopy = loader::urEnqueueMemImageCopy; + pDdiTable->pfnMemBufferMap = loader::urEnqueueMemBufferMap; + pDdiTable->pfnMemUnmap = loader::urEnqueueMemUnmap; + pDdiTable->pfnUSMMemset = loader::urEnqueueUSMMemset; + pDdiTable->pfnUSMMemcpy = loader::urEnqueueUSMMemcpy; + pDdiTable->pfnUSMPrefetch = loader::urEnqueueUSMPrefetch; + pDdiTable->pfnUSMMemAdvice = loader::urEnqueueUSMMemAdvice; + } + else + { + // return pointers directly to platform's DDIs + *pDdiTable = loader::context->platforms.front().dditable.ur.Enqueue; + } + } + + return result; +} + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Exported function for filling application's Event table +/// with current process' addresses +/// +/// @returns +/// - ::UR_RESULT_SUCCESS +/// - ::UR_RESULT_ERROR_UNINITIALIZED +/// - ::UR_RESULT_ERROR_INVALID_NULL_POINTER +/// - ::UR_RESULT_ERROR_UNSUPPORTED_VERSION +UR_DLLEXPORT ur_result_t UR_APICALL +urGetEventProcAddrTable( + ur_api_version_t version, ///< [in] API version requested + ur_event_dditable_t* pDdiTable ///< [in,out] pointer to table of DDI function pointers + ) +{ + if( loader::context->platforms.size() < 1 ) + return UR_RESULT_ERROR_UNINITIALIZED; + + if( nullptr == pDdiTable ) + return UR_RESULT_ERROR_INVALID_NULL_POINTER; + + if( loader::context->version < version ) + return UR_RESULT_ERROR_UNSUPPORTED_VERSION; + + ur_result_t result = UR_RESULT_SUCCESS; + + bool atLeastOneplatformValid = false; + // Load the device-platform DDI tables + for( auto& platform : loader::context->platforms ) + { + if(platform.initStatus != UR_RESULT_SUCCESS) + continue; + auto getTable = reinterpret_cast( + GET_FUNCTION_PTR( platform.handle, "urGetEventProcAddrTable") ); + if(!getTable) + continue; + auto getTableResult = getTable( version, &platform.dditable.ur.Event); + if(getTableResult == UR_RESULT_SUCCESS) + atLeastOneplatformValid = true; + else + platform.initStatus = getTableResult; + } + + if(!atLeastOneplatformValid) + result = UR_RESULT_ERROR_UNINITIALIZED; + else + result = UR_RESULT_SUCCESS; + + if( UR_RESULT_SUCCESS == result ) + { + if( ( loader::context->platforms.size() > 1 ) || loader::context->forceIntercept ) + { + // return pointers to loader's DDIs + pDdiTable->pfnGetInfo = loader::urEventGetInfo; + pDdiTable->pfnGetProfilingInfo = loader::urEventGetProfilingInfo; + pDdiTable->pfnWait = loader::urEventWait; + pDdiTable->pfnRetain = loader::urEventRetain; + pDdiTable->pfnRelease = loader::urEventRelease; + pDdiTable->pfnGetNativeHandle = loader::urEventGetNativeHandle; + pDdiTable->pfnCreateWithNativeHandle = loader::urEventCreateWithNativeHandle; + pDdiTable->pfnSetCallback = loader::urEventSetCallback; + } + else + { + // return pointers directly to platform's DDIs + *pDdiTable = loader::context->platforms.front().dditable.ur.Event; + } + } + + return result; +} + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Exported function for filling application's Kernel table +/// with current process' addresses +/// +/// @returns +/// - ::UR_RESULT_SUCCESS +/// - ::UR_RESULT_ERROR_UNINITIALIZED +/// - ::UR_RESULT_ERROR_INVALID_NULL_POINTER +/// - ::UR_RESULT_ERROR_UNSUPPORTED_VERSION +UR_DLLEXPORT ur_result_t UR_APICALL +urGetKernelProcAddrTable( + ur_api_version_t version, ///< [in] API version requested + ur_kernel_dditable_t* pDdiTable ///< [in,out] pointer to table of DDI function pointers + ) +{ + if( loader::context->platforms.size() < 1 ) + return UR_RESULT_ERROR_UNINITIALIZED; + + if( nullptr == pDdiTable ) + return UR_RESULT_ERROR_INVALID_NULL_POINTER; + + if( loader::context->version < version ) + return UR_RESULT_ERROR_UNSUPPORTED_VERSION; + + ur_result_t result = UR_RESULT_SUCCESS; + + bool atLeastOneplatformValid = false; + // Load the device-platform DDI tables + for( auto& platform : loader::context->platforms ) + { + if(platform.initStatus != UR_RESULT_SUCCESS) + continue; + auto getTable = reinterpret_cast( + GET_FUNCTION_PTR( platform.handle, "urGetKernelProcAddrTable") ); + if(!getTable) + continue; + auto getTableResult = getTable( version, &platform.dditable.ur.Kernel); + if(getTableResult == UR_RESULT_SUCCESS) + atLeastOneplatformValid = true; + else + platform.initStatus = getTableResult; + } + + if(!atLeastOneplatformValid) + result = UR_RESULT_ERROR_UNINITIALIZED; + else + result = UR_RESULT_SUCCESS; + + if( UR_RESULT_SUCCESS == result ) + { + if( ( loader::context->platforms.size() > 1 ) || loader::context->forceIntercept ) + { + // return pointers to loader's DDIs + pDdiTable->pfnCreate = loader::urKernelCreate; + pDdiTable->pfnGetInfo = loader::urKernelGetInfo; + pDdiTable->pfnGetGroupInfo = loader::urKernelGetGroupInfo; + pDdiTable->pfnGetSubGroupInfo = loader::urKernelGetSubGroupInfo; + pDdiTable->pfnRetain = loader::urKernelRetain; + pDdiTable->pfnRelease = loader::urKernelRelease; + pDdiTable->pfnGetNativeHandle = loader::urKernelGetNativeHandle; + pDdiTable->pfnCreateWithNativeHandle = loader::urKernelCreateWithNativeHandle; + pDdiTable->pfnSetArg = loader::urKernelSetArg; + pDdiTable->pfnSetArgPointer = loader::urKernelSetArgPointer; + pDdiTable->pfnSetExecInfo = loader::urKernelSetExecInfo; + pDdiTable->pfnSetArgSampler = loader::urKernelSetArgSampler; + pDdiTable->pfnSetArgMemObj = loader::urKernelSetArgMemObj; + } + else + { + // return pointers directly to platform's DDIs + *pDdiTable = loader::context->platforms.front().dditable.ur.Kernel; + } + } + + return result; +} + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Exported function for filling application's Mem table +/// with current process' addresses +/// +/// @returns +/// - ::UR_RESULT_SUCCESS +/// - ::UR_RESULT_ERROR_UNINITIALIZED +/// - ::UR_RESULT_ERROR_INVALID_NULL_POINTER +/// - ::UR_RESULT_ERROR_UNSUPPORTED_VERSION +UR_DLLEXPORT ur_result_t UR_APICALL +urGetMemProcAddrTable( + ur_api_version_t version, ///< [in] API version requested + ur_mem_dditable_t* pDdiTable ///< [in,out] pointer to table of DDI function pointers + ) +{ + if( loader::context->platforms.size() < 1 ) + return UR_RESULT_ERROR_UNINITIALIZED; + + if( nullptr == pDdiTable ) + return UR_RESULT_ERROR_INVALID_NULL_POINTER; + + if( loader::context->version < version ) + return UR_RESULT_ERROR_UNSUPPORTED_VERSION; + + ur_result_t result = UR_RESULT_SUCCESS; + + bool atLeastOneplatformValid = false; + // Load the device-platform DDI tables + for( auto& platform : loader::context->platforms ) + { + if(platform.initStatus != UR_RESULT_SUCCESS) + continue; + auto getTable = reinterpret_cast( + GET_FUNCTION_PTR( platform.handle, "urGetMemProcAddrTable") ); + if(!getTable) + continue; + auto getTableResult = getTable( version, &platform.dditable.ur.Mem); + if(getTableResult == UR_RESULT_SUCCESS) + atLeastOneplatformValid = true; + else + platform.initStatus = getTableResult; + } + + if(!atLeastOneplatformValid) + result = UR_RESULT_ERROR_UNINITIALIZED; + else + result = UR_RESULT_SUCCESS; + + if( UR_RESULT_SUCCESS == result ) + { + if( ( loader::context->platforms.size() > 1 ) || loader::context->forceIntercept ) + { + // return pointers to loader's DDIs + pDdiTable->pfnImageCreate = loader::urMemImageCreate; + pDdiTable->pfnBufferCreate = loader::urMemBufferCreate; + pDdiTable->pfnRetain = loader::urMemRetain; + pDdiTable->pfnRelease = loader::urMemRelease; + pDdiTable->pfnBufferPartition = loader::urMemBufferPartition; + pDdiTable->pfnGetNativeHandle = loader::urMemGetNativeHandle; + pDdiTable->pfnCreateWithNativeHandle = loader::urMemCreateWithNativeHandle; + pDdiTable->pfnGetInfo = loader::urMemGetInfo; + pDdiTable->pfnImageGetInfo = loader::urMemImageGetInfo; + pDdiTable->pfnFree = loader::urMemFree; + pDdiTable->pfnGetMemAllocInfo = loader::urMemGetMemAllocInfo; + } + else + { + // return pointers directly to platform's DDIs + *pDdiTable = loader::context->platforms.front().dditable.ur.Mem; + } + } + + return result; +} + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Exported function for filling application's Module table +/// with current process' addresses +/// +/// @returns +/// - ::UR_RESULT_SUCCESS +/// - ::UR_RESULT_ERROR_UNINITIALIZED +/// - ::UR_RESULT_ERROR_INVALID_NULL_POINTER +/// - ::UR_RESULT_ERROR_UNSUPPORTED_VERSION +UR_DLLEXPORT ur_result_t UR_APICALL +urGetModuleProcAddrTable( + ur_api_version_t version, ///< [in] API version requested + ur_module_dditable_t* pDdiTable ///< [in,out] pointer to table of DDI function pointers + ) +{ + if( loader::context->platforms.size() < 1 ) + return UR_RESULT_ERROR_UNINITIALIZED; + + if( nullptr == pDdiTable ) + return UR_RESULT_ERROR_INVALID_NULL_POINTER; + + if( loader::context->version < version ) + return UR_RESULT_ERROR_UNSUPPORTED_VERSION; + + ur_result_t result = UR_RESULT_SUCCESS; + + bool atLeastOneplatformValid = false; + // Load the device-platform DDI tables + for( auto& platform : loader::context->platforms ) + { + if(platform.initStatus != UR_RESULT_SUCCESS) + continue; + auto getTable = reinterpret_cast( + GET_FUNCTION_PTR( platform.handle, "urGetModuleProcAddrTable") ); + if(!getTable) + continue; + auto getTableResult = getTable( version, &platform.dditable.ur.Module); + if(getTableResult == UR_RESULT_SUCCESS) + atLeastOneplatformValid = true; + else + platform.initStatus = getTableResult; + } + + if(!atLeastOneplatformValid) + result = UR_RESULT_ERROR_UNINITIALIZED; + else + result = UR_RESULT_SUCCESS; + + if( UR_RESULT_SUCCESS == result ) + { + if( ( loader::context->platforms.size() > 1 ) || loader::context->forceIntercept ) + { + // return pointers to loader's DDIs + pDdiTable->pfnCreate = loader::urModuleCreate; + pDdiTable->pfnRetain = loader::urModuleRetain; + pDdiTable->pfnRelease = loader::urModuleRelease; + pDdiTable->pfnGetNativeHandle = loader::urModuleGetNativeHandle; + pDdiTable->pfnCreateWithNativeHandle = loader::urModuleCreateWithNativeHandle; + } + else + { + // return pointers directly to platform's DDIs + *pDdiTable = loader::context->platforms.front().dditable.ur.Module; + } + } + + return result; +} + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Exported function for filling application's Platform table +/// with current process' addresses +/// +/// @returns +/// - ::UR_RESULT_SUCCESS +/// - ::UR_RESULT_ERROR_UNINITIALIZED +/// - ::UR_RESULT_ERROR_INVALID_NULL_POINTER +/// - ::UR_RESULT_ERROR_UNSUPPORTED_VERSION +UR_DLLEXPORT ur_result_t UR_APICALL +urGetPlatformProcAddrTable( + ur_api_version_t version, ///< [in] API version requested + ur_platform_dditable_t* pDdiTable ///< [in,out] pointer to table of DDI function pointers + ) +{ + if( loader::context->platforms.size() < 1 ) + return UR_RESULT_ERROR_UNINITIALIZED; + + if( nullptr == pDdiTable ) + return UR_RESULT_ERROR_INVALID_NULL_POINTER; + + if( loader::context->version < version ) + return UR_RESULT_ERROR_UNSUPPORTED_VERSION; + + ur_result_t result = UR_RESULT_SUCCESS; + + bool atLeastOneplatformValid = false; + // Load the device-platform DDI tables + for( auto& platform : loader::context->platforms ) + { + if(platform.initStatus != UR_RESULT_SUCCESS) + continue; + auto getTable = reinterpret_cast( + GET_FUNCTION_PTR( platform.handle, "urGetPlatformProcAddrTable") ); + if(!getTable) + continue; + auto getTableResult = getTable( version, &platform.dditable.ur.Platform); + if(getTableResult == UR_RESULT_SUCCESS) + atLeastOneplatformValid = true; + else + platform.initStatus = getTableResult; + } + + if(!atLeastOneplatformValid) + result = UR_RESULT_ERROR_UNINITIALIZED; + else + result = UR_RESULT_SUCCESS; + + if( UR_RESULT_SUCCESS == result ) + { + if( ( loader::context->platforms.size() > 1 ) || loader::context->forceIntercept ) + { + // return pointers to loader's DDIs + pDdiTable->pfnGet = loader::urPlatformGet; + pDdiTable->pfnGetInfo = loader::urPlatformGetInfo; + pDdiTable->pfnGetNativeHandle = loader::urPlatformGetNativeHandle; + pDdiTable->pfnCreateWithNativeHandle = loader::urPlatformCreateWithNativeHandle; + pDdiTable->pfnGetApiVersion = loader::urPlatformGetApiVersion; + } + else + { + // return pointers directly to platform's DDIs + *pDdiTable = loader::context->platforms.front().dditable.ur.Platform; + } + } + + return result; +} + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Exported function for filling application's Program table +/// with current process' addresses +/// +/// @returns +/// - ::UR_RESULT_SUCCESS +/// - ::UR_RESULT_ERROR_UNINITIALIZED +/// - ::UR_RESULT_ERROR_INVALID_NULL_POINTER +/// - ::UR_RESULT_ERROR_UNSUPPORTED_VERSION +UR_DLLEXPORT ur_result_t UR_APICALL +urGetProgramProcAddrTable( + ur_api_version_t version, ///< [in] API version requested + ur_program_dditable_t* pDdiTable ///< [in,out] pointer to table of DDI function pointers + ) +{ + if( loader::context->platforms.size() < 1 ) + return UR_RESULT_ERROR_UNINITIALIZED; + + if( nullptr == pDdiTable ) + return UR_RESULT_ERROR_INVALID_NULL_POINTER; + + if( loader::context->version < version ) + return UR_RESULT_ERROR_UNSUPPORTED_VERSION; + + ur_result_t result = UR_RESULT_SUCCESS; + + bool atLeastOneplatformValid = false; + // Load the device-platform DDI tables + for( auto& platform : loader::context->platforms ) + { + if(platform.initStatus != UR_RESULT_SUCCESS) + continue; + auto getTable = reinterpret_cast( + GET_FUNCTION_PTR( platform.handle, "urGetProgramProcAddrTable") ); + if(!getTable) + continue; + auto getTableResult = getTable( version, &platform.dditable.ur.Program); + if(getTableResult == UR_RESULT_SUCCESS) + atLeastOneplatformValid = true; + else + platform.initStatus = getTableResult; + } + + if(!atLeastOneplatformValid) + result = UR_RESULT_ERROR_UNINITIALIZED; + else + result = UR_RESULT_SUCCESS; + + if( UR_RESULT_SUCCESS == result ) + { + if( ( loader::context->platforms.size() > 1 ) || loader::context->forceIntercept ) + { + // return pointers to loader's DDIs + pDdiTable->pfnCreate = loader::urProgramCreate; + pDdiTable->pfnCreateWithBinary = loader::urProgramCreateWithBinary; + pDdiTable->pfnRetain = loader::urProgramRetain; + pDdiTable->pfnRelease = loader::urProgramRelease; + pDdiTable->pfnGetFunctionPointer = loader::urProgramGetFunctionPointer; + pDdiTable->pfnGetInfo = loader::urProgramGetInfo; + pDdiTable->pfnGetBuildInfo = loader::urProgramGetBuildInfo; + pDdiTable->pfnSetSpecializationConstant = loader::urProgramSetSpecializationConstant; + pDdiTable->pfnGetNativeHandle = loader::urProgramGetNativeHandle; + pDdiTable->pfnCreateWithNativeHandle = loader::urProgramCreateWithNativeHandle; + } + else + { + // return pointers directly to platform's DDIs + *pDdiTable = loader::context->platforms.front().dditable.ur.Program; + } + } + + return result; +} + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Exported function for filling application's Queue table +/// with current process' addresses +/// +/// @returns +/// - ::UR_RESULT_SUCCESS +/// - ::UR_RESULT_ERROR_UNINITIALIZED +/// - ::UR_RESULT_ERROR_INVALID_NULL_POINTER +/// - ::UR_RESULT_ERROR_UNSUPPORTED_VERSION +UR_DLLEXPORT ur_result_t UR_APICALL +urGetQueueProcAddrTable( + ur_api_version_t version, ///< [in] API version requested + ur_queue_dditable_t* pDdiTable ///< [in,out] pointer to table of DDI function pointers + ) +{ + if( loader::context->platforms.size() < 1 ) + return UR_RESULT_ERROR_UNINITIALIZED; + + if( nullptr == pDdiTable ) + return UR_RESULT_ERROR_INVALID_NULL_POINTER; + + if( loader::context->version < version ) + return UR_RESULT_ERROR_UNSUPPORTED_VERSION; + + ur_result_t result = UR_RESULT_SUCCESS; + + bool atLeastOneplatformValid = false; + // Load the device-platform DDI tables + for( auto& platform : loader::context->platforms ) + { + if(platform.initStatus != UR_RESULT_SUCCESS) + continue; + auto getTable = reinterpret_cast( + GET_FUNCTION_PTR( platform.handle, "urGetQueueProcAddrTable") ); + if(!getTable) + continue; + auto getTableResult = getTable( version, &platform.dditable.ur.Queue); + if(getTableResult == UR_RESULT_SUCCESS) + atLeastOneplatformValid = true; + else + platform.initStatus = getTableResult; + } + + if(!atLeastOneplatformValid) + result = UR_RESULT_ERROR_UNINITIALIZED; + else + result = UR_RESULT_SUCCESS; + + if( UR_RESULT_SUCCESS == result ) + { + if( ( loader::context->platforms.size() > 1 ) || loader::context->forceIntercept ) + { + // return pointers to loader's DDIs + pDdiTable->pfnGetInfo = loader::urQueueGetInfo; + pDdiTable->pfnCreate = loader::urQueueCreate; + pDdiTable->pfnRetain = loader::urQueueRetain; + pDdiTable->pfnRelease = loader::urQueueRelease; + pDdiTable->pfnGetNativeHandle = loader::urQueueGetNativeHandle; + pDdiTable->pfnCreateWithNativeHandle = loader::urQueueCreateWithNativeHandle; + pDdiTable->pfnFinish = loader::urQueueFinish; + pDdiTable->pfnFlush = loader::urQueueFlush; + } + else + { + // return pointers directly to platform's DDIs + *pDdiTable = loader::context->platforms.front().dditable.ur.Queue; + } + } + + return result; +} + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Exported function for filling application's Sampler table +/// with current process' addresses +/// +/// @returns +/// - ::UR_RESULT_SUCCESS +/// - ::UR_RESULT_ERROR_UNINITIALIZED +/// - ::UR_RESULT_ERROR_INVALID_NULL_POINTER +/// - ::UR_RESULT_ERROR_UNSUPPORTED_VERSION +UR_DLLEXPORT ur_result_t UR_APICALL +urGetSamplerProcAddrTable( + ur_api_version_t version, ///< [in] API version requested + ur_sampler_dditable_t* pDdiTable ///< [in,out] pointer to table of DDI function pointers + ) +{ + if( loader::context->platforms.size() < 1 ) + return UR_RESULT_ERROR_UNINITIALIZED; + + if( nullptr == pDdiTable ) + return UR_RESULT_ERROR_INVALID_NULL_POINTER; + + if( loader::context->version < version ) + return UR_RESULT_ERROR_UNSUPPORTED_VERSION; + + ur_result_t result = UR_RESULT_SUCCESS; + + bool atLeastOneplatformValid = false; + // Load the device-platform DDI tables + for( auto& platform : loader::context->platforms ) + { + if(platform.initStatus != UR_RESULT_SUCCESS) + continue; + auto getTable = reinterpret_cast( + GET_FUNCTION_PTR( platform.handle, "urGetSamplerProcAddrTable") ); + if(!getTable) + continue; + auto getTableResult = getTable( version, &platform.dditable.ur.Sampler); + if(getTableResult == UR_RESULT_SUCCESS) + atLeastOneplatformValid = true; + else + platform.initStatus = getTableResult; + } + + if(!atLeastOneplatformValid) + result = UR_RESULT_ERROR_UNINITIALIZED; + else + result = UR_RESULT_SUCCESS; + + if( UR_RESULT_SUCCESS == result ) + { + if( ( loader::context->platforms.size() > 1 ) || loader::context->forceIntercept ) + { + // return pointers to loader's DDIs + pDdiTable->pfnCreate = loader::urSamplerCreate; + pDdiTable->pfnRetain = loader::urSamplerRetain; + pDdiTable->pfnRelease = loader::urSamplerRelease; + pDdiTable->pfnGetInfo = loader::urSamplerGetInfo; + pDdiTable->pfnGetNativeHandle = loader::urSamplerGetNativeHandle; + pDdiTable->pfnCreateWithNativeHandle = loader::urSamplerCreateWithNativeHandle; + } + else + { + // return pointers directly to platform's DDIs + *pDdiTable = loader::context->platforms.front().dditable.ur.Sampler; + } + } + + return result; +} + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Exported function for filling application's USM table +/// with current process' addresses +/// +/// @returns +/// - ::UR_RESULT_SUCCESS +/// - ::UR_RESULT_ERROR_UNINITIALIZED +/// - ::UR_RESULT_ERROR_INVALID_NULL_POINTER +/// - ::UR_RESULT_ERROR_UNSUPPORTED_VERSION +UR_DLLEXPORT ur_result_t UR_APICALL +urGetUSMProcAddrTable( + ur_api_version_t version, ///< [in] API version requested + ur_usm_dditable_t* pDdiTable ///< [in,out] pointer to table of DDI function pointers + ) +{ + if( loader::context->platforms.size() < 1 ) + return UR_RESULT_ERROR_UNINITIALIZED; + + if( nullptr == pDdiTable ) + return UR_RESULT_ERROR_INVALID_NULL_POINTER; + + if( loader::context->version < version ) + return UR_RESULT_ERROR_UNSUPPORTED_VERSION; + + ur_result_t result = UR_RESULT_SUCCESS; + + bool atLeastOneplatformValid = false; + // Load the device-platform DDI tables + for( auto& platform : loader::context->platforms ) + { + if(platform.initStatus != UR_RESULT_SUCCESS) + continue; + auto getTable = reinterpret_cast( + GET_FUNCTION_PTR( platform.handle, "urGetUSMProcAddrTable") ); + if(!getTable) + continue; + auto getTableResult = getTable( version, &platform.dditable.ur.USM); + if(getTableResult == UR_RESULT_SUCCESS) + atLeastOneplatformValid = true; + else + platform.initStatus = getTableResult; + } + + if(!atLeastOneplatformValid) + result = UR_RESULT_ERROR_UNINITIALIZED; + else + result = UR_RESULT_SUCCESS; + + if( UR_RESULT_SUCCESS == result ) + { + if( ( loader::context->platforms.size() > 1 ) || loader::context->forceIntercept ) + { + // return pointers to loader's DDIs + pDdiTable->pfnHostAlloc = loader::urUSMHostAlloc; + pDdiTable->pfnDeviceAlloc = loader::urUSMDeviceAlloc; + pDdiTable->pfnSharedAlloc = loader::urUSMSharedAlloc; + } + else + { + // return pointers directly to platform's DDIs + *pDdiTable = loader::context->platforms.front().dditable.ur.USM; + } + } + + return result; +} + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Exported function for filling application's Device table +/// with current process' addresses +/// +/// @returns +/// - ::UR_RESULT_SUCCESS +/// - ::UR_RESULT_ERROR_UNINITIALIZED +/// - ::UR_RESULT_ERROR_INVALID_NULL_POINTER +/// - ::UR_RESULT_ERROR_UNSUPPORTED_VERSION +UR_DLLEXPORT ur_result_t UR_APICALL +urGetDeviceProcAddrTable( + ur_api_version_t version, ///< [in] API version requested + ur_device_dditable_t* pDdiTable ///< [in,out] pointer to table of DDI function pointers + ) +{ + if( loader::context->platforms.size() < 1 ) + return UR_RESULT_ERROR_UNINITIALIZED; + + if( nullptr == pDdiTable ) + return UR_RESULT_ERROR_INVALID_NULL_POINTER; + + if( loader::context->version < version ) + return UR_RESULT_ERROR_UNSUPPORTED_VERSION; + + ur_result_t result = UR_RESULT_SUCCESS; + + bool atLeastOneplatformValid = false; + // Load the device-platform DDI tables + for( auto& platform : loader::context->platforms ) + { + if(platform.initStatus != UR_RESULT_SUCCESS) + continue; + auto getTable = reinterpret_cast( + GET_FUNCTION_PTR( platform.handle, "urGetDeviceProcAddrTable") ); + if(!getTable) + continue; + auto getTableResult = getTable( version, &platform.dditable.ur.Device); + if(getTableResult == UR_RESULT_SUCCESS) + atLeastOneplatformValid = true; + else + platform.initStatus = getTableResult; + } + + if(!atLeastOneplatformValid) + result = UR_RESULT_ERROR_UNINITIALIZED; + else + result = UR_RESULT_SUCCESS; + + if( UR_RESULT_SUCCESS == result ) + { + if( ( loader::context->platforms.size() > 1 ) || loader::context->forceIntercept ) + { + // return pointers to loader's DDIs + pDdiTable->pfnGet = loader::urDeviceGet; + pDdiTable->pfnGetInfo = loader::urDeviceGetInfo; + pDdiTable->pfnRetain = loader::urDeviceRetain; + pDdiTable->pfnRelease = loader::urDeviceRelease; + pDdiTable->pfnPartition = loader::urDevicePartition; + pDdiTable->pfnSelectBinary = loader::urDeviceSelectBinary; + pDdiTable->pfnGetNativeHandle = loader::urDeviceGetNativeHandle; + pDdiTable->pfnCreateWithNativeHandle = loader::urDeviceCreateWithNativeHandle; + } + else + { + // return pointers directly to platform's DDIs + *pDdiTable = loader::context->platforms.front().dditable.ur.Device; + } + } + + return result; +} + + +#if defined(__cplusplus) +}; +#endif diff --git a/source/loader/ur_ldrddi.h b/source/loader/ur_ldrddi.h new file mode 100644 index 0000000000..ff8b260d1e --- /dev/null +++ b/source/loader/ur_ldrddi.h @@ -0,0 +1,51 @@ +/* + * + * Copyright (C) 2022 Intel Corporation + * + * SPDX-License-Identifier: MIT + * + * @file ur_ldrddi.h + * + */ +#ifndef UR_LOADER_LDRDDI_H +#define UR_LOADER_LDRDDI_H 1 + +namespace loader +{ + /////////////////////////////////////////////////////////////////////////////// + using ur_platform_object_t = object_t < ur_platform_handle_t >; + using ur_platform_factory_t = singleton_factory_t < ur_platform_object_t, ur_platform_handle_t >; + + using ur_device_object_t = object_t < ur_device_handle_t >; + using ur_device_factory_t = singleton_factory_t < ur_device_object_t, ur_device_handle_t >; + + using ur_context_object_t = object_t < ur_context_handle_t >; + using ur_context_factory_t = singleton_factory_t < ur_context_object_t, ur_context_handle_t >; + + using ur_event_object_t = object_t < ur_event_handle_t >; + using ur_event_factory_t = singleton_factory_t < ur_event_object_t, ur_event_handle_t >; + + using ur_program_object_t = object_t < ur_program_handle_t >; + using ur_program_factory_t = singleton_factory_t < ur_program_object_t, ur_program_handle_t >; + + using ur_module_object_t = object_t < ur_module_handle_t >; + using ur_module_factory_t = singleton_factory_t < ur_module_object_t, ur_module_handle_t >; + + using ur_kernel_object_t = object_t < ur_kernel_handle_t >; + using ur_kernel_factory_t = singleton_factory_t < ur_kernel_object_t, ur_kernel_handle_t >; + + using ur_queue_object_t = object_t < ur_queue_handle_t >; + using ur_queue_factory_t = singleton_factory_t < ur_queue_object_t, ur_queue_handle_t >; + + using ur_native_object_t = object_t < ur_native_handle_t >; + using ur_native_factory_t = singleton_factory_t < ur_native_object_t, ur_native_handle_t >; + + using ur_sampler_object_t = object_t < ur_sampler_handle_t >; + using ur_sampler_factory_t = singleton_factory_t < ur_sampler_object_t, ur_sampler_handle_t >; + + using ur_mem_object_t = object_t < ur_mem_handle_t >; + using ur_mem_factory_t = singleton_factory_t < ur_mem_object_t, ur_mem_handle_t >; + +} + +#endif /* UR_LOADER_LDRDDI_H */ diff --git a/source/loader/ur_lib.cpp b/source/loader/ur_lib.cpp new file mode 100644 index 0000000000..cab83aa894 --- /dev/null +++ b/source/loader/ur_lib.cpp @@ -0,0 +1,42 @@ +/* + * + * Copyright (C) 2022 Intel Corporation + * + * SPDX-License-Identifier: MIT + * + * @file ur_lib.cpp + * + */ +#include "ur_lib.h" +#include "ur_loader.h" + +namespace ur_lib +{ + /////////////////////////////////////////////////////////////////////////////// + context_t *context; + + /////////////////////////////////////////////////////////////////////////////// + context_t::context_t() + { + }; + + /////////////////////////////////////////////////////////////////////////////// + context_t::~context_t() + { + }; + + ////////////////////////////////////////////////////////////////////////// + __urdlllocal ur_result_t context_t::Init(ur_platform_init_flags_t platform_flags, ur_device_init_flags_t device_flags) + { + ur_result_t result; + result = loader::context->init(); + + if( UR_RESULT_SUCCESS == result ) + { + result = urInit(); + } + + return result; + } + +} // namespace ur_lib diff --git a/source/loader/ur_lib.h b/source/loader/ur_lib.h new file mode 100644 index 0000000000..4b6d9e8c0d --- /dev/null +++ b/source/loader/ur_lib.h @@ -0,0 +1,46 @@ +/* + * + * Copyright (C) 2022 Intel Corporation + * + * SPDX-License-Identifier: MIT + * + * @file ur_lib.h + * + */ + +#ifndef UR_LOADER_LIB_H +#define UR_LOADER_LIB_H 1 + +#include "ur_api.h" +#include "ur_ddi.h" +#include "ur_util.h" +#include +#include + +namespace ur_lib +{ + /////////////////////////////////////////////////////////////////////////////// + class context_t + { + public: +#ifdef DYNAMIC_LOAD_LOADER + HMODULE loader = nullptr; +#endif + + context_t(); + ~context_t(); + + std::once_flag initOnce; + + ur_result_t Init(ur_platform_init_flags_t pflags, ur_device_init_flags_t dflags); + + ur_result_t urInit(); + ur_dditable_t urDdiTable = {}; + + }; + + extern context_t *context; + +} // namespace ur_lib + +#endif /* UR_LOADER_LIB_H */ diff --git a/source/loader/ur_libapi.cpp b/source/loader/ur_libapi.cpp new file mode 100644 index 0000000000..f84c6abfea --- /dev/null +++ b/source/loader/ur_libapi.cpp @@ -0,0 +1,3963 @@ +/* + * + * Copyright (C) 2022 Intel Corporation + * + * SPDX-License-Identifier: MIT + * + * @file ur_libapi.cpp + * + * @brief C++ library for ur + * + */ +#include "ur_lib.h" + +extern "C" { + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Creates a context with the given devices. +/// +/// @details +/// - All devices should be from the same platform. +/// - Context is used for resource sharing between all the devices +/// associated with it. +/// - Context also serves for resource isolation such that resources do not +/// cross context boundaries. +/// - The returned context is a reference and must be released with a +/// subsequent call to ::urContextRelease. +/// - The application may call this function from simultaneous threads. +/// - The implementation of this function must be thread-safe. +/// +/// @remarks +/// _Analogues_ +/// - **clCreateContext** +/// +/// @returns +/// - ::UR_RESULT_SUCCESS +/// - ::UR_RESULT_ERROR_UNINITIALIZED +/// - ::UR_RESULT_ERROR_DEVICE_LOST +/// - ::UR_RESULT_ERROR_INVALID_NULL_POINTER +/// + `NULL == phDevices` +/// + `NULL == phContext` +/// - ::UR_RESULT_ERROR_OUT_OF_HOST_MEMORY +/// - ::UR_RESULT_ERROR_OUT_OF_DEVICE_MEMORY +ur_result_t UR_APICALL +urContextCreate( + uint32_t DeviceCount, ///< [in] the number of devices given in phDevices + ur_device_handle_t* phDevices, ///< [in][range(0, DeviceCount)] array of handle of devices. + ur_context_handle_t* phContext ///< [out] pointer to handle of context object created + ) +{ + auto pfnCreate = ur_lib::context->urDdiTable.Context.pfnCreate; + if( nullptr == pfnCreate ) + return UR_RESULT_ERROR_UNINITIALIZED; + + return pfnCreate( DeviceCount, phDevices, phContext ); +} + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Makes a reference of the context handle indicating it's in use until +/// paired ::urContextRelease is called +/// +/// @details +/// - It is not valid to use a context handle, which has all of its +/// references released. +/// - The application may call this function from simultaneous threads for +/// the same device. +/// - The implementation of this function should be thread-safe. +/// +/// @remarks +/// _Analogues_ +/// - **clRetainContext** +/// +/// @returns +/// - ::UR_RESULT_SUCCESS +/// - ::UR_RESULT_ERROR_UNINITIALIZED +/// - ::UR_RESULT_ERROR_DEVICE_LOST +/// - ::UR_RESULT_ERROR_INVALID_NULL_HANDLE +/// + `NULL == hContext` +ur_result_t UR_APICALL +urContextRetain( + ur_context_handle_t hContext ///< [in] handle of the context to get a reference of. + ) +{ + auto pfnRetain = ur_lib::context->urDdiTable.Context.pfnRetain; + if( nullptr == pfnRetain ) + return UR_RESULT_ERROR_UNINITIALIZED; + + return pfnRetain( hContext ); +} + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Releases the context handle reference indicating end of its usage +/// +/// @details +/// - The application may call this function from simultaneous threads for +/// the same context. +/// - The implementation of this function should be thread-safe. +/// +/// @remarks +/// _Analogues_ +/// - **clReleaseContext** +/// +/// @returns +/// - ::UR_RESULT_SUCCESS +/// - ::UR_RESULT_ERROR_UNINITIALIZED +/// - ::UR_RESULT_ERROR_DEVICE_LOST +/// - ::UR_RESULT_ERROR_INVALID_NULL_HANDLE +/// + `NULL == hContext` +ur_result_t UR_APICALL +urContextRelease( + ur_context_handle_t hContext ///< [in] handle of the context to release. + ) +{ + auto pfnRelease = ur_lib::context->urDdiTable.Context.pfnRelease; + if( nullptr == pfnRelease ) + return UR_RESULT_ERROR_UNINITIALIZED; + + return pfnRelease( hContext ); +} + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Retrieves various information about context +/// +/// @details +/// - The application may call this function from simultaneous threads. +/// - The implementation of this function should be lock-free. +/// +/// @remarks +/// _Analogues_ +/// - **clGetContextInfo** +/// +/// @returns +/// - ::UR_RESULT_SUCCESS +/// - ::UR_RESULT_ERROR_UNINITIALIZED +/// - ::UR_RESULT_ERROR_DEVICE_LOST +/// - ::UR_RESULT_ERROR_INVALID_NULL_HANDLE +/// + `NULL == hContext` +/// - ::UR_RESULT_ERROR_INVALID_ENUMERATION +/// + `::UR_CONTEXT_INFO_DEVICES < ContextInfoType` +ur_result_t UR_APICALL +urContextGetInfo( + ur_context_handle_t hContext, ///< [in] handle of the context + ur_context_info_t ContextInfoType, ///< [in] type of the info to retrieve + size_t propSize, ///< [in] the number of bytes of memory pointed to by pContextInfo. + void* pContextInfo, ///< [out][optional] 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 ::UR_RESULT_ERROR_INVALID_SIZE error is returned and + ///< pContextInfo is not used. + size_t* pPropSizeRet ///< [out][optional] pointer to the actual size in bytes of data queried by ContextInfoType. + ) +{ + auto pfnGetInfo = ur_lib::context->urDdiTable.Context.pfnGetInfo; + if( nullptr == pfnGetInfo ) + return UR_RESULT_ERROR_UNINITIALIZED; + + return pfnGetInfo( hContext, ContextInfoType, propSize, pContextInfo, pPropSizeRet ); +} + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Return platform native context handle. +/// +/// @details +/// - Retrieved native handle can be used for direct interaction with the +/// native platform driver. +/// - Use interoperability platform extensions to convert native handle to +/// native type. +/// - The application may call this function from simultaneous threads for +/// the same context. +/// - The implementation of this function should be thread-safe. +/// +/// @returns +/// - ::UR_RESULT_SUCCESS +/// - ::UR_RESULT_ERROR_UNINITIALIZED +/// - ::UR_RESULT_ERROR_DEVICE_LOST +/// - ::UR_RESULT_ERROR_INVALID_NULL_HANDLE +/// + `NULL == hContext` +/// - ::UR_RESULT_ERROR_INVALID_NULL_POINTER +/// + `NULL == phNativeContext` +ur_result_t UR_APICALL +urContextGetNativeHandle( + ur_context_handle_t hContext, ///< [in] handle of the context. + ur_native_handle_t* phNativeContext ///< [out] a pointer to the native handle of the context. + ) +{ + auto pfnGetNativeHandle = ur_lib::context->urDdiTable.Context.pfnGetNativeHandle; + if( nullptr == pfnGetNativeHandle ) + return UR_RESULT_ERROR_UNINITIALIZED; + + return pfnGetNativeHandle( hContext, phNativeContext ); +} + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Create runtime context object from native context handle. +/// +/// @details +/// - Creates runtime context handle from native driver context handle. +/// - The application may call this function from simultaneous threads for +/// the same context. +/// - The implementation of this function should be thread-safe. +/// +/// @returns +/// - ::UR_RESULT_SUCCESS +/// - ::UR_RESULT_ERROR_UNINITIALIZED +/// - ::UR_RESULT_ERROR_DEVICE_LOST +/// - ::UR_RESULT_ERROR_INVALID_NULL_HANDLE +/// + `NULL == hNativeContext` +/// - ::UR_RESULT_ERROR_INVALID_NULL_POINTER +/// + `NULL == phContext` +ur_result_t UR_APICALL +urContextCreateWithNativeHandle( + ur_native_handle_t hNativeContext, ///< [in] the native handle of the context. + ur_context_handle_t* phContext ///< [out] pointer to the handle of the context object created. + ) +{ + auto pfnCreateWithNativeHandle = ur_lib::context->urDdiTable.Context.pfnCreateWithNativeHandle; + if( nullptr == pfnCreateWithNativeHandle ) + return UR_RESULT_ERROR_UNINITIALIZED; + + return pfnCreateWithNativeHandle( hNativeContext, phContext ); +} + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Call extended deleter function as callback. +/// +/// @details +/// - Calls exnteded deleter, a user-defined callback to delete context on +/// some platforms. +/// - This is done for performance reasons. +/// - This API might be called directly by an application instead of a +/// runtime backend. +/// - The application may call this function from simultaneous threads for +/// the same context. +/// - The implementation of this function should be thread-safe. +/// +/// @returns +/// - ::UR_RESULT_SUCCESS +/// - ::UR_RESULT_ERROR_UNINITIALIZED +/// - ::UR_RESULT_ERROR_DEVICE_LOST +/// - ::UR_RESULT_ERROR_INVALID_NULL_HANDLE +/// + `NULL == hContext` +/// - ::UR_RESULT_ERROR_INVALID_NULL_POINTER +/// + `NULL == pUserData` +ur_result_t UR_APICALL +urContextSetExtendedDeleter( + ur_context_handle_t hContext, ///< [in] handle of the context. + ur_context_extended_deleter_t pfnDeleter, ///< [in] Function pointer to extended deleter. + void* pUserData ///< [in][out] pointer to data to be passed to callback. + ) +{ + auto pfnSetExtendedDeleter = ur_lib::context->urDdiTable.Context.pfnSetExtendedDeleter; + if( nullptr == pfnSetExtendedDeleter ) + return UR_RESULT_ERROR_UNINITIALIZED; + + return pfnSetExtendedDeleter( hContext, pfnDeleter, pUserData ); +} + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Enqueue a command to execute a kernel +/// +/// @remarks +/// _Analogues_ +/// - **clEnqueueNDRangeKernel** +/// +/// @returns +/// - ::UR_RESULT_SUCCESS +/// - ::UR_RESULT_ERROR_UNINITIALIZED +/// - ::UR_RESULT_ERROR_DEVICE_LOST +/// - ::UR_RESULT_ERROR_INVALID_NULL_HANDLE +/// + `NULL == hQueue` +/// + `NULL == hKernel` +/// - ::UR_RESULT_ERROR_INVALID_NULL_POINTER +/// + `NULL == pGlobalWorkOffset` +/// + `NULL == pGlobalWorkSize` +/// + `NULL == phEvent` +/// - ::UR_RESULT_ERROR_INVALID_QUEUE +/// - ::UR_RESULT_ERROR_INVALID_KERNEL +/// - ::UR_RESULT_ERROR_INVALID_EVENT +/// - ::UR_RESULT_ERROR_INVALID_WORK_DIMENSION +/// - ::UR_RESULT_ERROR_INVALID_WORK_GROUP_SIZE +/// - ::UR_RESULT_ERROR_INVALID_VALUE +/// - ::UR_RESULT_ERROR_OUT_OF_HOST_MEMORY +/// - ::UR_RESULT_ERROR_OUT_OF_RESOURCES +ur_result_t UR_APICALL +urEnqueueKernelLaunch( + ur_queue_handle_t hQueue, ///< [in] handle of the queue object + ur_kernel_handle_t hKernel, ///< [in] handle of the kernel object + uint32_t workDim, ///< [in] number of dimensions, from 1 to 3, to specify the global and + ///< work-group work-items + const size_t* pGlobalWorkOffset, ///< [in] pointer to an array of workDim unsigned values that specify the + ///< offset used to calculate the global ID of a work-item + const size_t* pGlobalWorkSize, ///< [in] pointer to an array of workDim unsigned values that specify the + ///< number of global work-items in workDim that will execute the kernel + ///< function + const size_t* pLocalWorkSize, ///< [in][optional] pointer to an array of workDim unsigned values that + ///< specify the number of local work-items forming a work-group that will + ///< execute the kernel function. + ///< If nullptr, the runtime implementation will choose the work-group + ///< size. + uint32_t numEventsInWaitList, ///< [in] size of the event wait list + const ur_event_handle_t* phEventWaitList, ///< [in][optional][range(0, numEventsInWaitList)] pointer to a list of + ///< events that must be complete before the kernel execution. + ///< If nullptr, the numEventsInWaitList must be 0, indicating that no wait + ///< event. + ur_event_handle_t* phEvent ///< [in,out] return an event object that identifies this particular kernel + ///< execution instance. + ///< Contrary to clEnqueueNDRangeKernel, its input can not be a nullptr. + ///< TODO: change to allow nullptr. + ) +{ + auto pfnKernelLaunch = ur_lib::context->urDdiTable.Enqueue.pfnKernelLaunch; + if( nullptr == pfnKernelLaunch ) + return UR_RESULT_ERROR_UNINITIALIZED; + + return pfnKernelLaunch( hQueue, hKernel, workDim, pGlobalWorkOffset, pGlobalWorkSize, pLocalWorkSize, numEventsInWaitList, phEventWaitList, phEvent ); +} + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Enqueue a command which waits a list of events to complete before it +/// completes +/// +/// @details +/// - If the event list is empty, it waits for all previously enqueued +/// commands to complete. +/// - It returns an event which can be waited on. +/// +/// @remarks +/// _Analogues_ +/// - **clEnqueueMarkerWithWaitList** +/// +/// @returns +/// - ::UR_RESULT_SUCCESS +/// - ::UR_RESULT_ERROR_UNINITIALIZED +/// - ::UR_RESULT_ERROR_DEVICE_LOST +/// - ::UR_RESULT_ERROR_INVALID_NULL_HANDLE +/// + `NULL == hQueue` +/// - ::UR_RESULT_ERROR_INVALID_NULL_POINTER +/// + `NULL == phEvent` +/// - ::UR_RESULT_ERROR_INVALID_QUEUE +/// - ::UR_RESULT_ERROR_INVALID_EVENT +/// - ::UR_RESULT_ERROR_INVALID_VALUE +/// - ::UR_RESULT_ERROR_OUT_OF_HOST_MEMORY +/// - ::UR_RESULT_ERROR_OUT_OF_RESOURCES +ur_result_t UR_APICALL +urEnqueueEventsWait( + ur_queue_handle_t hQueue, ///< [in] handle of the queue object + uint32_t numEventsInWaitList, ///< [in] size of the event wait list + const ur_event_handle_t* phEventWaitList, ///< [in][optional][range(0, numEventsInWaitList)] pointer to a list of + ///< events that must be complete before this command can be executed. + ///< If nullptr, the numEventsInWaitList must be 0, indicating that all + ///< previously enqueued commands + ///< must be complete. + ur_event_handle_t* phEvent ///< [in,out] return an event object that identifies this particular + ///< command instance. + ///< Input can not be a nullptr. + ///< TODO: change to allow nullptr. + ) +{ + auto pfnEventsWait = ur_lib::context->urDdiTable.Enqueue.pfnEventsWait; + if( nullptr == pfnEventsWait ) + return UR_RESULT_ERROR_UNINITIALIZED; + + return pfnEventsWait( hQueue, numEventsInWaitList, phEventWaitList, phEvent ); +} + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Enqueue a barrier command which waits a list of events to complete +/// before it completes +/// +/// @details +/// - If the event list is empty, it waits for all previously enqueued +/// commands to complete. +/// - It blocks command execution - any following commands enqueued after it +/// do not execute until it completes. +/// - It returns an event which can be waited on. +/// +/// @remarks +/// _Analogues_ +/// - **clEnqueueBarrierWithWaitList** +/// +/// @returns +/// - ::UR_RESULT_SUCCESS +/// - ::UR_RESULT_ERROR_UNINITIALIZED +/// - ::UR_RESULT_ERROR_DEVICE_LOST +/// - ::UR_RESULT_ERROR_INVALID_NULL_HANDLE +/// + `NULL == hQueue` +/// - ::UR_RESULT_ERROR_INVALID_NULL_POINTER +/// + `NULL == phEvent` +/// - ::UR_RESULT_ERROR_INVALID_QUEUE +/// - ::UR_RESULT_ERROR_INVALID_EVENT +/// - ::UR_RESULT_ERROR_INVALID_VALUE +/// - ::UR_RESULT_ERROR_OUT_OF_HOST_MEMORY +/// - ::UR_RESULT_ERROR_OUT_OF_RESOURCES +ur_result_t UR_APICALL +urEnqueueEventsWaitWithBarrier( + ur_queue_handle_t hQueue, ///< [in] handle of the queue object + uint32_t numEventsInWaitList, ///< [in] size of the event wait list + const ur_event_handle_t* phEventWaitList, ///< [in][optional][range(0, numEventsInWaitList)] pointer to a list of + ///< events that must be complete before this command can be executed. + ///< If nullptr, the numEventsInWaitList must be 0, indicating that all + ///< previously enqueued commands + ///< must be complete. + ur_event_handle_t* phEvent ///< [in,out] return an event object that identifies this particular + ///< command instance. + ///< Input can not be a nullptr. + ///< TODO: change to allow nullptr. + ) +{ + auto pfnEventsWaitWithBarrier = ur_lib::context->urDdiTable.Enqueue.pfnEventsWaitWithBarrier; + if( nullptr == pfnEventsWaitWithBarrier ) + return UR_RESULT_ERROR_UNINITIALIZED; + + return pfnEventsWaitWithBarrier( hQueue, numEventsInWaitList, phEventWaitList, phEvent ); +} + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Enqueue a command to read from a buffer object to host memory +/// +/// @details +/// - Input parameter blockingRead indicates if the read is blocking or +/// non-blocking. +/// +/// @remarks +/// _Analogues_ +/// - **clEnqueueReadBuffer** +/// +/// @returns +/// - ::UR_RESULT_SUCCESS +/// - ::UR_RESULT_ERROR_UNINITIALIZED +/// - ::UR_RESULT_ERROR_DEVICE_LOST +/// - ::UR_RESULT_ERROR_INVALID_NULL_HANDLE +/// + `NULL == hQueue` +/// + `NULL == hBuffer` +/// - ::UR_RESULT_ERROR_INVALID_NULL_POINTER +/// + `NULL == pDst` +/// + `NULL == phEvent` +/// - ::UR_RESULT_ERROR_INVALID_QUEUE +/// - ::UR_RESULT_ERROR_INVALID_EVENT +/// - ::UR_RESULT_ERROR_INVALID_MEM_OBJECT +/// - ::UR_RESULT_ERROR_OUT_OF_HOST_MEMORY +/// - ::UR_RESULT_ERROR_OUT_OF_RESOURCES +ur_result_t UR_APICALL +urEnqueueMemBufferRead( + ur_queue_handle_t hQueue, ///< [in] handle of the queue object + ur_mem_handle_t hBuffer, ///< [in] handle of the buffer object + bool blockingRead, ///< [in] indicates blocking (true), non-blocking (false) + size_t offset, ///< [in] offset in bytes in the buffer object + size_t size, ///< [in] size in bytes of data being read + void* pDst, ///< [in] pointer to host memory where data is to be read into + uint32_t numEventsInWaitList, ///< [in] size of the event wait list + const ur_event_handle_t* phEventWaitList, ///< [in][optional][range(0, numEventsInWaitList)] pointer to a list of + ///< events that must be complete before this command can be executed. + ///< If nullptr, the numEventsInWaitList must be 0, indicating that this + ///< command does not wait on any event to complete. + ur_event_handle_t* phEvent ///< [in,out] return an event object that identifies this particular + ///< command instance. + ///< Input can not be a nullptr. + ///< TODO: change to allow nullptr. + ) +{ + auto pfnMemBufferRead = ur_lib::context->urDdiTable.Enqueue.pfnMemBufferRead; + if( nullptr == pfnMemBufferRead ) + return UR_RESULT_ERROR_UNINITIALIZED; + + return pfnMemBufferRead( hQueue, hBuffer, blockingRead, offset, size, pDst, numEventsInWaitList, phEventWaitList, phEvent ); +} + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Enqueue a command to write into a buffer object from host memory +/// +/// @details +/// - Input parameter blockingWrite indicates if the write is blocking or +/// non-blocking. +/// +/// @remarks +/// _Analogues_ +/// - **clEnqueueWriteBuffer** +/// +/// @returns +/// - ::UR_RESULT_SUCCESS +/// - ::UR_RESULT_ERROR_UNINITIALIZED +/// - ::UR_RESULT_ERROR_DEVICE_LOST +/// - ::UR_RESULT_ERROR_INVALID_NULL_HANDLE +/// + `NULL == hQueue` +/// + `NULL == hBuffer` +/// - ::UR_RESULT_ERROR_INVALID_NULL_POINTER +/// + `NULL == pSrc` +/// + `NULL == phEvent` +/// - ::UR_RESULT_ERROR_INVALID_QUEUE +/// - ::UR_RESULT_ERROR_INVALID_EVENT +/// - ::UR_RESULT_ERROR_INVALID_MEM_OBJECT +/// - ::UR_RESULT_ERROR_OUT_OF_HOST_MEMORY +/// - ::UR_RESULT_ERROR_OUT_OF_RESOURCES +ur_result_t UR_APICALL +urEnqueueMemBufferWrite( + ur_queue_handle_t hQueue, ///< [in] handle of the queue object + ur_mem_handle_t hBuffer, ///< [in] handle of the buffer object + bool blockingWrite, ///< [in] indicates blocking (true), non-blocking (false) + size_t offset, ///< [in] offset in bytes in the buffer object + size_t size, ///< [in] size in bytes of data being written + const void* pSrc, ///< [in] pointer to host memory where data is to be written from + uint32_t numEventsInWaitList, ///< [in] size of the event wait list + const ur_event_handle_t* phEventWaitList, ///< [in][optional][range(0, numEventsInWaitList)] pointer to a list of + ///< events that must be complete before this command can be executed. + ///< If nullptr, the numEventsInWaitList must be 0, indicating that this + ///< command does not wait on any event to complete. + ur_event_handle_t* phEvent ///< [in,out] return an event object that identifies this particular + ///< command instance. + ///< Input can not be a nullptr. + ///< TODO: change to allow nullptr. + ) +{ + auto pfnMemBufferWrite = ur_lib::context->urDdiTable.Enqueue.pfnMemBufferWrite; + if( nullptr == pfnMemBufferWrite ) + return UR_RESULT_ERROR_UNINITIALIZED; + + return pfnMemBufferWrite( hQueue, hBuffer, blockingWrite, offset, size, pSrc, numEventsInWaitList, phEventWaitList, phEvent ); +} + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Enqueue a command to read a 2D or 3D rectangular region from a buffer +/// object to host memory +/// +/// @details +/// - Input parameter blockingRead indicates if the read is blocking or +/// non-blocking. +/// - The buffer and host 2D or 3D rectangular regions can have different +/// shapes. +/// +/// @remarks +/// _Analogues_ +/// - **clEnqueueReadBufferRect** +/// +/// @returns +/// - ::UR_RESULT_SUCCESS +/// - ::UR_RESULT_ERROR_UNINITIALIZED +/// - ::UR_RESULT_ERROR_DEVICE_LOST +/// - ::UR_RESULT_ERROR_INVALID_NULL_HANDLE +/// + `NULL == hQueue` +/// + `NULL == hBuffer` +/// - ::UR_RESULT_ERROR_INVALID_NULL_POINTER +/// + `NULL == pDst` +/// + `NULL == phEvent` +/// - ::UR_RESULT_ERROR_INVALID_QUEUE +/// - ::UR_RESULT_ERROR_INVALID_EVENT +/// - ::UR_RESULT_ERROR_INVALID_MEM_OBJECT +/// - ::UR_RESULT_ERROR_OUT_OF_HOST_MEMORY +/// - ::UR_RESULT_ERROR_OUT_OF_RESOURCES +ur_result_t UR_APICALL +urEnqueueMemBufferReadRect( + ur_queue_handle_t hQueue, ///< [in] handle of the queue object + ur_mem_handle_t hBuffer, ///< [in] handle of the buffer object + bool blockingRead, ///< [in] indicates blocking (true), non-blocking (false) + ur_rect_offset_t bufferOffset, ///< [in] 3D offset in the buffer + ur_rect_offset_t hostOffset, ///< [in] 3D offset in the host region + ur_rect_region_t region, ///< [in] 3D rectangular region descriptor: width, height, depth + size_t bufferRowPitch, ///< [in] length of each row in bytes in the buffer object + size_t bufferSlicePitch, ///< [in] length of each 2D slice in bytes in the buffer object being read + size_t hostRowPitch, ///< [in] length of each row in bytes in the host memory region pointed by + ///< dst + size_t hostSlicePitch, ///< [in] length of each 2D slice in bytes in the host memory region + ///< pointed by dst + void* pDst, ///< [in] pointer to host memory where data is to be read into + uint32_t numEventsInWaitList, ///< [in] size of the event wait list + const ur_event_handle_t* phEventWaitList, ///< [in][optional][range(0, numEventsInWaitList)] pointer to a list of + ///< events that must be complete before this command can be executed. + ///< If nullptr, the numEventsInWaitList must be 0, indicating that this + ///< command does not wait on any event to complete. + ur_event_handle_t* phEvent ///< [in,out] return an event object that identifies this particular + ///< command instance. + ///< Input can not be a nullptr. + ///< TODO: change to allow nullptr. + ) +{ + auto pfnMemBufferReadRect = ur_lib::context->urDdiTable.Enqueue.pfnMemBufferReadRect; + if( nullptr == pfnMemBufferReadRect ) + return UR_RESULT_ERROR_UNINITIALIZED; + + return pfnMemBufferReadRect( hQueue, hBuffer, blockingRead, bufferOffset, hostOffset, region, bufferRowPitch, bufferSlicePitch, hostRowPitch, hostSlicePitch, pDst, numEventsInWaitList, phEventWaitList, phEvent ); +} + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Enqueue a command to write a 2D or 3D rectangular region in a buffer +/// object from host memory +/// +/// @details +/// - Input parameter blockingWrite indicates if the write is blocking or +/// non-blocking. +/// - The buffer and host 2D or 3D rectangular regions can have different +/// shapes. +/// +/// @remarks +/// _Analogues_ +/// - **clEnqueueWriteBufferRect** +/// +/// @returns +/// - ::UR_RESULT_SUCCESS +/// - ::UR_RESULT_ERROR_UNINITIALIZED +/// - ::UR_RESULT_ERROR_DEVICE_LOST +/// - ::UR_RESULT_ERROR_INVALID_NULL_HANDLE +/// + `NULL == hQueue` +/// + `NULL == hBuffer` +/// - ::UR_RESULT_ERROR_INVALID_NULL_POINTER +/// + `NULL == pSrc` +/// + `NULL == phEvent` +/// - ::UR_RESULT_ERROR_INVALID_QUEUE +/// - ::UR_RESULT_ERROR_INVALID_EVENT +/// - ::UR_RESULT_ERROR_INVALID_MEM_OBJECT +/// - ::UR_RESULT_ERROR_OUT_OF_HOST_MEMORY +/// - ::UR_RESULT_ERROR_OUT_OF_RESOURCES +ur_result_t UR_APICALL +urEnqueueMemBufferWriteRect( + ur_queue_handle_t hQueue, ///< [in] handle of the queue object + ur_mem_handle_t hBuffer, ///< [in] handle of the buffer object + bool blockingWrite, ///< [in] indicates blocking (true), non-blocking (false) + ur_rect_offset_t bufferOffset, ///< [in] 3D offset in the buffer + ur_rect_offset_t hostOffset, ///< [in] 3D offset in the host region + ur_rect_region_t region, ///< [in] 3D rectangular region descriptor: width, height, depth + size_t bufferRowPitch, ///< [in] length of each row in bytes in the buffer object + size_t bufferSlicePitch, ///< [in] length of each 2D slice in bytes in the buffer object being + ///< written + size_t hostRowPitch, ///< [in] length of each row in bytes in the host memory region pointed by + ///< src + size_t hostSlicePitch, ///< [in] length of each 2D slice in bytes in the host memory region + ///< pointed by src + void* pSrc, ///< [in] pointer to host memory where data is to be written from + uint32_t numEventsInWaitList, ///< [in] size of the event wait list + const ur_event_handle_t* phEventWaitList, ///< [in][optional][range(0, numEventsInWaitList)] points to a list of + ///< events that must be complete before this command can be executed. + ///< If nullptr, the numEventsInWaitList must be 0, indicating that this + ///< command does not wait on any event to complete. + ur_event_handle_t* phEvent ///< [in,out] return an event object that identifies this particular + ///< command instance. + ///< Input can not be a nullptr. + ///< TODO: change to allow nullptr. + ) +{ + auto pfnMemBufferWriteRect = ur_lib::context->urDdiTable.Enqueue.pfnMemBufferWriteRect; + if( nullptr == pfnMemBufferWriteRect ) + return UR_RESULT_ERROR_UNINITIALIZED; + + return pfnMemBufferWriteRect( hQueue, hBuffer, blockingWrite, bufferOffset, hostOffset, region, bufferRowPitch, bufferSlicePitch, hostRowPitch, hostSlicePitch, pSrc, numEventsInWaitList, phEventWaitList, phEvent ); +} + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Enqueue a command to copy from a buffer object to another +/// +/// @remarks +/// _Analogues_ +/// - **clEnqueueCopyBuffer** +/// +/// @returns +/// - ::UR_RESULT_SUCCESS +/// - ::UR_RESULT_ERROR_UNINITIALIZED +/// - ::UR_RESULT_ERROR_DEVICE_LOST +/// - ::UR_RESULT_ERROR_INVALID_NULL_HANDLE +/// + `NULL == hQueue` +/// + `NULL == hBufferSrc` +/// + `NULL == hBufferDst` +/// - ::UR_RESULT_ERROR_INVALID_NULL_POINTER +/// + `NULL == phEvent` +/// - ::UR_RESULT_ERROR_INVALID_QUEUE +/// - ::UR_RESULT_ERROR_INVALID_EVENT +/// - ::UR_RESULT_ERROR_INVALID_MEM_OBJECT +/// - ::UR_RESULT_ERROR_OUT_OF_HOST_MEMORY +/// - ::UR_RESULT_ERROR_OUT_OF_RESOURCES +ur_result_t UR_APICALL +urEnqueueMemBufferCopy( + ur_queue_handle_t hQueue, ///< [in] handle of the queue object + ur_mem_handle_t hBufferSrc, ///< [in] handle of the src buffer object + ur_mem_handle_t hBufferDst, ///< [in] handle of the dest buffer object + size_t size, ///< [in] size in bytes of data being copied + uint32_t numEventsInWaitList, ///< [in] size of the event wait list + const ur_event_handle_t* phEventWaitList, ///< [in][optional][range(0, numEventsInWaitList)] pointer to a list of + ///< events that must be complete before this command can be executed. + ///< If nullptr, the numEventsInWaitList must be 0, indicating that this + ///< command does not wait on any event to complete. + ur_event_handle_t* phEvent ///< [in,out] return an event object that identifies this particular + ///< command instance. + ///< Input can not be a nullptr. + ///< TODO: change to allow nullptr. + ) +{ + auto pfnMemBufferCopy = ur_lib::context->urDdiTable.Enqueue.pfnMemBufferCopy; + if( nullptr == pfnMemBufferCopy ) + return UR_RESULT_ERROR_UNINITIALIZED; + + return pfnMemBufferCopy( hQueue, hBufferSrc, hBufferDst, size, numEventsInWaitList, phEventWaitList, phEvent ); +} + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Enqueue a command to copy a 2D or 3D rectangular region from one +/// buffer object to another +/// +/// @remarks +/// _Analogues_ +/// - **clEnqueueCopyBufferRect** +/// +/// @returns +/// - ::UR_RESULT_SUCCESS +/// - ::UR_RESULT_ERROR_UNINITIALIZED +/// - ::UR_RESULT_ERROR_DEVICE_LOST +/// - ::UR_RESULT_ERROR_INVALID_NULL_HANDLE +/// + `NULL == hQueue` +/// + `NULL == hBufferSrc` +/// + `NULL == hBufferDst` +/// - ::UR_RESULT_ERROR_INVALID_NULL_POINTER +/// + `NULL == phEvent` +/// - ::UR_RESULT_ERROR_INVALID_QUEUE +/// - ::UR_RESULT_ERROR_INVALID_EVENT +/// - ::UR_RESULT_ERROR_INVALID_MEM_OBJECT +/// - ::UR_RESULT_ERROR_OUT_OF_HOST_MEMORY +/// - ::UR_RESULT_ERROR_OUT_OF_RESOURCES +ur_result_t UR_APICALL +urEnqueueMemBufferCopyRect( + ur_queue_handle_t hQueue, ///< [in] handle of the queue object + ur_mem_handle_t hBufferSrc, ///< [in] handle of the source buffer object + ur_mem_handle_t hBufferDst, ///< [in] handle of the dest buffer object + ur_rect_offset_t srcOrigin, ///< [in] 3D offset in the source buffer + ur_rect_offset_t dstOrigin, ///< [in] 3D offset in the destination buffer + ur_rect_region_t srcRegion, ///< [in] source 3D rectangular region descriptor: width, height, depth + size_t srcRowPitch, ///< [in] length of each row in bytes in the source buffer object + size_t srcSlicePitch, ///< [in] length of each 2D slice in bytes in the source buffer object + size_t dstRowPitch, ///< [in] length of each row in bytes in the destination buffer object + size_t dstSlicePitch, ///< [in] length of each 2D slice in bytes in the destination buffer object + uint32_t numEventsInWaitList, ///< [in] size of the event wait list + const ur_event_handle_t* phEventWaitList, ///< [in][optional][range(0, numEventsInWaitList)] pointer to a list of + ///< events that must be complete before this command can be executed. + ///< If nullptr, the numEventsInWaitList must be 0, indicating that this + ///< command does not wait on any event to complete. + ur_event_handle_t* phEvent ///< [in,out] return an event object that identifies this particular + ///< command instance. + ///< Input can not be a nullptr. + ///< TODO: change to allow nullptr. + ) +{ + auto pfnMemBufferCopyRect = ur_lib::context->urDdiTable.Enqueue.pfnMemBufferCopyRect; + if( nullptr == pfnMemBufferCopyRect ) + return UR_RESULT_ERROR_UNINITIALIZED; + + return pfnMemBufferCopyRect( hQueue, hBufferSrc, hBufferDst, srcOrigin, dstOrigin, srcRegion, srcRowPitch, srcSlicePitch, dstRowPitch, dstSlicePitch, numEventsInWaitList, phEventWaitList, phEvent ); +} + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Enqueue a command to fill a buffer object with a pattern of a given +/// size +/// +/// @remarks +/// _Analogues_ +/// - **clEnqueueFillBuffer** +/// +/// @returns +/// - ::UR_RESULT_SUCCESS +/// - ::UR_RESULT_ERROR_UNINITIALIZED +/// - ::UR_RESULT_ERROR_DEVICE_LOST +/// - ::UR_RESULT_ERROR_INVALID_NULL_HANDLE +/// + `NULL == hQueue` +/// + `NULL == hBuffer` +/// - ::UR_RESULT_ERROR_INVALID_NULL_POINTER +/// + `NULL == pPattern` +/// + `NULL == phEvent` +/// - ::UR_RESULT_ERROR_INVALID_QUEUE +/// - ::UR_RESULT_ERROR_INVALID_EVENT +/// - ::UR_RESULT_ERROR_INVALID_MEM_OBJECT +/// - ::UR_RESULT_ERROR_OUT_OF_HOST_MEMORY +/// - ::UR_RESULT_ERROR_OUT_OF_RESOURCES +ur_result_t UR_APICALL +urEnqueueMemBufferFill( + ur_queue_handle_t hQueue, ///< [in] handle of the queue object + ur_mem_handle_t hBuffer, ///< [in] handle of the buffer object + const void* pPattern, ///< [in] pointer to the fill pattern + size_t patternSize, ///< [in] size in bytes of the pattern + size_t offset, ///< [in] offset into the buffer + size_t size, ///< [in] fill size in bytes, must be a multiple of patternSize + uint32_t numEventsInWaitList, ///< [in] size of the event wait list + const ur_event_handle_t* phEventWaitList, ///< [in][optional][range(0, numEventsInWaitList)] pointer to a list of + ///< events that must be complete before this command can be executed. + ///< If nullptr, the numEventsInWaitList must be 0, indicating that this + ///< command does not wait on any event to complete. + ur_event_handle_t* phEvent ///< [in,out] return an event object that identifies this particular + ///< command instance. + ///< Input can not be a nullptr. + ///< TODO: change to allow nullptr. + ) +{ + auto pfnMemBufferFill = ur_lib::context->urDdiTable.Enqueue.pfnMemBufferFill; + if( nullptr == pfnMemBufferFill ) + return UR_RESULT_ERROR_UNINITIALIZED; + + return pfnMemBufferFill( hQueue, hBuffer, pPattern, patternSize, offset, size, numEventsInWaitList, phEventWaitList, phEvent ); +} + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Enqueue a command to read from an image or image array object to host +/// memory +/// +/// @details +/// - Input parameter blockingRead indicates if the read is blocking or +/// non-blocking. +/// +/// @remarks +/// _Analogues_ +/// - **clEnqueueReadImage** +/// +/// @returns +/// - ::UR_RESULT_SUCCESS +/// - ::UR_RESULT_ERROR_UNINITIALIZED +/// - ::UR_RESULT_ERROR_DEVICE_LOST +/// - ::UR_RESULT_ERROR_INVALID_NULL_HANDLE +/// + `NULL == hQueue` +/// + `NULL == hImage` +/// - ::UR_RESULT_ERROR_INVALID_NULL_POINTER +/// + `NULL == pDst` +/// + `NULL == phEvent` +/// - ::UR_RESULT_ERROR_INVALID_QUEUE +/// - ::UR_RESULT_ERROR_INVALID_EVENT +/// - ::UR_RESULT_ERROR_INVALID_MEM_OBJECT +/// - ::UR_RESULT_ERROR_OUT_OF_HOST_MEMORY +/// - ::UR_RESULT_ERROR_OUT_OF_RESOURCES +ur_result_t UR_APICALL +urEnqueueMemImageRead( + ur_queue_handle_t hQueue, ///< [in] handle of the queue object + ur_mem_handle_t hImage, ///< [in] handle of the image object + bool blockingRead, ///< [in] indicates blocking (true), non-blocking (false) + ur_rect_offset_t origin, ///< [in] defines the (x,y,z) offset in pixels in the 1D, 2D, or 3D image + ur_rect_region_t region, ///< [in] defines the (width, height, depth) in pixels of the 1D, 2D, or 3D + ///< image + size_t rowPitch, ///< [in] length of each row in bytes + size_t slicePitch, ///< [in] length of each 2D slice of the 3D image + void* pDst, ///< [in] pointer to host memory where image is to be read into + uint32_t numEventsInWaitList, ///< [in] size of the event wait list + const ur_event_handle_t* phEventWaitList, ///< [in][optional][range(0, numEventsInWaitList)] pointer to a list of + ///< events that must be complete before this command can be executed. + ///< If nullptr, the numEventsInWaitList must be 0, indicating that this + ///< command does not wait on any event to complete. + ur_event_handle_t* phEvent ///< [in,out] return an event object that identifies this particular + ///< command instance. + ///< Input can not be a nullptr. + ///< TODO: change to allow nullptr. + ) +{ + auto pfnMemImageRead = ur_lib::context->urDdiTable.Enqueue.pfnMemImageRead; + if( nullptr == pfnMemImageRead ) + return UR_RESULT_ERROR_UNINITIALIZED; + + return pfnMemImageRead( hQueue, hImage, blockingRead, origin, region, rowPitch, slicePitch, pDst, numEventsInWaitList, phEventWaitList, phEvent ); +} + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Enqueue a command to write an image or image array object from host +/// memory +/// +/// @details +/// - Input parameter blockingWrite indicates if the write is blocking or +/// non-blocking. +/// +/// @remarks +/// _Analogues_ +/// - **clEnqueueWriteImage** +/// +/// @returns +/// - ::UR_RESULT_SUCCESS +/// - ::UR_RESULT_ERROR_UNINITIALIZED +/// - ::UR_RESULT_ERROR_DEVICE_LOST +/// - ::UR_RESULT_ERROR_INVALID_NULL_HANDLE +/// + `NULL == hQueue` +/// + `NULL == hImage` +/// - ::UR_RESULT_ERROR_INVALID_NULL_POINTER +/// + `NULL == pSrc` +/// + `NULL == phEvent` +/// - ::UR_RESULT_ERROR_INVALID_QUEUE +/// - ::UR_RESULT_ERROR_INVALID_EVENT +/// - ::UR_RESULT_ERROR_INVALID_MEM_OBJECT +/// - ::UR_RESULT_ERROR_OUT_OF_HOST_MEMORY +/// - ::UR_RESULT_ERROR_OUT_OF_RESOURCES +ur_result_t UR_APICALL +urEnqueueMemImageWrite( + ur_queue_handle_t hQueue, ///< [in] handle of the queue object + ur_mem_handle_t hImage, ///< [in] handle of the image object + bool blockingWrite, ///< [in] indicates blocking (true), non-blocking (false) + ur_rect_offset_t origin, ///< [in] defines the (x,y,z) offset in pixels in the 1D, 2D, or 3D image + ur_rect_region_t region, ///< [in] defines the (width, height, depth) in pixels of the 1D, 2D, or 3D + ///< image + size_t inputRowPitch, ///< [in] length of each row in bytes + size_t inputSlicePitch, ///< [in] length of each 2D slice of the 3D image + void* pSrc, ///< [in] pointer to host memory where image is to be read into + uint32_t numEventsInWaitList, ///< [in] size of the event wait list + const ur_event_handle_t* phEventWaitList, ///< [in][optional][range(0, numEventsInWaitList)] pointer to a list of + ///< events that must be complete before this command can be executed. + ///< If nullptr, the numEventsInWaitList must be 0, indicating that this + ///< command does not wait on any event to complete. + ur_event_handle_t* phEvent ///< [in,out] return an event object that identifies this particular + ///< command instance. + ///< Input can not be a nullptr. + ///< TODO: change to allow nullptr. + ) +{ + auto pfnMemImageWrite = ur_lib::context->urDdiTable.Enqueue.pfnMemImageWrite; + if( nullptr == pfnMemImageWrite ) + return UR_RESULT_ERROR_UNINITIALIZED; + + return pfnMemImageWrite( hQueue, hImage, blockingWrite, origin, region, inputRowPitch, inputSlicePitch, pSrc, numEventsInWaitList, phEventWaitList, phEvent ); +} + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Enqueue a command to copy from an image object to another +/// +/// @remarks +/// _Analogues_ +/// - **clEnqueueCopyImage** +/// +/// @returns +/// - ::UR_RESULT_SUCCESS +/// - ::UR_RESULT_ERROR_UNINITIALIZED +/// - ::UR_RESULT_ERROR_DEVICE_LOST +/// - ::UR_RESULT_ERROR_INVALID_NULL_HANDLE +/// + `NULL == hQueue` +/// + `NULL == hImageSrc` +/// + `NULL == hImageDst` +/// - ::UR_RESULT_ERROR_INVALID_NULL_POINTER +/// + `NULL == phEvent` +/// - ::UR_RESULT_ERROR_INVALID_QUEUE +/// - ::UR_RESULT_ERROR_INVALID_EVENT +/// - ::UR_RESULT_ERROR_INVALID_MEM_OBJECT +/// - ::UR_RESULT_ERROR_OUT_OF_HOST_MEMORY +/// - ::UR_RESULT_ERROR_OUT_OF_RESOURCES +ur_result_t UR_APICALL +urEnqueueMemImageCopy( + ur_queue_handle_t hQueue, ///< [in] handle of the queue object + ur_mem_handle_t hImageSrc, ///< [in] handle of the src image object + ur_mem_handle_t hImageDst, ///< [in] handle of the dest image object + ur_rect_offset_t srcOrigin, ///< [in] defines the (x,y,z) offset in pixels in the source 1D, 2D, or 3D + ///< image + ur_rect_offset_t dstOrigin, ///< [in] defines the (x,y,z) offset in pixels in the destination 1D, 2D, + ///< or 3D image + ur_rect_region_t region, ///< [in] defines the (width, height, depth) in pixels of the 1D, 2D, or 3D + ///< image + uint32_t numEventsInWaitList, ///< [in] size of the event wait list + const ur_event_handle_t* phEventWaitList, ///< [in][optional][range(0, numEventsInWaitList)] pointer to a list of + ///< events that must be complete before this command can be executed. + ///< If nullptr, the numEventsInWaitList must be 0, indicating that this + ///< command does not wait on any event to complete. + ur_event_handle_t* phEvent ///< [in,out] return an event object that identifies this particular + ///< command instance. + ///< Input can not be a nullptr. + ///< TODO: change to allow nullptr. + ) +{ + auto pfnMemImageCopy = ur_lib::context->urDdiTable.Enqueue.pfnMemImageCopy; + if( nullptr == pfnMemImageCopy ) + return UR_RESULT_ERROR_UNINITIALIZED; + + return pfnMemImageCopy( hQueue, hImageSrc, hImageDst, srcOrigin, dstOrigin, region, numEventsInWaitList, phEventWaitList, phEvent ); +} + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Enqueue a command to map a region of the buffer object into the host +/// address space and return a pointer to the mapped region +/// +/// @details +/// - Input parameter blockingMap indicates if the map is blocking or +/// non-blocking. +/// - Currently, no direct support in Leverl Zero. Implemented as a shared +/// allocation followed by copying on discrete GPU +/// - TODO: add a driver function in Level Zero? +/// +/// @remarks +/// _Analogues_ +/// - **clEnqueueMapBuffer** +/// +/// @returns +/// - ::UR_RESULT_SUCCESS +/// - ::UR_RESULT_ERROR_UNINITIALIZED +/// - ::UR_RESULT_ERROR_DEVICE_LOST +/// - ::UR_RESULT_ERROR_INVALID_NULL_HANDLE +/// + `NULL == hQueue` +/// + `NULL == hBuffer` +/// - ::UR_RESULT_ERROR_INVALID_ENUMERATION +/// + `0x3 < mapFlags` +/// - ::UR_RESULT_ERROR_INVALID_NULL_POINTER +/// + `NULL == phEvent` +/// + `NULL == ppRetMap` +/// - ::UR_RESULT_ERROR_INVALID_QUEUE +/// - ::UR_RESULT_ERROR_INVALID_EVENT +/// - ::UR_RESULT_ERROR_INVALID_MEM_OBJECT +/// - ::UR_RESULT_ERROR_OUT_OF_HOST_MEMORY +/// - ::UR_RESULT_ERROR_OUT_OF_RESOURCES +ur_result_t UR_APICALL +urEnqueueMemBufferMap( + ur_queue_handle_t hQueue, ///< [in] handle of the queue object + ur_mem_handle_t hBuffer, ///< [in] handle of the buffer object + bool blockingMap, ///< [in] indicates blocking (true), non-blocking (false) + ur_map_flags_t mapFlags, ///< [in] flags for read, write, readwrite mapping + size_t offset, ///< [in] offset in bytes of the buffer region being mapped + size_t size, ///< [in] size in bytes of the buffer region being mapped + uint32_t numEventsInWaitList, ///< [in] size of the event wait list + const ur_event_handle_t* phEventWaitList, ///< [in][optional][range(0, numEventsInWaitList)] pointer to a list of + ///< events that must be complete before this command can be executed. + ///< If nullptr, the numEventsInWaitList must be 0, indicating that this + ///< command does not wait on any event to complete. + ur_event_handle_t* phEvent, ///< [in,out] return an event object that identifies this particular + ///< command instance. + ///< Input can not be a nullptr. + ///< TODO: change to allow nullptr. + void** ppRetMap ///< [in,out] return mapped pointer. TODO: move it before + ///< numEventsInWaitList? + ) +{ + auto pfnMemBufferMap = ur_lib::context->urDdiTable.Enqueue.pfnMemBufferMap; + if( nullptr == pfnMemBufferMap ) + return UR_RESULT_ERROR_UNINITIALIZED; + + return pfnMemBufferMap( hQueue, hBuffer, blockingMap, mapFlags, offset, size, numEventsInWaitList, phEventWaitList, phEvent, ppRetMap ); +} + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Enqueue a command to unmap a previously mapped region of a memory +/// object +/// +/// @remarks +/// _Analogues_ +/// - **clEnqueueUnmapMemObject** +/// +/// @returns +/// - ::UR_RESULT_SUCCESS +/// - ::UR_RESULT_ERROR_UNINITIALIZED +/// - ::UR_RESULT_ERROR_DEVICE_LOST +/// - ::UR_RESULT_ERROR_INVALID_NULL_HANDLE +/// + `NULL == hQueue` +/// + `NULL == hMem` +/// - ::UR_RESULT_ERROR_INVALID_NULL_POINTER +/// + `NULL == pMappedPtr` +/// + `NULL == phEvent` +/// - ::UR_RESULT_ERROR_INVALID_QUEUE +/// - ::UR_RESULT_ERROR_INVALID_EVENT +/// - ::UR_RESULT_ERROR_INVALID_MEM_OBJECT +/// - ::UR_RESULT_ERROR_OUT_OF_HOST_MEMORY +/// - ::UR_RESULT_ERROR_OUT_OF_RESOURCES +ur_result_t UR_APICALL +urEnqueueMemUnmap( + ur_queue_handle_t hQueue, ///< [in] handle of the queue object + ur_mem_handle_t hMem, ///< [in] handle of the memory (buffer or image) object + void* pMappedPtr, ///< [in] mapped host address + uint32_t numEventsInWaitList, ///< [in] size of the event wait list + const ur_event_handle_t* phEventWaitList, ///< [in][optional][range(0, numEventsInWaitList)] pointer to a list of + ///< events that must be complete before this command can be executed. + ///< If nullptr, the numEventsInWaitList must be 0, indicating that this + ///< command does not wait on any event to complete. + ur_event_handle_t* phEvent ///< [in,out] return an event object that identifies this particular + ///< command instance. + ///< Input can not be a nullptr. + ///< TODO: change to allow nullptr. + ) +{ + auto pfnMemUnmap = ur_lib::context->urDdiTable.Enqueue.pfnMemUnmap; + if( nullptr == pfnMemUnmap ) + return UR_RESULT_ERROR_UNINITIALIZED; + + return pfnMemUnmap( hQueue, hMem, pMappedPtr, numEventsInWaitList, phEventWaitList, phEvent ); +} + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Enqueue a command to set USM memory object value +/// +/// @returns +/// - ::UR_RESULT_SUCCESS +/// - ::UR_RESULT_ERROR_UNINITIALIZED +/// - ::UR_RESULT_ERROR_DEVICE_LOST +/// - ::UR_RESULT_ERROR_INVALID_NULL_HANDLE +/// + `NULL == hQueue` +/// - ::UR_RESULT_ERROR_INVALID_NULL_POINTER +/// + `NULL == ptr` +/// + `NULL == phEvent` +/// - ::UR_RESULT_ERROR_INVALID_QUEUE +/// - ::UR_RESULT_ERROR_INVALID_EVENT +/// - ::UR_RESULT_ERROR_INVALID_MEM_OBJECT +/// - ::UR_RESULT_ERROR_OUT_OF_HOST_MEMORY +/// - ::UR_RESULT_ERROR_OUT_OF_RESOURCES +ur_result_t UR_APICALL +urEnqueueUSMMemset( + ur_queue_handle_t hQueue, ///< [in] handle of the queue object + void* ptr, ///< [in] pointer to USM memory object + int8_t byteValue, ///< [in] byte value to fill + size_t count, ///< [in] size in bytes to be set + uint32_t numEventsInWaitList, ///< [in] size of the event wait list + const ur_event_handle_t* phEventWaitList, ///< [in][optional][range(0, numEventsInWaitList)] pointer to a list of + ///< events that must be complete before this command can be executed. + ///< If nullptr, the numEventsInWaitList must be 0, indicating that this + ///< command does not wait on any event to complete. + ur_event_handle_t* phEvent ///< [in,out] return an event object that identifies this particular + ///< command instance. + ///< Input can not be a nullptr. + ///< TODO: change to allow nullptr. + ) +{ + auto pfnUSMMemset = ur_lib::context->urDdiTable.Enqueue.pfnUSMMemset; + if( nullptr == pfnUSMMemset ) + return UR_RESULT_ERROR_UNINITIALIZED; + + return pfnUSMMemset( hQueue, ptr, byteValue, count, numEventsInWaitList, phEventWaitList, phEvent ); +} + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Enqueue a command to copy USM memory +/// +/// @returns +/// - ::UR_RESULT_SUCCESS +/// - ::UR_RESULT_ERROR_UNINITIALIZED +/// - ::UR_RESULT_ERROR_DEVICE_LOST +/// - ::UR_RESULT_ERROR_INVALID_NULL_HANDLE +/// + `NULL == hQueue` +/// - ::UR_RESULT_ERROR_INVALID_NULL_POINTER +/// + `NULL == pDst` +/// + `NULL == pSrc` +/// + `NULL == phEvent` +/// - ::UR_RESULT_ERROR_INVALID_QUEUE +/// - ::UR_RESULT_ERROR_INVALID_EVENT +/// - ::UR_RESULT_ERROR_INVALID_MEM_OBJECT +/// - ::UR_RESULT_ERROR_OUT_OF_HOST_MEMORY +/// - ::UR_RESULT_ERROR_OUT_OF_RESOURCES +ur_result_t UR_APICALL +urEnqueueUSMMemcpy( + ur_queue_handle_t hQueue, ///< [in] handle of the queue object + bool blocking, ///< [in] blocking or non-blocking copy + void* pDst, ///< [in] pointer to the destination USM memory object + const void* pSrc, ///< [in] pointer to the source USM memory object + size_t size, ///< [in] size in bytes to be copied + uint32_t numEventsInWaitList, ///< [in] size of the event wait list + const ur_event_handle_t* phEventWaitList, ///< [in][optional][range(0, numEventsInWaitList)] pointer to a list of + ///< events that must be complete before this command can be executed. + ///< If nullptr, the numEventsInWaitList must be 0, indicating that this + ///< command does not wait on any event to complete. + ur_event_handle_t* phEvent ///< [in,out] return an event object that identifies this particular + ///< command instance. + ///< Input can not be a nullptr. + ///< TODO: change to allow nullptr. + ) +{ + auto pfnUSMMemcpy = ur_lib::context->urDdiTable.Enqueue.pfnUSMMemcpy; + if( nullptr == pfnUSMMemcpy ) + return UR_RESULT_ERROR_UNINITIALIZED; + + return pfnUSMMemcpy( hQueue, blocking, pDst, pSrc, size, numEventsInWaitList, phEventWaitList, phEvent ); +} + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Enqueue a command to prefetch USM memory +/// +/// @returns +/// - ::UR_RESULT_SUCCESS +/// - ::UR_RESULT_ERROR_UNINITIALIZED +/// - ::UR_RESULT_ERROR_DEVICE_LOST +/// - ::UR_RESULT_ERROR_INVALID_NULL_HANDLE +/// + `NULL == hQueue` +/// - ::UR_RESULT_ERROR_INVALID_NULL_POINTER +/// + `NULL == pMem` +/// + `NULL == phEvent` +/// - ::UR_RESULT_ERROR_INVALID_ENUMERATION +/// + `0x1 < flags` +/// - ::UR_RESULT_ERROR_INVALID_QUEUE +/// - ::UR_RESULT_ERROR_INVALID_EVENT +/// - ::UR_RESULT_ERROR_INVALID_MEM_OBJECT +/// - ::UR_RESULT_ERROR_OUT_OF_HOST_MEMORY +/// - ::UR_RESULT_ERROR_OUT_OF_RESOURCES +ur_result_t UR_APICALL +urEnqueueUSMPrefetch( + ur_queue_handle_t hQueue, ///< [in] handle of the queue object + const void* pMem, ///< [in] pointer to the USM memory object + size_t size, ///< [in] size in bytes to be fetched + ur_usm_migration_flags_t flags, ///< [in] USM prefetch flags + uint32_t numEventsInWaitList, ///< [in] size of the event wait list + const ur_event_handle_t* phEventWaitList, ///< [in][optional][range(0, numEventsInWaitList)] pointer to a list of + ///< events that must be complete before this command can be executed. + ///< If nullptr, the numEventsInWaitList must be 0, indicating that this + ///< command does not wait on any event to complete. + ur_event_handle_t* phEvent ///< [in,out] return an event object that identifies this particular + ///< command instance. + ///< Input can not be a nullptr. + ///< TODO: change to allow nullptr. + ) +{ + auto pfnUSMPrefetch = ur_lib::context->urDdiTable.Enqueue.pfnUSMPrefetch; + if( nullptr == pfnUSMPrefetch ) + return UR_RESULT_ERROR_UNINITIALIZED; + + return pfnUSMPrefetch( hQueue, pMem, size, flags, numEventsInWaitList, phEventWaitList, phEvent ); +} + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Enqueue a command to set USM memory advice +/// +/// @returns +/// - ::UR_RESULT_SUCCESS +/// - ::UR_RESULT_ERROR_UNINITIALIZED +/// - ::UR_RESULT_ERROR_DEVICE_LOST +/// - ::UR_RESULT_ERROR_INVALID_NULL_HANDLE +/// + `NULL == hQueue` +/// - ::UR_RESULT_ERROR_INVALID_NULL_POINTER +/// + `NULL == pMem` +/// + `NULL == phEvent` +/// - ::UR_RESULT_ERROR_INVALID_ENUMERATION +/// + `::UR_MEM_ADVICE_DEFAULT < advice` +/// - ::UR_RESULT_ERROR_INVALID_QUEUE +/// - ::UR_RESULT_ERROR_INVALID_EVENT +/// - ::UR_RESULT_ERROR_INVALID_MEM_OBJECT +/// - ::UR_RESULT_ERROR_OUT_OF_HOST_MEMORY +/// - ::UR_RESULT_ERROR_OUT_OF_RESOURCES +ur_result_t UR_APICALL +urEnqueueUSMMemAdvice( + ur_queue_handle_t hQueue, ///< [in] handle of the queue object + const void* pMem, ///< [in] pointer to the USM memory object + size_t size, ///< [in] size in bytes to be adviced + ur_mem_advice_t advice, ///< [in] USM memory advice + ur_event_handle_t* phEvent ///< [in,out] return an event object that identifies this particular + ///< command instance. + ///< Input can not be a nullptr. + ///< TODO: change to allow nullptr. + ) +{ + auto pfnUSMMemAdvice = ur_lib::context->urDdiTable.Enqueue.pfnUSMMemAdvice; + if( nullptr == pfnUSMMemAdvice ) + return UR_RESULT_ERROR_UNINITIALIZED; + + return pfnUSMMemAdvice( hQueue, pMem, size, advice, phEvent ); +} + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Get event object information +/// +/// @remarks +/// _Analogues_ +/// - **clGetEventInfo** +/// +/// @returns +/// - ::UR_RESULT_SUCCESS +/// - ::UR_RESULT_ERROR_UNINITIALIZED +/// - ::UR_RESULT_ERROR_DEVICE_LOST +/// - ::UR_RESULT_ERROR_INVALID_NULL_HANDLE +/// + `NULL == hEvent` +/// - ::UR_RESULT_ERROR_INVALID_ENUMERATION +/// + `::UR_EVENT_INFO_REFERENCE_COUNT < propName` +/// - ::UR_RESULT_ERROR_INVALID_NULL_POINTER +/// + `NULL == pPropValue` +/// + `NULL == pPropValueSizeRet` +/// - ::UR_RESULT_ERROR_INVALID_VALUE +/// - ::UR_RESULT_ERROR_INVALID_EVENT +/// - ::UR_RESULT_ERROR_OUT_OF_RESOURCES +/// - ::UR_RESULT_ERROR_OUT_OF_HOST_MEMORY +ur_result_t UR_APICALL +urEventGetInfo( + ur_event_handle_t hEvent, ///< [in] handle of the event object + ur_event_info_t propName, ///< [in] the name of the event property to query + size_t propValueSize, ///< [in] size in bytes of the event property value + void* pPropValue, ///< [out] value of the event property + size_t* pPropValueSizeRet ///< [out] bytes returned in event property + ) +{ + auto pfnGetInfo = ur_lib::context->urDdiTable.Event.pfnGetInfo; + if( nullptr == pfnGetInfo ) + return UR_RESULT_ERROR_UNINITIALIZED; + + return pfnGetInfo( hEvent, propName, propValueSize, pPropValue, pPropValueSizeRet ); +} + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Get profiling information for the command associated with an event +/// object +/// +/// @remarks +/// _Analogues_ +/// - **clGetEventProfilingInfo** +/// +/// @returns +/// - ::UR_RESULT_SUCCESS +/// - ::UR_RESULT_ERROR_UNINITIALIZED +/// - ::UR_RESULT_ERROR_DEVICE_LOST +/// - ::UR_RESULT_ERROR_INVALID_NULL_HANDLE +/// + `NULL == hEvent` +/// - ::UR_RESULT_ERROR_INVALID_ENUMERATION +/// + `::UR_PROFILING_INFO_COMMAND_END < propName` +/// - ::UR_RESULT_ERROR_INVALID_VALUE +/// - ::UR_RESULT_ERROR_INVALID_EVENT +/// - ::UR_RESULT_ERROR_OUT_OF_RESOURCES +/// - ::UR_RESULT_ERROR_OUT_OF_HOST_MEMORY +ur_result_t UR_APICALL +urEventGetProfilingInfo( + ur_event_handle_t hEvent, ///< [in] handle of the event object + ur_profiling_info_t propName, ///< [in] the name of the profiling property to query + size_t propValueSize, ///< [in] size in bytes of the profiling property value + void* pPropValue, ///< [out][optional] value of the profiling property + size_t* pPropValueSizeRet ///< [out][optional] pointer to the actual size in bytes returned in + ///< propValue + ) +{ + auto pfnGetProfilingInfo = ur_lib::context->urDdiTable.Event.pfnGetProfilingInfo; + if( nullptr == pfnGetProfilingInfo ) + return UR_RESULT_ERROR_UNINITIALIZED; + + return pfnGetProfilingInfo( hEvent, propName, propValueSize, pPropValue, pPropValueSizeRet ); +} + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Wait for a list of events to finish. +/// +/// @remarks +/// _Analogues_ +/// - **clWaitForEvent** +/// +/// @returns +/// - ::UR_RESULT_SUCCESS +/// - ::UR_RESULT_ERROR_UNINITIALIZED +/// - ::UR_RESULT_ERROR_DEVICE_LOST +/// - ::UR_RESULT_ERROR_INVALID_NULL_POINTER +/// + `NULL == phEventWaitList` +/// - ::UR_RESULT_ERROR_INVALID_VALUE +/// - ::UR_RESULT_ERROR_INVALID_EVENT +/// - ::UR_RESULT_ERROR_INVALID_CONTEXT +/// - ::UR_RESULT_ERROR_OUT_OF_HOST_MEMORY +/// - ::UR_RESULT_ERROR_OUT_OF_RESOURCES +ur_result_t UR_APICALL +urEventWait( + uint32_t numEvents, ///< [in] number of events in the event list + const ur_event_handle_t* phEventWaitList ///< [in][range(0, numEvents)] pointer to a list of events to wait for + ///< completion + ) +{ + auto pfnWait = ur_lib::context->urDdiTable.Event.pfnWait; + if( nullptr == pfnWait ) + return UR_RESULT_ERROR_UNINITIALIZED; + + return pfnWait( numEvents, phEventWaitList ); +} + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Get a reference to an event handle. Increment the event object's +/// reference count. +/// +/// @remarks +/// _Analogues_ +/// - **clRetainEvent** +/// +/// @returns +/// - ::UR_RESULT_SUCCESS +/// - ::UR_RESULT_ERROR_UNINITIALIZED +/// - ::UR_RESULT_ERROR_DEVICE_LOST +/// - ::UR_RESULT_ERROR_INVALID_NULL_HANDLE +/// + `NULL == hEvent` +/// - ::UR_RESULT_ERROR_INVALID_EVENT +/// - ::UR_RESULT_ERROR_OUT_OF_RESOURCES +/// - ::UR_RESULT_ERROR_OUT_OF_HOST_MEMORY +ur_result_t UR_APICALL +urEventRetain( + ur_event_handle_t hEvent ///< [in] handle of the event object + ) +{ + auto pfnRetain = ur_lib::context->urDdiTable.Event.pfnRetain; + if( nullptr == pfnRetain ) + return UR_RESULT_ERROR_UNINITIALIZED; + + return pfnRetain( hEvent ); +} + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Decrement the event object's reference count and delete the event +/// object if the reference count becomes zero. +/// +/// @remarks +/// _Analogues_ +/// - **clReleaseEvent** +/// +/// @returns +/// - ::UR_RESULT_SUCCESS +/// - ::UR_RESULT_ERROR_UNINITIALIZED +/// - ::UR_RESULT_ERROR_DEVICE_LOST +/// - ::UR_RESULT_ERROR_INVALID_NULL_HANDLE +/// + `NULL == hEvent` +/// - ::UR_RESULT_ERROR_INVALID_EVENT +/// - ::UR_RESULT_ERROR_OUT_OF_RESOURCES +/// - ::UR_RESULT_ERROR_OUT_OF_HOST_MEMORY +ur_result_t UR_APICALL +urEventRelease( + ur_event_handle_t hEvent ///< [in] handle of the event object + ) +{ + auto pfnRelease = ur_lib::context->urDdiTable.Event.pfnRelease; + if( nullptr == pfnRelease ) + return UR_RESULT_ERROR_UNINITIALIZED; + + return pfnRelease( hEvent ); +} + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Return platform native event handle. +/// +/// @details +/// - Retrieved native handle can be used for direct interaction with the +/// native platform driver. +/// - Use interoperability platform extensions to convert native handle to +/// native type. +/// - The application may call this function from simultaneous threads for +/// the same context. +/// - The implementation of this function should be thread-safe. +/// +/// @returns +/// - ::UR_RESULT_SUCCESS +/// - ::UR_RESULT_ERROR_UNINITIALIZED +/// - ::UR_RESULT_ERROR_DEVICE_LOST +/// - ::UR_RESULT_ERROR_INVALID_NULL_HANDLE +/// + `NULL == hEvent` +/// - ::UR_RESULT_ERROR_INVALID_NULL_POINTER +/// + `NULL == phNativeEvent` +ur_result_t UR_APICALL +urEventGetNativeHandle( + ur_event_handle_t hEvent, ///< [in] handle of the event. + ur_native_handle_t* phNativeEvent ///< [out] a pointer to the native handle of the event. + ) +{ + auto pfnGetNativeHandle = ur_lib::context->urDdiTable.Event.pfnGetNativeHandle; + if( nullptr == pfnGetNativeHandle ) + return UR_RESULT_ERROR_UNINITIALIZED; + + return pfnGetNativeHandle( hEvent, phNativeEvent ); +} + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Create runtime event object from native event handle. +/// +/// @details +/// - Creates runtime event handle from native driver event handle. +/// - The application may call this function from simultaneous threads for +/// the same context. +/// - The implementation of this function should be thread-safe. +/// +/// @returns +/// - ::UR_RESULT_SUCCESS +/// - ::UR_RESULT_ERROR_UNINITIALIZED +/// - ::UR_RESULT_ERROR_DEVICE_LOST +/// - ::UR_RESULT_ERROR_INVALID_NULL_HANDLE +/// + `NULL == hNativeEvent` +/// + `NULL == hContext` +/// - ::UR_RESULT_ERROR_INVALID_NULL_POINTER +/// + `NULL == phEvent` +ur_result_t UR_APICALL +urEventCreateWithNativeHandle( + ur_native_handle_t hNativeEvent, ///< [in] the native handle of the event. + ur_context_handle_t hContext, ///< [in] handle of the context object + ur_event_handle_t* phEvent ///< [out] pointer to the handle of the event object created. + ) +{ + auto pfnCreateWithNativeHandle = ur_lib::context->urDdiTable.Event.pfnCreateWithNativeHandle; + if( nullptr == pfnCreateWithNativeHandle ) + return UR_RESULT_ERROR_UNINITIALIZED; + + return pfnCreateWithNativeHandle( hNativeEvent, hContext, phEvent ); +} + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Register a user callback function for a specific command execution +/// status. +/// +/// @details +/// - The registered callback function will be called when the execution +/// status of command associated with event changes to an execution status +/// equal to or past the status specified by command_exec_status. +/// - The application may call this function from simultaneous threads for +/// the same context. +/// - The implementation of this function should be thread-safe. +/// +/// @returns +/// - ::UR_RESULT_SUCCESS +/// - ::UR_RESULT_ERROR_UNINITIALIZED +/// - ::UR_RESULT_ERROR_DEVICE_LOST +/// - ::UR_RESULT_ERROR_INVALID_NULL_HANDLE +/// + `NULL == hEvent` +/// - ::UR_RESULT_ERROR_INVALID_ENUMERATION +/// + `::UR_EXECUTION_INFO_EXECUTION_INFO_QUEUED < execStatus` +ur_result_t UR_APICALL +urEventSetCallback( + ur_event_handle_t hEvent, ///< [in] handle of the event object + ur_execution_info_t execStatus, ///< [in] execution status of the event + ur_event_callback_t pfnNotify, ///< [in] execution status of the event + void* pUserData ///< [in][out][optional] pointer to data to be passed to callback. + ) +{ + auto pfnSetCallback = ur_lib::context->urDdiTable.Event.pfnSetCallback; + if( nullptr == pfnSetCallback ) + return UR_RESULT_ERROR_UNINITIALIZED; + + return pfnSetCallback( hEvent, execStatus, pfnNotify, pUserData ); +} + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Create an image object +/// +/// @remarks +/// _Analogues_ +/// - **clCreateImage** +/// +/// @returns +/// - ::UR_RESULT_SUCCESS +/// - ::UR_RESULT_ERROR_UNINITIALIZED +/// - ::UR_RESULT_ERROR_DEVICE_LOST +/// - ::UR_RESULT_ERROR_INVALID_NULL_HANDLE +/// + `NULL == hContext` +/// - ::UR_RESULT_ERROR_INVALID_ENUMERATION +/// + `0x3f < flags` +/// + `::UR_MEM_TYPE_IMAGE1D_BUFFER < pImageDesc->type` +/// - ::UR_RESULT_ERROR_INVALID_NULL_POINTER +/// + `NULL == pImageFormat` +/// + `NULL == pImageDesc` +/// + `NULL == pHost` +/// + `NULL == phMem` +/// - ::UR_RESULT_ERROR_INVALID_CONTEXT +/// - ::UR_RESULT_ERROR_INVALID_VALUE +/// - ::UR_RESULT_ERROR_INVALID_IMAGE_FORMAT_DESCRIPTOR +/// - ::UR_RESULT_ERROR_INVALID_IMAGE_SIZE +/// - ::UR_RESULT_ERROR_INVALID_OPERATION +/// - ::UR_RESULT_ERROR_INVALID_HOST_PTR +/// - ::UR_RESULT_ERROR_OUT_OF_HOST_MEMORY +/// - ::UR_RESULT_ERROR_OUT_OF_RESOURCES +ur_result_t UR_APICALL +urMemImageCreate( + ur_context_handle_t hContext, ///< [in] handle of the context object + ur_mem_flags_t flags, ///< [in] allocation and usage information flags + const ur_image_format_t* pImageFormat, ///< [in] pointer to image format specification + const ur_image_desc_t* pImageDesc, ///< [in] pointer to image description + void* pHost, ///< [in] pointer to the buffer data + ur_mem_handle_t* phMem ///< [out] pointer to handle of image object created + ) +{ + auto pfnImageCreate = ur_lib::context->urDdiTable.Mem.pfnImageCreate; + if( nullptr == pfnImageCreate ) + return UR_RESULT_ERROR_UNINITIALIZED; + + return pfnImageCreate( hContext, flags, pImageFormat, pImageDesc, pHost, phMem ); +} + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Create a memory buffer +/// +/// @remarks +/// _Analogues_ +/// - **clCreateBuffer** +/// +/// @returns +/// - ::UR_RESULT_SUCCESS +/// - ::UR_RESULT_ERROR_UNINITIALIZED +/// - ::UR_RESULT_ERROR_DEVICE_LOST +/// - ::UR_RESULT_ERROR_INVALID_NULL_HANDLE +/// + `NULL == hContext` +/// - ::UR_RESULT_ERROR_INVALID_ENUMERATION +/// + `0x3f < flags` +/// - ::UR_RESULT_ERROR_INVALID_NULL_POINTER +/// + `NULL == pHost` +/// + `NULL == phBuffer` +/// - ::UR_RESULT_ERROR_INVALID_CONTEXT +/// - ::UR_RESULT_ERROR_INVALID_VALUE +/// - ::UR_RESULT_ERROR_INVALID_BUFFER_SIZE +/// - ::UR_RESULT_ERROR_INVALID_HOST_PTR +/// - ::UR_RESULT_ERROR_OUT_OF_HOST_MEMORY +/// - ::UR_RESULT_ERROR_OUT_OF_RESOURCES +ur_result_t UR_APICALL +urMemBufferCreate( + ur_context_handle_t hContext, ///< [in] handle of the context object + ur_mem_flags_t flags, ///< [in] allocation and usage information flags + size_t size, ///< [in] size in bytes of the memory object to be allocated + void* pHost, ///< [in] pointer to the buffer data + ur_mem_handle_t* phBuffer ///< [out] pointer to handle of the memory buffer created + ) +{ + auto pfnBufferCreate = ur_lib::context->urDdiTable.Mem.pfnBufferCreate; + if( nullptr == pfnBufferCreate ) + return UR_RESULT_ERROR_UNINITIALIZED; + + return pfnBufferCreate( hContext, flags, size, pHost, phBuffer ); +} + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Get a reference the memory object. Increment the memory object's +/// reference count +/// +/// @details +/// - Useful in library function to retain access to the memory object after +/// the caller released the object +/// +/// @remarks +/// _Analogues_ +/// - **clRetainMemoryObject** +/// +/// @returns +/// - ::UR_RESULT_SUCCESS +/// - ::UR_RESULT_ERROR_UNINITIALIZED +/// - ::UR_RESULT_ERROR_DEVICE_LOST +/// - ::UR_RESULT_ERROR_INVALID_NULL_HANDLE +/// + `NULL == hMem` +/// - ::UR_RESULT_ERROR_INVALID_MEM_OBJECT +/// - ::UR_RESULT_ERROR_OUT_OF_HOST_MEMORY +/// - ::UR_RESULT_ERROR_OUT_OF_RESOURCES +ur_result_t UR_APICALL +urMemRetain( + ur_mem_handle_t hMem ///< [in] handle of the memory object to get access + ) +{ + auto pfnRetain = ur_lib::context->urDdiTable.Mem.pfnRetain; + if( nullptr == pfnRetain ) + return UR_RESULT_ERROR_UNINITIALIZED; + + return pfnRetain( hMem ); +} + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Decrement the memory object's reference count and delete the object if +/// the reference count becomes zero. +/// +/// @remarks +/// _Analogues_ +/// - **clReleaseMemoryObject** +/// +/// @returns +/// - ::UR_RESULT_SUCCESS +/// - ::UR_RESULT_ERROR_UNINITIALIZED +/// - ::UR_RESULT_ERROR_DEVICE_LOST +/// - ::UR_RESULT_ERROR_INVALID_NULL_HANDLE +/// + `NULL == hMem` +/// - ::UR_RESULT_ERROR_INVALID_MEM_OBJECT +/// - ::UR_RESULT_ERROR_OUT_OF_HOST_MEMORY +ur_result_t UR_APICALL +urMemRelease( + ur_mem_handle_t hMem ///< [in] handle of the memory object to release + ) +{ + auto pfnRelease = ur_lib::context->urDdiTable.Mem.pfnRelease; + if( nullptr == pfnRelease ) + return UR_RESULT_ERROR_UNINITIALIZED; + + return pfnRelease( hMem ); +} + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Create a sub buffer representing a region in an existing buffer +/// +/// @remarks +/// _Analogues_ +/// - **clCreateSubBuffer** +/// +/// @returns +/// - ::UR_RESULT_SUCCESS +/// - ::UR_RESULT_ERROR_UNINITIALIZED +/// - ::UR_RESULT_ERROR_DEVICE_LOST +/// - ::UR_RESULT_ERROR_INVALID_NULL_HANDLE +/// + `NULL == hBuffer` +/// - ::UR_RESULT_ERROR_INVALID_ENUMERATION +/// + `0x3f < flags` +/// + `::UR_BUFFER_CREATE_TYPE_REGION < bufferCreateType` +/// - ::UR_RESULT_ERROR_INVALID_NULL_POINTER +/// + `NULL == pBufferCreateInfo` +/// + `NULL == phMem` +/// - ::UR_RESULT_ERROR_INVALID_MEM_OBJECT +/// - ::UR_RESULT_ERROR_OBJECT_ALLOCATION_FAILURE +/// - ::UR_RESULT_ERROR_INVALID_VALUE +/// - ::UR_RESULT_ERROR_INVALID_BUFFER_SIZE +/// - ::UR_RESULT_ERROR_INVALID_HOST_PTR +/// - ::UR_RESULT_ERROR_OUT_OF_HOST_MEMORY +/// - ::UR_RESULT_ERROR_OUT_OF_RESOURCES +ur_result_t UR_APICALL +urMemBufferPartition( + ur_mem_handle_t hBuffer, ///< [in] handle of the buffer object to allocate from + ur_mem_flags_t flags, ///< [in] allocation and usage information flags + ur_buffer_create_type_t bufferCreateType, ///< [in] buffer creation type + ur_buffer_region_t* pBufferCreateInfo, ///< [in] pointer to buffer create region information + ur_mem_handle_t* phMem ///< [out] pointer to the handle of sub buffer created + ) +{ + auto pfnBufferPartition = ur_lib::context->urDdiTable.Mem.pfnBufferPartition; + if( nullptr == pfnBufferPartition ) + return UR_RESULT_ERROR_UNINITIALIZED; + + return pfnBufferPartition( hBuffer, flags, bufferCreateType, pBufferCreateInfo, phMem ); +} + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Return platform native mem handle. +/// +/// @details +/// - Retrieved native handle can be used for direct interaction with the +/// native platform driver. +/// - Use interoperability platform extensions to convert native handle to +/// native type. +/// - The application may call this function from simultaneous threads for +/// the same context. +/// - The implementation of this function should be thread-safe. +/// +/// @returns +/// - ::UR_RESULT_SUCCESS +/// - ::UR_RESULT_ERROR_UNINITIALIZED +/// - ::UR_RESULT_ERROR_DEVICE_LOST +/// - ::UR_RESULT_ERROR_INVALID_NULL_HANDLE +/// + `NULL == hMem` +/// - ::UR_RESULT_ERROR_INVALID_NULL_POINTER +/// + `NULL == phNativeMem` +ur_result_t UR_APICALL +urMemGetNativeHandle( + ur_mem_handle_t hMem, ///< [in] handle of the mem. + ur_native_handle_t* phNativeMem ///< [out] a pointer to the native handle of the mem. + ) +{ + auto pfnGetNativeHandle = ur_lib::context->urDdiTable.Mem.pfnGetNativeHandle; + if( nullptr == pfnGetNativeHandle ) + return UR_RESULT_ERROR_UNINITIALIZED; + + return pfnGetNativeHandle( hMem, phNativeMem ); +} + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Create runtime mem object from native mem handle. +/// +/// @details +/// - Creates runtime mem handle from native driver mem handle. +/// - The application may call this function from simultaneous threads for +/// the same context. +/// - The implementation of this function should be thread-safe. +/// +/// @returns +/// - ::UR_RESULT_SUCCESS +/// - ::UR_RESULT_ERROR_UNINITIALIZED +/// - ::UR_RESULT_ERROR_DEVICE_LOST +/// - ::UR_RESULT_ERROR_INVALID_NULL_HANDLE +/// + `NULL == hNativeMem` +/// + `NULL == hContext` +/// - ::UR_RESULT_ERROR_INVALID_NULL_POINTER +/// + `NULL == phMem` +ur_result_t UR_APICALL +urMemCreateWithNativeHandle( + ur_native_handle_t hNativeMem, ///< [in] the native handle of the mem. + ur_context_handle_t hContext, ///< [in] handle of the context object + ur_mem_handle_t* phMem ///< [out] pointer to the handle of the mem object created. + ) +{ + auto pfnCreateWithNativeHandle = ur_lib::context->urDdiTable.Mem.pfnCreateWithNativeHandle; + if( nullptr == pfnCreateWithNativeHandle ) + return UR_RESULT_ERROR_UNINITIALIZED; + + return pfnCreateWithNativeHandle( hNativeMem, hContext, phMem ); +} + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Retrieve information about a memory object. +/// +/// @details +/// - Query information that is common to all memory objects. +/// +/// @remarks +/// _Analogues_ +/// - **clGetMemObjectInfo** +/// +/// @returns +/// - ::UR_RESULT_SUCCESS +/// - ::UR_RESULT_ERROR_UNINITIALIZED +/// - ::UR_RESULT_ERROR_DEVICE_LOST +/// - ::UR_RESULT_ERROR_INVALID_NULL_HANDLE +/// + `NULL == hMemory` +/// - ::UR_RESULT_ERROR_INVALID_ENUMERATION +/// + `::UR_MEM_INFO_CONTEXT < MemInfoType` +ur_result_t UR_APICALL +urMemGetInfo( + ur_mem_handle_t hMemory, ///< [in] handle to the memory object being queried. + ur_mem_info_t MemInfoType, ///< [in] type of the info to retrieve. + size_t propSize, ///< [in] the number of bytes of memory pointed to by pMemInfo. + void* pMemInfo, ///< [out][optional] array of bytes holding the info. + ///< If propSize is less than the real number of bytes needed to return + ///< the info then the ::UR_RESULT_ERROR_INVALID_SIZE error is returned and + ///< pMemInfo is not used. + size_t* pPropSizeRet ///< [out][optional] pointer to the actual size in bytes of data queried by pMemInfo. + ) +{ + auto pfnGetInfo = ur_lib::context->urDdiTable.Mem.pfnGetInfo; + if( nullptr == pfnGetInfo ) + return UR_RESULT_ERROR_UNINITIALIZED; + + return pfnGetInfo( hMemory, MemInfoType, propSize, pMemInfo, pPropSizeRet ); +} + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Retrieve information about an image object. +/// +/// @details +/// - Query information specific to an image object. +/// +/// @remarks +/// _Analogues_ +/// - **clGetImageInfo** +/// +/// @returns +/// - ::UR_RESULT_SUCCESS +/// - ::UR_RESULT_ERROR_UNINITIALIZED +/// - ::UR_RESULT_ERROR_DEVICE_LOST +/// - ::UR_RESULT_ERROR_INVALID_NULL_HANDLE +/// + `NULL == hMemory` +/// - ::UR_RESULT_ERROR_INVALID_ENUMERATION +/// + `::UR_IMAGE_INFO_DEPTH < ImgInfoType` +ur_result_t UR_APICALL +urMemImageGetInfo( + ur_mem_handle_t hMemory, ///< [in] handle to the image object being queried. + ur_image_info_t ImgInfoType, ///< [in] type of image info to retrieve. + size_t propSize, ///< [in] the number of bytes of memory pointer to by pImgInfo. + void* pImgInfo, ///< [out][optional] array of bytes holding the info. + ///< If propSize is less than the real number of bytes needed to return + ///< the info then the ::UR_RESULT_ERROR_INVALID_SIZE error is returned and + ///< pImgInfo is not used. + size_t* pPropSizeRet ///< [out][optional] pointer to the actual size in bytes of data queried by pImgInfo. + ) +{ + auto pfnImageGetInfo = ur_lib::context->urDdiTable.Mem.pfnImageGetInfo; + if( nullptr == pfnImageGetInfo ) + return UR_RESULT_ERROR_UNINITIALIZED; + + return pfnImageGetInfo( hMemory, ImgInfoType, propSize, pImgInfo, pPropSizeRet ); +} + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Tear down L0 runtime instance and release all its resources +/// +/// @returns +/// - ::UR_RESULT_SUCCESS +/// - ::UR_RESULT_ERROR_UNINITIALIZED +/// - ::UR_RESULT_ERROR_DEVICE_LOST +/// - ::UR_RESULT_ERROR_INVALID_NULL_POINTER +/// + `NULL == pParams` +/// - ::UR_RESULT_ERROR_OUT_OF_HOST_MEMORY +ur_result_t UR_APICALL +urTearDown( + void* pParams ///< [in] pointer to tear down parameters + ) +{ + auto pfnTearDown = ur_lib::context->urDdiTable.Global.pfnTearDown; + if( nullptr == pfnTearDown ) + return UR_RESULT_ERROR_UNINITIALIZED; + + return pfnTearDown( pParams ); +} + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Query information about a command queue +/// +/// @remarks +/// _Analogues_ +/// - **clGetCommandQueueInfo** +/// +/// @returns +/// - ::UR_RESULT_SUCCESS +/// - ::UR_RESULT_ERROR_UNINITIALIZED +/// - ::UR_RESULT_ERROR_DEVICE_LOST +/// - ::UR_RESULT_ERROR_INVALID_NULL_HANDLE +/// + `NULL == hQueue` +/// - ::UR_RESULT_ERROR_INVALID_ENUMERATION +/// + `::UR_QUEUE_INFO_SIZE < propName` +/// - ::UR_RESULT_ERROR_INVALID_NULL_POINTER +/// + `NULL == pPropValue` +/// + `NULL == pPropSizeRet` +/// - ::UR_RESULT_ERROR_INVALID_QUEUE +/// - ::UR_RESULT_ERROR_INVALID_VALUE +/// - ::UR_RESULT_ERROR_OUT_OF_HOST_MEMORY +/// - ::UR_RESULT_ERROR_OUT_OF_RESOURCES +ur_result_t UR_APICALL +urQueueGetInfo( + ur_queue_handle_t hQueue, ///< [in] handle of the queue object + ur_queue_info_t propName, ///< [in] name of the queue property to query + size_t propValueSize, ///< [in] size in bytes of the queue property value provided + void* pPropValue, ///< [out] value of the queue property + size_t* pPropSizeRet ///< [out] size in bytes returned in queue property value + ) +{ + auto pfnGetInfo = ur_lib::context->urDdiTable.Queue.pfnGetInfo; + if( nullptr == pfnGetInfo ) + return UR_RESULT_ERROR_UNINITIALIZED; + + return pfnGetInfo( hQueue, propName, propValueSize, pPropValue, pPropSizeRet ); +} + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Create a command queue for a device in a context +/// +/// @remarks +/// _Analogues_ +/// - **clCreateCommandQueueWithProperties** +/// +/// @returns +/// - ::UR_RESULT_SUCCESS +/// - ::UR_RESULT_ERROR_UNINITIALIZED +/// - ::UR_RESULT_ERROR_DEVICE_LOST +/// - ::UR_RESULT_ERROR_INVALID_NULL_HANDLE +/// + `NULL == hContext` +/// + `NULL == hDevice` +/// - ::UR_RESULT_ERROR_INVALID_ENUMERATION +/// + `0xf < props` +/// - ::UR_RESULT_ERROR_INVALID_NULL_POINTER +/// + `NULL == phQueue` +/// - ::UR_RESULT_ERROR_INVALID_CONTEXT +/// - ::UR_RESULT_ERROR_INVALID_DEVICE +/// - ::UR_RESULT_ERROR_INVALID_VALUE +/// - ::UR_RESULT_ERROR_INVALID_QUEUE_PROPERTIES +/// - ::UR_RESULT_ERROR_OUT_OF_HOST_MEMORY +/// - ::UR_RESULT_ERROR_OUT_OF_RESOURCES +ur_result_t UR_APICALL +urQueueCreate( + ur_context_handle_t hContext, ///< [in] handle of the context object + ur_device_handle_t hDevice, ///< [in] handle of the device object + ur_queue_flags_t props, ///< [in] initialization properties. + ///< must be 0 (default) or a combination of ::ur_queue_flags_t. + ur_queue_handle_t* phQueue ///< [out] pointer to handle of queue object created + ) +{ + auto pfnCreate = ur_lib::context->urDdiTable.Queue.pfnCreate; + if( nullptr == pfnCreate ) + return UR_RESULT_ERROR_UNINITIALIZED; + + return pfnCreate( hContext, hDevice, props, phQueue ); +} + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Get a reference to the command queue handle. Increment the command +/// queue's reference count +/// +/// @details +/// - Useful in library function to retain access to the command queue after +/// the caller released the queue. +/// +/// @remarks +/// _Analogues_ +/// - **clRetainCommandQueue** +/// +/// @returns +/// - ::UR_RESULT_SUCCESS +/// - ::UR_RESULT_ERROR_UNINITIALIZED +/// - ::UR_RESULT_ERROR_DEVICE_LOST +/// - ::UR_RESULT_ERROR_INVALID_NULL_HANDLE +/// + `NULL == hQueue` +/// - ::UR_RESULT_ERROR_INVALID_QUEUE +/// - ::UR_RESULT_ERROR_OUT_OF_HOST_MEMORY +/// - ::UR_RESULT_ERROR_OUT_OF_RESOURCES +ur_result_t UR_APICALL +urQueueRetain( + ur_queue_handle_t hQueue ///< [in] handle of the queue object to get access + ) +{ + auto pfnRetain = ur_lib::context->urDdiTable.Queue.pfnRetain; + if( nullptr == pfnRetain ) + return UR_RESULT_ERROR_UNINITIALIZED; + + return pfnRetain( hQueue ); +} + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Decrement the command queue's reference count and delete the command +/// queue if the reference count becomes zero. +/// +/// @details +/// - After the command queue reference count becomes zero and all queued +/// commands in the queue have finished, the queue is deleted. +/// - It also performs an implicit flush to issue all previously queued +/// commands in the queue. +/// +/// @remarks +/// _Analogues_ +/// - **clReleaseCommandQueue** +/// +/// @returns +/// - ::UR_RESULT_SUCCESS +/// - ::UR_RESULT_ERROR_UNINITIALIZED +/// - ::UR_RESULT_ERROR_DEVICE_LOST +/// - ::UR_RESULT_ERROR_INVALID_NULL_HANDLE +/// + `NULL == hQueue` +/// - ::UR_RESULT_ERROR_INVALID_QUEUE +/// - ::UR_RESULT_ERROR_OUT_OF_HOST_MEMORY +/// - ::UR_RESULT_ERROR_OUT_OF_RESOURCES +ur_result_t UR_APICALL +urQueueRelease( + ur_queue_handle_t hQueue ///< [in] handle of the queue object to release + ) +{ + auto pfnRelease = ur_lib::context->urDdiTable.Queue.pfnRelease; + if( nullptr == pfnRelease ) + return UR_RESULT_ERROR_UNINITIALIZED; + + return pfnRelease( hQueue ); +} + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Return queue native queue handle. +/// +/// @details +/// - Retrieved native handle can be used for direct interaction with the +/// native platform driver. +/// - Use interoperability queue extensions to convert native handle to +/// native type. +/// - The application may call this function from simultaneous threads for +/// the same context. +/// - The implementation of this function should be thread-safe. +/// +/// @returns +/// - ::UR_RESULT_SUCCESS +/// - ::UR_RESULT_ERROR_UNINITIALIZED +/// - ::UR_RESULT_ERROR_DEVICE_LOST +/// - ::UR_RESULT_ERROR_INVALID_NULL_HANDLE +/// + `NULL == hQueue` +/// - ::UR_RESULT_ERROR_INVALID_NULL_POINTER +/// + `NULL == phNativeQueue` +ur_result_t UR_APICALL +urQueueGetNativeHandle( + ur_queue_handle_t hQueue, ///< [in] handle of the queue. + ur_native_handle_t* phNativeQueue ///< [out] a pointer to the native handle of the queue. + ) +{ + auto pfnGetNativeHandle = ur_lib::context->urDdiTable.Queue.pfnGetNativeHandle; + if( nullptr == pfnGetNativeHandle ) + return UR_RESULT_ERROR_UNINITIALIZED; + + return pfnGetNativeHandle( hQueue, phNativeQueue ); +} + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Create runtime queue object from native queue handle. +/// +/// @details +/// - Creates runtime queue handle from native driver queue handle. +/// - The application may call this function from simultaneous threads for +/// the same context. +/// - The implementation of this function should be thread-safe. +/// +/// @returns +/// - ::UR_RESULT_SUCCESS +/// - ::UR_RESULT_ERROR_UNINITIALIZED +/// - ::UR_RESULT_ERROR_DEVICE_LOST +/// - ::UR_RESULT_ERROR_INVALID_NULL_HANDLE +/// + `NULL == hNativeQueue` +/// + `NULL == hContext` +/// - ::UR_RESULT_ERROR_INVALID_NULL_POINTER +/// + `NULL == phQueue` +ur_result_t UR_APICALL +urQueueCreateWithNativeHandle( + ur_native_handle_t hNativeQueue, ///< [in] the native handle of the queue. + ur_context_handle_t hContext, ///< [in] handle of the context object + ur_queue_handle_t* phQueue ///< [out] pointer to the handle of the queue object created. + ) +{ + auto pfnCreateWithNativeHandle = ur_lib::context->urDdiTable.Queue.pfnCreateWithNativeHandle; + if( nullptr == pfnCreateWithNativeHandle ) + return UR_RESULT_ERROR_UNINITIALIZED; + + return pfnCreateWithNativeHandle( hNativeQueue, hContext, phQueue ); +} + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Blocks until all previously issued commands to the command queue are +/// finished. +/// +/// @details +/// - Blocks until all previously issued commands to the command queue are +/// issued and completed. +/// - ::urQueueFinish does not return until all enqueued commands have been +/// processed and finished. +/// - ::urQueueFinish acts as a synchronization point. +/// +/// @remarks +/// _Analogues_ +/// - **clFinish** +/// +/// @returns +/// - ::UR_RESULT_SUCCESS +/// - ::UR_RESULT_ERROR_UNINITIALIZED +/// - ::UR_RESULT_ERROR_DEVICE_LOST +/// - ::UR_RESULT_ERROR_INVALID_NULL_HANDLE +/// + `NULL == hQueue` +/// - ::UR_RESULT_ERROR_INVALID_QUEUE +/// - ::UR_RESULT_ERROR_OUT_OF_HOST_MEMORY +ur_result_t UR_APICALL +urQueueFinish( + ur_queue_handle_t hQueue ///< [in] handle of the queue to be finished. + ) +{ + auto pfnFinish = ur_lib::context->urDdiTable.Queue.pfnFinish; + if( nullptr == pfnFinish ) + return UR_RESULT_ERROR_UNINITIALIZED; + + return pfnFinish( hQueue ); +} + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Issues all previously enqueued commands in a command queue to the +/// device. +/// +/// @details +/// - Guarantees that all enqueued commands will be issued to the +/// appropriate device. +/// - There is no guarantee that they will be completed after ::urQueueFlush +/// returns. +/// +/// @remarks +/// _Analogues_ +/// - **clFlush** +/// +/// @returns +/// - ::UR_RESULT_SUCCESS +/// - ::UR_RESULT_ERROR_UNINITIALIZED +/// - ::UR_RESULT_ERROR_DEVICE_LOST +/// - ::UR_RESULT_ERROR_INVALID_NULL_HANDLE +/// + `NULL == hQueue` +/// - ::UR_RESULT_ERROR_INVALID_QUEUE +/// - ::UR_RESULT_ERROR_OUT_OF_HOST_MEMORY +ur_result_t UR_APICALL +urQueueFlush( + ur_queue_handle_t hQueue ///< [in] handle of the queue to be flushed. + ) +{ + auto pfnFlush = ur_lib::context->urDdiTable.Queue.pfnFlush; + if( nullptr == pfnFlush ) + return UR_RESULT_ERROR_UNINITIALIZED; + + return pfnFlush( hQueue ); +} + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Create a sampler object in a context +/// +/// @details +/// - The props parameter specifies a list of sampler property names and +/// their corresponding values. +/// - The list is terminated with 0. If the list is NULL, default values +/// will be used. +/// +/// @remarks +/// _Analogues_ +/// - **clCreateSamplerWithProperties** +/// +/// @returns +/// - ::UR_RESULT_SUCCESS +/// - ::UR_RESULT_ERROR_UNINITIALIZED +/// - ::UR_RESULT_ERROR_DEVICE_LOST +/// - ::UR_RESULT_ERROR_INVALID_NULL_HANDLE +/// + `NULL == hContext` +/// - ::UR_RESULT_ERROR_INVALID_NULL_POINTER +/// + `NULL == pProps` +/// + `NULL == phSampler` +/// - ::UR_RESULT_ERROR_INVALID_CONTEXT +/// - ::UR_RESULT_ERROR_INVALID_VALUE +/// - ::UR_RESULT_ERROR_INVALID_OPERATION +/// - ::UR_RESULT_ERROR_OUT_OF_HOST_MEMORY +/// - ::UR_RESULT_ERROR_OUT_OF_RESOURCES +ur_result_t UR_APICALL +urSamplerCreate( + ur_context_handle_t hContext, ///< [in] handle of the context object + const ur_sampler_property_value_t* pProps, ///< [in] specifies a list of sampler property names and their + ///< corresponding values. + ur_sampler_handle_t* phSampler ///< [out] pointer to handle of sampler object created + ) +{ + auto pfnCreate = ur_lib::context->urDdiTable.Sampler.pfnCreate; + if( nullptr == pfnCreate ) + return UR_RESULT_ERROR_UNINITIALIZED; + + return pfnCreate( hContext, pProps, phSampler ); +} + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Get a reference to the sampler object handle. Increment its reference +/// count +/// +/// @remarks +/// _Analogues_ +/// - **clRetainSampler** +/// +/// @returns +/// - ::UR_RESULT_SUCCESS +/// - ::UR_RESULT_ERROR_UNINITIALIZED +/// - ::UR_RESULT_ERROR_DEVICE_LOST +/// - ::UR_RESULT_ERROR_INVALID_NULL_HANDLE +/// + `NULL == hSampler` +/// - ::UR_RESULT_ERROR_INVALID_SAMPLER +/// - ::UR_RESULT_ERROR_OUT_OF_HOST_MEMORY +/// - ::UR_RESULT_ERROR_OUT_OF_RESOURCES +ur_result_t UR_APICALL +urSamplerRetain( + ur_sampler_handle_t hSampler ///< [in] handle of the sampler object to get access + ) +{ + auto pfnRetain = ur_lib::context->urDdiTable.Sampler.pfnRetain; + if( nullptr == pfnRetain ) + return UR_RESULT_ERROR_UNINITIALIZED; + + return pfnRetain( hSampler ); +} + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Decrement the sampler's reference count and delete the sampler if the +/// reference count becomes zero. +/// +/// @remarks +/// _Analogues_ +/// - **clReleaseSampler** +/// +/// @returns +/// - ::UR_RESULT_SUCCESS +/// - ::UR_RESULT_ERROR_UNINITIALIZED +/// - ::UR_RESULT_ERROR_DEVICE_LOST +/// - ::UR_RESULT_ERROR_INVALID_NULL_HANDLE +/// + `NULL == hSampler` +/// - ::UR_RESULT_ERROR_INVALID_SAMPLER +/// - ::UR_RESULT_ERROR_OUT_OF_HOST_MEMORY +/// - ::UR_RESULT_ERROR_OUT_OF_RESOURCES +ur_result_t UR_APICALL +urSamplerRelease( + ur_sampler_handle_t hSampler ///< [in] handle of the sampler object to release + ) +{ + auto pfnRelease = ur_lib::context->urDdiTable.Sampler.pfnRelease; + if( nullptr == pfnRelease ) + return UR_RESULT_ERROR_UNINITIALIZED; + + return pfnRelease( hSampler ); +} + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Query information about a sampler object +/// +/// @remarks +/// _Analogues_ +/// - **clGetSamplerInfo** +/// +/// @returns +/// - ::UR_RESULT_SUCCESS +/// - ::UR_RESULT_ERROR_UNINITIALIZED +/// - ::UR_RESULT_ERROR_DEVICE_LOST +/// - ::UR_RESULT_ERROR_INVALID_NULL_HANDLE +/// + `NULL == hSampler` +/// - ::UR_RESULT_ERROR_INVALID_ENUMERATION +/// + `::UR_SAMPLER_INFO_LOD_MAX < propName` +/// - ::UR_RESULT_ERROR_INVALID_NULL_POINTER +/// + `NULL == pPropValue` +/// + `NULL == pPropSizeRet` +/// - ::UR_RESULT_ERROR_INVALID_SAMPLER +/// - ::UR_RESULT_ERROR_INVALID_VALUE +/// - ::UR_RESULT_ERROR_OUT_OF_HOST_MEMORY +/// - ::UR_RESULT_ERROR_OUT_OF_RESOURCES +ur_result_t UR_APICALL +urSamplerGetInfo( + ur_sampler_handle_t hSampler, ///< [in] handle of the sampler object + ur_sampler_info_t propName, ///< [in] name of the sampler property to query + size_t propValueSize, ///< [in] size in bytes of the sampler property value provided + void* pPropValue, ///< [out] value of the sampler property + size_t* pPropSizeRet ///< [out] size in bytes returned in sampler property value + ) +{ + auto pfnGetInfo = ur_lib::context->urDdiTable.Sampler.pfnGetInfo; + if( nullptr == pfnGetInfo ) + return UR_RESULT_ERROR_UNINITIALIZED; + + return pfnGetInfo( hSampler, propName, propValueSize, pPropValue, pPropSizeRet ); +} + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Return sampler native sampler handle. +/// +/// @details +/// - Retrieved native handle can be used for direct interaction with the +/// native platform driver. +/// - Use interoperability sampler extensions to convert native handle to +/// native type. +/// - The application may call this function from simultaneous threads for +/// the same context. +/// - The implementation of this function should be thread-safe. +/// +/// @returns +/// - ::UR_RESULT_SUCCESS +/// - ::UR_RESULT_ERROR_UNINITIALIZED +/// - ::UR_RESULT_ERROR_DEVICE_LOST +/// - ::UR_RESULT_ERROR_INVALID_NULL_HANDLE +/// + `NULL == hSampler` +/// - ::UR_RESULT_ERROR_INVALID_NULL_POINTER +/// + `NULL == phNativeSampler` +ur_result_t UR_APICALL +urSamplerGetNativeHandle( + ur_sampler_handle_t hSampler, ///< [in] handle of the sampler. + ur_native_handle_t* phNativeSampler ///< [out] a pointer to the native handle of the sampler. + ) +{ + auto pfnGetNativeHandle = ur_lib::context->urDdiTable.Sampler.pfnGetNativeHandle; + if( nullptr == pfnGetNativeHandle ) + return UR_RESULT_ERROR_UNINITIALIZED; + + return pfnGetNativeHandle( hSampler, phNativeSampler ); +} + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Create runtime sampler object from native sampler handle. +/// +/// @details +/// - Creates runtime sampler handle from native driver sampler handle. +/// - The application may call this function from simultaneous threads for +/// the same context. +/// - The implementation of this function should be thread-safe. +/// +/// @returns +/// - ::UR_RESULT_SUCCESS +/// - ::UR_RESULT_ERROR_UNINITIALIZED +/// - ::UR_RESULT_ERROR_DEVICE_LOST +/// - ::UR_RESULT_ERROR_INVALID_NULL_HANDLE +/// + `NULL == hNativeSampler` +/// + `NULL == hContext` +/// - ::UR_RESULT_ERROR_INVALID_NULL_POINTER +/// + `NULL == phSampler` +ur_result_t UR_APICALL +urSamplerCreateWithNativeHandle( + ur_native_handle_t hNativeSampler, ///< [in] the native handle of the sampler. + ur_context_handle_t hContext, ///< [in] handle of the context object + ur_sampler_handle_t* phSampler ///< [out] pointer to the handle of the sampler object created. + ) +{ + auto pfnCreateWithNativeHandle = ur_lib::context->urDdiTable.Sampler.pfnCreateWithNativeHandle; + if( nullptr == pfnCreateWithNativeHandle ) + return UR_RESULT_ERROR_UNINITIALIZED; + + return pfnCreateWithNativeHandle( hNativeSampler, hContext, phSampler ); +} + +/////////////////////////////////////////////////////////////////////////////// +/// @brief USM allocate host memory +/// +/// @returns +/// - ::UR_RESULT_SUCCESS +/// - ::UR_RESULT_ERROR_UNINITIALIZED +/// - ::UR_RESULT_ERROR_DEVICE_LOST +/// - ::UR_RESULT_ERROR_INVALID_NULL_HANDLE +/// + `NULL == hContext` +/// - ::UR_RESULT_ERROR_INVALID_NULL_POINTER +/// + `NULL == pUSMFlag` +/// + `NULL == ppMem` +/// - ::UR_RESULT_ERROR_INVALID_CONTEXT +/// - ::UR_RESULT_ERROR_INVALID_VALUE +/// - ::UR_RESULT_ERROR_INVALID_USM_SIZE +/// - ::UR_RESULT_ERROR_OUT_OF_HOST_MEMORY +/// - ::UR_RESULT_ERROR_OUT_OF_RESOURCES +ur_result_t UR_APICALL +urUSMHostAlloc( + ur_context_handle_t hContext, ///< [in] handle of the context object + ur_usm_mem_flags_t* pUSMFlag, ///< [in] USM memory allocation flags + size_t size, ///< [in] size in bytes of the USM memory object to be allocated + uint32_t align, ///< [in] alignment of the USM memory object + void** ppMem ///< [out] pointer to USM host memory object + ) +{ + auto pfnHostAlloc = ur_lib::context->urDdiTable.USM.pfnHostAlloc; + if( nullptr == pfnHostAlloc ) + return UR_RESULT_ERROR_UNINITIALIZED; + + return pfnHostAlloc( hContext, pUSMFlag, size, align, ppMem ); +} + +/////////////////////////////////////////////////////////////////////////////// +/// @brief USM allocate device memory +/// +/// @returns +/// - ::UR_RESULT_SUCCESS +/// - ::UR_RESULT_ERROR_UNINITIALIZED +/// - ::UR_RESULT_ERROR_DEVICE_LOST +/// - ::UR_RESULT_ERROR_INVALID_NULL_HANDLE +/// + `NULL == hContext` +/// + `NULL == hDevice` +/// - ::UR_RESULT_ERROR_INVALID_NULL_POINTER +/// + `NULL == pUSMProp` +/// + `NULL == ppMem` +/// - ::UR_RESULT_ERROR_INVALID_CONTEXT +/// - ::UR_RESULT_ERROR_INVALID_VALUE +/// - ::UR_RESULT_ERROR_INVALID_USM_SIZE +/// - ::UR_RESULT_ERROR_OUT_OF_HOST_MEMORY +/// - ::UR_RESULT_ERROR_OUT_OF_RESOURCES +ur_result_t UR_APICALL +urUSMDeviceAlloc( + ur_context_handle_t hContext, ///< [in] handle of the context object + ur_device_handle_t hDevice, ///< [in] handle of the device object + ur_usm_mem_flags_t* pUSMProp, ///< [in] USM memory properties + size_t size, ///< [in] size in bytes of the USM memory object to be allocated + uint32_t align, ///< [in] alignment of the USM memory object + void** ppMem ///< [out] pointer to USM device memory object + ) +{ + auto pfnDeviceAlloc = ur_lib::context->urDdiTable.USM.pfnDeviceAlloc; + if( nullptr == pfnDeviceAlloc ) + return UR_RESULT_ERROR_UNINITIALIZED; + + return pfnDeviceAlloc( hContext, hDevice, pUSMProp, size, align, ppMem ); +} + +/////////////////////////////////////////////////////////////////////////////// +/// @brief USM allocate shared memory +/// +/// @returns +/// - ::UR_RESULT_SUCCESS +/// - ::UR_RESULT_ERROR_UNINITIALIZED +/// - ::UR_RESULT_ERROR_DEVICE_LOST +/// - ::UR_RESULT_ERROR_INVALID_NULL_HANDLE +/// + `NULL == hContext` +/// + `NULL == hDevice` +/// - ::UR_RESULT_ERROR_INVALID_NULL_POINTER +/// + `NULL == pUSMProp` +/// + `NULL == ppMem` +/// - ::UR_RESULT_ERROR_INVALID_CONTEXT +/// - ::UR_RESULT_ERROR_INVALID_VALUE +/// - ::UR_RESULT_ERROR_INVALID_USM_SIZE +/// - ::UR_RESULT_ERROR_OUT_OF_HOST_MEMORY +/// - ::UR_RESULT_ERROR_OUT_OF_RESOURCES +ur_result_t UR_APICALL +urUSMSharedAlloc( + ur_context_handle_t hContext, ///< [in] handle of the context object + ur_device_handle_t hDevice, ///< [in] handle of the device object + ur_usm_mem_flags_t* pUSMProp, ///< [in] USM memory properties + size_t size, ///< [in] size in bytes of the USM memory object to be allocated + uint32_t align, ///< [in] alignment of the USM memory object + void** ppMem ///< [out] pointer to USM shared memory object + ) +{ + auto pfnSharedAlloc = ur_lib::context->urDdiTable.USM.pfnSharedAlloc; + if( nullptr == pfnSharedAlloc ) + return UR_RESULT_ERROR_UNINITIALIZED; + + return pfnSharedAlloc( hContext, hDevice, pUSMProp, size, align, ppMem ); +} + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Free the USM memory object +/// +/// @returns +/// - ::UR_RESULT_SUCCESS +/// - ::UR_RESULT_ERROR_UNINITIALIZED +/// - ::UR_RESULT_ERROR_DEVICE_LOST +/// - ::UR_RESULT_ERROR_INVALID_NULL_HANDLE +/// + `NULL == hContext` +/// - ::UR_RESULT_ERROR_INVALID_NULL_POINTER +/// + `NULL == pMem` +/// - ::UR_RESULT_ERROR_INVALID_MEM_OBJECT +/// - ::UR_RESULT_ERROR_OUT_OF_HOST_MEMORY +ur_result_t UR_APICALL +urMemFree( + ur_context_handle_t hContext, ///< [in] handle of the context object + void* pMem ///< [in] pointer to USM memory object + ) +{ + auto pfnFree = ur_lib::context->urDdiTable.Mem.pfnFree; + if( nullptr == pfnFree ) + return UR_RESULT_ERROR_UNINITIALIZED; + + return pfnFree( hContext, pMem ); +} + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Get USM memory object allocation information +/// +/// @returns +/// - ::UR_RESULT_SUCCESS +/// - ::UR_RESULT_ERROR_UNINITIALIZED +/// - ::UR_RESULT_ERROR_DEVICE_LOST +/// - ::UR_RESULT_ERROR_INVALID_NULL_HANDLE +/// + `NULL == hContext` +/// - ::UR_RESULT_ERROR_INVALID_NULL_POINTER +/// + `NULL == pMem` +/// + `NULL == pPropValue` +/// + `NULL == pPropValueSizeRet` +/// - ::UR_RESULT_ERROR_INVALID_ENUMERATION +/// + `::UR_MEM_ALLOC_INFO_ALLOC_DEVICE < propName` +/// - ::UR_RESULT_ERROR_INVALID_CONTEXT +/// - ::UR_RESULT_ERROR_INVALID_VALUE +/// - ::UR_RESULT_ERROR_INVALID_MEM_OBJECT +/// - ::UR_RESULT_ERROR_OUT_OF_HOST_MEMORY +ur_result_t UR_APICALL +urMemGetMemAllocInfo( + ur_context_handle_t hContext, ///< [in] handle of the context object + const void* pMem, ///< [in] pointer to USM memory object + ur_mem_alloc_info_t propName, ///< [in] the name of the USM allocation property to query + size_t propValueSize, ///< [in] size in bytes of the USM allocation property value + void* pPropValue, ///< [out] value of the USM allocation property + size_t* pPropValueSizeRet ///< [out] bytes returned in USM allocation property + ) +{ + auto pfnGetMemAllocInfo = ur_lib::context->urDdiTable.Mem.pfnGetMemAllocInfo; + if( nullptr == pfnGetMemAllocInfo ) + return UR_RESULT_ERROR_UNINITIALIZED; + + return pfnGetMemAllocInfo( hContext, pMem, propName, propValueSize, pPropValue, pPropValueSizeRet ); +} + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Retrieves devices within a platform +/// +/// @details +/// - Multiple calls to this function will return identical device handles, +/// in the same order. +/// - The number and order of handles returned from this function can be +/// affected by environment variables that filter devices exposed through +/// API. +/// - The returned devices are taken a reference of and must be released +/// with a subsequent call to ::urDeviceRelease. +/// - The application may call this function from simultaneous threads, the +/// implementation must be thread-safe +/// +/// @remarks +/// _Analogues_ +/// - **clGetDeviceIDs** +/// +/// @returns +/// - ::UR_RESULT_SUCCESS +/// - ::UR_RESULT_ERROR_UNINITIALIZED +/// - ::UR_RESULT_ERROR_DEVICE_LOST +/// - ::UR_RESULT_ERROR_INVALID_NULL_HANDLE +/// + `NULL == hPlatform` +/// - ::UR_RESULT_ERROR_INVALID_ENUMERATION +/// + `::UR_DEVICE_TYPE_VPU < DeviceType` +/// - ::UR_RESULT_ERROR_INVALID_SIZE +ur_result_t UR_APICALL +urDeviceGet( + ur_platform_handle_t hPlatform, ///< [in] handle of the platform instance + ur_device_type_t DeviceType, ///< [in] the type of the devices. + uint32_t NumEntries, ///< [in] the number of devices to be added to phDevices. + ///< If phDevices in not NULL then NumEntries should be greater than zero, + ///< otherwise ::UR_RESULT_ERROR_INVALID_SIZE, + ///< will be returned. + ur_device_handle_t* phDevices, ///< [out][optional][range(0, NumEntries)] array of handle of devices. + ///< If NumEntries is less than the number of devices available, then + ///< platform shall only retrieve that number of devices. + uint32_t* pNumDevices ///< [out][optional] pointer to the number of devices. + ///< pNumDevices will be updated with the total number of devices available. + ) +{ + auto pfnGet = ur_lib::context->urDdiTable.Device.pfnGet; + if( nullptr == pfnGet ) + return UR_RESULT_ERROR_UNINITIALIZED; + + return pfnGet( hPlatform, DeviceType, NumEntries, phDevices, pNumDevices ); +} + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Retrieves various information about device +/// +/// @details +/// - The application may call this function from simultaneous threads. +/// - The implementation of this function should be lock-free. +/// +/// @remarks +/// _Analogues_ +/// - **clGetDeviceInfo** +/// +/// @returns +/// - ::UR_RESULT_SUCCESS +/// - ::UR_RESULT_ERROR_UNINITIALIZED +/// - ::UR_RESULT_ERROR_DEVICE_LOST +/// - ::UR_RESULT_ERROR_INVALID_NULL_HANDLE +/// + `NULL == hDevice` +/// - ::UR_RESULT_ERROR_INVALID_ENUMERATION +/// + `::UR_DEVICE_INFO_BFLOAT16 < infoType` +ur_result_t UR_APICALL +urDeviceGetInfo( + ur_device_handle_t hDevice, ///< [in] handle of the device instance + ur_device_info_t infoType, ///< [in] type of the info to retrieve + size_t propSize, ///< [in] the number of bytes pointed to by pDeviceInfo. + void* pDeviceInfo, ///< [out][optional] 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 ::UR_RESULT_ERROR_INVALID_SIZE error is returned and + ///< pDeviceInfo is not used. + size_t* pPropSizeRet ///< [out][optional] pointer to the actual size in bytes of the queried infoType. + ) +{ + auto pfnGetInfo = ur_lib::context->urDdiTable.Device.pfnGetInfo; + if( nullptr == pfnGetInfo ) + return UR_RESULT_ERROR_UNINITIALIZED; + + return pfnGetInfo( hDevice, infoType, propSize, pDeviceInfo, pPropSizeRet ); +} + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Makes a reference of the device handle indicating it's in use until +/// paired ::urDeviceRelease is called +/// +/// @details +/// - It is not valid to use the device handle, which has all of its +/// references released. +/// - The application may call this function from simultaneous threads for +/// the same device. +/// - The implementation of this function should be thread-safe. +/// +/// @remarks +/// _Analogues_ +/// - **clRetainDevice** +/// +/// @returns +/// - ::UR_RESULT_SUCCESS +/// - ::UR_RESULT_ERROR_UNINITIALIZED +/// - ::UR_RESULT_ERROR_DEVICE_LOST +/// - ::UR_RESULT_ERROR_INVALID_NULL_HANDLE +/// + `NULL == hDevice` +ur_result_t UR_APICALL +urDeviceRetain( + ur_device_handle_t hDevice ///< [in] handle of the device to get a reference of. + ) +{ + auto pfnRetain = ur_lib::context->urDdiTable.Device.pfnRetain; + if( nullptr == pfnRetain ) + return UR_RESULT_ERROR_UNINITIALIZED; + + return pfnRetain( hDevice ); +} + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Releases the device handle reference indicating end of its usage +/// +/// @details +/// - The application may call this function from simultaneous threads for +/// the same device. +/// - The implementation of this function should be thread-safe. +/// +/// @remarks +/// _Analogues_ +/// - **clReleaseDevice** +/// +/// @returns +/// - ::UR_RESULT_SUCCESS +/// - ::UR_RESULT_ERROR_UNINITIALIZED +/// - ::UR_RESULT_ERROR_DEVICE_LOST +/// - ::UR_RESULT_ERROR_INVALID_NULL_HANDLE +/// + `NULL == hDevice` +ur_result_t UR_APICALL +urDeviceRelease( + ur_device_handle_t hDevice ///< [in] handle of the device to release. + ) +{ + auto pfnRelease = ur_lib::context->urDdiTable.Device.pfnRelease; + if( nullptr == pfnRelease ) + return UR_RESULT_ERROR_UNINITIALIZED; + + return pfnRelease( hDevice ); +} + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Partition the device into sub-devices +/// +/// @details +/// - Repeated calls to this function with the same inputs will produce the +/// same output in the same order. +/// - The function may be called to request a further partitioning of a +/// sub-device into sub-sub-devices, and so on. +/// - The application may call this function from simultaneous threads for +/// the same device. +/// - The implementation of this function should be thread-safe. +/// +/// @remarks +/// _Analogues_ +/// - **clCreateSubDevices** +/// +/// @returns +/// - ::UR_RESULT_SUCCESS +/// - ::UR_RESULT_ERROR_UNINITIALIZED +/// - ::UR_RESULT_ERROR_DEVICE_LOST +/// - ::UR_RESULT_ERROR_INVALID_NULL_HANDLE +/// + `NULL == hDevice` +/// - ::UR_RESULT_ERROR_INVALID_NULL_POINTER +/// + `NULL == Properties` +ur_result_t UR_APICALL +urDevicePartition( + ur_device_handle_t hDevice, ///< [in] handle of the device to partition. + ur_device_partition_property_value_t* Properties, ///< [in] null-terminated array of pair of the requested partitioning. + uint32_t NumDevices, ///< [in] the number of sub-devices. + ur_device_handle_t* phSubDevices, ///< [out][optional][range(0, NumDevices)] array of handle of devices. + ///< If NumDevices is less than the number of sub-devices available, then + ///< the function shall only retrieve that number of sub-devices. + uint32_t* pNumDevicesRet ///< [out][optional] pointer to the number of sub-devices the device can be + ///< partitioned into according to the partitioning property. + ) +{ + auto pfnPartition = ur_lib::context->urDdiTable.Device.pfnPartition; + if( nullptr == pfnPartition ) + return UR_RESULT_ERROR_UNINITIALIZED; + + return pfnPartition( hDevice, Properties, NumDevices, phSubDevices, pNumDevicesRet ); +} + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Selects the most appropriate device binary based on runtime +/// information and the IR characteristics. +/// +/// @details +/// - The input binaries are various AOT images, and possibly a SPIR-V +/// binary for JIT compilation. +/// - The selected binary will be able to be run on the target device. +/// - If no suitable binary can be found then function returns +/// ${X}_INVALID_BINARY. +/// - The application may call this function from simultaneous threads for +/// the same device. +/// - The implementation of this function should be thread-safe. +/// +/// @returns +/// - ::UR_RESULT_SUCCESS +/// - ::UR_RESULT_ERROR_UNINITIALIZED +/// - ::UR_RESULT_ERROR_DEVICE_LOST +/// - ::UR_RESULT_ERROR_INVALID_NULL_HANDLE +/// + `NULL == hDevice` +/// - ::UR_RESULT_ERROR_INVALID_NULL_POINTER +/// + `NULL == ppBinaries` +/// + `NULL == pSelectedBinary` +ur_result_t UR_APICALL +urDeviceSelectBinary( + ur_device_handle_t hDevice, ///< [in] handle of the device to select binary for. + const uint8_t** ppBinaries, ///< [in] the array of binaries to select from. + uint32_t NumBinaries, ///< [in] the number of binaries passed in ppBinaries. Must greater than or + ///< equal to zero. + uint32_t* pSelectedBinary ///< [out] the index of the selected binary in the input array of binaries. + ///< If a suitable binary was not found the function returns ${X}_INVALID_BINARY. + ) +{ + auto pfnSelectBinary = ur_lib::context->urDdiTable.Device.pfnSelectBinary; + if( nullptr == pfnSelectBinary ) + return UR_RESULT_ERROR_UNINITIALIZED; + + return pfnSelectBinary( hDevice, ppBinaries, NumBinaries, pSelectedBinary ); +} + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Return platform native device handle. +/// +/// @details +/// - Retrieved native handle can be used for direct interaction with the +/// native platform driver. +/// - Use interoperability platform extensions to convert native handle to +/// native type. +/// - The application may call this function from simultaneous threads for +/// the same context. +/// - The implementation of this function should be thread-safe. +/// +/// @returns +/// - ::UR_RESULT_SUCCESS +/// - ::UR_RESULT_ERROR_UNINITIALIZED +/// - ::UR_RESULT_ERROR_DEVICE_LOST +/// - ::UR_RESULT_ERROR_INVALID_NULL_HANDLE +/// + `NULL == hDevice` +/// - ::UR_RESULT_ERROR_INVALID_NULL_POINTER +/// + `NULL == phNativeDevice` +ur_result_t UR_APICALL +urDeviceGetNativeHandle( + ur_device_handle_t hDevice, ///< [in] handle of the device. + ur_native_handle_t* phNativeDevice ///< [out] a pointer to the native handle of the device. + ) +{ + auto pfnGetNativeHandle = ur_lib::context->urDdiTable.Device.pfnGetNativeHandle; + if( nullptr == pfnGetNativeHandle ) + return UR_RESULT_ERROR_UNINITIALIZED; + + return pfnGetNativeHandle( hDevice, phNativeDevice ); +} + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Create runtime device object from native device handle. +/// +/// @details +/// - Creates runtime device handle from native driver device handle. +/// - The application may call this function from simultaneous threads for +/// the same context. +/// - The implementation of this function should be thread-safe. +/// +/// @returns +/// - ::UR_RESULT_SUCCESS +/// - ::UR_RESULT_ERROR_UNINITIALIZED +/// - ::UR_RESULT_ERROR_DEVICE_LOST +/// - ::UR_RESULT_ERROR_INVALID_NULL_HANDLE +/// + `NULL == hNativeDevice` +/// + `NULL == hPlatform` +/// - ::UR_RESULT_ERROR_INVALID_NULL_POINTER +/// + `NULL == phDevice` +ur_result_t UR_APICALL +urDeviceCreateWithNativeHandle( + ur_native_handle_t hNativeDevice, ///< [in] the native handle of the device. + ur_platform_handle_t hPlatform, ///< [in] handle of the platform instance + ur_device_handle_t* phDevice ///< [out] pointer to the handle of the device object created. + ) +{ + auto pfnCreateWithNativeHandle = ur_lib::context->urDdiTable.Device.pfnCreateWithNativeHandle; + if( nullptr == pfnCreateWithNativeHandle ) + return UR_RESULT_ERROR_UNINITIALIZED; + + return pfnCreateWithNativeHandle( hNativeDevice, hPlatform, phDevice ); +} + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Create kernel object from a program. +/// +/// @details +/// - Multiple calls to this function will return identical device handles, +/// in the same order. +/// - The application may call this function from simultaneous threads. +/// - The implementation of this function should be lock-free. +/// +/// @returns +/// - ::UR_RESULT_SUCCESS +/// - ::UR_RESULT_ERROR_UNINITIALIZED +/// - ::UR_RESULT_ERROR_DEVICE_LOST +/// - ::UR_RESULT_ERROR_INVALID_NULL_HANDLE +/// + `NULL == hProgram` +/// - ::UR_RESULT_ERROR_INVALID_NULL_POINTER +/// + `NULL == pKernelName` +/// + `NULL == phKernel` +ur_result_t UR_APICALL +urKernelCreate( + ur_program_handle_t hProgram, ///< [in] handle of the program instance + const char* pKernelName, ///< [in] pointer to null-terminated string. + ur_kernel_handle_t* phKernel ///< [out] pointer to handle of kernel object created. + ) +{ + auto pfnCreate = ur_lib::context->urDdiTable.Kernel.pfnCreate; + if( nullptr == pfnCreate ) + return UR_RESULT_ERROR_UNINITIALIZED; + + return pfnCreate( hProgram, pKernelName, phKernel ); +} + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Set kernel argument for a kernel. +/// +/// @details +/// - The application must **not** call this function from simultaneous +/// threads with the same kernel handle. +/// - The implementation of this function should be lock-free. +/// +/// @remarks +/// _Analogues_ +/// - **clSetKernelArg** +/// +/// @returns +/// - ::UR_RESULT_SUCCESS +/// - ::UR_RESULT_ERROR_UNINITIALIZED +/// - ::UR_RESULT_ERROR_DEVICE_LOST +/// - ::UR_RESULT_ERROR_INVALID_NULL_HANDLE +/// + `NULL == hKernel` +ur_result_t UR_APICALL +urKernelSetArg( + ur_kernel_handle_t hKernel, ///< [in] handle of the kernel object + uint32_t argIndex, ///< [in] argument index in range [0, num args - 1] + size_t argSize, ///< [in] size of argument type + const void* pArgValue ///< [in][optional] argument value represented as matching arg type. If + ///< null then argument value is considered null. + ) +{ + auto pfnSetArg = ur_lib::context->urDdiTable.Kernel.pfnSetArg; + if( nullptr == pfnSetArg ) + return UR_RESULT_ERROR_UNINITIALIZED; + + return pfnSetArg( hKernel, argIndex, argSize, pArgValue ); +} + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Query information about a Kernel object +/// +/// @remarks +/// _Analogues_ +/// - **clGetKernelInfo** +/// +/// @returns +/// - ::UR_RESULT_SUCCESS +/// - ::UR_RESULT_ERROR_UNINITIALIZED +/// - ::UR_RESULT_ERROR_DEVICE_LOST +/// - ::UR_RESULT_ERROR_INVALID_NULL_HANDLE +/// + `NULL == hKernel` +/// - ::UR_RESULT_ERROR_INVALID_ENUMERATION +/// + `::UR_KERNEL_INFO_ATTRIBUTES < propName` +ur_result_t UR_APICALL +urKernelGetInfo( + ur_kernel_handle_t hKernel, ///< [in] handle of the Kernel object + ur_kernel_info_t propName, ///< [in] name of the Kernel property to query + size_t propSize, ///< [in] the size of the Kernel property value. + void* pKernelInfo, ///< [in,out][optional] array of bytes holding the kernel info property. + ///< If propSize is not equal to or greater than the real number of bytes + ///< needed to return + ///< the info then the ::UR_RESULT_ERROR_INVALID_SIZE error is returned and + ///< pKernelInfo is not used. + size_t* pPropSizeRet ///< [out][optional] pointer to the actual size in bytes of data being + ///< queried by propName. + ) +{ + auto pfnGetInfo = ur_lib::context->urDdiTable.Kernel.pfnGetInfo; + if( nullptr == pfnGetInfo ) + return UR_RESULT_ERROR_UNINITIALIZED; + + return pfnGetInfo( hKernel, propName, propSize, pKernelInfo, pPropSizeRet ); +} + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Query work Group information about a Kernel object +/// +/// @remarks +/// _Analogues_ +/// - **clGetKernelWorkGroupInfo** +/// +/// @returns +/// - ::UR_RESULT_SUCCESS +/// - ::UR_RESULT_ERROR_UNINITIALIZED +/// - ::UR_RESULT_ERROR_DEVICE_LOST +/// - ::UR_RESULT_ERROR_INVALID_NULL_HANDLE +/// + `NULL == hKernel` +/// + `NULL == hDevice` +/// - ::UR_RESULT_ERROR_INVALID_ENUMERATION +/// + `::UR_KERNEL_GROUP_INFO_PRIVATE_MEM_SIZE < propName` +ur_result_t UR_APICALL +urKernelGetGroupInfo( + ur_kernel_handle_t hKernel, ///< [in] handle of the Kernel object + ur_device_handle_t hDevice, ///< [in] handle of the Device object + ur_kernel_group_info_t propName, ///< [in] name of the work Group property to query + size_t propSize, ///< [in] size of the Kernel Work Group property value + void* pPropValue, ///< [in,out][optional][range(0, propSize)] value of the Kernel Work Group + ///< property. + size_t* pPropSizeRet ///< [out][optional] pointer to the actual size in bytes of data being + ///< queried by propName. + ) +{ + auto pfnGetGroupInfo = ur_lib::context->urDdiTable.Kernel.pfnGetGroupInfo; + if( nullptr == pfnGetGroupInfo ) + return UR_RESULT_ERROR_UNINITIALIZED; + + return pfnGetGroupInfo( hKernel, hDevice, propName, propSize, pPropValue, pPropSizeRet ); +} + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Query SubGroup information about a Kernel object +/// +/// @returns +/// - ::UR_RESULT_SUCCESS +/// - ::UR_RESULT_ERROR_UNINITIALIZED +/// - ::UR_RESULT_ERROR_DEVICE_LOST +/// - ::UR_RESULT_ERROR_INVALID_NULL_HANDLE +/// + `NULL == hKernel` +/// + `NULL == hDevice` +/// - ::UR_RESULT_ERROR_INVALID_ENUMERATION +/// + `::UR_KERNEL_SUB_GROUP_INFO_SUB_GROUP_SIZE_INTEL < propName` +ur_result_t UR_APICALL +urKernelGetSubGroupInfo( + ur_kernel_handle_t hKernel, ///< [in] handle of the Kernel object + ur_device_handle_t hDevice, ///< [in] handle of the Device object + ur_kernel_sub_group_info_t propName, ///< [in] name of the SubGroup property to query + size_t propSize, ///< [in] size of the Kernel SubGroup property value + void* pPropValue, ///< [in,out][range(0, propSize)][optional] value of the Kernel SubGroup + ///< property. + size_t* pPropSizeRet ///< [out][optional] pointer to the actual size in bytes of data being + ///< queried by propName. + ) +{ + auto pfnGetSubGroupInfo = ur_lib::context->urDdiTable.Kernel.pfnGetSubGroupInfo; + if( nullptr == pfnGetSubGroupInfo ) + return UR_RESULT_ERROR_UNINITIALIZED; + + return pfnGetSubGroupInfo( hKernel, hDevice, propName, propSize, pPropValue, pPropSizeRet ); +} + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Get a reference to the Kernel object. +/// +/// @details +/// - Get a reference to the Kernel object handle. Increment its reference +/// count +/// - The application may call this function from simultaneous threads. +/// - The implementation of this function should be lock-free. +/// +/// @remarks +/// _Analogues_ +/// - **clRetainKernel** +/// +/// @returns +/// - ::UR_RESULT_SUCCESS +/// - ::UR_RESULT_ERROR_UNINITIALIZED +/// - ::UR_RESULT_ERROR_DEVICE_LOST +/// - ::UR_RESULT_ERROR_INVALID_NULL_HANDLE +/// + `NULL == hKernel` +ur_result_t UR_APICALL +urKernelRetain( + ur_kernel_handle_t hKernel ///< [in] handle for the Kernel to retain + ) +{ + auto pfnRetain = ur_lib::context->urDdiTable.Kernel.pfnRetain; + if( nullptr == pfnRetain ) + return UR_RESULT_ERROR_UNINITIALIZED; + + return pfnRetain( hKernel ); +} + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Release Kernel. +/// +/// @details +/// - Decrement reference count and destroy the Kernel if reference count +/// becomes zero. +/// - The application may call this function from simultaneous threads. +/// - The implementation of this function should be lock-free. +/// +/// @remarks +/// _Analogues_ +/// - **clReleaseKernel** +/// +/// @returns +/// - ::UR_RESULT_SUCCESS +/// - ::UR_RESULT_ERROR_UNINITIALIZED +/// - ::UR_RESULT_ERROR_DEVICE_LOST +/// - ::UR_RESULT_ERROR_INVALID_NULL_HANDLE +/// + `NULL == hKernel` +ur_result_t UR_APICALL +urKernelRelease( + ur_kernel_handle_t hKernel ///< [in] handle for the Kernel to release + ) +{ + auto pfnRelease = ur_lib::context->urDdiTable.Kernel.pfnRelease; + if( nullptr == pfnRelease ) + return UR_RESULT_ERROR_UNINITIALIZED; + + return pfnRelease( hKernel ); +} + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Set a USM pointer as the argument value of a Kernel. +/// +/// @details +/// - The application must **not** call this function from simultaneous +/// threads with the same kernel handle. +/// - The implementation of this function should be lock-free. +/// +/// @remarks +/// _Analogues_ +/// - **clSetKernelArgSVMPointer** +/// +/// @returns +/// - ::UR_RESULT_SUCCESS +/// - ::UR_RESULT_ERROR_UNINITIALIZED +/// - ::UR_RESULT_ERROR_DEVICE_LOST +/// - ::UR_RESULT_ERROR_INVALID_NULL_HANDLE +/// + `NULL == hKernel` +ur_result_t UR_APICALL +urKernelSetArgPointer( + ur_kernel_handle_t hKernel, ///< [in] handle of the kernel object + uint32_t argIndex, ///< [in] argument index in range [0, num args - 1] + size_t argSize, ///< [in] size of argument type + const void* pArgValue ///< [in][optional] SVM pointer to memory location holding the argument + ///< value. If null then argument value is considered null. + ) +{ + auto pfnSetArgPointer = ur_lib::context->urDdiTable.Kernel.pfnSetArgPointer; + if( nullptr == pfnSetArgPointer ) + return UR_RESULT_ERROR_UNINITIALIZED; + + return pfnSetArgPointer( hKernel, argIndex, argSize, pArgValue ); +} + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Set additional Kernel execution attributes. +/// +/// @details +/// - The application must **not** call this function from simultaneous +/// threads with the same kernel handle. +/// - The implementation of this function should be lock-free. +/// +/// @remarks +/// _Analogues_ +/// - **clSetKernelExecInfo** +/// +/// @returns +/// - ::UR_RESULT_SUCCESS +/// - ::UR_RESULT_ERROR_UNINITIALIZED +/// - ::UR_RESULT_ERROR_DEVICE_LOST +/// - ::UR_RESULT_ERROR_INVALID_NULL_HANDLE +/// + `NULL == hKernel` +/// - ::UR_RESULT_ERROR_INVALID_ENUMERATION +/// + `::UR_KERNEL_EXEC_INFO_USM_PTRS < propName` +/// - ::UR_RESULT_ERROR_INVALID_NULL_POINTER +/// + `NULL == pPropValue` +ur_result_t UR_APICALL +urKernelSetExecInfo( + ur_kernel_handle_t hKernel, ///< [in] handle of the kernel object + ur_kernel_exec_info_t propName, ///< [in] name of the execution attribute + size_t propSize, ///< [in] size in byte the attribute value + const void* pPropValue ///< [in][range(0, propSize)] pointer to memory location holding the + ///< property value. + ) +{ + auto pfnSetExecInfo = ur_lib::context->urDdiTable.Kernel.pfnSetExecInfo; + if( nullptr == pfnSetExecInfo ) + return UR_RESULT_ERROR_UNINITIALIZED; + + return pfnSetExecInfo( hKernel, propName, propSize, pPropValue ); +} + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Set a Sampler object as the argument value of a Kernel. +/// +/// @details +/// - The application must **not** call this function from simultaneous +/// threads with the same kernel handle. +/// - The implementation of this function should be lock-free. +/// +/// @returns +/// - ::UR_RESULT_SUCCESS +/// - ::UR_RESULT_ERROR_UNINITIALIZED +/// - ::UR_RESULT_ERROR_DEVICE_LOST +/// - ::UR_RESULT_ERROR_INVALID_NULL_HANDLE +/// + `NULL == hKernel` +/// + `NULL == hArgValue` +ur_result_t UR_APICALL +urKernelSetArgSampler( + ur_kernel_handle_t hKernel, ///< [in] handle of the kernel object + uint32_t argIndex, ///< [in] argument index in range [0, num args - 1] + ur_sampler_handle_t hArgValue ///< [in] handle of Sampler object. + ) +{ + auto pfnSetArgSampler = ur_lib::context->urDdiTable.Kernel.pfnSetArgSampler; + if( nullptr == pfnSetArgSampler ) + return UR_RESULT_ERROR_UNINITIALIZED; + + return pfnSetArgSampler( hKernel, argIndex, hArgValue ); +} + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Set a Memory object as the argument value of a Kernel. +/// +/// @details +/// - The application must **not** call this function from simultaneous +/// threads with the same kernel handle. +/// - The implementation of this function should be lock-free. +/// +/// @returns +/// - ::UR_RESULT_SUCCESS +/// - ::UR_RESULT_ERROR_UNINITIALIZED +/// - ::UR_RESULT_ERROR_DEVICE_LOST +/// - ::UR_RESULT_ERROR_INVALID_NULL_HANDLE +/// + `NULL == hKernel` +/// + `NULL == hArgValue` +ur_result_t UR_APICALL +urKernelSetArgMemObj( + ur_kernel_handle_t hKernel, ///< [in] handle of the kernel object + uint32_t argIndex, ///< [in] argument index in range [0, num args - 1] + ur_mem_handle_t hArgValue ///< [in] handle of Memory object. + ) +{ + auto pfnSetArgMemObj = ur_lib::context->urDdiTable.Kernel.pfnSetArgMemObj; + if( nullptr == pfnSetArgMemObj ) + return UR_RESULT_ERROR_UNINITIALIZED; + + return pfnSetArgMemObj( hKernel, argIndex, hArgValue ); +} + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Return platform native kernel handle. +/// +/// @details +/// - Retrieved native handle can be used for direct interaction with the +/// native platform driver. +/// - Use interoperability platform extensions to convert native handle to +/// native type. +/// - The application may call this function from simultaneous threads for +/// the same context. +/// - The implementation of this function should be thread-safe. +/// +/// @returns +/// - ::UR_RESULT_SUCCESS +/// - ::UR_RESULT_ERROR_UNINITIALIZED +/// - ::UR_RESULT_ERROR_DEVICE_LOST +/// - ::UR_RESULT_ERROR_INVALID_NULL_HANDLE +/// + `NULL == hKernel` +/// - ::UR_RESULT_ERROR_INVALID_NULL_POINTER +/// + `NULL == phNativeKernel` +ur_result_t UR_APICALL +urKernelGetNativeHandle( + ur_kernel_handle_t hKernel, ///< [in] handle of the kernel. + ur_native_handle_t* phNativeKernel ///< [out] a pointer to the native handle of the kernel. + ) +{ + auto pfnGetNativeHandle = ur_lib::context->urDdiTable.Kernel.pfnGetNativeHandle; + if( nullptr == pfnGetNativeHandle ) + return UR_RESULT_ERROR_UNINITIALIZED; + + return pfnGetNativeHandle( hKernel, phNativeKernel ); +} + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Create runtime kernel object from native kernel handle. +/// +/// @details +/// - Creates runtime kernel handle from native driver kernel handle. +/// - The application may call this function from simultaneous threads for +/// the same context. +/// - The implementation of this function should be thread-safe. +/// +/// @returns +/// - ::UR_RESULT_SUCCESS +/// - ::UR_RESULT_ERROR_UNINITIALIZED +/// - ::UR_RESULT_ERROR_DEVICE_LOST +/// - ::UR_RESULT_ERROR_INVALID_NULL_HANDLE +/// + `NULL == hNativeKernel` +/// + `NULL == hContext` +/// - ::UR_RESULT_ERROR_INVALID_NULL_POINTER +/// + `NULL == phKernel` +ur_result_t UR_APICALL +urKernelCreateWithNativeHandle( + ur_native_handle_t hNativeKernel, ///< [in] the native handle of the kernel. + ur_context_handle_t hContext, ///< [in] handle of the context object + ur_kernel_handle_t* phKernel ///< [out] pointer to the handle of the kernel object created. + ) +{ + auto pfnCreateWithNativeHandle = ur_lib::context->urDdiTable.Kernel.pfnCreateWithNativeHandle; + if( nullptr == pfnCreateWithNativeHandle ) + return UR_RESULT_ERROR_UNINITIALIZED; + + return pfnCreateWithNativeHandle( hNativeKernel, hContext, phKernel ); +} + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Create Module object from IL. +/// +/// @details +/// - Multiple calls to this function will return identical device handles, +/// in the same order. +/// - The application may call this function from simultaneous threads. +/// - The implementation of this function should be lock-free. +/// +/// @returns +/// - ::UR_RESULT_SUCCESS +/// - ::UR_RESULT_ERROR_UNINITIALIZED +/// - ::UR_RESULT_ERROR_DEVICE_LOST +/// - ::UR_RESULT_ERROR_INVALID_NULL_HANDLE +/// + `NULL == hContext` +/// - ::UR_RESULT_ERROR_INVALID_NULL_POINTER +/// + `NULL == pIL` +/// + `NULL == pOptions` +/// + `NULL == phModule` +ur_result_t UR_APICALL +urModuleCreate( + ur_context_handle_t hContext, ///< [in] handle of the context instance. + const void* pIL, ///< [in] pointer to IL string. + size_t length, ///< [in] length of IL in bytes. + const char* pOptions, ///< [in] pointer to compiler options null-terminated string. + ur_modulecreate_callback_t pfnNotify, ///< [in][optional] A function pointer to a notification routine that is + ///< called when program compilation is complete. + void* pUserData, ///< [in][optional] Passed as an argument when pfnNotify is called. + ur_module_handle_t* phModule ///< [out] pointer to handle of Module object created. + ) +{ + auto pfnCreate = ur_lib::context->urDdiTable.Module.pfnCreate; + if( nullptr == pfnCreate ) + return UR_RESULT_ERROR_UNINITIALIZED; + + return pfnCreate( hContext, pIL, length, pOptions, pfnNotify, pUserData, phModule ); +} + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Get a reference to the Module object. +/// +/// @details +/// - Get a reference to the Module object handle. Increment its reference +/// count +/// - The application may call this function from simultaneous threads. +/// - The implementation of this function should be lock-free. +/// +/// @returns +/// - ::UR_RESULT_SUCCESS +/// - ::UR_RESULT_ERROR_UNINITIALIZED +/// - ::UR_RESULT_ERROR_DEVICE_LOST +/// - ::UR_RESULT_ERROR_INVALID_NULL_HANDLE +/// + `NULL == hModule` +ur_result_t UR_APICALL +urModuleRetain( + ur_module_handle_t hModule ///< [in] handle for the Module to retain + ) +{ + auto pfnRetain = ur_lib::context->urDdiTable.Module.pfnRetain; + if( nullptr == pfnRetain ) + return UR_RESULT_ERROR_UNINITIALIZED; + + return pfnRetain( hModule ); +} + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Release Module. +/// +/// @details +/// - Decrement reference count and destroy the Module if reference count +/// becomes zero. +/// - The application may call this function from simultaneous threads. +/// - The implementation of this function should be lock-free. +/// +/// @returns +/// - ::UR_RESULT_SUCCESS +/// - ::UR_RESULT_ERROR_UNINITIALIZED +/// - ::UR_RESULT_ERROR_DEVICE_LOST +/// - ::UR_RESULT_ERROR_INVALID_NULL_HANDLE +/// + `NULL == hModule` +ur_result_t UR_APICALL +urModuleRelease( + ur_module_handle_t hModule ///< [in] handle for the Module to release + ) +{ + auto pfnRelease = ur_lib::context->urDdiTable.Module.pfnRelease; + if( nullptr == pfnRelease ) + return UR_RESULT_ERROR_UNINITIALIZED; + + return pfnRelease( hModule ); +} + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Return platform native module handle. +/// +/// @details +/// - Retrieved native handle can be used for direct interaction with the +/// native platform driver. +/// - Use interoperability platform extensions to convert native handle to +/// native type. +/// - The application may call this function from simultaneous threads for +/// the same context. +/// - The implementation of this function should be thread-safe. +/// +/// @returns +/// - ::UR_RESULT_SUCCESS +/// - ::UR_RESULT_ERROR_UNINITIALIZED +/// - ::UR_RESULT_ERROR_DEVICE_LOST +/// - ::UR_RESULT_ERROR_INVALID_NULL_HANDLE +/// + `NULL == hModule` +/// - ::UR_RESULT_ERROR_INVALID_NULL_POINTER +/// + `NULL == phNativeModule` +ur_result_t UR_APICALL +urModuleGetNativeHandle( + ur_module_handle_t hModule, ///< [in] handle of the module. + ur_native_handle_t* phNativeModule ///< [out] a pointer to the native handle of the module. + ) +{ + auto pfnGetNativeHandle = ur_lib::context->urDdiTable.Module.pfnGetNativeHandle; + if( nullptr == pfnGetNativeHandle ) + return UR_RESULT_ERROR_UNINITIALIZED; + + return pfnGetNativeHandle( hModule, phNativeModule ); +} + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Create runtime module object from native module handle. +/// +/// @details +/// - Creates runtime module handle from native driver module handle. +/// - The application may call this function from simultaneous threads for +/// the same context. +/// - The implementation of this function should be thread-safe. +/// +/// @returns +/// - ::UR_RESULT_SUCCESS +/// - ::UR_RESULT_ERROR_UNINITIALIZED +/// - ::UR_RESULT_ERROR_DEVICE_LOST +/// - ::UR_RESULT_ERROR_INVALID_NULL_HANDLE +/// + `NULL == hNativeModule` +/// + `NULL == hContext` +/// - ::UR_RESULT_ERROR_INVALID_NULL_POINTER +/// + `NULL == phModule` +ur_result_t UR_APICALL +urModuleCreateWithNativeHandle( + ur_native_handle_t hNativeModule, ///< [in] the native handle of the module. + ur_context_handle_t hContext, ///< [in] handle of the context instance. + ur_module_handle_t* phModule ///< [out] pointer to the handle of the module object created. + ) +{ + auto pfnCreateWithNativeHandle = ur_lib::context->urDdiTable.Module.pfnCreateWithNativeHandle; + if( nullptr == pfnCreateWithNativeHandle ) + return UR_RESULT_ERROR_UNINITIALIZED; + + return pfnCreateWithNativeHandle( hNativeModule, hContext, phModule ); +} + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Retrieves all available platforms +/// +/// @details +/// - Multiple calls to this function will return identical platforms +/// handles, in the same order. +/// - The application may call this function from simultaneous threads, the +/// implementation must be thread-safe +/// +/// @remarks +/// _Analogues_ +/// - **clGetPlatformIDs** +/// +/// @returns +/// - ::UR_RESULT_SUCCESS +/// - ::UR_RESULT_ERROR_UNINITIALIZED +/// - ::UR_RESULT_ERROR_DEVICE_LOST +/// - ::UR_RESULT_ERROR_INVALID_SIZE +ur_result_t UR_APICALL +urPlatformGet( + uint32_t NumEntries, ///< [in] the number of platforms to be added to phPlatforms. + ///< If phPlatforms is not NULL, then NumEntries should be greater than + ///< zero, otherwise ::UR_RESULT_ERROR_INVALID_SIZE, + ///< will be returned. + ur_platform_handle_t* phPlatforms, ///< [out][optional][range(0, NumEntries)] array of handle of platforms. + ///< If NumEntries is less than the number of platforms available, then + ///< ::urPlatformGet shall only retrieve that number of platforms. + uint32_t* pNumPlatforms ///< [out][optional] returns the total number of platforms available. + ) +{ + auto pfnGet = ur_lib::context->urDdiTable.Platform.pfnGet; + if( nullptr == pfnGet ) + return UR_RESULT_ERROR_UNINITIALIZED; + + return pfnGet( NumEntries, phPlatforms, pNumPlatforms ); +} + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Retrieves various information about platform +/// +/// @details +/// - The application may call this function from simultaneous threads. +/// - The implementation of this function should be lock-free. +/// +/// @remarks +/// _Analogues_ +/// - **clGetPlatformInfo** +/// +/// @returns +/// - ::UR_RESULT_SUCCESS +/// - ::UR_RESULT_ERROR_UNINITIALIZED +/// - ::UR_RESULT_ERROR_DEVICE_LOST +/// - ::UR_RESULT_ERROR_INVALID_NULL_HANDLE +/// + `NULL == hPlatform` +/// - ::UR_RESULT_ERROR_INVALID_ENUMERATION +/// + `::UR_PLATFORM_INFO_PROFILE < PlatformInfoType` +ur_result_t UR_APICALL +urPlatformGetInfo( + ur_platform_handle_t hPlatform, ///< [in] handle of the platform + ur_platform_info_t PlatformInfoType, ///< [in] type of the info to retrieve + size_t Size, ///< [in] the number of bytes pointed to by pPlatformInfo. + void* pPlatformInfo, ///< [out][optional] 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 ::UR_RESULT_ERROR_INVALID_SIZE error is + ///< returned and pPlatformInfo is not used. + size_t* pSizeRet ///< [out][optional] pointer to the actual number of bytes being queried by pPlatformInfo. + ) +{ + auto pfnGetInfo = ur_lib::context->urDdiTable.Platform.pfnGetInfo; + if( nullptr == pfnGetInfo ) + return UR_RESULT_ERROR_UNINITIALIZED; + + return pfnGetInfo( hPlatform, PlatformInfoType, Size, pPlatformInfo, pSizeRet ); +} + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Returns the API version supported by the specified platform +/// +/// @details +/// - The application may call this function from simultaneous threads. +/// - The implementation of this function should be lock-free. +/// +/// @returns +/// - ::UR_RESULT_SUCCESS +/// - ::UR_RESULT_ERROR_UNINITIALIZED +/// - ::UR_RESULT_ERROR_DEVICE_LOST +/// - ::UR_RESULT_ERROR_INVALID_NULL_HANDLE +/// + `NULL == hDriver` +/// - ::UR_RESULT_ERROR_INVALID_NULL_POINTER +/// + `NULL == pVersion` +ur_result_t UR_APICALL +urPlatformGetApiVersion( + ur_platform_handle_t hDriver, ///< [in] handle of the platform + ur_api_version_t* pVersion ///< [out] api version + ) +{ + auto pfnGetApiVersion = ur_lib::context->urDdiTable.Platform.pfnGetApiVersion; + if( nullptr == pfnGetApiVersion ) + return UR_RESULT_ERROR_UNINITIALIZED; + + return pfnGetApiVersion( hDriver, pVersion ); +} + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Return platform native platform handle. +/// +/// @details +/// - Retrieved native handle can be used for direct interaction with the +/// native platform driver. +/// - Use interoperability platform extensions to convert native handle to +/// native type. +/// - The application may call this function from simultaneous threads for +/// the same context. +/// - The implementation of this function should be thread-safe. +/// +/// @returns +/// - ::UR_RESULT_SUCCESS +/// - ::UR_RESULT_ERROR_UNINITIALIZED +/// - ::UR_RESULT_ERROR_DEVICE_LOST +/// - ::UR_RESULT_ERROR_INVALID_NULL_HANDLE +/// + `NULL == hPlatform` +/// - ::UR_RESULT_ERROR_INVALID_NULL_POINTER +/// + `NULL == phNativePlatform` +ur_result_t UR_APICALL +urPlatformGetNativeHandle( + ur_platform_handle_t hPlatform, ///< [in] handle of the platform. + ur_native_handle_t* phNativePlatform ///< [out] a pointer to the native handle of the platform. + ) +{ + auto pfnGetNativeHandle = ur_lib::context->urDdiTable.Platform.pfnGetNativeHandle; + if( nullptr == pfnGetNativeHandle ) + return UR_RESULT_ERROR_UNINITIALIZED; + + return pfnGetNativeHandle( hPlatform, phNativePlatform ); +} + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Create runtime platform object from native platform handle. +/// +/// @details +/// - Creates runtime platform handle from native driver platform handle. +/// - The application may call this function from simultaneous threads for +/// the same context. +/// - The implementation of this function should be thread-safe. +/// +/// @returns +/// - ::UR_RESULT_SUCCESS +/// - ::UR_RESULT_ERROR_UNINITIALIZED +/// - ::UR_RESULT_ERROR_DEVICE_LOST +/// - ::UR_RESULT_ERROR_INVALID_NULL_HANDLE +/// + `NULL == hNativePlatform` +/// - ::UR_RESULT_ERROR_INVALID_NULL_POINTER +/// + `NULL == phPlatform` +ur_result_t UR_APICALL +urPlatformCreateWithNativeHandle( + ur_native_handle_t hNativePlatform, ///< [in] the native handle of the platform. + ur_platform_handle_t* phPlatform ///< [out] pointer to the handle of the platform object created. + ) +{ + auto pfnCreateWithNativeHandle = ur_lib::context->urDdiTable.Platform.pfnCreateWithNativeHandle; + if( nullptr == pfnCreateWithNativeHandle ) + return UR_RESULT_ERROR_UNINITIALIZED; + + return pfnCreateWithNativeHandle( hNativePlatform, phPlatform ); +} + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Retrieve string representation of the underlying adapter specific +/// result reported by the the last API that returned +/// UR_RESULT_ADAPTER_SPECIFIC. Allows for an adapter independent way to +/// return an adapter specific result. +/// +/// @details +/// - The string returned via the ppMessage is a NULL terminated C style +/// string. +/// - The string returned via the ppMessage is thread local. +/// - The entry point will return UR_RESULT_SUCCESS if the result being +/// reported is to be considered a warning. Any other result code returned +/// indicates that the adapter specific result is an error. +/// - The memory in the string returned via the ppMessage is owned by the +/// adapter. +/// - The application may call this function from simultaneous threads. +/// - The implementation of this function should be lock-free. +/// +/// @returns +/// - ::UR_RESULT_SUCCESS +/// - ::UR_RESULT_ERROR_UNINITIALIZED +/// - ::UR_RESULT_ERROR_DEVICE_LOST +/// - ::UR_RESULT_ERROR_INVALID_NULL_HANDLE +/// + `NULL == hPlatform` +/// - ::UR_RESULT_ERROR_INVALID_NULL_POINTER +/// + `NULL == ppMessage` +ur_result_t UR_APICALL +urGetLastResult( + ur_platform_handle_t hPlatform, ///< [in] handle of the platform instance + const char** ppMessage ///< [out] pointer to a string containing adapter specific result in string + ///< representation. + ) +{ + auto pfnGetLastResult = ur_lib::context->urDdiTable.Global.pfnGetLastResult; + if( nullptr == pfnGetLastResult ) + return UR_RESULT_ERROR_UNINITIALIZED; + + return pfnGetLastResult( hPlatform, ppMessage ); +} + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Create Program from input SPIR-V modules. +/// +/// @details +/// - The application may call this function from simultaneous threads. +/// +/// @remarks +/// _Analogues_ +/// - **clCreateProgram** +/// +/// @returns +/// - ::UR_RESULT_SUCCESS +/// - ::UR_RESULT_ERROR_UNINITIALIZED +/// - ::UR_RESULT_ERROR_DEVICE_LOST +/// - ::UR_RESULT_ERROR_INVALID_NULL_HANDLE +/// + `NULL == hContext` +/// - ::UR_RESULT_ERROR_INVALID_NULL_POINTER +/// + `NULL == phModules` +/// + `NULL == phProgram` +ur_result_t UR_APICALL +urProgramCreate( + ur_context_handle_t hContext, ///< [in] handle of the context instance + uint32_t count, ///< [in] number of module handles in module list. + const ur_module_handle_t* phModules, ///< [in][range(0, count)] pointer to array of modules. + const char* pOptions, ///< [in][optional] pointer to linker options null-terminated string. + ur_program_handle_t* phProgram ///< [out] pointer to handle of program object created. + ) +{ + auto pfnCreate = ur_lib::context->urDdiTable.Program.pfnCreate; + if( nullptr == pfnCreate ) + return UR_RESULT_ERROR_UNINITIALIZED; + + return pfnCreate( hContext, count, phModules, pOptions, phProgram ); +} + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Create program object from native binary. +/// +/// @details +/// - The application may call this function from simultaneous threads. +/// +/// @remarks +/// _Analogues_ +/// - **clCreateProgramWithBinary** +/// +/// @returns +/// - ::UR_RESULT_SUCCESS +/// - ::UR_RESULT_ERROR_UNINITIALIZED +/// - ::UR_RESULT_ERROR_DEVICE_LOST +/// - ::UR_RESULT_ERROR_INVALID_NULL_HANDLE +/// + `NULL == hContext` +/// + `NULL == hDevice` +/// - ::UR_RESULT_ERROR_INVALID_NULL_POINTER +/// + `NULL == pBinary` +/// + `NULL == phProgram` +ur_result_t UR_APICALL +urProgramCreateWithBinary( + ur_context_handle_t hContext, ///< [in] handle of the context instance + ur_device_handle_t hDevice, ///< [in] handle to device associated with binary. + size_t size, ///< [in] size in bytes. + const uint8_t* pBinary, ///< [in] pointer to binary. + ur_program_handle_t* phProgram ///< [out] pointer to handle of Program object created. + ) +{ + auto pfnCreateWithBinary = ur_lib::context->urDdiTable.Program.pfnCreateWithBinary; + if( nullptr == pfnCreateWithBinary ) + return UR_RESULT_ERROR_UNINITIALIZED; + + return pfnCreateWithBinary( hContext, hDevice, size, pBinary, phProgram ); +} + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Get a reference to the Program object. +/// +/// @details +/// - Get a reference to the Program object handle. Increment its reference +/// count +/// - The application may call this function from simultaneous threads. +/// - The implementation of this function should be lock-free. +/// +/// @remarks +/// _Analogues_ +/// - **clRetainProgram** +/// +/// @returns +/// - ::UR_RESULT_SUCCESS +/// - ::UR_RESULT_ERROR_UNINITIALIZED +/// - ::UR_RESULT_ERROR_DEVICE_LOST +/// - ::UR_RESULT_ERROR_INVALID_NULL_HANDLE +/// + `NULL == hProgram` +ur_result_t UR_APICALL +urProgramRetain( + ur_program_handle_t hProgram ///< [in] handle for the Program to retain + ) +{ + auto pfnRetain = ur_lib::context->urDdiTable.Program.pfnRetain; + if( nullptr == pfnRetain ) + return UR_RESULT_ERROR_UNINITIALIZED; + + return pfnRetain( hProgram ); +} + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Release Program. +/// +/// @details +/// - Decrement reference count and destroy the Program if reference count +/// becomes zero. +/// - The application may call this function from simultaneous threads. +/// - The implementation of this function should be lock-free. +/// +/// @remarks +/// _Analogues_ +/// - **clReleaseProgram** +/// +/// @returns +/// - ::UR_RESULT_SUCCESS +/// - ::UR_RESULT_ERROR_UNINITIALIZED +/// - ::UR_RESULT_ERROR_DEVICE_LOST +/// - ::UR_RESULT_ERROR_INVALID_NULL_HANDLE +/// + `NULL == hProgram` +ur_result_t UR_APICALL +urProgramRelease( + ur_program_handle_t hProgram ///< [in] handle for the Program to release + ) +{ + auto pfnRelease = ur_lib::context->urDdiTable.Program.pfnRelease; + if( nullptr == pfnRelease ) + return UR_RESULT_ERROR_UNINITIALIZED; + + return pfnRelease( hProgram ); +} + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Retrieves a device function pointer to a user-defined function. +/// +/// @details +/// - Retrieves a pointer to the functions with the given name and defined +/// in the given program. +/// - ::UR_RESULT_ERROR_INVALID_FUNCTION_NAME is returned if the function +/// can not be obtained. +/// - The application may call this function from simultaneous threads for +/// the same device. +/// - The implementation of this function should be thread-safe. +/// +/// @remarks +/// _Analogues_ +/// - **clGetDeviceFunctionPointerINTEL** +/// +/// @returns +/// - ::UR_RESULT_SUCCESS +/// - ::UR_RESULT_ERROR_UNINITIALIZED +/// - ::UR_RESULT_ERROR_DEVICE_LOST +/// - ::UR_RESULT_ERROR_INVALID_NULL_HANDLE +/// + `NULL == hDevice` +/// + `NULL == hProgram` +/// - ::UR_RESULT_ERROR_INVALID_NULL_POINTER +/// + `NULL == pFunctionName` +/// + `NULL == ppFunctionPointer` +ur_result_t UR_APICALL +urProgramGetFunctionPointer( + ur_device_handle_t hDevice, ///< [in] handle of the device to retrieve pointer for. + ur_program_handle_t hProgram, ///< [in] handle of the program to search for function in. + ///< The program must already be built to the specified device, or + ///< otherwise ::UR_RESULT_ERROR_INVALID_PROGRAM_EXECUTABLE is returned. + const char* pFunctionName, ///< [in] A null-terminates string denoting the mangled function name. + void** ppFunctionPointer ///< [out] Returns the pointer to the function if it is found in the program. + ) +{ + auto pfnGetFunctionPointer = ur_lib::context->urDdiTable.Program.pfnGetFunctionPointer; + if( nullptr == pfnGetFunctionPointer ) + return UR_RESULT_ERROR_UNINITIALIZED; + + return pfnGetFunctionPointer( hDevice, hProgram, pFunctionName, ppFunctionPointer ); +} + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Query information about a Program object +/// +/// @remarks +/// _Analogues_ +/// - **clGetProgramInfo** +/// +/// @returns +/// - ::UR_RESULT_SUCCESS +/// - ::UR_RESULT_ERROR_UNINITIALIZED +/// - ::UR_RESULT_ERROR_DEVICE_LOST +/// - ::UR_RESULT_ERROR_INVALID_NULL_HANDLE +/// + `NULL == hProgram` +/// - ::UR_RESULT_ERROR_INVALID_ENUMERATION +/// + `::UR_PROGRAM_INFO_KERNEL_NAMES < propName` +ur_result_t UR_APICALL +urProgramGetInfo( + ur_program_handle_t hProgram, ///< [in] handle of the Program object + ur_program_info_t propName, ///< [in] name of the Program property to query + size_t propSize, ///< [in] the size of the Program property. + void* pProgramInfo, ///< [in,out][optional] array of bytes of holding the program info property. + ///< If propSize is not equal to or greater than the real number of bytes + ///< needed to return + ///< the info then the ::UR_RESULT_ERROR_INVALID_SIZE error is returned and + ///< pProgramInfo is not used. + size_t* pPropSizeRet ///< [out][optional] pointer to the actual size in bytes of data copied to propName. + ) +{ + auto pfnGetInfo = ur_lib::context->urDdiTable.Program.pfnGetInfo; + if( nullptr == pfnGetInfo ) + return UR_RESULT_ERROR_UNINITIALIZED; + + return pfnGetInfo( hProgram, propName, propSize, pProgramInfo, pPropSizeRet ); +} + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Query build information about a Program object for a Device +/// +/// @remarks +/// _Analogues_ +/// - **clGetProgramBuildInfo** +/// +/// @returns +/// - ::UR_RESULT_SUCCESS +/// - ::UR_RESULT_ERROR_UNINITIALIZED +/// - ::UR_RESULT_ERROR_DEVICE_LOST +/// - ::UR_RESULT_ERROR_INVALID_NULL_HANDLE +/// + `NULL == hProgram` +/// + `NULL == hDevice` +/// - ::UR_RESULT_ERROR_INVALID_ENUMERATION +/// + `::UR_PROGRAM_BUILD_INFO_BINARY_TYPE < propName` +ur_result_t UR_APICALL +urProgramGetBuildInfo( + ur_program_handle_t hProgram, ///< [in] handle of the Program object + ur_device_handle_t hDevice, ///< [in] handle of the Device object + ur_program_build_info_t propName, ///< [in] name of the Program build info to query + size_t propSize, ///< [in] size of the Program build info property. + void* pPropValue, ///< [in,out][optional] value of the Program build property. + ///< If propSize is not equal to or greater than the real number of bytes + ///< needed to return the info then the ::UR_RESULT_ERROR_INVALID_SIZE + ///< error is returned and pKernelInfo is not used. + size_t* pPropSizeRet ///< [out][optional] pointer to the actual size in bytes of data being + ///< queried by propName. + ) +{ + auto pfnGetBuildInfo = ur_lib::context->urDdiTable.Program.pfnGetBuildInfo; + if( nullptr == pfnGetBuildInfo ) + return UR_RESULT_ERROR_UNINITIALIZED; + + return pfnGetBuildInfo( hProgram, hDevice, propName, propSize, pPropValue, pPropSizeRet ); +} + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Set a Program object specialization constant to a specific value +/// +/// @returns +/// - ::UR_RESULT_SUCCESS +/// - ::UR_RESULT_ERROR_UNINITIALIZED +/// - ::UR_RESULT_ERROR_DEVICE_LOST +/// - ::UR_RESULT_ERROR_INVALID_NULL_HANDLE +/// + `NULL == hProgram` +/// - ::UR_RESULT_ERROR_INVALID_NULL_POINTER +/// + `NULL == pSpecValue` +ur_result_t UR_APICALL +urProgramSetSpecializationConstant( + ur_program_handle_t hProgram, ///< [in] handle of the Program object + uint32_t specId, ///< [in] specification constant Id + size_t specSize, ///< [in] size of the specialization constant value + const void* pSpecValue ///< [in] pointer to the specialization value bytes + ) +{ + auto pfnSetSpecializationConstant = ur_lib::context->urDdiTable.Program.pfnSetSpecializationConstant; + if( nullptr == pfnSetSpecializationConstant ) + return UR_RESULT_ERROR_UNINITIALIZED; + + return pfnSetSpecializationConstant( hProgram, specId, specSize, pSpecValue ); +} + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Return program native program handle. +/// +/// @details +/// - Retrieved native handle can be used for direct interaction with the +/// native platform driver. +/// - Use interoperability program extensions to convert native handle to +/// native type. +/// - The application may call this function from simultaneous threads for +/// the same context. +/// - The implementation of this function should be thread-safe. +/// +/// @returns +/// - ::UR_RESULT_SUCCESS +/// - ::UR_RESULT_ERROR_UNINITIALIZED +/// - ::UR_RESULT_ERROR_DEVICE_LOST +/// - ::UR_RESULT_ERROR_INVALID_NULL_HANDLE +/// + `NULL == hProgram` +/// - ::UR_RESULT_ERROR_INVALID_NULL_POINTER +/// + `NULL == phNativeProgram` +ur_result_t UR_APICALL +urProgramGetNativeHandle( + ur_program_handle_t hProgram, ///< [in] handle of the program. + ur_native_handle_t* phNativeProgram ///< [out] a pointer to the native handle of the program. + ) +{ + auto pfnGetNativeHandle = ur_lib::context->urDdiTable.Program.pfnGetNativeHandle; + if( nullptr == pfnGetNativeHandle ) + return UR_RESULT_ERROR_UNINITIALIZED; + + return pfnGetNativeHandle( hProgram, phNativeProgram ); +} + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Create runtime program object from native program handle. +/// +/// @details +/// - Creates runtime program handle from native driver program handle. +/// - The application may call this function from simultaneous threads for +/// the same context. +/// - The implementation of this function should be thread-safe. +/// +/// @returns +/// - ::UR_RESULT_SUCCESS +/// - ::UR_RESULT_ERROR_UNINITIALIZED +/// - ::UR_RESULT_ERROR_DEVICE_LOST +/// - ::UR_RESULT_ERROR_INVALID_NULL_HANDLE +/// + `NULL == hNativeProgram` +/// + `NULL == hContext` +/// - ::UR_RESULT_ERROR_INVALID_NULL_POINTER +/// + `NULL == phProgram` +ur_result_t UR_APICALL +urProgramCreateWithNativeHandle( + ur_native_handle_t hNativeProgram, ///< [in] the native handle of the program. + ur_context_handle_t hContext, ///< [in] handle of the context instance + ur_program_handle_t* phProgram ///< [out] pointer to the handle of the program object created. + ) +{ + auto pfnCreateWithNativeHandle = ur_lib::context->urDdiTable.Program.pfnCreateWithNativeHandle; + if( nullptr == pfnCreateWithNativeHandle ) + return UR_RESULT_ERROR_UNINITIALIZED; + + return pfnCreateWithNativeHandle( hNativeProgram, hContext, phProgram ); +} + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Initialize the 'oneAPI' driver(s) +/// +/// @details +/// - The application must call this function before calling any other +/// function. +/// - If this function is not called then all other functions will return +/// ::UR_RESULT_ERROR_UNINITIALIZED. +/// - Only one instance of each driver will be initialized per process. +/// - The application may call this function multiple times with different +/// flags or environment variables enabled. +/// - The application must call this function after forking new processes. +/// Each forked process must call this function. +/// - The application may call this function from simultaneous threads. +/// - The implementation of this function must be thread-safe for scenarios +/// where multiple libraries may initialize the driver(s) simultaneously. +/// +/// @returns +/// - ::UR_RESULT_SUCCESS +/// - ::UR_RESULT_ERROR_UNINITIALIZED +/// - ::UR_RESULT_ERROR_DEVICE_LOST +/// - ::UR_RESULT_ERROR_INVALID_ENUMERATION +/// + `0x1 < platform_flags` +/// + `0x1 < device_flags` +/// - ::UR_RESULT_ERROR_OUT_OF_HOST_MEMORY +ur_result_t UR_APICALL +urInit( + ur_platform_init_flags_t platform_flags, ///< [in] platform initialization flags. + ///< must be 0 (default) or a combination of ::ur_platform_init_flag_t. + ur_device_init_flags_t device_flags ///< [in] device initialization flags. + ///< must be 0 (default) or a combination of ::ur_device_init_flag_t. + ) +{ + static ur_result_t result = UR_RESULT_SUCCESS; + std::call_once(ur_lib::context->initOnce, [platform_flags, device_flags]() { + result = ur_lib::context->Init(platform_flags, device_flags); + }); + + if( UR_RESULT_SUCCESS != result ) + return result; + + auto pfnInit = ur_lib::context->urDdiTable.Global.pfnInit; + if( nullptr == pfnInit ) + return UR_RESULT_ERROR_UNINITIALIZED; + + return pfnInit( platform_flags, device_flags ); +} + +} // extern "C" diff --git a/source/loader/ur_libddi.cpp b/source/loader/ur_libddi.cpp new file mode 100644 index 0000000000..af3477a160 --- /dev/null +++ b/source/loader/ur_libddi.cpp @@ -0,0 +1,92 @@ +/* + * + * Copyright (C) 2022 Intel Corporation + * + * SPDX-License-Identifier: MIT + * + * @file ur_libddi.cpp + * + */ +#include "ur_lib.h" +#ifndef DYNAMIC_LOAD_LOADER +#include "ur_ddi.h" +#endif + +namespace ur_lib +{ + /////////////////////////////////////////////////////////////////////////////// + + + __urdlllocal ur_result_t context_t::urInit() + { + ur_result_t result = UR_RESULT_SUCCESS; + + if( UR_RESULT_SUCCESS == result ) + { + result = urGetGlobalProcAddrTable( UR_API_VERSION_0_9, &urDdiTable.Global ); + } + + if( UR_RESULT_SUCCESS == result ) + { + result = urGetContextProcAddrTable( UR_API_VERSION_0_9, &urDdiTable.Context ); + } + + if( UR_RESULT_SUCCESS == result ) + { + result = urGetEnqueueProcAddrTable( UR_API_VERSION_0_9, &urDdiTable.Enqueue ); + } + + if( UR_RESULT_SUCCESS == result ) + { + result = urGetEventProcAddrTable( UR_API_VERSION_0_9, &urDdiTable.Event ); + } + + if( UR_RESULT_SUCCESS == result ) + { + result = urGetKernelProcAddrTable( UR_API_VERSION_0_9, &urDdiTable.Kernel ); + } + + if( UR_RESULT_SUCCESS == result ) + { + result = urGetMemProcAddrTable( UR_API_VERSION_0_9, &urDdiTable.Mem ); + } + + if( UR_RESULT_SUCCESS == result ) + { + result = urGetModuleProcAddrTable( UR_API_VERSION_0_9, &urDdiTable.Module ); + } + + if( UR_RESULT_SUCCESS == result ) + { + result = urGetPlatformProcAddrTable( UR_API_VERSION_0_9, &urDdiTable.Platform ); + } + + if( UR_RESULT_SUCCESS == result ) + { + result = urGetProgramProcAddrTable( UR_API_VERSION_0_9, &urDdiTable.Program ); + } + + if( UR_RESULT_SUCCESS == result ) + { + result = urGetQueueProcAddrTable( UR_API_VERSION_0_9, &urDdiTable.Queue ); + } + + if( UR_RESULT_SUCCESS == result ) + { + result = urGetSamplerProcAddrTable( UR_API_VERSION_0_9, &urDdiTable.Sampler ); + } + + if( UR_RESULT_SUCCESS == result ) + { + result = urGetUSMProcAddrTable( UR_API_VERSION_0_9, &urDdiTable.USM ); + } + + if( UR_RESULT_SUCCESS == result ) + { + result = urGetDeviceProcAddrTable( UR_API_VERSION_0_9, &urDdiTable.Device ); + } + + return result; + } + +} // namespace ur_lib diff --git a/source/loader/ur_loader.cpp b/source/loader/ur_loader.cpp new file mode 100644 index 0000000000..fa5fb05500 --- /dev/null +++ b/source/loader/ur_loader.cpp @@ -0,0 +1,57 @@ +/* + * + * Copyright (C) 2022 Intel Corporation + * + * SPDX-License-Identifier: MIT + * + */ +#include "ur_loader.h" +#include "platform_discovery.h" + +namespace loader +{ + /////////////////////////////////////////////////////////////////////////////// + context_t *context; + + /////////////////////////////////////////////////////////////////////////////// + ur_result_t context_t::init() + { + auto discoveredPlatforms = discoverEnabledPlatforms(); + + for( auto name : discoveredPlatforms ) + { + auto handle = LOAD_DRIVER_LIBRARY( name.c_str() ); + if( NULL != handle ) + { + platforms.emplace_back(); + platforms.rbegin()->handle = handle; + } + } + + if(platforms.size()==0) + return UR_RESULT_ERROR_UNINITIALIZED; + + forceIntercept = getenv_tobool( "UR_ENABLE_LOADER_INTERCEPT" ); + + if(forceIntercept || platforms.size() > 1) + intercept_enabled = true; + + return UR_RESULT_SUCCESS; + }; + + /////////////////////////////////////////////////////////////////////////////// + context_t::~context_t() + { + for( auto& drv : platforms ) + { + FREE_DRIVER_LIBRARY( drv.handle ); + } + }; + +} + +ur_result_t +urLoaderInit() +{ + return loader::context->init(); +} diff --git a/source/loader/ur_loader.h b/source/loader/ur_loader.h new file mode 100644 index 0000000000..a2ec39f0d7 --- /dev/null +++ b/source/loader/ur_loader.h @@ -0,0 +1,54 @@ +/* + * + * Copyright (C) 2022 Intel Corporation + * + * SPDX-License-Identifier: MIT + * + */ + +#ifndef UR_LOADER_H +#define UR_LOADER_H 1 + +#include + +#include "ur_ddi.h" + +#include "ur_util.h" +#include "ur_object.h" + +#include "ur_ldrddi.h" + + +namespace loader +{ + ////////////////////////////////////////////////////////////////////////// + struct platform_t + { + HMODULE handle = NULL; + ur_result_t initStatus = UR_RESULT_SUCCESS; + dditable_t dditable = {}; + }; + + using platform_vector_t = std::vector< platform_t >; + + /////////////////////////////////////////////////////////////////////////////// + class context_t + { + public: + ur_api_version_t version = UR_API_VERSION_0_9; + + platform_vector_t platforms; + + bool forceIntercept = false; + + ur_result_t init(); + ~context_t(); + bool intercept_enabled = false; + }; + + extern context_t *context; + extern ur_event_factory_t ur_event_factory; + +} + +#endif /* UR_LOADER_H */ diff --git a/source/loader/ur_object.h b/source/loader/ur_object.h new file mode 100644 index 0000000000..85e3113ff1 --- /dev/null +++ b/source/loader/ur_object.h @@ -0,0 +1,44 @@ +/* + * + * Copyright (C) 2022 Intel Corporation + * + * SPDX-License-Identifier: MIT + * + * @file ur_object.h + * + */ + +#ifndef UR_OBJECT_H +#define UR_OBJECT_H 1 + +#include "ur_singleton.h" + +////////////////////////////////////////////////////////////////////////// +struct dditable_t +{ + ur_dditable_t ur; + //urs_dditable_t urs; + //urt_dditable_t urt; +}; + +////////////////////////////////////////////////////////////////////////// +template +class __urdlllocal object_t +{ +public: + using handle_t = _handle_t; + + handle_t handle; + dditable_t* dditable; + + object_t() = delete; + + object_t( handle_t _handle, dditable_t* _dditable ) + : handle( _handle ), dditable( _dditable ) + { + } + + ~object_t() = default; +}; + +#endif /* UR_OBJECT_H */ diff --git a/source/loader/windows/lib_init.cpp b/source/loader/windows/lib_init.cpp new file mode 100644 index 0000000000..14dce1a5fc --- /dev/null +++ b/source/loader/windows/lib_init.cpp @@ -0,0 +1,26 @@ +/* + * + * Copyright (C) 2021 Intel Corporation + * + * SPDX-License-Identifier: MIT + * + */ + +#include "ur_lib.h" +#include "ur_loader.h" + +namespace ur_lib +{ + + extern "C" BOOL APIENTRY DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved) { + if (fdwReason == DLL_PROCESS_DETACH) { + delete context; + delete loader::context; + } else if (fdwReason == DLL_PROCESS_ATTACH) { + context = new context_t; + loader::context = new loader::context_t; + } + return TRUE; + } + +} diff --git a/source/loader/windows/loader_init.cpp b/source/loader/windows/loader_init.cpp new file mode 100644 index 0000000000..7d8b3e8344 --- /dev/null +++ b/source/loader/windows/loader_init.cpp @@ -0,0 +1,14 @@ +/* + * + * Copyright (C) 2021 Intel Corporation + * + * SPDX-License-Identifier: MIT + * + */ + +#include "ur_loader.h" + +namespace loader +{ + +} diff --git a/source/loader/windows/platform_discovery_win.cpp b/source/loader/windows/platform_discovery_win.cpp new file mode 100644 index 0000000000..891a872566 --- /dev/null +++ b/source/loader/windows/platform_discovery_win.cpp @@ -0,0 +1,28 @@ +/* + * + * Copyright (C) 2022 Intel Corporation + * + * SPDX-License-Identifier: MIT + * + */ + +#include "platform_discovery.h" + +#include + +#include +#include +#include +#include +#include +#include +#include + +namespace loader { + +std::vector discoverEnabledPlatforms() { + //TODO:Enable windows driver discovery + std::vector enabledPlatforms; + return enabledPlatforms; +} +} // namespace loader diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt new file mode 100644 index 0000000000..89b40cf6d8 --- /dev/null +++ b/test/CMakeLists.txt @@ -0,0 +1,5 @@ +# Copyright (C) 2022 Intel Corporation +# SPDX-License-Identifier: MIT + +add_subdirectory(python) + diff --git a/test/python/CMakeLists.txt b/test/python/CMakeLists.txt new file mode 100644 index 0000000000..881d55946a --- /dev/null +++ b/test/python/CMakeLists.txt @@ -0,0 +1,14 @@ +# Copyright (C) 2022 Intel Corporation +# SPDX-License-Identifier: MIT + +add_test(NAME python-basic + WORKING_DIRECTORY ${CMAKE_BINARY_DIR} + COMMAND ${Python3_EXECUTABLE} -m pytest ${CMAKE_CURRENT_SOURCE_DIR}/basic.py +) + +# python uses LD_LIBRARY_PATH to search for dynamic libraries, so set it to +# the location where it can find the loader. +if(UNIX) + set_property(TEST python-basic PROPERTY + ENVIRONMENT "LD_LIBRARY_PATH=${CMAKE_LIBRARY_OUTPUT_DIRECTORY}") +endif() \ No newline at end of file diff --git a/test/python/basic.py b/test/python/basic.py new file mode 100755 index 0000000000..019e457098 --- /dev/null +++ b/test/python/basic.py @@ -0,0 +1,20 @@ +#! /usr/bin/env python3 +""" + Copyright (C) 2022 Intel Corporation + + SPDX-License-Identifier: MIT + +""" + +import pytest +import sys +import os + +# not ideal, but this solution is simple and portable. Alternative is to set +# PYTHONPATH or test on installed sources. +sys.path.insert(1, '../include') +import ur + +def test_ddi(): + ddi = ur.UR_DDI(ur.ur_api_version_v.CURRENT); + assert True diff --git a/third_party/requirements.txt b/third_party/requirements.txt index 7d17eec9f7..b336f8ff62 100644 --- a/third_party/requirements.txt +++ b/third_party/requirements.txt @@ -11,7 +11,7 @@ exhale==0.3.0 idna==2.8 imagesize==1.1.0 Jinja2==2.11.3 -lxml==4.4.2 +lxml==4.9.1 Mako==1.1.0 MarkupSafe==1.1.1 packaging==19.2 @@ -35,3 +35,4 @@ sphinxcontrib-serializinghtml==1.1.5 sphinxcontrib-websupport==1.2.4 sphinx-book-theme==0.3.3 urllib3==1.25.7 +pytest>=7.0