xref: /aosp_15_r20/external/angle/src/libANGLE/renderer/cl/CLContextCL.cpp (revision 8975f5c5ed3d1c378011245431ada316dfb6f244)
1 //
2 // Copyright 2021 The ANGLE Project Authors. All rights reserved.
3 // Use of this source code is governed by a BSD-style license that can be
4 // found in the LICENSE file.
5 //
6 // CLContextCL.cpp: Implements the class methods for CLContextCL.
7 
8 #include "libANGLE/renderer/cl/CLContextCL.h"
9 
10 #include "libANGLE/renderer/cl/CLCommandQueueCL.h"
11 #include "libANGLE/renderer/cl/CLDeviceCL.h"
12 #include "libANGLE/renderer/cl/CLEventCL.h"
13 #include "libANGLE/renderer/cl/CLMemoryCL.h"
14 #include "libANGLE/renderer/cl/CLPlatformCL.h"
15 #include "libANGLE/renderer/cl/CLProgramCL.h"
16 #include "libANGLE/renderer/cl/CLSamplerCL.h"
17 
18 #include "libANGLE/CLBuffer.h"
19 #include "libANGLE/CLCommandQueue.h"
20 #include "libANGLE/CLContext.h"
21 #include "libANGLE/CLDevice.h"
22 #include "libANGLE/CLEvent.h"
23 #include "libANGLE/CLImage.h"
24 #include "libANGLE/CLMemory.h"
25 #include "libANGLE/CLPlatform.h"
26 #include "libANGLE/CLProgram.h"
27 #include "libANGLE/CLSampler.h"
28 #include "libANGLE/cl_utils.h"
29 
30 namespace rx
31 {
32 
CLContextCL(const cl::Context & context,cl_context native)33 CLContextCL::CLContextCL(const cl::Context &context, cl_context native)
34     : CLContextImpl(context), mNative(native)
35 {}
36 
~CLContextCL()37 CLContextCL::~CLContextCL()
38 {
39     if (mNative->getDispatch().clReleaseContext(mNative) != CL_SUCCESS)
40     {
41         ERR() << "Error while releasing CL context";
42     }
43 }
44 
getDevices(cl::DevicePtrs * devicePtrsOut) const45 angle::Result CLContextCL::getDevices(cl::DevicePtrs *devicePtrsOut) const
46 {
47     size_t valueSize = 0u;
48     ANGLE_CL_TRY(mNative->getDispatch().clGetContextInfo(mNative, CL_CONTEXT_DEVICES, 0u, nullptr,
49                                                          &valueSize));
50     if ((valueSize % sizeof(cl_device_id)) == 0u)
51     {
52         std::vector<cl_device_id> nativeDevices(valueSize / sizeof(cl_device_id), nullptr);
53         ANGLE_CL_TRY(mNative->getDispatch().clGetContextInfo(mNative, CL_CONTEXT_DEVICES, valueSize,
54                                                              nativeDevices.data(), nullptr));
55         const cl::DevicePtrs &platformDevices = mContext.getPlatform().getDevices();
56         devicePtrsOut->reserve(nativeDevices.size());
57         for (cl_device_id nativeDevice : nativeDevices)
58         {
59             auto it = platformDevices.cbegin();
60             while (it != platformDevices.cend() &&
61                    (*it)->getImpl<CLDeviceCL>().getNative() != nativeDevice)
62             {
63                 ++it;
64             }
65             if (it != platformDevices.cend())
66             {
67                 devicePtrsOut->emplace_back(it->get());
68             }
69             else
70             {
71                 ASSERT(false);
72                 ERR() << "Device not found in platform list";
73                 ANGLE_CL_RETURN_ERROR(CL_INVALID_DEVICE);
74             }
75         }
76         return angle::Result::Continue;
77     }
78     return angle::Result::Continue;
79 }
80 
createCommandQueue(const cl::CommandQueue & commandQueue,CLCommandQueueImpl::Ptr * commandQueueOut)81 angle::Result CLContextCL::createCommandQueue(const cl::CommandQueue &commandQueue,
82                                               CLCommandQueueImpl::Ptr *commandQueueOut)
83 {
84     cl_int errorCode                = CL_SUCCESS;
85     const cl::Device &device        = commandQueue.getDevice();
86     const cl_device_id nativeDevice = device.getImpl<CLDeviceCL>().getNative();
87     cl_command_queue nativeQueue    = nullptr;
88 
89     if (!device.isVersionOrNewer(2u, 0u))
90     {
91         nativeQueue = mNative->getDispatch().clCreateCommandQueue(
92             mNative, nativeDevice, commandQueue.getProperties().get(), &errorCode);
93     }
94     else
95     {
96         const cl_queue_properties propArray[] = {
97             CL_QUEUE_PROPERTIES, commandQueue.getProperties().get(),
98             commandQueue.hasSize() ? CL_QUEUE_SIZE : 0u, commandQueue.getSize(), 0u};
99         nativeQueue = mNative->getDispatch().clCreateCommandQueueWithProperties(
100             mNative, nativeDevice, propArray, &errorCode);
101     }
102     ANGLE_CL_TRY(errorCode);
103 
104     *commandQueueOut = CLCommandQueueImpl::Ptr(
105         nativeQueue != nullptr ? new CLCommandQueueCL(commandQueue, nativeQueue) : nullptr);
106     return angle::Result::Continue;
107 }
108 
createBuffer(const cl::Buffer & buffer,void * hostPtr,CLMemoryImpl::Ptr * bufferOut)109 angle::Result CLContextCL::createBuffer(const cl::Buffer &buffer,
110                                         void *hostPtr,
111                                         CLMemoryImpl::Ptr *bufferOut)
112 {
113     cl_int errorCode    = CL_SUCCESS;
114     cl_mem nativeBuffer = nullptr;
115 
116     if (buffer.getProperties().empty())
117     {
118         nativeBuffer = mNative->getDispatch().clCreateBuffer(mNative, buffer.getFlags().get(),
119                                                              buffer.getSize(), hostPtr, &errorCode);
120     }
121     else
122     {
123         nativeBuffer = mNative->getDispatch().clCreateBufferWithProperties(
124             mNative, buffer.getProperties().data(), buffer.getFlags().get(), buffer.getSize(),
125             hostPtr, &errorCode);
126     }
127     ANGLE_CL_TRY(errorCode);
128 
129     *bufferOut =
130         CLMemoryImpl::Ptr(nativeBuffer != nullptr ? new CLMemoryCL(buffer, nativeBuffer) : nullptr);
131     return angle::Result::Continue;
132 }
133 
createImage(const cl::Image & image,void * hostPtr,CLMemoryImpl::Ptr * imageOut)134 angle::Result CLContextCL::createImage(const cl::Image &image,
135                                        void *hostPtr,
136                                        CLMemoryImpl::Ptr *imageOut)
137 {
138     cl_int errorCode         = CL_SUCCESS;
139     cl_mem nativeImage       = nullptr;
140     cl::ImageDescriptor desc = image.getDescriptor();
141     cl::MemFlags flags       = image.getFlags();
142     cl_image_format format   = image.getFormat();
143 
144     if (mContext.getPlatform().isVersionOrNewer(1u, 2u))
145     {
146         const cl_mem_object_type nativeType = cl::ToCLenum(desc.type);
147         const cl_mem nativeParent =
148             image.getParent() ? image.getParent()->getImpl<CLMemoryCL>().getNative() : nullptr;
149         const cl_image_desc nativeDesc = {
150             nativeType,    desc.width,      desc.height,       desc.depth,      desc.arraySize,
151             desc.rowPitch, desc.slicePitch, desc.numMipLevels, desc.numSamples, {nativeParent}};
152 
153         if (image.getProperties().empty())
154         {
155             nativeImage = mNative->getDispatch().clCreateImage(mNative, flags.get(), &format,
156                                                                &nativeDesc, hostPtr, &errorCode);
157         }
158         else
159         {
160             nativeImage = mNative->getDispatch().clCreateImageWithProperties(
161                 mNative, image.getProperties().data(), flags.get(), &format, &nativeDesc, hostPtr,
162                 &errorCode);
163         }
164     }
165     else
166     {
167         switch (desc.type)
168         {
169             case cl::MemObjectType::Image2D:
170                 nativeImage = mNative->getDispatch().clCreateImage2D(
171                     mNative, flags.get(), &format, desc.width, desc.height, desc.rowPitch, hostPtr,
172                     &errorCode);
173                 break;
174             case cl::MemObjectType::Image3D:
175                 nativeImage = mNative->getDispatch().clCreateImage3D(
176                     mNative, flags.get(), &format, desc.width, desc.height, desc.depth,
177                     desc.rowPitch, desc.slicePitch, hostPtr, &errorCode);
178                 break;
179             default:
180                 ASSERT(false);
181                 ERR() << "Failed to create unsupported image type";
182                 break;
183         }
184     }
185     ANGLE_CL_TRY(errorCode);
186 
187     *imageOut =
188         CLMemoryImpl::Ptr(nativeImage != nullptr ? new CLMemoryCL(image, nativeImage) : nullptr);
189     return angle::Result::Continue;
190 }
191 
getSupportedImageFormats(cl::MemFlags flags,cl::MemObjectType imageType,cl_uint numEntries,cl_image_format * imageFormats,cl_uint * numImageFormats)192 angle::Result CLContextCL::getSupportedImageFormats(cl::MemFlags flags,
193                                                     cl::MemObjectType imageType,
194                                                     cl_uint numEntries,
195                                                     cl_image_format *imageFormats,
196                                                     cl_uint *numImageFormats)
197 {
198     // Fetch available image formats for given flags and image type.
199     cl_uint numFormats = 0u;
200     ANGLE_CL_TRY(mNative->getDispatch().clGetSupportedImageFormats(
201         mNative, flags.get(), cl::ToCLenum(imageType), 0u, nullptr, &numFormats));
202     std::vector<cl_image_format> formats(numFormats);
203     ANGLE_CL_TRY(mNative->getDispatch().clGetSupportedImageFormats(
204         mNative, flags.get(), cl::ToCLenum(imageType), numFormats, formats.data(), nullptr));
205 
206     // Filter out formats which are not supported by front end.
207     const CLPlatformImpl::Info &info = mContext.getPlatform().getInfo();
208     std::vector<cl_image_format> supportedFormats;
209     supportedFormats.reserve(formats.size());
210     std::copy_if(
211         formats.cbegin(), formats.cend(), std::back_inserter(supportedFormats),
212         [&](const cl_image_format &format) { return cl::IsValidImageFormat(&format, info); });
213 
214     if (imageFormats != nullptr)
215     {
216         auto formatIt = supportedFormats.cbegin();
217         while (numEntries-- != 0u && formatIt != supportedFormats.cend())
218         {
219             *imageFormats++ = *formatIt++;
220         }
221     }
222     if (numImageFormats != nullptr)
223     {
224         *numImageFormats = static_cast<cl_uint>(supportedFormats.size());
225     }
226     return angle::Result::Continue;
227 }
228 
createSampler(const cl::Sampler & sampler,CLSamplerImpl::Ptr * samplerOut)229 angle::Result CLContextCL::createSampler(const cl::Sampler &sampler, CLSamplerImpl::Ptr *samplerOut)
230 {
231     cl_int errorCode         = CL_SUCCESS;
232     cl_sampler nativeSampler = nullptr;
233 
234     if (!mContext.getPlatform().isVersionOrNewer(2u, 0u))
235     {
236         nativeSampler = mNative->getDispatch().clCreateSampler(
237             mNative, sampler.getNormalizedCoords(), cl::ToCLenum(sampler.getAddressingMode()),
238             cl::ToCLenum(sampler.getFilterMode()), &errorCode);
239     }
240     else if (!sampler.getProperties().empty())
241     {
242         nativeSampler = mNative->getDispatch().clCreateSamplerWithProperties(
243             mNative, sampler.getProperties().data(), &errorCode);
244     }
245     else
246     {
247         const cl_sampler_properties propArray[] = {CL_SAMPLER_NORMALIZED_COORDS,
248                                                    sampler.getNormalizedCoords(),
249                                                    CL_SAMPLER_ADDRESSING_MODE,
250                                                    cl::ToCLenum(sampler.getAddressingMode()),
251                                                    CL_SAMPLER_FILTER_MODE,
252                                                    cl::ToCLenum(sampler.getFilterMode()),
253                                                    0u};
254         nativeSampler =
255             mNative->getDispatch().clCreateSamplerWithProperties(mNative, propArray, &errorCode);
256     }
257     ANGLE_CL_TRY(errorCode);
258 
259     *samplerOut = CLSamplerImpl::Ptr(
260         nativeSampler != nullptr ? new CLSamplerCL(sampler, nativeSampler) : nullptr);
261     return angle::Result::Continue;
262 }
263 
createProgramWithSource(const cl::Program & program,const std::string & source,CLProgramImpl::Ptr * programOut)264 angle::Result CLContextCL::createProgramWithSource(const cl::Program &program,
265                                                    const std::string &source,
266                                                    CLProgramImpl::Ptr *programOut)
267 {
268     cl_int errorCode      = CL_SUCCESS;
269     const char *sourceStr = source.c_str();
270     const size_t length   = source.length();
271 
272     const cl_program nativeProgram = mNative->getDispatch().clCreateProgramWithSource(
273         mNative, 1u, &sourceStr, &length, &errorCode);
274     ANGLE_CL_TRY(errorCode);
275 
276     *programOut = CLProgramImpl::Ptr(
277         nativeProgram != nullptr ? new CLProgramCL(program, nativeProgram) : nullptr);
278     return angle::Result::Continue;
279 }
280 
createProgramWithIL(const cl::Program & program,const void * il,size_t length,CLProgramImpl::Ptr * programOut)281 angle::Result CLContextCL::createProgramWithIL(const cl::Program &program,
282                                                const void *il,
283                                                size_t length,
284                                                CLProgramImpl::Ptr *programOut)
285 {
286     cl_int errorCode = CL_SUCCESS;
287 
288     const cl_program nativeProgram =
289         mNative->getDispatch().clCreateProgramWithIL(mNative, il, length, &errorCode);
290     ANGLE_CL_TRY(errorCode);
291 
292     *programOut = CLProgramImpl::Ptr(
293         nativeProgram != nullptr ? new CLProgramCL(program, nativeProgram) : nullptr);
294     return angle::Result::Continue;
295 }
296 
createProgramWithBinary(const cl::Program & program,const size_t * lengths,const unsigned char ** binaries,cl_int * binaryStatus,CLProgramImpl::Ptr * programOut)297 angle::Result CLContextCL::createProgramWithBinary(const cl::Program &program,
298                                                    const size_t *lengths,
299                                                    const unsigned char **binaries,
300                                                    cl_int *binaryStatus,
301                                                    CLProgramImpl::Ptr *programOut)
302 {
303     cl_int errorCode = CL_SUCCESS;
304     std::vector<cl_device_id> nativeDevices;
305     for (const cl::DevicePtr &device : program.getDevices())
306     {
307         nativeDevices.emplace_back(device->getImpl<CLDeviceCL>().getNative());
308     }
309 
310     cl_program nativeProgram = mNative->getDispatch().clCreateProgramWithBinary(
311         mNative, static_cast<cl_uint>(nativeDevices.size()), nativeDevices.data(), lengths,
312         binaries, binaryStatus, &errorCode);
313     ANGLE_CL_TRY(errorCode);
314 
315     *programOut = CLProgramImpl::Ptr(
316         nativeProgram != nullptr ? new CLProgramCL(program, nativeProgram) : nullptr);
317     return angle::Result::Continue;
318 }
319 
createProgramWithBuiltInKernels(const cl::Program & program,const char * kernel_names,CLProgramImpl::Ptr * programOut)320 angle::Result CLContextCL::createProgramWithBuiltInKernels(const cl::Program &program,
321                                                            const char *kernel_names,
322                                                            CLProgramImpl::Ptr *programOut)
323 {
324     cl_int errorCode = CL_SUCCESS;
325     std::vector<cl_device_id> nativeDevices;
326     for (const cl::DevicePtr &device : program.getDevices())
327     {
328         nativeDevices.emplace_back(device->getImpl<CLDeviceCL>().getNative());
329     }
330 
331     const cl_program nativeProgram = mNative->getDispatch().clCreateProgramWithBuiltInKernels(
332         mNative, static_cast<cl_uint>(nativeDevices.size()), nativeDevices.data(), kernel_names,
333         &errorCode);
334     ANGLE_CL_TRY(errorCode);
335 
336     *programOut = CLProgramImpl::Ptr(
337         nativeProgram != nullptr ? new CLProgramCL(program, nativeProgram) : nullptr);
338     return angle::Result::Continue;
339 }
340 
linkProgram(const cl::Program & program,const cl::DevicePtrs & devices,const char * options,const cl::ProgramPtrs & inputPrograms,cl::Program * notify,CLProgramImpl::Ptr * programOut)341 angle::Result CLContextCL::linkProgram(const cl::Program &program,
342                                        const cl::DevicePtrs &devices,
343                                        const char *options,
344                                        const cl::ProgramPtrs &inputPrograms,
345                                        cl::Program *notify,
346                                        CLProgramImpl::Ptr *programOut)
347 {
348     cl_int errorCode = CL_SUCCESS;
349     std::vector<cl_device_id> nativeDevices;
350     for (const cl::DevicePtr &device : devices)
351     {
352         nativeDevices.emplace_back(device->getImpl<CLDeviceCL>().getNative());
353     }
354     const cl_uint numDevices = static_cast<cl_uint>(nativeDevices.size());
355     const cl_device_id *const nativeDevicesPtr =
356         !nativeDevices.empty() ? nativeDevices.data() : nullptr;
357 
358     std::vector<cl_program> nativePrograms;
359     for (const cl::ProgramPtr &inputProgram : inputPrograms)
360     {
361         nativePrograms.emplace_back(inputProgram->getImpl<CLProgramCL>().getNative());
362     }
363     const cl_uint numInputHeaders = static_cast<cl_uint>(nativePrograms.size());
364 
365     const cl::ProgramCB callback   = notify != nullptr ? CLProgramCL::Callback : nullptr;
366     const cl_program nativeProgram = mNative->getDispatch().clLinkProgram(
367         mNative, numDevices, nativeDevicesPtr, options, numInputHeaders, nativePrograms.data(),
368         callback, notify, &errorCode);
369     ANGLE_CL_TRY(errorCode);
370 
371     *programOut = CLProgramImpl::Ptr(
372         nativeProgram != nullptr ? new CLProgramCL(program, nativeProgram) : nullptr);
373     return angle::Result::Continue;
374 }
375 
createUserEvent(const cl::Event & event,CLEventImpl::Ptr * programOut)376 angle::Result CLContextCL::createUserEvent(const cl::Event &event, CLEventImpl::Ptr *programOut)
377 {
378     cl_int errorCode = CL_SUCCESS;
379 
380     const cl_event nativeEvent = mNative->getDispatch().clCreateUserEvent(mNative, &errorCode);
381     ANGLE_CL_TRY(errorCode);
382 
383     *programOut =
384         CLEventImpl::Ptr(nativeEvent != nullptr ? new CLEventCL(event, nativeEvent) : nullptr);
385     return angle::Result::Continue;
386 }
387 
waitForEvents(const cl::EventPtrs & events)388 angle::Result CLContextCL::waitForEvents(const cl::EventPtrs &events)
389 {
390     const std::vector<cl_event> nativeEvents = CLEventCL::Cast(events);
391     ANGLE_CL_TRY(mNative->getDispatch().clWaitForEvents(static_cast<cl_uint>(nativeEvents.size()),
392                                                         nativeEvents.data()));
393     return angle::Result::Continue;
394 }
395 
396 }  // namespace rx
397