xref: /aosp_15_r20/external/OpenCL-CTS/test_common/harness/typeWrappers.h (revision 6467f958c7de8070b317fc65bcb0f6472e388d82)
1 //
2 // Copyright (c) 2017 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 _typeWrappers_h
17 #define _typeWrappers_h
18 
19 #if !defined(_WIN32)
20 #include <sys/mman.h>
21 #endif
22 
23 #include "compat.h"
24 #include "mt19937.h"
25 #include "errorHelpers.h"
26 #include "kernelHelpers.h"
27 
28 #include <cstdlib>
29 #include <type_traits>
30 
31 namespace wrapper_details {
32 
33 // clRetain*() and clRelease*() functions share the same type.
34 template <typename T> // T should be cl_context, cl_program, ...
35 using RetainReleaseType = cl_int CL_API_CALL(T);
36 
37 // A generic wrapper class that follows OpenCL retain/release semantics.
38 //
39 // This Wrapper class implement copy and move semantics, which makes it
40 // compatible with standard containers for example.
41 //
42 // Template parameters:
43 //  - T is the cl_* type (e.g. cl_context, cl_program, ...)
44 //  - Retain is the clRetain* function (e.g. clRetainContext, ...)
45 //  - Release is the clRelease* function (e.g. clReleaseContext, ...)
46 template <typename T, RetainReleaseType<T> Retain, RetainReleaseType<T> Release>
47 class Wrapper {
48     static_assert(std::is_pointer<T>::value, "T should be a pointer type.");
49     T object = nullptr;
50 
retain()51     void retain()
52     {
53         if (!object) return;
54 
55         auto err = Retain(object);
56         if (err != CL_SUCCESS)
57         {
58             print_error(err, "clRetain*() failed");
59             std::abort();
60         }
61     }
62 
release()63     void release()
64     {
65         if (!object) return;
66 
67         auto err = Release(object);
68         if (err != CL_SUCCESS)
69         {
70             print_error(err, "clRelease*() failed");
71             std::abort();
72         }
73     }
74 
75 public:
76     Wrapper() = default;
77 
78     // On initialisation, assume the object has a refcount of one.
Wrapper(T object)79     Wrapper(T object): object(object) {}
80 
81     // On assignment, assume the object has a refcount of one.
82     Wrapper &operator=(T rhs)
83     {
84         reset(rhs);
85         return *this;
86     }
87 
88     // Copy semantics, increase retain count.
Wrapper(Wrapper const & w)89     Wrapper(Wrapper const &w) { *this = w; }
90     Wrapper &operator=(Wrapper const &w)
91     {
92         reset(w.object);
93         retain();
94         return *this;
95     }
96 
97     // Move semantics, directly take ownership.
Wrapper(Wrapper && w)98     Wrapper(Wrapper &&w) { *this = std::move(w); }
99     Wrapper &operator=(Wrapper &&w)
100     {
101         reset(w.object);
102         w.object = nullptr;
103         return *this;
104     }
105 
~Wrapper()106     ~Wrapper() { reset(); }
107 
108     // Release the existing object, if any, and own the new one, if any.
109     void reset(T new_object = nullptr)
110     {
111         release();
112         object = new_object;
113     }
114 
T()115     operator T() const { return object; }
116 
117     // Ideally this function should not exist as it breaks encapsulation by
118     // allowing external mutation of the Wrapper internal state. However, too
119     // much code currently relies on this. For example, instead of using T* as
120     // output parameters, existing code can be updated to use Wrapper& instead.
121     T *operator&() { return &object; }
122 };
123 
124 } // namespace wrapper_details
125 
126 using clContextWrapper =
127     wrapper_details::Wrapper<cl_context, clRetainContext, clReleaseContext>;
128 
129 using clProgramWrapper =
130     wrapper_details::Wrapper<cl_program, clRetainProgram, clReleaseProgram>;
131 
132 using clKernelWrapper =
133     wrapper_details::Wrapper<cl_kernel, clRetainKernel, clReleaseKernel>;
134 
135 using clMemWrapper =
136     wrapper_details::Wrapper<cl_mem, clRetainMemObject, clReleaseMemObject>;
137 
138 using clCommandQueueWrapper =
139     wrapper_details::Wrapper<cl_command_queue, clRetainCommandQueue,
140                              clReleaseCommandQueue>;
141 
142 using clSamplerWrapper =
143     wrapper_details::Wrapper<cl_sampler, clRetainSampler, clReleaseSampler>;
144 
145 using clEventWrapper =
146     wrapper_details::Wrapper<cl_event, clRetainEvent, clReleaseEvent>;
147 
148 class clSVMWrapper {
149     void *Ptr = nullptr;
150     cl_context Ctx = nullptr;
151 
152 public:
153     clSVMWrapper() = default;
154 
155     clSVMWrapper(cl_context C, size_t Size,
156                  cl_svm_mem_flags F = CL_MEM_READ_WRITE)
Ctx(C)157         : Ctx(C)
158     {
159         Ptr = clSVMAlloc(C, F, Size, 0);
160     }
161 
162     clSVMWrapper &operator=(void *other) = delete;
163     clSVMWrapper(clSVMWrapper const &other) = delete;
164     clSVMWrapper &operator=(clSVMWrapper const &other) = delete;
clSVMWrapper(clSVMWrapper && other)165     clSVMWrapper(clSVMWrapper &&other)
166     {
167         Ptr = other.Ptr;
168         Ctx = other.Ctx;
169         other.Ptr = nullptr;
170         other.Ctx = nullptr;
171     }
172     clSVMWrapper &operator=(clSVMWrapper &&other)
173     {
174         Ptr = other.Ptr;
175         Ctx = other.Ctx;
176         other.Ptr = nullptr;
177         other.Ctx = nullptr;
178         return *this;
179     }
180 
~clSVMWrapper()181     ~clSVMWrapper()
182     {
183         if (Ptr) clSVMFree(Ctx, Ptr);
184     }
185 
operator()186     void *operator()() const { return Ptr; }
187 };
188 
189 
190 class clProtectedImage {
191 public:
clProtectedImage()192     clProtectedImage()
193     {
194         image = NULL;
195         backingStore = NULL;
196     }
197     clProtectedImage(cl_context context, cl_mem_flags flags,
198                      const cl_image_format *fmt, size_t width,
199                      cl_int *errcode_ret);
200     clProtectedImage(cl_context context, cl_mem_flags flags,
201                      const cl_image_format *fmt, size_t width, size_t height,
202                      cl_int *errcode_ret);
203     clProtectedImage(cl_context context, cl_mem_flags flags,
204                      const cl_image_format *fmt, size_t width, size_t height,
205                      size_t depth, cl_int *errcode_ret);
206     clProtectedImage(cl_context context, cl_mem_object_type imageType,
207                      cl_mem_flags flags, const cl_image_format *fmt,
208                      size_t width, size_t height, size_t depth,
209                      size_t arraySize, cl_int *errcode_ret);
~clProtectedImage()210     ~clProtectedImage()
211     {
212         if (image != NULL) clReleaseMemObject(image);
213 
214 #if defined(__APPLE__)
215         if (backingStore) munmap(backingStore, backingStoreSize);
216 #endif
217     }
218 
219     cl_int Create(cl_context context, cl_mem_flags flags,
220                   const cl_image_format *fmt, size_t width);
221     cl_int Create(cl_context context, cl_mem_flags flags,
222                   const cl_image_format *fmt, size_t width, size_t height);
223     cl_int Create(cl_context context, cl_mem_flags flags,
224                   const cl_image_format *fmt, size_t width, size_t height,
225                   size_t depth);
226     cl_int Create(cl_context context, cl_mem_object_type imageType,
227                   cl_mem_flags flags, const cl_image_format *fmt, size_t width,
228                   size_t height, size_t depth, size_t arraySize);
229 
230     clProtectedImage &operator=(const cl_mem &rhs)
231     {
232         image = rhs;
233         backingStore = NULL;
234         return *this;
235     }
cl_mem()236     operator cl_mem() { return image; }
237 
238     cl_mem *operator&() { return &image; }
239 
240 protected:
241     void *backingStore;
242     size_t backingStoreSize;
243     cl_mem image;
244 };
245 
246 /* Generic protected memory buffer, for verifying access within bounds */
247 class clProtectedArray {
248 public:
249     clProtectedArray();
250     clProtectedArray(size_t sizeInBytes);
251     virtual ~clProtectedArray();
252 
253     void Allocate(size_t sizeInBytes);
254 
255     operator void *() { return (void *)mValidBuffer; }
256     operator const void *() const { return (const void *)mValidBuffer; }
257 
258 protected:
259     char *mBuffer;
260     char *mValidBuffer;
261     size_t mRealSize, mRoundedSize;
262 };
263 
264 class RandomSeed {
265 public:
RandomSeed(cl_uint seed)266     RandomSeed(cl_uint seed)
267     {
268         if (seed) log_info("(seed = %10.10u) ", seed);
269         mtData = init_genrand(seed);
270     }
~RandomSeed()271     ~RandomSeed()
272     {
273         if (gReSeed) gRandomSeed = genrand_int32(mtData);
274         free_mtdata(mtData);
275     }
276 
MTdata()277     operator MTdata() { return mtData; }
278 
279 protected:
280     MTdata mtData;
281 };
282 
283 
284 template <typename T> class BufferOwningPtr {
285     BufferOwningPtr(BufferOwningPtr const &); // do not implement
286     void operator=(BufferOwningPtr const &); // do not implement
287 
288     void *ptr;
289     void *map;
290     // Bytes allocated total, pointed to by map:
291     size_t mapsize;
292     // Bytes allocated in unprotected pages, pointed to by ptr:
293     size_t allocsize;
294     bool aligned;
295 
296 public:
297     explicit BufferOwningPtr(void *p = 0)
ptr(p)298         : ptr(p), map(0), mapsize(0), allocsize(0), aligned(false)
299     {}
BufferOwningPtr(void * p,void * m,size_t s)300     explicit BufferOwningPtr(void *p, void *m, size_t s)
301         : ptr(p), map(m), mapsize(s), allocsize(0), aligned(false)
302     {
303 #if !defined(__APPLE__)
304         if (m)
305         {
306             log_error("ERROR: unhandled code path. BufferOwningPtr allocated "
307                       "with mapped buffer!");
308             abort();
309         }
310 #endif
311     }
~BufferOwningPtr()312     ~BufferOwningPtr()
313     {
314         if (map)
315         {
316 #if defined(__APPLE__)
317             int error = munmap(map, mapsize);
318             if (error)
319                 log_error("WARNING: munmap failed in BufferOwningPtr.\n");
320 #endif
321         }
322         else
323         {
324             if (aligned)
325             {
326                 align_free(ptr);
327             }
328             else
329             {
330                 free(ptr);
331             }
332         }
333     }
334     void reset(void *p, void *m = 0, size_t mapsize_ = 0, size_t allocsize_ = 0,
335                bool aligned_ = false)
336     {
337         if (map)
338         {
339 #if defined(__APPLE__)
340             int error = munmap(map, mapsize);
341             if (error)
342                 log_error("WARNING: munmap failed in BufferOwningPtr.\n");
343 #else
344             log_error("ERROR: unhandled code path. BufferOwningPtr reset with "
345                       "mapped buffer!");
346             abort();
347 #endif
348         }
349         else
350         {
351             if (aligned)
352             {
353                 align_free(ptr);
354             }
355             else
356             {
357                 free(ptr);
358             }
359         }
360         ptr = p;
361         map = m;
362         mapsize = mapsize_;
363         // Force allocsize to zero if ptr is NULL:
364         allocsize = (ptr != NULL) ? allocsize_ : 0;
365         aligned = aligned_;
366 #if !defined(__APPLE__)
367         if (m)
368         {
369             log_error("ERROR: unhandled code path. BufferOwningPtr allocated "
370                       "with mapped buffer!");
371             abort();
372         }
373 #endif
374     }
375     operator T *() { return (T *)ptr; }
376 
getSize()377     size_t getSize() const { return allocsize; };
378 };
379 
380 #endif // _typeWrappers_h
381