// // 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 #include #include "harness/testHarness.h" #include "harness/deviceInfo.h" using uuid = std::array; using luid = std::array; template static void log_info_uuid(const T &id) { for (const cl_uchar c : id) { log_info("%02x", static_cast(c)); } } template static void log_error_uuid(const T &id) { for (const cl_uchar c : id) { log_error("%02x", static_cast(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 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(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(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; }