• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 #ifndef _CL_KHR_COMMAND_BUFFER_TEST_BASE_H
17 #define _CL_KHR_COMMAND_BUFFER_TEST_BASE_H
18 
19 #include <CL/cl_ext.h>
20 #include "harness/deviceInfo.h"
21 #include "harness/testHarness.h"
22 
23 
24 // Base class for setting function pointers to new extension entry points
25 struct CommandBufferTestBase
26 {
CommandBufferTestBaseCommandBufferTestBase27     CommandBufferTestBase(cl_device_id device): device(device) {}
28 
init_extension_functionsCommandBufferTestBase29     cl_int init_extension_functions()
30     {
31         cl_platform_id platform;
32         cl_int error =
33             clGetDeviceInfo(device, CL_DEVICE_PLATFORM, sizeof(cl_platform_id),
34                             &platform, nullptr);
35         test_error(error, "clGetDeviceInfo for CL_DEVICE_PLATFORM failed");
36 
37         // If it is supported get the addresses of all the APIs here.
38 #define GET_EXTENSION_ADDRESS(FUNC)                                            \
39     FUNC = reinterpret_cast<FUNC##_fn>(                                        \
40         clGetExtensionFunctionAddressForPlatform(platform, #FUNC));            \
41     if (FUNC == nullptr)                                                       \
42     {                                                                          \
43         log_error("ERROR: clGetExtensionFunctionAddressForPlatform failed"     \
44                   " with " #FUNC "\n");                                        \
45         return TEST_FAIL;                                                      \
46     }
47 
48         GET_EXTENSION_ADDRESS(clCreateCommandBufferKHR);
49         GET_EXTENSION_ADDRESS(clReleaseCommandBufferKHR);
50         GET_EXTENSION_ADDRESS(clRetainCommandBufferKHR);
51         GET_EXTENSION_ADDRESS(clFinalizeCommandBufferKHR);
52         GET_EXTENSION_ADDRESS(clEnqueueCommandBufferKHR);
53         GET_EXTENSION_ADDRESS(clCommandBarrierWithWaitListKHR);
54         GET_EXTENSION_ADDRESS(clCommandCopyBufferKHR);
55         GET_EXTENSION_ADDRESS(clCommandCopyBufferRectKHR);
56         GET_EXTENSION_ADDRESS(clCommandCopyBufferToImageKHR);
57         GET_EXTENSION_ADDRESS(clCommandCopyImageKHR);
58         GET_EXTENSION_ADDRESS(clCommandCopyImageToBufferKHR);
59         GET_EXTENSION_ADDRESS(clCommandFillBufferKHR);
60         GET_EXTENSION_ADDRESS(clCommandFillImageKHR);
61         GET_EXTENSION_ADDRESS(clCommandNDRangeKernelKHR);
62         GET_EXTENSION_ADDRESS(clGetCommandBufferInfoKHR);
63 #undef GET_EXTENSION_ADDRESS
64         return CL_SUCCESS;
65     }
66 
67     clCreateCommandBufferKHR_fn clCreateCommandBufferKHR = nullptr;
68     clReleaseCommandBufferKHR_fn clReleaseCommandBufferKHR = nullptr;
69     clRetainCommandBufferKHR_fn clRetainCommandBufferKHR = nullptr;
70     clFinalizeCommandBufferKHR_fn clFinalizeCommandBufferKHR = nullptr;
71     clEnqueueCommandBufferKHR_fn clEnqueueCommandBufferKHR = nullptr;
72     clCommandBarrierWithWaitListKHR_fn clCommandBarrierWithWaitListKHR =
73         nullptr;
74     clCommandCopyBufferKHR_fn clCommandCopyBufferKHR = nullptr;
75     clCommandCopyBufferRectKHR_fn clCommandCopyBufferRectKHR = nullptr;
76     clCommandCopyBufferToImageKHR_fn clCommandCopyBufferToImageKHR = nullptr;
77     clCommandCopyImageKHR_fn clCommandCopyImageKHR = nullptr;
78     clCommandCopyImageToBufferKHR_fn clCommandCopyImageToBufferKHR = nullptr;
79     clCommandFillBufferKHR_fn clCommandFillBufferKHR = nullptr;
80     clCommandFillImageKHR_fn clCommandFillImageKHR = nullptr;
81     clCommandNDRangeKernelKHR_fn clCommandNDRangeKernelKHR = nullptr;
82     clGetCommandBufferInfoKHR_fn clGetCommandBufferInfoKHR = nullptr;
83 
84     cl_device_id device = nullptr;
85 };
86 
87 // Wrapper class based off generic typeWrappers.h wrappers. However, because
88 // the release/retain functions are queried at runtime from the platform,
89 // rather than known at compile time we cannot link the instantiated template.
90 // Instead, pass an instance of `CommandBufferTestBase` on wrapper construction
91 // to access the release/retain functions.
92 class clCommandBufferWrapper {
93     cl_command_buffer_khr object = nullptr;
94 
retain()95     void retain()
96     {
97         if (!object) return;
98 
99         auto err = base->clRetainCommandBufferKHR(object);
100         if (err != CL_SUCCESS)
101         {
102             print_error(err, "clRetainCommandBufferKHR() failed");
103             std::abort();
104         }
105     }
106 
release()107     void release()
108     {
109         if (!object) return;
110 
111         auto err = base->clReleaseCommandBufferKHR(object);
112         if (err != CL_SUCCESS)
113         {
114             print_error(err, "clReleaseCommandBufferKHR() failed");
115             std::abort();
116         }
117     }
118 
119     // Used to access release/retain functions
120     CommandBufferTestBase *base;
121 
122 public:
123     // We always want to have base available to dereference
124     clCommandBufferWrapper() = delete;
125 
clCommandBufferWrapper(CommandBufferTestBase * base)126     clCommandBufferWrapper(CommandBufferTestBase *base): base(base) {}
127 
128     // On assignment, assume the object has a refcount of one.
129     clCommandBufferWrapper &operator=(cl_command_buffer_khr rhs)
130     {
131         reset(rhs);
132         return *this;
133     }
134 
135     // Copy semantics, increase retain count.
clCommandBufferWrapper(clCommandBufferWrapper const & w)136     clCommandBufferWrapper(clCommandBufferWrapper const &w) { *this = w; }
137     clCommandBufferWrapper &operator=(clCommandBufferWrapper const &w)
138     {
139         reset(w.object);
140         retain();
141         return *this;
142     }
143 
144     // Move semantics, directly take ownership.
clCommandBufferWrapper(clCommandBufferWrapper && w)145     clCommandBufferWrapper(clCommandBufferWrapper &&w) { *this = std::move(w); }
146     clCommandBufferWrapper &operator=(clCommandBufferWrapper &&w)
147     {
148         reset(w.object);
149         w.object = nullptr;
150         return *this;
151     }
152 
~clCommandBufferWrapper()153     ~clCommandBufferWrapper() { reset(); }
154 
155     // Release the existing object, if any, and own the new one, if any.
156     void reset(cl_command_buffer_khr new_object = nullptr)
157     {
158         release();
159         object = new_object;
160     }
161 
cl_command_buffer_khr()162     operator cl_command_buffer_khr() const { return object; }
163 };
164 
165 #define CHECK_COMMAND_BUFFER_EXTENSION_AVAILABLE(device)                       \
166     {                                                                          \
167         if (!is_extension_available(device, "cl_khr_command_buffer"))          \
168         {                                                                      \
169             log_info(                                                          \
170                 "Device does not support 'cl_khr_command_buffer'. Skipping "   \
171                 "the test.\n");                                                \
172             return TEST_SKIPPED_ITSELF;                                        \
173         }                                                                      \
174     }
175 
176 
177 #endif // _CL_KHR_COMMAND_BUFFER_TEST_BASE_H
178