xref: /aosp_15_r20/external/OpenCL-CTS/test_conformance/api/test_kernel_attributes.cpp (revision 6467f958c7de8070b317fc65bcb0f6472e388d82)
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 <iostream>
17 #include <vector>
18 #include <string>
19 #include <algorithm>
20 #include "procs.h"
21 #include "harness/errorHelpers.h"
22 #include "harness/typeWrappers.h"
23 #include "harness/parseParameters.h"
24 
25 using KernelAttributes = std::vector<std::string>;
26 
generate_kernel_source(const KernelAttributes & attributes)27 static std::string generate_kernel_source(const KernelAttributes& attributes)
28 {
29     std::string kernel;
30     for (auto attribute : attributes)
31     {
32         kernel += "__attribute__((" + attribute + "))\n";
33     }
34     kernel += "__kernel void test_kernel(){}";
35     return kernel;
36 }
37 
38 
39 using AttributePermutations = std::vector<KernelAttributes>;
40 
41 // The following combinations have been chosen as they place each of the
42 // attribute types in the different orders that they can occur. While distinct
43 // permutations would provide a complete overview of the API the sheer number of
44 // combinations increases the runtime of this test by an unreasonable amount
45 AttributePermutations vect_tests;
46 AttributePermutations work_tests;
47 AttributePermutations reqd_tests;
48 
49 AttributePermutations vect_reqd_tests;
50 AttributePermutations work_vect_tests;
51 AttributePermutations reqd_work_tests;
52 
53 AttributePermutations vect_work_reqd_tests;
54 AttributePermutations work_reqd_vect_tests;
55 AttributePermutations reqd_vect_work_tests;
56 
57 
58 // Generate a vector with vec_type_hint(<data_type>) so that it can be used to
59 // generate different kernels
generate_vec_type_hint_data(cl_device_id deviceID)60 static KernelAttributes generate_vec_type_hint_data(cl_device_id deviceID)
61 {
62     KernelAttributes vec_type_hint_data;
63     // TODO Test for signed vectors (char/short/int/etc)
64     std::vector<std::string> vector_types = { "uchar", "ushort", "uint",
65                                               "float" };
66     if (gHasLong)
67     {
68         vector_types.push_back("ulong");
69     }
70     if (device_supports_half(deviceID))
71     {
72         vector_types.push_back("half");
73     }
74     if (device_supports_double(deviceID))
75     {
76         vector_types.push_back("double");
77     }
78 
79     const auto vector_sizes = { "2", "3", "4", "8", "16" };
80     for (auto type : vector_types)
81     {
82         for (auto size : vector_sizes)
83         {
84             vec_type_hint_data.push_back("vec_type_hint(" + type + size + ")");
85         }
86     }
87     return vec_type_hint_data;
88 }
89 
90 
91 struct WorkGroupDimensions
92 {
93     int x;
94     int y;
95     int z;
96 };
97 
98 // Generate vectors to store reqd_work_group_size(<dimensions>) and
99 // work_group_size_hint(<dimensions>) so that they can be used to generate
100 // different kernels
generate_reqd_work_group_size_data(const std::vector<WorkGroupDimensions> & work_group_dimensions)101 static KernelAttributes generate_reqd_work_group_size_data(
102     const std::vector<WorkGroupDimensions>& work_group_dimensions)
103 {
104     KernelAttributes reqd_work_group_size_data;
105     for (auto dimension : work_group_dimensions)
106     {
107         reqd_work_group_size_data.push_back(
108             "reqd_work_group_size(" + std::to_string(dimension.x) + ","
109             + std::to_string(dimension.y) + "," + std::to_string(dimension.z)
110             + ")");
111     }
112     return reqd_work_group_size_data;
113 }
114 
generate_work_group_size_data(const std::vector<WorkGroupDimensions> & work_group_dimensions)115 static KernelAttributes generate_work_group_size_data(
116     const std::vector<WorkGroupDimensions>& work_group_dimensions)
117 {
118     KernelAttributes work_group_size_hint_data;
119     for (auto dimension : work_group_dimensions)
120     {
121         work_group_size_hint_data.push_back(
122             "work_group_size_hint(" + std::to_string(dimension.x) + ","
123             + std::to_string(dimension.y) + "," + std::to_string(dimension.z)
124             + ")");
125     }
126     return work_group_size_hint_data;
127 }
128 
129 // Populate the Global Vectors which store individual Kernel Attributes
populate_single_attribute_tests(const KernelAttributes & vec_type_hint_data,const KernelAttributes & work_group_size_hint_data,const KernelAttributes & reqd_work_group_size_data)130 static void populate_single_attribute_tests(
131     // Vectors to store the different data that fill the attributes
132     const KernelAttributes& vec_type_hint_data,
133     const KernelAttributes& work_group_size_hint_data,
134     const KernelAttributes& reqd_work_group_size_data)
135 {
136     for (auto vector_test : vec_type_hint_data)
137     {
138         // Initialise vec_type_hint attribute tests
139         vect_tests.push_back({ vector_test });
140     }
141     for (auto work_group_test : work_group_size_hint_data)
142     {
143 
144         // Initialise work_group_size_hint attribute test
145         work_tests.push_back({ work_group_test });
146     }
147     for (auto reqd_work_group_test : reqd_work_group_size_data)
148     {
149 
150         // Initialise reqd_work_group_size attribute tests
151         reqd_tests.push_back({ reqd_work_group_test });
152     }
153 }
154 
155 // Populate the Global Vectors which store the different permutations of 2
156 // Kernel Attributes
populate_double_attribute_tests(const KernelAttributes & vec_type_hint_data,const KernelAttributes & work_group_size_hint_data,const KernelAttributes & reqd_work_group_size_data)157 static void populate_double_attribute_tests(
158     const KernelAttributes& vec_type_hint_data,
159     const KernelAttributes& work_group_size_hint_data,
160     const KernelAttributes& reqd_work_group_size_data)
161 {
162     for (auto vector_test : vec_type_hint_data)
163     {
164         for (auto work_group_test : work_group_size_hint_data)
165         {
166             // Initialise the tests for the permutation of work_group_size_hint
167             // combined with vec_type_hint
168             work_vect_tests.push_back({ work_group_test, vector_test });
169         }
170         for (auto reqd_work_group_test : reqd_work_group_size_data)
171         {
172             // Initialise the tests for the permutation of vec_type_hint and
173             // reqd_work_group_size
174             vect_reqd_tests.push_back({ vector_test, reqd_work_group_test });
175         }
176     }
177     for (auto work_group_test : work_group_size_hint_data)
178     {
179 
180         for (auto reqd_work_group_test : reqd_work_group_size_data)
181         {
182             // Initialse the tests for the permutation of reqd_work_group_size
183             // and  work_group_size_hint
184             reqd_work_tests.push_back(
185                 { reqd_work_group_test, work_group_test });
186         }
187     }
188 }
189 
190 // Populate the Global Vectors which store the different permutations of 3
191 // Kernel Attributes
populate_triple_attribute_tests(const KernelAttributes & vec_type_hint_data,const KernelAttributes & work_group_size_hint_data,const KernelAttributes & reqd_work_group_size_data)192 static void populate_triple_attribute_tests(
193     const KernelAttributes& vec_type_hint_data,
194     const KernelAttributes& work_group_size_hint_data,
195     const KernelAttributes& reqd_work_group_size_data)
196 {
197     for (auto vector_test : vec_type_hint_data)
198     {
199         for (auto work_group_test : work_group_size_hint_data)
200         {
201             for (auto reqd_work_group_test : reqd_work_group_size_data)
202             {
203                 //  Initialise the chosen permutations of 3 attributes
204                 vect_work_reqd_tests.push_back(
205                     { vector_test, work_group_test, reqd_work_group_test });
206                 work_reqd_vect_tests.push_back(
207                     { work_group_test, reqd_work_group_test, vector_test });
208                 reqd_vect_work_tests.push_back(
209                     { reqd_work_group_test, vector_test, work_group_test });
210             }
211         }
212     }
213 }
214 
215 static const std::vector<AttributePermutations*>
generate_attribute_tests(const KernelAttributes & vec_type_hint_data,const KernelAttributes & work_group_size_hint_data,const KernelAttributes & reqd_work_group_size_data)216 generate_attribute_tests(const KernelAttributes& vec_type_hint_data,
217                          const KernelAttributes& work_group_size_hint_data,
218                          const KernelAttributes& reqd_work_group_size_data)
219 {
220     populate_single_attribute_tests(vec_type_hint_data,
221                                     work_group_size_hint_data,
222                                     reqd_work_group_size_data);
223     populate_double_attribute_tests(vec_type_hint_data,
224                                     work_group_size_hint_data,
225                                     reqd_work_group_size_data);
226     populate_triple_attribute_tests(vec_type_hint_data,
227                                     work_group_size_hint_data,
228                                     reqd_work_group_size_data);
229 
230     // Store all of the filled vectors in a single structure
231     const std::vector<AttributePermutations*> all_tests = {
232         &vect_tests,           &work_tests,           &reqd_tests,
233 
234         &work_vect_tests,      &vect_reqd_tests,      &reqd_work_tests,
235 
236         &vect_work_reqd_tests, &work_reqd_vect_tests, &reqd_vect_work_tests
237     };
238     return all_tests;
239 }
240 
241 static const std::vector<AttributePermutations*>
initialise_attribute_data(cl_device_id deviceID)242 initialise_attribute_data(cl_device_id deviceID)
243 {
244     // This vector stores different work group dimensions that can be used by
245     // the reqd_work_group_size and work_group_size_hint attributes. It
246     // currently only has a single value to minimise time complexity of the
247     // overall test but can be easily changed.
248     static const std::vector<WorkGroupDimensions> work_group_dimensions = {
249         { 1, 1, 1 }
250     };
251     KernelAttributes vec_type_hint_data = generate_vec_type_hint_data(deviceID);
252     KernelAttributes work_group_size_hint_data =
253         generate_work_group_size_data(work_group_dimensions);
254     KernelAttributes reqd_work_group_size_data =
255         generate_reqd_work_group_size_data(work_group_dimensions);
256 
257     // Generate all the permutations of attributes to create different test
258     // suites
259     return generate_attribute_tests(vec_type_hint_data,
260                                     work_group_size_hint_data,
261                                     reqd_work_group_size_data);
262 }
263 
run_test(cl_context context,cl_device_id deviceID,const AttributePermutations & permutations)264 static bool run_test(cl_context context, cl_device_id deviceID,
265                      const AttributePermutations& permutations)
266 {
267     bool success = true;
268     for (auto attribute_permutation : permutations)
269     {
270 
271         std::string kernel_source_string =
272             generate_kernel_source(attribute_permutation);
273         const char* kernel_src = kernel_source_string.c_str();
274         clProgramWrapper program;
275         clKernelWrapper kernel;
276         cl_int err = create_single_kernel_helper(context, &program, &kernel, 1,
277                                                  &kernel_src, "test_kernel");
278         test_error_ret(err, "create_single_kernel_helper", false);
279 
280         // Get the size of the kernel attribute string returned
281         size_t size = 0;
282         err = clGetKernelInfo(kernel, CL_KERNEL_ATTRIBUTES, 0, nullptr, &size);
283         test_error_ret(err, "clGetKernelInfo", false);
284         std::vector<char> attributes(size);
285         err = clGetKernelInfo(kernel, CL_KERNEL_ATTRIBUTES, attributes.size(),
286                               attributes.data(), nullptr);
287         test_error_ret(err, "clGetKernelInfo", false);
288         std::string attribute_string(attributes.data());
289         attribute_string.erase(
290             std::remove(attribute_string.begin(), attribute_string.end(), ' '),
291             attribute_string.end());
292         if (gCompilationMode != kOnline)
293         {
294             if (!attribute_string.empty())
295             {
296                 success = false;
297                 log_error("Error: Expected an empty string\n");
298                 log_error("Attribute string reported as: %s\n",
299                           attribute_string.c_str());
300             }
301         }
302         else
303         {
304             bool permutation_success = true;
305             for (auto attribute : attribute_permutation)
306             {
307                 if (attribute_string.find(attribute) == std::string::npos)
308                 {
309                     success = false;
310                     permutation_success = false;
311                     log_error("ERROR: did not find expected attribute: '%s'\n",
312                               attribute.c_str());
313                 }
314             }
315             if (!permutation_success)
316             {
317                 log_error("Attribute string reported as: %s\n",
318                           attribute_string.c_str());
319             }
320         }
321     }
322     return success;
323 }
324 
test_kernel_attributes(cl_device_id deviceID,cl_context context,cl_command_queue queue,int num_elements)325 int test_kernel_attributes(cl_device_id deviceID, cl_context context,
326                            cl_command_queue queue, int num_elements)
327 {
328     bool success = true;
329 
330     // Vector to store all of the tests
331     const std::vector<AttributePermutations*> all_tests =
332         initialise_attribute_data(deviceID);
333 
334     for (auto permutations : all_tests)
335     {
336         success = success && run_test(context, deviceID, *permutations);
337     }
338     return success ? TEST_PASS : TEST_FAIL;
339 }
340