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 "testBase.h"
17 #include "harness/propertyHelpers.h"
18 #include "harness/typeWrappers.h"
19 #include <vector>
20 #include <algorithm>
21 
22 struct test_queue_array_properties_data
23 {
24     std::vector<cl_queue_properties> properties;
25     std::string description;
26 };
27 
verify_if_properties_supported(cl_device_id deviceID,cl_command_queue_properties requested_bitfield,cl_uint requested_size)28 int verify_if_properties_supported(
29     cl_device_id deviceID, cl_command_queue_properties requested_bitfield,
30     cl_uint requested_size)
31 {
32     int error = CL_SUCCESS;
33     bool on_host_queue = true;
34 
35     if (requested_bitfield & CL_QUEUE_ON_DEVICE)
36     {
37         on_host_queue = false;
38 
39         if (requested_size > 0)
40         {
41             cl_uint max_queue_size = 0;
42             error =
43                 clGetDeviceInfo(deviceID, CL_DEVICE_QUEUE_ON_DEVICE_MAX_SIZE,
44                                 sizeof(max_queue_size), &max_queue_size, NULL);
45             test_error(error,
46                        "clGetDeviceInfo for "
47                        "CL_DEVICE_QUEUE_ON_DEVICE_MAX_SIZE failed");
48             if (requested_size > max_queue_size)
49             {
50                 log_info(
51                     "The value of CL_QUEUE_SIZE = %d cannot be bigger than "
52                     "CL_DEVICE_QUEUE_ON_DEVICE_MAX_SIZE = %d, skipped\n",
53                     requested_size, max_queue_size);
54                 return TEST_SKIPPED_ITSELF;
55             }
56         }
57     }
58 
59     cl_command_queue_properties supported_properties = 0;
60     cl_command_queue_properties all_properties = 0;
61 
62     std::vector<cl_command_queue_properties> all_properties_vector{
63         CL_QUEUE_OUT_OF_ORDER_EXEC_MODE_ENABLE, CL_QUEUE_PROFILING_ENABLE
64     };
65     for (auto each_property : all_properties_vector)
66     {
67         all_properties |= each_property;
68     }
69     cl_command_queue_properties requested_properties =
70         all_properties & requested_bitfield;
71 
72     if (on_host_queue)
73     {
74         error = clGetDeviceInfo(deviceID, CL_DEVICE_QUEUE_ON_HOST_PROPERTIES,
75                                 sizeof(supported_properties),
76                                 &supported_properties, NULL);
77         test_error(error,
78                    "clGetDeviceInfo asking for "
79                    "CL_DEVICE_QUEUE_ON_HOST_PROPERTIES failed");
80     }
81     else
82     {
83         error = clGetDeviceInfo(deviceID, CL_DEVICE_QUEUE_ON_DEVICE_PROPERTIES,
84                                 sizeof(supported_properties),
85                                 &supported_properties, NULL);
86         test_error(error,
87                    "clGetDeviceInfo asking for "
88                    "CL_DEVICE_QUEUE_ON_DEVICE_PROPERTIES failed");
89     }
90 
91     for (auto each_property : all_properties_vector)
92     {
93         if ((each_property & requested_properties)
94             && !(each_property & supported_properties))
95         {
96             log_info("\t%s not supported, skipped\n",
97                      GetQueuePropertyName(each_property));
98             return TEST_SKIPPED_ITSELF;
99         }
100         else if ((each_property & requested_properties)
101                  && each_property & supported_properties)
102         {
103             log_info("\t%s supported\n", GetQueuePropertyName(each_property));
104         }
105     }
106     return error;
107 }
108 
create_queue_and_check_array_properties(cl_context context,cl_device_id deviceID,test_queue_array_properties_data test_case)109 static int create_queue_and_check_array_properties(
110     cl_context context, cl_device_id deviceID,
111     test_queue_array_properties_data test_case)
112 {
113     cl_int error = CL_SUCCESS;
114 
115     clCommandQueueWrapper test_queue;
116 
117     if (test_case.properties.size() > 0)
118     {
119         test_queue = clCreateCommandQueueWithProperties(
120             context, deviceID, test_case.properties.data(), &error);
121         test_error(error, "clCreateCommandQueueWithProperties failed");
122     }
123     else
124     {
125         test_queue =
126             clCreateCommandQueueWithProperties(context, deviceID, NULL, &error);
127         test_error(error, "clCreateCommandQueueWithProperties failed");
128     }
129 
130     std::vector<cl_queue_properties> check_properties;
131     size_t set_size = 0;
132 
133     error = clGetCommandQueueInfo(test_queue, CL_QUEUE_PROPERTIES_ARRAY, 0,
134                                   NULL, &set_size);
135     test_error(error,
136                "clGetCommandQueueInfo failed asking for "
137                "CL_QUEUE_PROPERTIES_ARRAY size.");
138 
139     if (set_size == 0 && test_case.properties.size() == 0)
140     {
141         return TEST_PASS;
142     }
143     if (set_size != test_case.properties.size() * sizeof(cl_queue_properties))
144     {
145         log_error("ERROR: CL_QUEUE_PROPERTIES_ARRAY size is %d, expected %d.\n",
146                   set_size,
147                   test_case.properties.size() * sizeof(cl_queue_properties));
148         return TEST_FAIL;
149     }
150 
151     cl_uint number_of_props = set_size / sizeof(cl_queue_properties);
152     check_properties.resize(number_of_props);
153     error = clGetCommandQueueInfo(test_queue, CL_QUEUE_PROPERTIES_ARRAY,
154                                   set_size, check_properties.data(), NULL);
155     test_error(
156         error,
157         "clGetCommandQueueInfo failed asking for CL_QUEUE_PROPERTIES_ARRAY.");
158 
159     error = compareProperties(check_properties, test_case.properties);
160     return error;
161 }
162 
163 static int
run_test_queue_array_properties(cl_context context,cl_device_id deviceID,test_queue_array_properties_data test_case)164 run_test_queue_array_properties(cl_context context, cl_device_id deviceID,
165                                 test_queue_array_properties_data test_case)
166 {
167     int error = TEST_PASS;
168 
169     std::vector<cl_queue_properties> requested_properties =
170         test_case.properties;
171     log_info("\nTC description: %s\n", test_case.description.c_str());
172 
173     // first verify if user properties are supported
174     if (requested_properties.size() != 0)
175     {
176         requested_properties.pop_back();
177         cl_command_queue_properties requested_bitfield = 0;
178         cl_uint requested_size = 0;
179         for (cl_uint i = 0; i < requested_properties.size(); i = i + 2)
180         {
181             if (requested_properties[i] == CL_QUEUE_PROPERTIES)
182             {
183                 requested_bitfield = requested_properties[i + 1];
184             }
185             if (requested_properties[i] == CL_QUEUE_SIZE)
186             {
187                 requested_size = requested_properties[i + 1];
188             }
189         }
190 
191         error = verify_if_properties_supported(deviceID, requested_bitfield,
192                                                requested_size);
193         if (error == TEST_SKIPPED_ITSELF)
194         {
195             log_info("TC result: skipped\n");
196             return TEST_PASS;
197         }
198         test_error(error,
199                    "Checking which queue properties supported failed.\n");
200     }
201 
202     // continue testing if supported user properties
203     error =
204         create_queue_and_check_array_properties(context, deviceID, test_case);
205     test_error(error, "create_queue_and_check_array_properties failed.\n");
206 
207     log_info("TC result: passed\n");
208     return TEST_PASS;
209 }
210 
test_queue_properties_queries(cl_device_id deviceID,cl_context context,cl_command_queue queue,int num_elements)211 int test_queue_properties_queries(cl_device_id deviceID, cl_context context,
212                                   cl_command_queue queue, int num_elements)
213 {
214     int error = TEST_PASS;
215     std::vector<test_queue_array_properties_data> test_cases;
216 
217     test_cases.push_back({ {}, "host queue, NULL properties" });
218 
219     test_cases.push_back(
220         { { CL_QUEUE_PROPERTIES, 0, 0 }, "host queue, zero properties" });
221 
222     test_cases.push_back(
223         { { CL_QUEUE_PROPERTIES, CL_QUEUE_PROFILING_ENABLE, 0 },
224           "host queue, CL_QUEUE_PROFILING_ENABLE" });
225 
226     test_cases.push_back(
227         { { CL_QUEUE_PROPERTIES, CL_QUEUE_OUT_OF_ORDER_EXEC_MODE_ENABLE, 0 },
228           "host queue, CL_QUEUE_OUT_OF_ORDER_EXEC_MODE_ENABLE" });
229 
230     test_cases.push_back(
231         { { CL_QUEUE_PROPERTIES,
232             CL_QUEUE_OUT_OF_ORDER_EXEC_MODE_ENABLE | CL_QUEUE_PROFILING_ENABLE,
233             0 },
234           "host queue, CL_QUEUE_OUT_OF_ORDER_EXEC_MODE_ENABLE | "
235           "CL_QUEUE_PROFILING_ENABLE" });
236 
237     test_cases.push_back(
238         { { CL_QUEUE_PROPERTIES,
239             CL_QUEUE_OUT_OF_ORDER_EXEC_MODE_ENABLE | CL_QUEUE_ON_DEVICE, 0 },
240           "device queue, CL_QUEUE_OUT_OF_ORDER_EXEC_MODE_ENABLE | "
241           "CL_QUEUE_ON_DEVICE" });
242 
243     test_cases.push_back(
244         { { CL_QUEUE_PROPERTIES,
245             CL_QUEUE_OUT_OF_ORDER_EXEC_MODE_ENABLE | CL_QUEUE_ON_DEVICE
246                 | CL_QUEUE_ON_DEVICE_DEFAULT | CL_QUEUE_PROFILING_ENABLE,
247             CL_QUEUE_SIZE, 124, 0 },
248           "device queue, all possible properties" });
249 
250     test_cases.push_back(
251         { { CL_QUEUE_PROPERTIES,
252             CL_QUEUE_OUT_OF_ORDER_EXEC_MODE_ENABLE | CL_QUEUE_ON_DEVICE
253                 | CL_QUEUE_PROFILING_ENABLE,
254             CL_QUEUE_SIZE, 124, 0 },
255           "device queue, all without CL_QUEUE_ON_DEVICE_DEFAULT" });
256 
257     test_cases.push_back(
258         { { CL_QUEUE_PROPERTIES,
259             CL_QUEUE_OUT_OF_ORDER_EXEC_MODE_ENABLE | CL_QUEUE_ON_DEVICE
260                 | CL_QUEUE_ON_DEVICE_DEFAULT | CL_QUEUE_PROFILING_ENABLE,
261             0 },
262           "device queue, all without CL_QUEUE_SIZE" });
263 
264     for (auto test_case : test_cases)
265     {
266         error |= run_test_queue_array_properties(context, deviceID, test_case);
267     }
268     return error;
269 }
270