1 //
2 // Copyright (c) 2020 The Khronos Group Inc.
3 //
4 // Licensed under the Apache License, Version 2.0 (the "License");
5 // you may not use this file except in compliance with the License.
6 // You may obtain a copy of the License at
7 //
8 // http://www.apache.org/licenses/LICENSE-2.0
9 //
10 // Unless required by applicable law or agreed to in writing, software
11 // distributed under the License is distributed on an "AS IS" BASIS,
12 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 // See the License for the specific language governing permissions and
14 // limitations under the License.
15 //
16 #include "harness/compat.h"
17
18 #include <array>
19 #include <bitset>
20
21 #include "harness/testHarness.h"
22 #include "harness/deviceInfo.h"
23
24 using uuid = std::array<cl_uchar, CL_UUID_SIZE_KHR>;
25 using luid = std::array<cl_uchar, CL_LUID_SIZE_KHR>;
26
log_info_uuid(const T & id)27 template <typename T> static void log_info_uuid(const T &id)
28 {
29 for (const cl_uchar c : id)
30 {
31 log_info("%02x", static_cast<unsigned>(c));
32 }
33 }
34
log_error_uuid(const T & id)35 template <typename T> static void log_error_uuid(const T &id)
36 {
37 for (const cl_uchar c : id)
38 {
39 log_error("%02x", static_cast<unsigned>(c));
40 }
41 }
42
check_device_info_returns(const cl_int err,const size_t size,const size_t expected_size)43 static bool check_device_info_returns(const cl_int err, const size_t size,
44 const size_t expected_size)
45 {
46 if (err != CL_SUCCESS)
47 {
48 print_error(err, "clGetDeviceInfo failed");
49 return false;
50 }
51 else if (size != expected_size)
52 {
53 log_error("Invalid size written by clGetDeviceInfo (%zu != %zu)\n",
54 size, expected_size);
55 return false;
56 }
57
58 return true;
59 }
60
61 template <typename T>
get_uuid(const cl_device_id device,const cl_device_info info,T & id,const bool twice=true)62 static bool get_uuid(const cl_device_id device, const cl_device_info info,
63 T &id, const bool twice = true)
64 {
65 const size_t id_size = id.size() * sizeof(id[0]);
66
67 size_t size_ret;
68 cl_int err = clGetDeviceInfo(device, info, id_size, id.data(), &size_ret);
69 if (!check_device_info_returns(err, size_ret, id_size))
70 {
71 return false;
72 }
73
74 /* Check that IDs are (at the very least) stable across two successive
75 * clGetDeviceInfo calls. Check conditionally, as it is undefined what the
76 * query for CL_DEVICE_LUID_KHR returns if CL_DEVICE_LUID_VALID_KHR returns
77 * false. */
78 if (twice)
79 {
80 T id_2;
81 size_t size_ret_2;
82 err = clGetDeviceInfo(device, info, id_size, id_2.data(), &size_ret_2);
83 if (!check_device_info_returns(err, size_ret_2, id_size))
84 {
85 return false;
86 }
87
88 if (id != id_2)
89 {
90 log_error("Got different IDs from the same ID device info (");
91 log_error_uuid(id);
92 log_error(" != ");
93 log_error_uuid(id_2);
94 log_error(")\n");
95 return false;
96 }
97 }
98
99 return true;
100 }
101
test_device_uuid(cl_device_id deviceID,cl_context context,cl_command_queue ignoreQueue,int num_elements)102 int test_device_uuid(cl_device_id deviceID, cl_context context,
103 cl_command_queue ignoreQueue, int num_elements)
104 {
105 if (!is_extension_available(deviceID, "cl_khr_device_uuid"))
106 {
107 log_info("cl_khr_device_uuid not supported. Skipping test...\n");
108 return 0;
109 }
110
111 int total_errors = 0;
112
113 /* CL_DEVICE_UUID_KHR */
114 uuid device_uuid;
115 bool success = get_uuid(deviceID, CL_DEVICE_UUID_KHR, device_uuid);
116 if (!success)
117 {
118 log_error("Error getting device UUID\n");
119 ++total_errors;
120 }
121 else
122 {
123 log_info("\tDevice UUID: ");
124 log_info_uuid(device_uuid);
125 log_info("\n");
126 }
127
128 /* CL_DRIVER_UUID_KHR */
129 uuid driver_uuid;
130 success = get_uuid(deviceID, CL_DRIVER_UUID_KHR, driver_uuid);
131 if (!success)
132 {
133 log_error("Error getting driver UUID\n");
134 ++total_errors;
135 }
136 else
137 {
138 log_info("\tDriver UUID: ");
139 log_info_uuid(driver_uuid);
140 log_info("\n");
141 }
142
143 size_t size_ret{};
144
145 /* CL_DEVICE_LUID_VALID_KHR */
146 cl_bool device_luid_valid{};
147 cl_int err = clGetDeviceInfo(deviceID, CL_DEVICE_LUID_VALID_KHR,
148 sizeof(device_luid_valid), &device_luid_valid,
149 &size_ret);
150 if (!check_device_info_returns(err, size_ret, sizeof(device_luid_valid)))
151 {
152 log_error("Error getting device LUID validity\n");
153 ++total_errors;
154 device_luid_valid = false;
155 }
156 else
157 {
158 log_info("\tDevice LUID validity is %s\n",
159 device_luid_valid ? "true" : "false");
160 }
161
162 /* CL_DEVICE_LUID_KHR */
163 luid device_luid;
164 success =
165 get_uuid(deviceID, CL_DEVICE_LUID_KHR, device_luid, device_luid_valid);
166 if (!success)
167 {
168 log_error("Error getting device LUID\n");
169 ++total_errors;
170 }
171 else
172 {
173 log_info("\tDevice LUID: ");
174 log_info_uuid(device_luid);
175 log_info("\n");
176 }
177
178 /* CL_DEVICE_NODE_MASK_KHR */
179 cl_uint device_node_mask{};
180 err =
181 clGetDeviceInfo(deviceID, CL_DEVICE_NODE_MASK_KHR,
182 sizeof(device_node_mask), &device_node_mask, &size_ret);
183 if (!check_device_info_returns(err, size_ret, sizeof(device_node_mask)))
184 {
185 log_error("Error getting device node mask\n");
186 ++total_errors;
187 }
188 else
189 {
190 log_info("\tNode mask : %08lx\n",
191 static_cast<unsigned long>(device_node_mask));
192
193 /* If the LUID is valid, there must be one and only one bit set in the
194 * node mask */
195 if (device_luid_valid)
196 {
197 static constexpr size_t cl_uint_size_in_bits = 32;
198 const size_t bit_count =
199 std::bitset<cl_uint_size_in_bits>(device_node_mask).count();
200 if (1 != bit_count)
201 {
202 log_error("Wrong amount of bits set in node mask (%zu != 1) "
203 "with valid LUID\n",
204 bit_count);
205 ++total_errors;
206 }
207 }
208 }
209
210 return total_errors;
211 }
212