From be7c5e7f269a6770ffaf57c1d2b00e82be0a4ddb Mon Sep 17 00:00:00 2001 From: Ross Brunton Date: Thu, 9 Jan 2025 14:10:31 +0000 Subject: [PATCH] Added `DEVICE_INFO_PROGRAM_SET_SPECIALIZATION_CONSTANTS` This is similar to the existing `DEVICE_INFO_KERNEL_SET_SPECIALIZATION_CONSTANTS` device info, only it applies to programs rather than kernels. All of the adapters should be updated to report it correctly, and tests have been added. --- include/ur_api.h | 8 +++ include/ur_print.hpp | 15 +++++ scripts/core/device.yml | 2 + scripts/core/program.yml | 3 + source/adapters/cuda/device.cpp | 1 + source/adapters/hip/device.cpp | 4 ++ source/adapters/level_zero/device.cpp | 2 + source/adapters/native_cpu/device.cpp | 5 ++ source/adapters/opencl/device.cpp | 6 ++ source/loader/ur_libapi.cpp | 6 ++ source/ur_api.cpp | 6 ++ test/conformance/device/urDeviceGetInfo.cpp | 1 + .../urProgramSetSpecializationConstants.cpp | 64 +++++++++++++++---- tools/urinfo/urinfo.hpp | 3 + 14 files changed, 114 insertions(+), 12 deletions(-) diff --git a/include/ur_api.h b/include/ur_api.h index 226b9f41f8..ec49f9de1d 100644 --- a/include/ur_api.h +++ b/include/ur_api.h @@ -1656,6 +1656,8 @@ typedef enum ur_device_info_t { UR_DEVICE_INFO_USM_POOL_SUPPORT = 119, ///< [::ur_bool_t] return true if the device supports USM pooling. Pertains ///< to the `USMPool` entry points and usage of the `pool` parameter of the ///< USM alloc entry points. + UR_DEVICE_INFO_PROGRAM_SET_SPECIALIZATION_CONSTANTS = 120, ///< [::ur_bool_t] support the ::urProgramSetSpecializationConstants entry + ///< point UR_DEVICE_INFO_COMMAND_BUFFER_SUPPORT_EXP = 0x1000, ///< [::ur_bool_t] Returns true if the device supports the use of ///< command-buffers. UR_DEVICE_INFO_COMMAND_BUFFER_UPDATE_CAPABILITIES_EXP = 0x1001, ///< [::ur_device_command_buffer_update_capability_flags_t] Command-buffer @@ -4726,6 +4728,10 @@ typedef struct ur_specialization_constant_info_t { /// @brief Set an array of specialization constants on a Program. /// /// @details +/// - This entry point is optional, the application should query for support +/// with device query +/// ::UR_DEVICE_INFO_PROGRAM_SET_SPECIALIZATION_CONSTANTS passed to +/// ::urDeviceGetInfo. /// - The application may call this function from simultaneous threads for /// the same device. /// - The implementation of this function should be thread-safe. @@ -4745,6 +4751,8 @@ typedef struct ur_specialization_constant_info_t { /// + `NULL == pSpecConstants` /// - ::UR_RESULT_ERROR_INVALID_SIZE /// + `count == 0` +/// - ::UR_RESULT_ERROR_UNSUPPORTED_FEATURE +/// + If ::UR_DEVICE_INFO_PROGRAM_SET_SPECIALIZATION_CONSTANTS query is false /// - ::UR_RESULT_ERROR_INVALID_VALUE /// + A pSpecConstant entry contains a size that does not match that of the specialization constant in the module. /// + A pSpecConstant entry contains a nullptr pValue. diff --git a/include/ur_print.hpp b/include/ur_print.hpp index c350f206c6..57d19a204e 100644 --- a/include/ur_print.hpp +++ b/include/ur_print.hpp @@ -2639,6 +2639,9 @@ inline std::ostream &operator<<(std::ostream &os, enum ur_device_info_t value) { case UR_DEVICE_INFO_USM_POOL_SUPPORT: os << "UR_DEVICE_INFO_USM_POOL_SUPPORT"; break; + case UR_DEVICE_INFO_PROGRAM_SET_SPECIALIZATION_CONSTANTS: + os << "UR_DEVICE_INFO_PROGRAM_SET_SPECIALIZATION_CONSTANTS"; + break; case UR_DEVICE_INFO_COMMAND_BUFFER_SUPPORT_EXP: os << "UR_DEVICE_INFO_COMMAND_BUFFER_SUPPORT_EXP"; break; @@ -4160,6 +4163,18 @@ inline ur_result_t printTagged(std::ostream &os, const void *ptr, ur_device_info os << ")"; } break; + case UR_DEVICE_INFO_PROGRAM_SET_SPECIALIZATION_CONSTANTS: { + const ur_bool_t *tptr = (const ur_bool_t *)ptr; + if (sizeof(ur_bool_t) > size) { + os << "invalid size (is: " << size << ", expected: >=" << sizeof(ur_bool_t) << ")"; + return UR_RESULT_ERROR_INVALID_SIZE; + } + os << (const void *)(tptr) << " ("; + + os << *tptr; + + os << ")"; + } break; case UR_DEVICE_INFO_COMMAND_BUFFER_SUPPORT_EXP: { const ur_bool_t *tptr = (const ur_bool_t *)ptr; if (sizeof(ur_bool_t) > size) { diff --git a/scripts/core/device.yml b/scripts/core/device.yml index ce671c24d6..c260303c87 100644 --- a/scripts/core/device.yml +++ b/scripts/core/device.yml @@ -443,6 +443,8 @@ etors: desc: "[$x_bool_t] return true if the device supports the `EnqueueDeviceGlobalVariableWrite` and `EnqueueDeviceGlobalVariableRead` entry points." - name: USM_POOL_SUPPORT desc: "[$x_bool_t] return true if the device supports USM pooling. Pertains to the `USMPool` entry points and usage of the `pool` parameter of the USM alloc entry points." + - name: PROGRAM_SET_SPECIALIZATION_CONSTANTS + desc: "[$x_bool_t] support the $xProgramSetSpecializationConstants entry point" --- #-------------------------------------------------------------------------- type: function desc: "Retrieves various information about device" diff --git a/scripts/core/program.yml b/scripts/core/program.yml index 0449a58d6d..037b65ccc5 100644 --- a/scripts/core/program.yml +++ b/scripts/core/program.yml @@ -528,6 +528,7 @@ desc: "Set an array of specialization constants on a Program." class: $xProgram name: SetSpecializationConstants details: + - "This entry point is optional, the application should query for support with device query $X_DEVICE_INFO_PROGRAM_SET_SPECIALIZATION_CONSTANTS passed to $xDeviceGetInfo." - "The application may call this function from simultaneous threads for the same device." - "The implementation of this function should be thread-safe." - "`hProgram` must have been created with the $xProgramCreateWithIL entry point." @@ -546,6 +547,8 @@ params: returns: - $X_RESULT_ERROR_INVALID_SIZE: - "`count == 0`" + - $X_RESULT_ERROR_UNSUPPORTED_FEATURE: + - "If $X_DEVICE_INFO_PROGRAM_SET_SPECIALIZATION_CONSTANTS query is false" - $X_RESULT_ERROR_INVALID_VALUE: - "A pSpecConstant entry contains a size that does not match that of the specialization constant in the module." - "A pSpecConstant entry contains a nullptr pValue." diff --git a/source/adapters/cuda/device.cpp b/source/adapters/cuda/device.cpp index 10c4e1d1af..bcdfe8f6dd 100644 --- a/source/adapters/cuda/device.cpp +++ b/source/adapters/cuda/device.cpp @@ -1065,6 +1065,7 @@ UR_APIEXPORT ur_result_t UR_APICALL urDeviceGetInfo(ur_device_handle_t hDevice, return ReturnValue(AddressBuffer, strnlen(AddressBuffer, AddressBufferSize - 1) + 1); } + case UR_DEVICE_INFO_PROGRAM_SET_SPECIALIZATION_CONSTANTS: case UR_DEVICE_INFO_KERNEL_SET_SPECIALIZATION_CONSTANTS: return ReturnValue(static_cast(false)); // TODO: Investigate if this information is available on CUDA. diff --git a/source/adapters/hip/device.cpp b/source/adapters/hip/device.cpp index 85c4dba8f6..76bfefaa33 100644 --- a/source/adapters/hip/device.cpp +++ b/source/adapters/hip/device.cpp @@ -789,6 +789,10 @@ UR_APIEXPORT ur_result_t UR_APICALL urDeviceGetInfo(ur_device_handle_t hDevice, return ReturnValue(ur_bool_t{false}); } + case UR_DEVICE_INFO_PROGRAM_SET_SPECIALIZATION_CONSTANTS: { + return ReturnValue(ur_bool_t{false}); + } + case UR_DEVICE_INFO_ATOMIC_MEMORY_ORDER_CAPABILITIES: { ur_memory_order_capability_flags_t Capabilities = UR_MEMORY_ORDER_CAPABILITY_FLAG_RELAXED | diff --git a/source/adapters/level_zero/device.cpp b/source/adapters/level_zero/device.cpp index 373826f0fd..d26cef79f2 100644 --- a/source/adapters/level_zero/device.cpp +++ b/source/adapters/level_zero/device.cpp @@ -1154,6 +1154,8 @@ ur_result_t urDeviceGetInfo( // L0 does not support sampling 1D USM sampled image data. return ReturnValue(false); } + case UR_DEVICE_INFO_PROGRAM_SET_SPECIALIZATION_CONSTANTS: + return ReturnValue(true); case UR_DEVICE_INFO_KERNEL_SET_SPECIALIZATION_CONSTANTS: return ReturnValue(false); case UR_DEVICE_INFO_GLOBAL_VARIABLE_SUPPORT: diff --git a/source/adapters/native_cpu/device.cpp b/source/adapters/native_cpu/device.cpp index b00892d040..6f3234ab0b 100644 --- a/source/adapters/native_cpu/device.cpp +++ b/source/adapters/native_cpu/device.cpp @@ -428,6 +428,11 @@ UR_APIEXPORT ur_result_t UR_APICALL urDeviceGetInfo(ur_device_handle_t hDevice, case UR_DEVICE_INFO_LOW_POWER_EVENTS_EXP: return ReturnValue(false); + + case UR_DEVICE_INFO_KERNEL_SET_SPECIALIZATION_CONSTANTS: + case UR_DEVICE_INFO_PROGRAM_SET_SPECIALIZATION_CONSTANTS: + return ReturnValue(false); + default: DIE_NO_IMPLEMENTATION; } diff --git a/source/adapters/opencl/device.cpp b/source/adapters/opencl/device.cpp index dc5343b51c..4ed3eeb3b0 100644 --- a/source/adapters/opencl/device.cpp +++ b/source/adapters/opencl/device.cpp @@ -7,6 +7,7 @@ //===-----------------------------------------------------------------===// #include "device.hpp" +#include "adapter.hpp" #include "common.hpp" #include "platform.hpp" @@ -1125,6 +1126,11 @@ UR_APIEXPORT ur_result_t UR_APICALL urDeviceGetInfo(ur_device_handle_t hDevice, return ReturnValue(UUID); } + case UR_DEVICE_INFO_PROGRAM_SET_SPECIALIZATION_CONSTANTS: { + return ReturnValue( + ur::cl::getAdapter()->clSetProgramSpecializationConstant != nullptr); + } + // We can't query to check if these are supported, they will need to be // manually updated if support is ever implemented. case UR_DEVICE_INFO_KERNEL_SET_SPECIALIZATION_CONSTANTS: diff --git a/source/loader/ur_libapi.cpp b/source/loader/ur_libapi.cpp index c434f750b6..a9558fdb6c 100644 --- a/source/loader/ur_libapi.cpp +++ b/source/loader/ur_libapi.cpp @@ -3531,6 +3531,10 @@ ur_result_t UR_APICALL urProgramGetBuildInfo( /// @brief Set an array of specialization constants on a Program. /// /// @details +/// - This entry point is optional, the application should query for support +/// with device query +/// ::UR_DEVICE_INFO_PROGRAM_SET_SPECIALIZATION_CONSTANTS passed to +/// ::urDeviceGetInfo. /// - The application may call this function from simultaneous threads for /// the same device. /// - The implementation of this function should be thread-safe. @@ -3550,6 +3554,8 @@ ur_result_t UR_APICALL urProgramGetBuildInfo( /// + `NULL == pSpecConstants` /// - ::UR_RESULT_ERROR_INVALID_SIZE /// + `count == 0` +/// - ::UR_RESULT_ERROR_UNSUPPORTED_FEATURE +/// + If ::UR_DEVICE_INFO_PROGRAM_SET_SPECIALIZATION_CONSTANTS query is false /// - ::UR_RESULT_ERROR_INVALID_VALUE /// + A pSpecConstant entry contains a size that does not match that of the specialization constant in the module. /// + A pSpecConstant entry contains a nullptr pValue. diff --git a/source/ur_api.cpp b/source/ur_api.cpp index 7aa9cfcdd4..cf239024cf 100644 --- a/source/ur_api.cpp +++ b/source/ur_api.cpp @@ -3019,6 +3019,10 @@ ur_result_t UR_APICALL urProgramGetBuildInfo( /// @brief Set an array of specialization constants on a Program. /// /// @details +/// - This entry point is optional, the application should query for support +/// with device query +/// ::UR_DEVICE_INFO_PROGRAM_SET_SPECIALIZATION_CONSTANTS passed to +/// ::urDeviceGetInfo. /// - The application may call this function from simultaneous threads for /// the same device. /// - The implementation of this function should be thread-safe. @@ -3038,6 +3042,8 @@ ur_result_t UR_APICALL urProgramGetBuildInfo( /// + `NULL == pSpecConstants` /// - ::UR_RESULT_ERROR_INVALID_SIZE /// + `count == 0` +/// - ::UR_RESULT_ERROR_UNSUPPORTED_FEATURE +/// + If ::UR_DEVICE_INFO_PROGRAM_SET_SPECIALIZATION_CONSTANTS query is false /// - ::UR_RESULT_ERROR_INVALID_VALUE /// + A pSpecConstant entry contains a size that does not match that of the specialization constant in the module. /// + A pSpecConstant entry contains a nullptr pValue. diff --git a/test/conformance/device/urDeviceGetInfo.cpp b/test/conformance/device/urDeviceGetInfo.cpp index 39cca23581..46f12bc348 100644 --- a/test/conformance/device/urDeviceGetInfo.cpp +++ b/test/conformance/device/urDeviceGetInfo.cpp @@ -109,6 +109,7 @@ static std::unordered_map device_info_size_map = { {UR_DEVICE_INFO_BFLOAT16, sizeof(ur_bool_t)}, {UR_DEVICE_INFO_MAX_COMPUTE_QUEUE_INDICES, sizeof(uint32_t)}, {UR_DEVICE_INFO_KERNEL_SET_SPECIALIZATION_CONSTANTS, sizeof(ur_bool_t)}, + {UR_DEVICE_INFO_PROGRAM_SET_SPECIALIZATION_CONSTANTS, sizeof(ur_bool_t)}, {UR_DEVICE_INFO_MEMORY_BUS_WIDTH, sizeof(uint32_t)}, {UR_DEVICE_INFO_MAX_WORK_GROUPS_3D, sizeof(size_t[3])}, {UR_DEVICE_INFO_ASYNC_BARRIER, sizeof(ur_bool_t)}, diff --git a/test/conformance/program/urProgramSetSpecializationConstants.cpp b/test/conformance/program/urProgramSetSpecializationConstants.cpp index 7f477c4582..c1f5b150e8 100644 --- a/test/conformance/program/urProgramSetSpecializationConstants.cpp +++ b/test/conformance/program/urProgramSetSpecializationConstants.cpp @@ -10,6 +10,16 @@ struct urProgramSetSpecializationConstantsTest : uur::urKernelExecutionTest { void SetUp() override { program_name = "spec_constant"; UUR_RETURN_ON_FATAL_FAILURE(urProgramTest::SetUp()); + + bool supports_kernel_spec_constant = false; + ASSERT_SUCCESS(urDeviceGetInfo( + device, UR_DEVICE_INFO_PROGRAM_SET_SPECIALIZATION_CONSTANTS, + sizeof(supports_kernel_spec_constant), + &supports_kernel_spec_constant, nullptr)); + if (!supports_kernel_spec_constant) { + GTEST_SKIP() + << "Device does not support setting program spec constants."; + } } uint32_t spec_value = 42; @@ -19,20 +29,53 @@ struct urProgramSetSpecializationConstantsTest : uur::urKernelExecutionTest { }; UUR_INSTANTIATE_DEVICE_TEST_SUITE_P(urProgramSetSpecializationConstantsTest); +struct urProgramSetSpecializationConstantsNegativeTest + : uur::urKernelExecutionTest { + void SetUp() override { + program_name = "spec_constant"; + UUR_RETURN_ON_FATAL_FAILURE(urProgramTest::SetUp()); + + bool supports_kernel_spec_constant = false; + ASSERT_SUCCESS(urDeviceGetInfo( + device, UR_DEVICE_INFO_PROGRAM_SET_SPECIALIZATION_CONSTANTS, + sizeof(supports_kernel_spec_constant), + &supports_kernel_spec_constant, nullptr)); + if (supports_kernel_spec_constant) { + GTEST_SKIP() + << "Device does supports setting program spec constants."; + } + } + + uint32_t spec_value = 42; + uint32_t default_spec_value = 1000; // Must match the one in the SYCL source + ur_specialization_constant_info_t info = {0, sizeof(spec_value), + &spec_value}; +}; +UUR_INSTANTIATE_DEVICE_TEST_SUITE_P( + urProgramSetSpecializationConstantsNegativeTest); + struct urProgramSetMultipleSpecializationConstantsTest : uur::urKernelExecutionTest { // The types of spec constants in this program are {uint32_t, uint64_t, bool} void SetUp() override { program_name = "spec_constant_multiple"; UUR_RETURN_ON_FATAL_FAILURE(urProgramTest::SetUp()); + + bool supports_kernel_spec_constant = false; + ASSERT_SUCCESS(urDeviceGetInfo( + device, UR_DEVICE_INFO_PROGRAM_SET_SPECIALIZATION_CONSTANTS, + sizeof(supports_kernel_spec_constant), + &supports_kernel_spec_constant, nullptr)); + if (!supports_kernel_spec_constant) { + GTEST_SKIP() + << "Device does not support setting program spec constants."; + } } }; UUR_INSTANTIATE_DEVICE_TEST_SUITE_P( urProgramSetMultipleSpecializationConstantsTest); TEST_P(urProgramSetSpecializationConstantsTest, Success) { - UUR_KNOWN_FAILURE_ON(uur::CUDA{}, uur::HIP{}); - ASSERT_SUCCESS(urProgramSetSpecializationConstants(program, 1, &info)); ASSERT_SUCCESS(urProgramBuild(context, program, nullptr)); auto entry_points = @@ -46,9 +89,12 @@ TEST_P(urProgramSetSpecializationConstantsTest, Success) { ValidateBuffer(buffer, sizeof(spec_value), spec_value); } -TEST_P(urProgramSetSpecializationConstantsTest, UseDefaultValue) { - UUR_KNOWN_FAILURE_ON(uur::CUDA{}, uur::HIP{}); +TEST_P(urProgramSetSpecializationConstantsNegativeTest, Unsupported) { + ASSERT_EQ_RESULT(UR_RESULT_ERROR_UNSUPPORTED_FEATURE, + urProgramSetSpecializationConstants(program, 1, &info)); +} +TEST_P(urProgramSetSpecializationConstantsTest, UseDefaultValue) { ur_platform_backend_t backend; ASSERT_SUCCESS(urPlatformGetInfo(platform, UR_PLATFORM_INFO_BACKEND, sizeof(ur_platform_backend_t), &backend, @@ -72,8 +118,6 @@ TEST_P(urProgramSetSpecializationConstantsTest, UseDefaultValue) { } TEST_P(urProgramSetMultipleSpecializationConstantsTest, MultipleCalls) { - UUR_KNOWN_FAILURE_ON(uur::CUDA{}, uur::HIP{}); - uint32_t a = 100; uint64_t b = 200; bool c = false; @@ -105,8 +149,6 @@ TEST_P(urProgramSetMultipleSpecializationConstantsTest, MultipleCalls) { } TEST_P(urProgramSetMultipleSpecializationConstantsTest, SingleCall) { - UUR_KNOWN_FAILURE_ON(uur::CUDA{}, uur::HIP{}); - uint32_t a = 200; uint64_t b = 300; bool c = true; @@ -162,8 +204,7 @@ TEST_P(urProgramSetSpecializationConstantsTest, InvalidValueSize) { } TEST_P(urProgramSetSpecializationConstantsTest, InvalidValueId) { - UUR_KNOWN_FAILURE_ON(uur::CUDA{}, uur::HIP{}, uur::LevelZero{}, - uur::LevelZeroV2{}); + UUR_KNOWN_FAILURE_ON(uur::LevelZero{}, uur::LevelZeroV2{}); ur_specialization_constant_info_t bad_info = {999, sizeof(spec_value), &spec_value}; @@ -173,8 +214,7 @@ TEST_P(urProgramSetSpecializationConstantsTest, InvalidValueId) { } TEST_P(urProgramSetSpecializationConstantsTest, InvalidValuePtr) { - UUR_KNOWN_FAILURE_ON(uur::CUDA{}, uur::HIP{}, uur::LevelZero{}, - uur::LevelZeroV2{}); + UUR_KNOWN_FAILURE_ON(uur::LevelZero{}, uur::LevelZeroV2{}); ur_specialization_constant_info_t bad_info = {0, sizeof(spec_value), nullptr}; diff --git a/tools/urinfo/urinfo.hpp b/tools/urinfo/urinfo.hpp index 9b052fee39..724a5e3d36 100644 --- a/tools/urinfo/urinfo.hpp +++ b/tools/urinfo/urinfo.hpp @@ -337,6 +337,9 @@ inline void printDeviceInfos(ur_device_handle_t hDevice, std::cout << prefix; printDeviceInfo(hDevice, UR_DEVICE_INFO_USM_POOL_SUPPORT); std::cout << prefix; + printDeviceInfo( + hDevice, UR_DEVICE_INFO_PROGRAM_SET_SPECIALIZATION_CONSTANTS); + std::cout << prefix; printDeviceInfo(hDevice, UR_DEVICE_INFO_COMMAND_BUFFER_SUPPORT_EXP); std::cout << prefix;