xref: /aosp_15_r20/external/angle/src/libANGLE/CLContext.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 // CLContext.cpp: Implements the cl::Context class.
7 
8 #include "libANGLE/CLContext.h"
9 
10 #include "libANGLE/CLBuffer.h"
11 #include "libANGLE/CLCommandQueue.h"
12 #include "libANGLE/CLEvent.h"
13 #include "libANGLE/CLImage.h"
14 #include "libANGLE/CLMemory.h"
15 #include "libANGLE/CLProgram.h"
16 #include "libANGLE/CLSampler.h"
17 
18 #include <cstring>
19 
20 namespace cl
21 {
22 
getInfo(ContextInfo name,size_t valueSize,void * value,size_t * valueSizeRet) const23 angle::Result Context::getInfo(ContextInfo name,
24                                size_t valueSize,
25                                void *value,
26                                size_t *valueSizeRet) const
27 {
28     std::vector<cl_device_id> devices;
29     cl_uint valUInt       = 0u;
30     const void *copyValue = nullptr;
31     size_t copySize       = 0u;
32 
33     switch (name)
34     {
35         case ContextInfo::ReferenceCount:
36             valUInt   = getRefCount();
37             copyValue = &valUInt;
38             copySize  = sizeof(valUInt);
39             break;
40         case ContextInfo::NumDevices:
41             valUInt   = static_cast<decltype(valUInt)>(mDevices.size());
42             copyValue = &valUInt;
43             copySize  = sizeof(valUInt);
44             break;
45         case ContextInfo::Devices:
46             devices.reserve(mDevices.size());
47             for (const DevicePtr &device : mDevices)
48             {
49                 devices.emplace_back(device->getNative());
50             }
51             copyValue = devices.data();
52             copySize  = devices.size() * sizeof(decltype(devices)::value_type);
53             break;
54         case ContextInfo::Properties:
55             copyValue = mProperties.data();
56             copySize  = mProperties.size() * sizeof(decltype(mProperties)::value_type);
57             break;
58         default:
59             ASSERT(false);
60             ANGLE_CL_RETURN_ERROR(CL_INVALID_VALUE);
61     }
62 
63     if (value != nullptr)
64     {
65         // CL_INVALID_VALUE if size in bytes specified by param_value_size is < size of return type
66         // as specified in the Context Attributes table and param_value is not a NULL value.
67         if (valueSize < copySize)
68         {
69             ANGLE_CL_RETURN_ERROR(CL_INVALID_VALUE);
70         }
71         if (copyValue != nullptr)
72         {
73             std::memcpy(value, copyValue, copySize);
74         }
75     }
76     if (valueSizeRet != nullptr)
77     {
78         *valueSizeRet = copySize;
79     }
80     return angle::Result::Continue;
81 }
82 
createCommandQueueWithProperties(cl_device_id device,const cl_queue_properties * properties)83 cl_command_queue Context::createCommandQueueWithProperties(cl_device_id device,
84                                                            const cl_queue_properties *properties)
85 {
86     CommandQueue::PropArray propArray;
87     CommandQueueProperties props;
88     cl_uint size = CommandQueue::kNoSize;
89     if (properties != nullptr)
90     {
91         const cl_queue_properties *propIt = properties;
92         while (*propIt != 0)
93         {
94             switch (*propIt++)
95             {
96                 case CL_QUEUE_PROPERTIES:
97                     props = static_cast<cl_command_queue_properties>(*propIt++);
98                     break;
99                 case CL_QUEUE_SIZE:
100                     size = static_cast<decltype(size)>(*propIt++);
101                     break;
102             }
103         }
104         // Include the trailing zero
105         ++propIt;
106         propArray.reserve(propIt - properties);
107         propArray.insert(propArray.cend(), properties, propIt);
108     }
109     return Object::Create<CommandQueue>(*this, device->cast<Device>(), std::move(propArray), props,
110                                         size);
111 }
112 
createCommandQueue(cl_device_id device,CommandQueueProperties properties)113 cl_command_queue Context::createCommandQueue(cl_device_id device, CommandQueueProperties properties)
114 {
115     return Object::Create<CommandQueue>(*this, device->cast<Device>(), properties);
116 }
117 
createBuffer(const cl_mem_properties * properties,MemFlags flags,size_t size,void * hostPtr)118 cl_mem Context::createBuffer(const cl_mem_properties *properties,
119                              MemFlags flags,
120                              size_t size,
121                              void *hostPtr)
122 {
123     // If the properties argument specified in clCreateBufferWithProperties or
124     // clCreateImageWithProperties used to create memobj was not NULL, the implementation must
125     // return the values specified in the properties argument in the same order and without
126     // including additional properties. So pass them as is.
127     Memory::PropArray propArray;
128     if (properties != nullptr)
129     {
130         const cl_mem_properties *propIt = properties;
131         while (*propIt != 0)
132         {
133             propArray.push_back(*propIt);
134             ++propIt;
135         }
136         // there is at least one property - special property 0
137         propArray.push_back(0);
138     }
139     return Object::Create<Buffer>(*this, std::move(propArray), flags, size, hostPtr);
140 }
141 
createImage(const cl_mem_properties * properties,MemFlags flags,const cl_image_format * format,const cl_image_desc * desc,void * hostPtr)142 cl_mem Context::createImage(const cl_mem_properties *properties,
143                             MemFlags flags,
144                             const cl_image_format *format,
145                             const cl_image_desc *desc,
146                             void *hostPtr)
147 {
148     const ImageDescriptor imageDesc = {FromCLenum<MemObjectType>(desc->image_type),
149                                        desc->image_width,
150                                        desc->image_height,
151                                        desc->image_depth,
152                                        desc->image_array_size,
153                                        desc->image_row_pitch,
154                                        desc->image_slice_pitch,
155                                        desc->num_mip_levels,
156                                        desc->num_samples};
157     Memory::PropArray propArray;
158 
159     // If the properties argument specified in clCreateBufferWithProperties or
160     // clCreateImageWithProperties used to create memobj was not NULL, the implementation must
161     // return the values specified in the properties argument in the same order and without
162     // including additional properties. So Pass them as is.
163     if (properties != nullptr)
164     {
165         const cl_mem_properties *propIt = properties;
166         while (*propIt != 0)
167         {
168             propArray.push_back(*propIt);
169             ++propIt;
170         }
171         // there is at least one property - special property 0
172         propArray.push_back(0);
173     }
174     return Object::Create<Image>(*this, std::move(propArray), flags, *format, imageDesc,
175                                  Memory::Cast(desc->buffer), hostPtr);
176 }
177 
createImage2D(MemFlags flags,const cl_image_format * format,size_t width,size_t height,size_t rowPitch,void * hostPtr)178 cl_mem Context::createImage2D(MemFlags flags,
179                               const cl_image_format *format,
180                               size_t width,
181                               size_t height,
182                               size_t rowPitch,
183                               void *hostPtr)
184 {
185     const ImageDescriptor imageDesc(MemObjectType::Image2D, width, height, 0u, 0u, rowPitch, 0u, 0u,
186                                     0u);
187     return Object::Create<Image>(*this, Memory::PropArray{}, flags, *format, imageDesc, nullptr,
188                                  hostPtr);
189 }
190 
createImage3D(MemFlags flags,const cl_image_format * format,size_t width,size_t height,size_t depth,size_t rowPitch,size_t slicePitch,void * hostPtr)191 cl_mem Context::createImage3D(MemFlags flags,
192                               const cl_image_format *format,
193                               size_t width,
194                               size_t height,
195                               size_t depth,
196                               size_t rowPitch,
197                               size_t slicePitch,
198                               void *hostPtr)
199 {
200     const ImageDescriptor imageDesc(MemObjectType::Image3D, width, height, depth, 0u, rowPitch,
201                                     slicePitch, 0u, 0u);
202     return Object::Create<Image>(*this, Memory::PropArray{}, flags, *format, imageDesc, nullptr,
203                                  hostPtr);
204 }
205 
getSupportedImageFormats(MemFlags flags,MemObjectType imageType,cl_uint numEntries,cl_image_format * imageFormats,cl_uint * numImageFormats)206 angle::Result Context::getSupportedImageFormats(MemFlags flags,
207                                                 MemObjectType imageType,
208                                                 cl_uint numEntries,
209                                                 cl_image_format *imageFormats,
210                                                 cl_uint *numImageFormats)
211 {
212     return mImpl->getSupportedImageFormats(flags, imageType, numEntries, imageFormats,
213                                            numImageFormats);
214 }
215 
createSamplerWithProperties(const cl_sampler_properties * properties)216 cl_sampler Context::createSamplerWithProperties(const cl_sampler_properties *properties)
217 {
218     Sampler::PropArray propArray;
219     cl_bool normalizedCoords      = CL_TRUE;
220     AddressingMode addressingMode = AddressingMode::Clamp;
221     FilterMode filterMode         = FilterMode::Nearest;
222 
223     if (properties != nullptr)
224     {
225         const cl_sampler_properties *propIt = properties;
226         while (*propIt != 0)
227         {
228             switch (*propIt++)
229             {
230                 case CL_SAMPLER_NORMALIZED_COORDS:
231                     normalizedCoords = static_cast<decltype(normalizedCoords)>(*propIt++);
232                     break;
233                 case CL_SAMPLER_ADDRESSING_MODE:
234                     addressingMode = FromCLenum<AddressingMode>(static_cast<CLenum>(*propIt++));
235                     break;
236                 case CL_SAMPLER_FILTER_MODE:
237                     filterMode = FromCLenum<FilterMode>(static_cast<CLenum>(*propIt++));
238                     break;
239             }
240         }
241         // Include the trailing zero
242         ++propIt;
243         propArray.reserve(propIt - properties);
244         propArray.insert(propArray.cend(), properties, propIt);
245     }
246 
247     return Object::Create<Sampler>(*this, std::move(propArray), normalizedCoords, addressingMode,
248                                    filterMode);
249 }
250 
createSampler(cl_bool normalizedCoords,AddressingMode addressingMode,FilterMode filterMode)251 cl_sampler Context::createSampler(cl_bool normalizedCoords,
252                                   AddressingMode addressingMode,
253                                   FilterMode filterMode)
254 {
255     return Object::Create<Sampler>(*this, Sampler::PropArray{}, normalizedCoords, addressingMode,
256                                    filterMode);
257 }
258 
createProgramWithSource(cl_uint count,const char ** strings,const size_t * lengths)259 cl_program Context::createProgramWithSource(cl_uint count,
260                                             const char **strings,
261                                             const size_t *lengths)
262 {
263     std::string source;
264     if (lengths == nullptr)
265     {
266         while (count-- != 0u)
267         {
268             source.append(*strings++);
269         }
270     }
271     else
272     {
273         while (count-- != 0u)
274         {
275             if (*lengths != 0u)
276             {
277                 source.append(*strings++, *lengths);
278             }
279             else
280             {
281                 source.append(*strings++);
282             }
283             ++lengths;
284         }
285     }
286     return Object::Create<Program>(*this, std::move(source));
287 }
288 
createProgramWithIL(const void * il,size_t length)289 cl_program Context::createProgramWithIL(const void *il, size_t length)
290 {
291     return Object::Create<Program>(*this, il, length);
292 }
293 
createProgramWithBinary(cl_uint numDevices,const cl_device_id * devices,const size_t * lengths,const unsigned char ** binaries,cl_int * binaryStatus)294 cl_program Context::createProgramWithBinary(cl_uint numDevices,
295                                             const cl_device_id *devices,
296                                             const size_t *lengths,
297                                             const unsigned char **binaries,
298                                             cl_int *binaryStatus)
299 {
300     DevicePtrs devs;
301     devs.reserve(numDevices);
302     while (numDevices-- != 0u)
303     {
304         devs.emplace_back(&(*devices++)->cast<Device>());
305     }
306     return Object::Create<Program>(*this, std::move(devs), lengths, binaries, binaryStatus);
307 }
308 
createProgramWithBuiltInKernels(cl_uint numDevices,const cl_device_id * devices,const char * kernelNames)309 cl_program Context::createProgramWithBuiltInKernels(cl_uint numDevices,
310                                                     const cl_device_id *devices,
311                                                     const char *kernelNames)
312 {
313     DevicePtrs devs;
314     devs.reserve(numDevices);
315     while (numDevices-- != 0u)
316     {
317         devs.emplace_back(&(*devices++)->cast<Device>());
318     }
319     return Object::Create<Program>(*this, std::move(devs), kernelNames);
320 }
321 
linkProgram(cl_uint numDevices,const cl_device_id * deviceList,const char * options,cl_uint numInputPrograms,const cl_program * inputPrograms,ProgramCB pfnNotify,void * userData)322 cl_program Context::linkProgram(cl_uint numDevices,
323                                 const cl_device_id *deviceList,
324                                 const char *options,
325                                 cl_uint numInputPrograms,
326                                 const cl_program *inputPrograms,
327                                 ProgramCB pfnNotify,
328                                 void *userData)
329 {
330     DevicePtrs devices;
331     devices.reserve(numDevices);
332     while (numDevices-- != 0u)
333     {
334         devices.emplace_back(&(*deviceList++)->cast<Device>());
335     }
336     ProgramPtrs programs;
337     programs.reserve(numInputPrograms);
338     while (numInputPrograms-- != 0u)
339     {
340         programs.emplace_back(&(*inputPrograms++)->cast<Program>());
341     }
342     return Object::Create<Program>(*this, devices, options, programs, pfnNotify, userData);
343 }
344 
createUserEvent()345 cl_event Context::createUserEvent()
346 {
347     return Object::Create<Event>(*this);
348 }
349 
waitForEvents(cl_uint numEvents,const cl_event * eventList)350 angle::Result Context::waitForEvents(cl_uint numEvents, const cl_event *eventList)
351 {
352     return mImpl->waitForEvents(Event::Cast(numEvents, eventList));
353 }
354 
355 Context::~Context() = default;
356 
ErrorCallback(const char * errinfo,const void * privateInfo,size_t cb,void * userData)357 void Context::ErrorCallback(const char *errinfo, const void *privateInfo, size_t cb, void *userData)
358 {
359     Context *const context = static_cast<Context *>(userData);
360     if (!Context::IsValid(context))
361     {
362         WARN() << "Context error for invalid context";
363         return;
364     }
365     if (context->mNotify != nullptr)
366     {
367         context->mNotify(errinfo, privateInfo, cb, context->mUserData);
368     }
369 }
370 
Context(Platform & platform,PropArray && properties,DevicePtrs && devices,ContextErrorCB notify,void * userData,bool userSync)371 Context::Context(Platform &platform,
372                  PropArray &&properties,
373                  DevicePtrs &&devices,
374                  ContextErrorCB notify,
375                  void *userData,
376                  bool userSync)
377     : mPlatform(platform),
378       mProperties(std::move(properties)),
379       mNotify(notify),
380       mUserData(userData),
381       mImpl(nullptr),
382       mDevices(std::move(devices))
383 {
384     ANGLE_CL_IMPL_TRY(platform.getImpl().createContext(*this, mDevices, userSync, &mImpl));
385 }
386 
Context(Platform & platform,PropArray && properties,DeviceType deviceType,ContextErrorCB notify,void * userData,bool userSync)387 Context::Context(Platform &platform,
388                  PropArray &&properties,
389                  DeviceType deviceType,
390                  ContextErrorCB notify,
391                  void *userData,
392                  bool userSync)
393     : mPlatform(platform),
394       mProperties(std::move(properties)),
395       mNotify(notify),
396       mUserData(userData),
397       mImpl(nullptr)
398 {
399     if (!IsError(platform.getImpl().createContextFromType(*this, deviceType, userSync, &mImpl)))
400     {
401         ANGLE_CL_IMPL_TRY(mImpl->getDevices(&mDevices));
402     }
403 }
404 
405 }  // namespace cl
406