1 //
2 // Copyright (c) 2022 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
17 #include "basic_command_buffer.h"
18 #include "procs.h"
19
20 #include <vector>
21
22 //--------------------------------------------------------------------------
23 enum class CombufInfoTestMode
24 {
25 CITM_QUEUES = 0,
26 CITM_REF_COUNT,
27 CITM_STATE,
28 CITM_PROP_ARRAY,
29 CITM_CONTEXT,
30 };
31
32 namespace {
33
34 ////////////////////////////////////////////////////////////////////////////////
35 // clGetCommandBufferInfoKHR tests for cl_khr_command_buffer which handles below
36 // cases:
37 // -test case for CL_COMMAND_BUFFER_NUM_QUEUES_KHR &
38 // CL_COMMAND_BUFFER_QUEUES_KHR queries
39 // -test case for CL_COMMAND_BUFFER_REFERENCE_COUNT_KHR query
40 // -test case for CL_COMMAND_BUFFER_STATE_KHR query
41 // -test case for CL_COMMAND_BUFFER_PROPERTIES_ARRAY_KHR query
42 // -test case for CL_COMMAND_BUFFER_CONTEXT_KHR query
43
44 template <CombufInfoTestMode test_mode>
45 struct CommandBufferGetCommandBufferInfo : public BasicCommandBufferTest
46 {
CommandBufferGetCommandBufferInfo__anone5ca8e470111::CommandBufferGetCommandBufferInfo47 CommandBufferGetCommandBufferInfo(cl_device_id device, cl_context context,
48 cl_command_queue queue)
49 : BasicCommandBufferTest(device, context, queue)
50 {}
51
52 //--------------------------------------------------------------------------
Run__anone5ca8e470111::CommandBufferGetCommandBufferInfo53 cl_int Run() override
54 {
55 cl_int error = CL_SUCCESS;
56
57 switch (test_mode)
58 {
59 case CombufInfoTestMode::CITM_QUEUES:
60 error = RunQueuesInfoTest();
61 test_error(error, "RunQueuesInfoTest failed");
62 break;
63 case CombufInfoTestMode::CITM_REF_COUNT:
64 error = RunRefCountInfoTest();
65 test_error(error, "RunRefCountInfoTest failed");
66 break;
67 case CombufInfoTestMode::CITM_STATE:
68 error = RunStateInfoTest();
69 test_error(error, "RunStateInfoTest failed");
70 break;
71 case CombufInfoTestMode::CITM_PROP_ARRAY:
72 error = RunPropArrayInfoTest();
73 test_error(error, "RunPropArrayInfoTest failed");
74 break;
75 case CombufInfoTestMode::CITM_CONTEXT:
76 error = RunContextInfoTest();
77 test_error(error, "RunContextInfoTest failed");
78 break;
79 }
80
81 return CL_SUCCESS;
82 }
83
84 //--------------------------------------------------------------------------
RecordCommandBuffer__anone5ca8e470111::CommandBufferGetCommandBufferInfo85 cl_int RecordCommandBuffer()
86 {
87 cl_int error = CL_SUCCESS;
88
89 error = clCommandNDRangeKernelKHR(
90 command_buffer, nullptr, nullptr, kernel, 1, nullptr, &num_elements,
91 nullptr, 0, nullptr, nullptr, nullptr);
92 test_error(error, "clCommandNDRangeKernelKHR failed");
93
94 error = clFinalizeCommandBufferKHR(command_buffer);
95 test_error(error, "clFinalizeCommandBufferKHR failed");
96 return CL_SUCCESS;
97 }
98
99 //--------------------------------------------------------------------------
RunQueuesInfoTest__anone5ca8e470111::CommandBufferGetCommandBufferInfo100 cl_int RunQueuesInfoTest()
101 {
102 cl_int error = TEST_PASS;
103
104 // record command buffers
105 error = RecordCommandBuffer();
106 test_error(error, "RecordCommandBuffer failed");
107
108 // vector containter added due to potential future growth, at the moment
109 // spec of cl_khr_command_buffer says command-buffer accepts only 1
110 // queue
111 std::vector<cl_command_queue> expect_queue_list = { queue };
112 cl_uint num_queues = 0;
113 size_t ret_value_size = 0;
114 error = clGetCommandBufferInfoKHR(
115 command_buffer, CL_COMMAND_BUFFER_NUM_QUEUES_KHR, sizeof(cl_uint),
116 &num_queues, &ret_value_size);
117 test_error(error, "clGetCommandBufferInfoKHR failed");
118
119 test_assert_error(
120 ret_value_size == sizeof(cl_int),
121 "Unexpected result of CL_COMMAND_BUFFER_NUM_QUEUES_KHR query!");
122
123 test_assert_error(num_queues == expect_queue_list.size(),
124 "Unexpected queue list size!");
125
126 std::vector<cl_command_queue> queue_list(num_queues);
127 size_t expect_size = queue_list.size() * sizeof(cl_command_queue);
128 error = clGetCommandBufferInfoKHR(
129 command_buffer, CL_COMMAND_BUFFER_QUEUES_KHR, expect_size,
130 &queue_list.front(), &ret_value_size);
131 test_error(error, "clGetCommandBufferInfoKHR failed");
132
133 test_assert_error(
134 ret_value_size == expect_size,
135 "Unexpected result of CL_COMMAND_BUFFER_NUM_QUEUES_KHR query!");
136
137 // We can not check if this is the right queue because this is an opaque
138 // object, test against NULL.
139 for (size_t i = 0; i < queue_list.size(); i++)
140 {
141 test_assert_error(
142 queue_list[i] == queue,
143 "clGetCommandBufferInfoKHR return values not as expected\n");
144 }
145 return TEST_PASS;
146 }
147
148 //--------------------------------------------------------------------------
RunRefCountInfoTest__anone5ca8e470111::CommandBufferGetCommandBufferInfo149 cl_int RunRefCountInfoTest()
150 {
151 cl_int error = CL_SUCCESS;
152
153 // record command buffer
154 error = RecordCommandBuffer();
155 test_error(error, "RecordCommandBuffer failed");
156
157 // collect initial reference count
158 cl_uint init_ref_count = 0;
159 error = clGetCommandBufferInfoKHR(
160 command_buffer, CL_COMMAND_BUFFER_REFERENCE_COUNT_KHR,
161 sizeof(cl_uint), &init_ref_count, nullptr);
162 test_error(error, "clGetCommandBufferInfoKHR failed");
163
164 // increase reference count through clRetainCommandBufferKHR calls
165 const cl_int min_retain_count = 2;
166 const cl_int max_retain_count = 6;
167 cl_int retain_count = std::max(
168 min_retain_count, min_retain_count + rand() % max_retain_count);
169
170 for (int i = 0; i < retain_count; i++)
171 {
172 error = clRetainCommandBufferKHR(command_buffer);
173 test_error(error, "clRetainCommandBufferKHR failed");
174 }
175
176 // verify new reference count value
177 cl_uint new_ref_count = 0;
178 error = clGetCommandBufferInfoKHR(
179 command_buffer, CL_COMMAND_BUFFER_REFERENCE_COUNT_KHR,
180 sizeof(cl_uint), &new_ref_count, nullptr);
181 test_error(error, "clGetCommandBufferInfoKHR failed");
182
183 test_assert_error(new_ref_count == (retain_count + init_ref_count),
184 "Unexpected result of "
185 "CL_COMMAND_BUFFER_REFERENCE_COUNT_KHR query!");
186
187 // decrease reference count through clReleaseCommandBufferKHR calls
188 for (int i = 0; i < retain_count; i++)
189 {
190 error = clReleaseCommandBufferKHR(command_buffer);
191 test_error(error, "clReleaseCommandBufferKHR failed");
192 }
193
194 // verify new reference count value
195 error = clGetCommandBufferInfoKHR(
196 command_buffer, CL_COMMAND_BUFFER_REFERENCE_COUNT_KHR,
197 sizeof(cl_uint), &new_ref_count, nullptr);
198 test_error(error, "clGetCommandBufferInfoKHR failed");
199
200 test_assert_error(new_ref_count == init_ref_count,
201 "Unexpected result of "
202 "CL_COMMAND_BUFFER_REFERENCE_COUNT_KHR query!");
203
204 return TEST_PASS;
205 }
206
207 //--------------------------------------------------------------------------
RunStateInfoTest__anone5ca8e470111::CommandBufferGetCommandBufferInfo208 cl_int RunStateInfoTest()
209 {
210 cl_int error = CL_SUCCESS;
211
212 // lambda to verify given state
213 auto verify_state = [&](const cl_command_buffer_state_khr &expected) {
214 cl_command_buffer_state_khr state = ~cl_command_buffer_state_khr(0);
215
216 cl_int error = clGetCommandBufferInfoKHR(
217 command_buffer, CL_COMMAND_BUFFER_STATE_KHR, sizeof(state),
218 &state, nullptr);
219 test_error_ret(error, "clGetCommandBufferInfoKHR failed",
220 TEST_FAIL);
221
222 test_assert_error(
223 state == expected,
224 "Unexpected result of CL_COMMAND_BUFFER_STATE_KHR query!");
225
226 return TEST_PASS;
227 };
228
229 // verify recording state
230 error = verify_state(CL_COMMAND_BUFFER_STATE_RECORDING_KHR);
231 test_error(error, "verify_state failed");
232
233 // record command buffer
234 error = RecordCommandBuffer();
235 test_error(error, "RecordCommandBuffer failed");
236
237 // verify executable state
238 error = verify_state(CL_COMMAND_BUFFER_STATE_EXECUTABLE_KHR);
239 test_error(error, "verify_state failed");
240
241 error = clEnqueueFillBuffer(queue, out_mem, &pattern, sizeof(cl_int), 0,
242 data_size(), 0, nullptr, nullptr);
243 test_error(error, "clEnqueueFillBuffer failed");
244
245 clEventWrapper trigger_event = clCreateUserEvent(context, &error);
246 test_error(error, "clCreateUserEvent failed");
247
248 clEventWrapper execute_event;
249 // enqueued command buffer blocked on user event
250 error = clEnqueueCommandBufferKHR(0, nullptr, command_buffer, 1,
251 &trigger_event, &execute_event);
252 test_error(error, "clEnqueueCommandBufferKHR failed");
253
254 // verify pending state
255 error = verify_state(CL_COMMAND_BUFFER_STATE_PENDING_KHR);
256
257 // execute command buffer
258 cl_int signal_error = clSetUserEventStatus(trigger_event, CL_COMPLETE);
259
260 test_error(error, "verify_state failed");
261
262 test_error(signal_error, "clSetUserEventStatus failed");
263
264 error = clWaitForEvents(1, &execute_event);
265 test_error(error, "Unable to wait for execute event");
266
267 // verify executable state
268 error = verify_state(CL_COMMAND_BUFFER_STATE_EXECUTABLE_KHR);
269 test_error(error, "verify_state failed");
270
271 return CL_SUCCESS;
272 }
273
274 //--------------------------------------------------------------------------
RunPropArrayInfoTest__anone5ca8e470111::CommandBufferGetCommandBufferInfo275 cl_int RunPropArrayInfoTest()
276 {
277 cl_int error = CL_SUCCESS;
278
279 // record command buffer
280 error = RecordCommandBuffer();
281 test_error(error, "RecordCommandBuffer failed");
282
283 size_t ret_value_size = 0;
284 std::vector<cl_command_buffer_properties_khr> combuf_props;
285 error = clGetCommandBufferInfoKHR(
286 command_buffer, CL_COMMAND_BUFFER_PROPERTIES_ARRAY_KHR, 0, nullptr,
287 &ret_value_size);
288 test_error_ret(error, "clGetCommandBufferInfoKHR failed", TEST_FAIL);
289
290 // command buffer created without sumultaneous use ? 0 size possible
291 if (!simultaneous_use_support && ret_value_size == 0) return TEST_PASS;
292
293 // ... otherwise 0 size prop array is not an acceptable value
294 test_assert_error(ret_value_size != 0,
295 "Unexpected result of "
296 "CL_COMMAND_BUFFER_PROPERTIES_ARRAY_KHR query!");
297
298 cl_uint num_ret_props =
299 ret_value_size / sizeof(cl_command_buffer_properties_khr);
300 test_assert_error(num_ret_props != 0,
301 "Unexpected result of "
302 "CL_COMMAND_BUFFER_PROPERTIES_ARRAY_KHR query!");
303
304 combuf_props.resize(num_ret_props);
305 error = clGetCommandBufferInfoKHR(
306 command_buffer, CL_COMMAND_BUFFER_PROPERTIES_ARRAY_KHR,
307 num_ret_props * sizeof(cl_command_buffer_properties_khr),
308 combuf_props.data(), nullptr);
309 test_error_ret(error, "clGetCommandBufferInfoKHR failed", TEST_FAIL);
310
311 if (simultaneous_use_support)
312 {
313 // in simultaneous use case at least 3 elements in array expected
314 test_assert_error(num_ret_props >= 3,
315 "Unexpected result of "
316 "CL_COMMAND_BUFFER_PROPERTIES_ARRAY_KHR query!");
317
318 if (combuf_props[0] == CL_COMMAND_BUFFER_FLAGS_KHR
319 && combuf_props[1] == CL_COMMAND_BUFFER_SIMULTANEOUS_USE_KHR
320 && combuf_props.back() == 0)
321 return TEST_PASS;
322 }
323 else
324 {
325 if (combuf_props.back() == 0) return TEST_PASS;
326 }
327
328 return TEST_FAIL;
329 }
330
RunContextInfoTest__anone5ca8e470111::CommandBufferGetCommandBufferInfo331 cl_int RunContextInfoTest()
332 {
333 cl_int error = TEST_PASS;
334
335 // record command buffers
336 error = RecordCommandBuffer();
337 test_error(error, "RecordCommandBuffer failed");
338
339 size_t ret_value_size = 0;
340 error = clGetCommandBufferInfoKHR(command_buffer,
341 CL_COMMAND_BUFFER_CONTEXT_KHR, 0,
342 nullptr, &ret_value_size);
343 test_error(error, "clGetCommandBufferInfoKHR failed");
344
345 test_assert_error(
346 ret_value_size == sizeof(cl_context),
347 "Unexpected result of CL_COMMAND_BUFFER_CONTEXT_KHR query!");
348
349 cl_context ret_context = nullptr;
350 error = clGetCommandBufferInfoKHR(
351 command_buffer, CL_COMMAND_BUFFER_CONTEXT_KHR, sizeof(cl_context),
352 &ret_context, nullptr);
353 test_error(error, "clGetCommandBufferInfoKHR failed");
354 test_assert_error(
355 ret_context != nullptr,
356 "Unexpected result of CL_COMMAND_BUFFER_CONTEXT_KHR query!");
357
358 cl_context expected_context = nullptr;
359 error =
360 clGetCommandQueueInfo(queue, CL_QUEUE_CONTEXT, sizeof(cl_context),
361 &expected_context, nullptr);
362 test_error(error, "clGetCommandQueueInfo failed");
363
364 test_assert_error(
365 ret_context == expected_context,
366 "Unexpected result of CL_COMMAND_BUFFER_CONTEXT_KHR query!");
367
368 return TEST_PASS;
369 }
370
371 const cl_int pattern = 0xE;
372 };
373
374 } // anonymous namespace
375
376
test_info_queues(cl_device_id device,cl_context context,cl_command_queue queue,int num_elements)377 int test_info_queues(cl_device_id device, cl_context context,
378 cl_command_queue queue, int num_elements)
379 {
380 return MakeAndRunTest<
381 CommandBufferGetCommandBufferInfo<CombufInfoTestMode::CITM_QUEUES>>(
382 device, context, queue, num_elements);
383 }
384
test_info_ref_count(cl_device_id device,cl_context context,cl_command_queue queue,int num_elements)385 int test_info_ref_count(cl_device_id device, cl_context context,
386 cl_command_queue queue, int num_elements)
387 {
388 return MakeAndRunTest<
389 CommandBufferGetCommandBufferInfo<CombufInfoTestMode::CITM_REF_COUNT>>(
390 device, context, queue, num_elements);
391 }
392
test_info_state(cl_device_id device,cl_context context,cl_command_queue queue,int num_elements)393 int test_info_state(cl_device_id device, cl_context context,
394 cl_command_queue queue, int num_elements)
395 {
396 return MakeAndRunTest<
397 CommandBufferGetCommandBufferInfo<CombufInfoTestMode::CITM_STATE>>(
398 device, context, queue, num_elements);
399 }
400
test_info_prop_array(cl_device_id device,cl_context context,cl_command_queue queue,int num_elements)401 int test_info_prop_array(cl_device_id device, cl_context context,
402 cl_command_queue queue, int num_elements)
403 {
404 return MakeAndRunTest<
405 CommandBufferGetCommandBufferInfo<CombufInfoTestMode::CITM_PROP_ARRAY>>(
406 device, context, queue, num_elements);
407 }
408
test_info_context(cl_device_id device,cl_context context,cl_command_queue queue,int num_elements)409 int test_info_context(cl_device_id device, cl_context context,
410 cl_command_queue queue, int num_elements)
411 {
412 return MakeAndRunTest<
413 CommandBufferGetCommandBufferInfo<CombufInfoTestMode::CITM_CONTEXT>>(
414 device, context, queue, num_elements);
415 }
416