xref: /aosp_15_r20/external/OpenCL-CTS/test_conformance/conversions/basic_test_conversions.h (revision 6467f958c7de8070b317fc65bcb0f6472e388d82)
1 //
2 // Copyright (c) 2023 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 #ifndef BASIC_TEST_CONVERSIONS_H
17 #define BASIC_TEST_CONVERSIONS_H
18 
19 #if !defined(_WIN32)
20 #include <unistd.h>
21 #endif
22 
23 #include "harness/errorHelpers.h"
24 #include "harness/rounding_mode.h"
25 
26 #include <stdio.h>
27 #if defined( __APPLE__ )
28     #include <OpenCL/opencl.h>
29 #else
30     #include <CL/opencl.h>
31 #endif
32 
33 #include "harness/mt19937.h"
34 #include "harness/testHarness.h"
35 #include "harness/typeWrappers.h"
36 
37 #include <memory>
38 #include <tuple>
39 #include <vector>
40 
41 #include "conversions_data_info.h"
42 
43 #define kVectorSizeCount 6
44 #define kMaxVectorSize 16
45 #define kPageSize 4096
46 
47 #define BUFFER_SIZE (1024 * 1024)
48 #define EMBEDDED_REDUCTION_FACTOR 16
49 #define PERF_LOOP_COUNT 100
50 
51 extern const char *gTypeNames[ kTypeCount ];
52 extern const char *gRoundingModeNames[ kRoundingModeCount ];        // { "", "_rte", "_rtp", "_rtn", "_rtz" }
53 extern const char *gSaturationNames[ kSaturationModeCount ];        // { "", "_sat" }
54 extern const char *gVectorSizeNames[kVectorSizeCount];              // { "", "2", "4", "8", "16" }
55 extern size_t gTypeSizes[ kTypeCount ];
56 
57 //Functions for clamping floating point numbers into the representable range for the type
58 typedef float (*clampf)( float );
59 typedef double (*clampd)( double );
60 
61 extern clampf gClampFloat[ kTypeCount ][kRoundingModeCount];
62 extern clampd gClampDouble[ kTypeCount ][kRoundingModeCount];
63 
64 typedef void (*InitDataFunc)( void *dest, SaturationMode, RoundingMode, Type destType, uint64_t start, int count, MTdata d );
65 extern InitDataFunc gInitFunctions[ kTypeCount ];
66 
67 typedef int (*CheckResults)( void *out1, void *out2, void *allowZ, uint32_t count, int vectorSize );
68 extern CheckResults gCheckResults[ kTypeCount ];
69 
70 #define kCallStyleCount (kVectorSizeCount + 1 /* for implicit scalar */)
71 
72 extern MTdata gMTdata;
73 extern cl_command_queue gQueue;
74 extern cl_context gContext;
75 extern cl_mem gInBuffer;
76 extern cl_mem gOutBuffers[];
77 extern int gHasDouble;
78 extern int gTestDouble;
79 extern int gWimpyMode;
80 extern int gWimpyReductionFactor;
81 extern int gSkipTesting;
82 extern int gMinVectorSize;
83 extern int gMaxVectorSize;
84 extern int gForceFTZ;
85 extern int gTimeResults;
86 extern int gReportAverageTimes;
87 extern int gStartTestNumber;
88 extern int gEndTestNumber;
89 extern int gIsRTZ;
90 extern void *gIn;
91 extern void *gRef;
92 extern void *gAllowZ;
93 extern void *gOut[];
94 
95 extern const char **argList;
96 extern int argCount;
97 
98 extern const char *sizeNames[];
99 extern int vectorSizes[];
100 
101 extern size_t gComputeDevices;
102 extern uint32_t gDeviceFrequency;
103 
104 namespace conv_test {
105 
106 cl_program MakeProgram(Type outType, Type inType, SaturationMode sat,
107                        RoundingMode round, int vectorSize,
108                        cl_kernel *outKernel);
109 
110 int RunKernel(cl_kernel kernel, void *inBuf, void *outBuf, size_t blockCount);
111 
112 int GetTestCase(const char *name, Type *outType, Type *inType,
113                 SaturationMode *sat, RoundingMode *round);
114 
115 cl_int InitData(cl_uint job_id, cl_uint thread_id, void *p);
116 cl_int PrepareReference(cl_uint job_id, cl_uint thread_id, void *p);
117 uint64_t GetTime(void);
118 
119 void WriteInputBufferComplete(void *);
120 void *FlushToZero(void);
121 void UnFlushToZero(void *);
122 }
123 
124 struct CalcRefValsBase
125 {
126     virtual ~CalcRefValsBase() = default;
check_resultCalcRefValsBase127     virtual int check_result(void *, uint32_t, int) { return 0; }
128 
129     // pointer back to the parent WriteInputBufferInfo struct
130     struct WriteInputBufferInfo *parent;
131     clKernelWrapper kernel; // the kernel for this vector size
132     clProgramWrapper program; // the program for this vector size
133     cl_uint vectorSize; // the vector size for this callback chain
134     void *p; // the pointer to mapped result data for this vector size
135     cl_int result;
136 };
137 
138 template <typename InType, typename OutType>
139 struct CalcRefValsPat : CalcRefValsBase
140 {
141     int check_result(void *, uint32_t, int) override;
142 };
143 
144 struct WriteInputBufferInfo
145 {
WriteInputBufferInfoWriteInputBufferInfo146     WriteInputBufferInfo()
147         : calcReferenceValues(nullptr), doneBarrier(nullptr), count(0),
148           outType(kuchar), inType(kuchar), barrierCount(0)
149     {}
150 
151     volatile cl_event
152         calcReferenceValues; // user event which signals when main thread is
153                              // done calculating reference values
154     volatile cl_event
155         doneBarrier; // user event which signals when worker threads are done
156     cl_uint count; // the number of elements in the array
157     Type outType; // the data type of the conversion result
158     Type inType; // the data type of the conversion input
159     volatile int barrierCount;
160 
161     std::vector<std::unique_ptr<CalcRefValsBase>> calcInfo;
162 };
163 
164 // Must be aligned with Type enums!
165 using TypeIter = std::tuple<cl_uchar, cl_char, cl_ushort, cl_short, cl_uint,
166                             cl_int, cl_float, cl_double, cl_ulong, cl_long>;
167 
168 // Helper test fixture for constructing OpenCL objects used in testing
169 // a variety of simple command-buffer enqueue scenarios.
170 struct ConversionsTest
171 {
172     virtual ~ConversionsTest() = default;
173 
174     ConversionsTest(cl_device_id device, cl_context context,
175                     cl_command_queue queue);
176 
177     cl_int SetUp(int elements);
178 
179     // Test body returning an OpenCL error code
180     cl_int Run();
181 
182     template <typename InType, typename OutType>
183     int DoTest(Type outType, Type inType, SaturationMode sat,
184                RoundingMode round);
185 
186     template <typename InType, typename OutType>
187     void TestTypesConversion(const Type &inType, const Type &outType, int &tn,
188                              const int smvs);
189 
190 protected:
191     cl_context context;
192     cl_device_id device;
193     cl_command_queue queue;
194 
195     size_t num_elements;
196 
197     TypeIter typeIterator;
198 };
199 
200 struct CustomConversionsTest : ConversionsTest
201 {
CustomConversionsTestCustomConversionsTest202     CustomConversionsTest(cl_device_id device, cl_context context,
203                           cl_command_queue queue)
204         : ConversionsTest(device, context, queue)
205     {}
206 
207     cl_int Run();
208 };
209 
210 template <class T>
MakeAndRunTest(cl_device_id device,cl_context context,cl_command_queue queue,int num_elements)211 int MakeAndRunTest(cl_device_id device, cl_context context,
212                    cl_command_queue queue, int num_elements)
213 {
214     T test_fixture(device, context, queue);
215 
216     cl_int error = test_fixture.SetUp(num_elements);
217     test_error_ret(error, "Error in test initialization", TEST_FAIL);
218 
219     return test_fixture.Run();
220 }
221 
222 struct TestType
223 {
testTypeTestType224     template <typename T> bool testType(Type in)
225     {
226         switch (in)
227         {
228             default: return false;
229             case kuchar: return std::is_same<cl_uchar, T>::value;
230             case kchar: return std::is_same<cl_char, T>::value;
231             case kushort: return std::is_same<cl_ushort, T>::value;
232             case kshort: return std::is_same<cl_short, T>::value;
233             case kuint: return std::is_same<cl_uint, T>::value;
234             case kint: return std::is_same<cl_int, T>::value;
235             case kfloat: return std::is_same<cl_float, T>::value;
236             case kdouble: return std::is_same<cl_double, T>::value;
237             case kulong: return std::is_same<cl_ulong, T>::value;
238             case klong: return std::is_same<cl_long, T>::value;
239         }
240     }
241 };
242 
243 // Helper structures to iterate over all tuple attributes of different types
244 struct IterOverTypes : public TestType
245 {
IterOverTypesIterOverTypes246     IterOverTypes(const TypeIter &typeIter, ConversionsTest &test)
247         : inType((Type)0), outType((Type)0), typeIter(typeIter), test(test),
248           testNumber(-1), startMinVectorSize(gMinVectorSize)
249     {}
250 
RunIterOverTypes251     void Run() { for_each_out_elem(typeIter); }
252 
253 protected:
254     template <std::size_t Out = 0, typename OutType>
iterate_out_typeIterOverTypes255     void iterate_out_type(const OutType &t)
256     {
257         for_each_in_elem<0, Out, OutType>(typeIter);
258         outType = (Type)(outType + 1);
259         inType = (Type)0;
260     }
261 
262     template <std::size_t In, std::size_t Out, typename OutType,
263               typename InType>
iterate_in_typeIterOverTypes264     void iterate_in_type(const InType &t)
265     {
266         if (!testType<InType>(inType)) vlog_error("Unexpected data type!\n");
267 
268         if (!testType<OutType>(outType)) vlog_error("Unexpected data type!\n");
269 
270         // run the conversions
271         test.TestTypesConversion<InType, OutType>(inType, outType, testNumber,
272                                                   startMinVectorSize);
273         inType = (Type)(inType + 1);
274     }
275 
276     template <std::size_t Out = 0, typename... Tp>
277     inline typename std::enable_if<Out == sizeof...(Tp), void>::type
for_each_out_elemIterOverTypes278     for_each_out_elem(
279         const std::tuple<Tp...> &) // Unused arguments are given no names.
280     {}
281 
282     template <std::size_t Out = 0, typename... Tp>
283         inline typename std::enable_if < Out<sizeof...(Tp), void>::type
284         for_each_out_elem(const std::tuple<Tp...> &t)
285     {
286         iterate_out_type<Out>(std::get<Out>(t));
287         for_each_out_elem<Out + 1, Tp...>(t);
288     }
289 
290     template <std::size_t In = 0, std::size_t Out, typename OutType,
291               typename... Tp>
292     inline typename std::enable_if<In == sizeof...(Tp), void>::type
for_each_in_elemIterOverTypes293     for_each_in_elem(
294         const std::tuple<Tp...> &) // Unused arguments are given no names.
295     {}
296 
297     template <std::size_t In = 0, std::size_t Out, typename OutType,
298               typename... Tp>
299         inline typename std::enable_if < In<sizeof...(Tp), void>::type
300         for_each_in_elem(const std::tuple<Tp...> &t)
301     {
302         iterate_in_type<In, Out, OutType>(std::get<In>(t));
303         for_each_in_elem<In + 1, Out, OutType, Tp...>(t);
304     }
305 
306 protected:
307     Type inType;
308     Type outType;
309     const TypeIter &typeIter;
310     ConversionsTest &test;
311     int testNumber;
312     int startMinVectorSize;
313 };
314 
315 
316 // Helper structures to select type 2 type conversion test case
317 struct IterOverSelectedTypes : public TestType
318 {
IterOverSelectedTypesIterOverSelectedTypes319     IterOverSelectedTypes(const TypeIter &typeIter, ConversionsTest &test,
320                           const Type in, const Type out,
321                           const RoundingMode round, const SaturationMode sat)
322         : inType(in), outType(out), rounding(round), saturation(sat),
323           typeIter(typeIter), test(test), testNumber(-1),
324           startMinVectorSize(gMinVectorSize)
325     {}
326 
RunIterOverSelectedTypes327     void Run() { for_each_out_elem(typeIter); }
328 
329 protected:
330     template <std::size_t Out = 0, typename OutType>
iterate_out_typeIterOverSelectedTypes331     void iterate_out_type(const OutType &t)
332     {
333         for_each_in_elem<0, Out, OutType>(typeIter);
334     }
335 
336     template <std::size_t In, std::size_t Out, typename OutType,
337               typename InType>
iterate_in_typeIterOverSelectedTypes338     void iterate_in_type(const InType &t)
339     {
340         if (testType<InType>(inType) && testType<OutType>(outType))
341         {
342             // run selected conversion
343             // testing of the result will happen afterwards
344             test.DoTest<InType, OutType>(outType, inType, saturation, rounding);
345         }
346     }
347 
348     template <std::size_t Out = 0, typename... Tp>
349     inline typename std::enable_if<Out == sizeof...(Tp), void>::type
for_each_out_elemIterOverSelectedTypes350     for_each_out_elem(const std::tuple<Tp...> &)
351     {}
352 
353     template <std::size_t Out = 0, typename... Tp>
354         inline typename std::enable_if < Out<sizeof...(Tp), void>::type
355         for_each_out_elem(const std::tuple<Tp...> &t)
356     {
357         iterate_out_type<Out>(std::get<Out>(t));
358         for_each_out_elem<Out + 1, Tp...>(t);
359     }
360 
361     template <std::size_t In = 0, std::size_t Out, typename OutType,
362               typename... Tp>
363     inline typename std::enable_if<In == sizeof...(Tp), void>::type
for_each_in_elemIterOverSelectedTypes364     for_each_in_elem(const std::tuple<Tp...> &)
365     {}
366 
367     template <std::size_t In = 0, std::size_t Out, typename OutType,
368               typename... Tp>
369         inline typename std::enable_if < In<sizeof...(Tp), void>::type
370         for_each_in_elem(const std::tuple<Tp...> &t)
371     {
372         iterate_in_type<In, Out, OutType>(std::get<In>(t));
373         for_each_in_elem<In + 1, Out, OutType, Tp...>(t);
374     }
375 
376 protected:
377     Type inType;
378     Type outType;
379     RoundingMode rounding;
380     SaturationMode saturation;
381 
382     const TypeIter &typeIter;
383     ConversionsTest &test;
384     int testNumber;
385     int startMinVectorSize;
386 };
387 
388 
389 #endif /* BASIC_TEST_CONVERSIONS_H */
390 
391