| // |
| // Copyright (c) 2020 The Khronos Group Inc. |
| // |
| // Licensed under the Apache License, Version 2.0 (the "License"); |
| // you may not use this file except in compliance with the License. |
| // You may obtain a copy of the License at |
| // |
| // http://www.apache.org/licenses/LICENSE-2.0 |
| // |
| // Unless required by applicable law or agreed to in writing, software |
| // distributed under the License is distributed on an "AS IS" BASIS, |
| // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| // See the License for the specific language governing permissions and |
| // limitations under the License. |
| // |
| #include "harness/compat.h" |
| |
| #include <array> |
| #include <bitset> |
| |
| #include "harness/testHarness.h" |
| #include "harness/deviceInfo.h" |
| |
| using uuid = std::array<cl_uchar, CL_UUID_SIZE_KHR>; |
| using luid = std::array<cl_uchar, CL_LUID_SIZE_KHR>; |
| |
| template <typename T> static void log_info_uuid(const T &id) |
| { |
| for (const cl_uchar c : id) |
| { |
| log_info("%02x", static_cast<unsigned>(c)); |
| } |
| } |
| |
| template <typename T> static void log_error_uuid(const T &id) |
| { |
| for (const cl_uchar c : id) |
| { |
| log_error("%02x", static_cast<unsigned>(c)); |
| } |
| } |
| |
| static bool check_device_info_returns(const cl_int err, const size_t size, |
| const size_t expected_size) |
| { |
| if (err != CL_SUCCESS) |
| { |
| print_error(err, "clGetDeviceInfo failed"); |
| return false; |
| } |
| else if (size != expected_size) |
| { |
| log_error("Invalid size written by clGetDeviceInfo (%zu != %zu)\n", |
| size, expected_size); |
| return false; |
| } |
| |
| return true; |
| } |
| |
| template <typename T> |
| static bool get_uuid(const cl_device_id device, const cl_device_info info, |
| T &id, const bool twice = true) |
| { |
| const size_t id_size = id.size() * sizeof(id[0]); |
| |
| size_t size_ret; |
| cl_int err = clGetDeviceInfo(device, info, id_size, id.data(), &size_ret); |
| if (!check_device_info_returns(err, size_ret, id_size)) |
| { |
| return false; |
| } |
| |
| /* Check that IDs are (at the very least) stable across two successive |
| * clGetDeviceInfo calls. Check conditionally, as it is undefined what the |
| * query for CL_DEVICE_LUID_KHR returns if CL_DEVICE_LUID_VALID_KHR returns |
| * false. */ |
| if (twice) |
| { |
| T id_2; |
| size_t size_ret_2; |
| err = clGetDeviceInfo(device, info, id_size, id_2.data(), &size_ret_2); |
| if (!check_device_info_returns(err, size_ret_2, id_size)) |
| { |
| return false; |
| } |
| |
| if (id != id_2) |
| { |
| log_error("Got different IDs from the same ID device info ("); |
| log_error_uuid(id); |
| log_error(" != "); |
| log_error_uuid(id_2); |
| log_error(")\n"); |
| return false; |
| } |
| } |
| |
| return true; |
| } |
| |
| int test_device_uuid(cl_device_id deviceID, cl_context context, |
| cl_command_queue ignoreQueue, int num_elements) |
| { |
| if (!is_extension_available(deviceID, "cl_khr_device_uuid")) |
| { |
| log_info("cl_khr_device_uuid not supported. Skipping test...\n"); |
| return 0; |
| } |
| |
| int total_errors = 0; |
| |
| /* CL_DEVICE_UUID_KHR */ |
| uuid device_uuid; |
| bool success = get_uuid(deviceID, CL_DEVICE_UUID_KHR, device_uuid); |
| if (!success) |
| { |
| log_error("Error getting device UUID\n"); |
| ++total_errors; |
| } |
| else |
| { |
| log_info("\tDevice UUID: "); |
| log_info_uuid(device_uuid); |
| log_info("\n"); |
| } |
| |
| /* CL_DRIVER_UUID_KHR */ |
| uuid driver_uuid; |
| success = get_uuid(deviceID, CL_DRIVER_UUID_KHR, driver_uuid); |
| if (!success) |
| { |
| log_error("Error getting driver UUID\n"); |
| ++total_errors; |
| } |
| else |
| { |
| log_info("\tDriver UUID: "); |
| log_info_uuid(driver_uuid); |
| log_info("\n"); |
| } |
| |
| size_t size_ret{}; |
| |
| /* CL_DEVICE_LUID_VALID_KHR */ |
| cl_bool device_luid_valid{}; |
| cl_int err = clGetDeviceInfo(deviceID, CL_DEVICE_LUID_VALID_KHR, |
| sizeof(device_luid_valid), &device_luid_valid, |
| &size_ret); |
| if (!check_device_info_returns(err, size_ret, sizeof(device_luid_valid))) |
| { |
| log_error("Error getting device LUID validity\n"); |
| ++total_errors; |
| device_luid_valid = false; |
| } |
| else |
| { |
| log_info("\tDevice LUID validity is %s\n", |
| device_luid_valid ? "true" : "false"); |
| } |
| |
| /* CL_DEVICE_LUID_KHR */ |
| luid device_luid; |
| success = |
| get_uuid(deviceID, CL_DEVICE_LUID_KHR, device_luid, device_luid_valid); |
| if (!success) |
| { |
| log_error("Error getting device LUID\n"); |
| ++total_errors; |
| } |
| else |
| { |
| log_info("\tDevice LUID: "); |
| log_info_uuid(device_luid); |
| log_info("\n"); |
| } |
| |
| /* CL_DEVICE_NODE_MASK_KHR */ |
| cl_uint device_node_mask{}; |
| err = |
| clGetDeviceInfo(deviceID, CL_DEVICE_NODE_MASK_KHR, |
| sizeof(device_node_mask), &device_node_mask, &size_ret); |
| if (!check_device_info_returns(err, size_ret, sizeof(device_node_mask))) |
| { |
| log_error("Error getting device node mask\n"); |
| ++total_errors; |
| } |
| else |
| { |
| log_info("\tNode mask : %08lx\n", |
| static_cast<unsigned long>(device_node_mask)); |
| |
| /* If the LUID is valid, there must be one and only one bit set in the |
| * node mask */ |
| if (device_luid_valid) |
| { |
| static constexpr size_t cl_uint_size_in_bits = 32; |
| const size_t bit_count = |
| std::bitset<cl_uint_size_in_bits>(device_node_mask).count(); |
| if (1 != bit_count) |
| { |
| log_error("Wrong amount of bits set in node mask (%zu != 1) " |
| "with valid LUID\n", |
| bit_count); |
| ++total_errors; |
| } |
| } |
| } |
| |
| return total_errors; |
| } |