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