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