• 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 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     return Object::Create<Buffer>(*this, Memory::PropArray{}, flags, size, hostPtr);
124 }
125 
createImage(const cl_mem_properties * properties,MemFlags flags,const cl_image_format * format,const cl_image_desc * desc,void * hostPtr)126 cl_mem Context::createImage(const cl_mem_properties *properties,
127                             MemFlags flags,
128                             const cl_image_format *format,
129                             const cl_image_desc *desc,
130                             void *hostPtr)
131 {
132     const ImageDescriptor imageDesc = {FromCLenum<MemObjectType>(desc->image_type),
133                                        desc->image_width,
134                                        desc->image_height,
135                                        desc->image_depth,
136                                        desc->image_array_size,
137                                        desc->image_row_pitch,
138                                        desc->image_slice_pitch,
139                                        desc->num_mip_levels,
140                                        desc->num_samples};
141     return Object::Create<Image>(*this, Memory::PropArray{}, flags, *format, imageDesc,
142                                  Memory::Cast(desc->buffer), hostPtr);
143 }
144 
createImage2D(MemFlags flags,const cl_image_format * format,size_t width,size_t height,size_t rowPitch,void * hostPtr)145 cl_mem Context::createImage2D(MemFlags flags,
146                               const cl_image_format *format,
147                               size_t width,
148                               size_t height,
149                               size_t rowPitch,
150                               void *hostPtr)
151 {
152     const ImageDescriptor imageDesc = {
153         MemObjectType::Image2D, width, height, 0u, 0u, rowPitch, 0u, 0u, 0u};
154     return Object::Create<Image>(*this, Memory::PropArray{}, flags, *format, imageDesc, nullptr,
155                                  hostPtr);
156 }
157 
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)158 cl_mem Context::createImage3D(MemFlags flags,
159                               const cl_image_format *format,
160                               size_t width,
161                               size_t height,
162                               size_t depth,
163                               size_t rowPitch,
164                               size_t slicePitch,
165                               void *hostPtr)
166 {
167     const ImageDescriptor imageDesc = {
168         MemObjectType::Image3D, width, height, depth, 0u, rowPitch, slicePitch, 0u, 0u};
169     return Object::Create<Image>(*this, Memory::PropArray{}, flags, *format, imageDesc, nullptr,
170                                  hostPtr);
171 }
172 
getSupportedImageFormats(MemFlags flags,MemObjectType imageType,cl_uint numEntries,cl_image_format * imageFormats,cl_uint * numImageFormats)173 angle::Result Context::getSupportedImageFormats(MemFlags flags,
174                                                 MemObjectType imageType,
175                                                 cl_uint numEntries,
176                                                 cl_image_format *imageFormats,
177                                                 cl_uint *numImageFormats)
178 {
179     return mImpl->getSupportedImageFormats(flags, imageType, numEntries, imageFormats,
180                                            numImageFormats);
181 }
182 
createSamplerWithProperties(const cl_sampler_properties * properties)183 cl_sampler Context::createSamplerWithProperties(const cl_sampler_properties *properties)
184 {
185     Sampler::PropArray propArray;
186     cl_bool normalizedCoords      = CL_TRUE;
187     AddressingMode addressingMode = AddressingMode::Clamp;
188     FilterMode filterMode         = FilterMode::Nearest;
189 
190     if (properties != nullptr)
191     {
192         const cl_sampler_properties *propIt = properties;
193         while (*propIt != 0)
194         {
195             switch (*propIt++)
196             {
197                 case CL_SAMPLER_NORMALIZED_COORDS:
198                     normalizedCoords = static_cast<decltype(normalizedCoords)>(*propIt++);
199                     break;
200                 case CL_SAMPLER_ADDRESSING_MODE:
201                     addressingMode = FromCLenum<AddressingMode>(static_cast<CLenum>(*propIt++));
202                     break;
203                 case CL_SAMPLER_FILTER_MODE:
204                     filterMode = FromCLenum<FilterMode>(static_cast<CLenum>(*propIt++));
205                     break;
206             }
207         }
208         // Include the trailing zero
209         ++propIt;
210         propArray.reserve(propIt - properties);
211         propArray.insert(propArray.cend(), properties, propIt);
212     }
213 
214     return Object::Create<Sampler>(*this, std::move(propArray), normalizedCoords, addressingMode,
215                                    filterMode);
216 }
217 
createSampler(cl_bool normalizedCoords,AddressingMode addressingMode,FilterMode filterMode)218 cl_sampler Context::createSampler(cl_bool normalizedCoords,
219                                   AddressingMode addressingMode,
220                                   FilterMode filterMode)
221 {
222     return Object::Create<Sampler>(*this, Sampler::PropArray{}, normalizedCoords, addressingMode,
223                                    filterMode);
224 }
225 
createProgramWithSource(cl_uint count,const char ** strings,const size_t * lengths)226 cl_program Context::createProgramWithSource(cl_uint count,
227                                             const char **strings,
228                                             const size_t *lengths)
229 {
230     std::string source;
231     if (lengths == nullptr)
232     {
233         while (count-- != 0u)
234         {
235             source.append(*strings++);
236         }
237     }
238     else
239     {
240         while (count-- != 0u)
241         {
242             if (*lengths != 0u)
243             {
244                 source.append(*strings++, *lengths);
245             }
246             else
247             {
248                 source.append(*strings++);
249             }
250             ++lengths;
251         }
252     }
253     return Object::Create<Program>(*this, std::move(source));
254 }
255 
createProgramWithIL(const void * il,size_t length)256 cl_program Context::createProgramWithIL(const void *il, size_t length)
257 {
258     return Object::Create<Program>(*this, il, length);
259 }
260 
createProgramWithBinary(cl_uint numDevices,const cl_device_id * devices,const size_t * lengths,const unsigned char ** binaries,cl_int * binaryStatus)261 cl_program Context::createProgramWithBinary(cl_uint numDevices,
262                                             const cl_device_id *devices,
263                                             const size_t *lengths,
264                                             const unsigned char **binaries,
265                                             cl_int *binaryStatus)
266 {
267     DevicePtrs devs;
268     devs.reserve(numDevices);
269     while (numDevices-- != 0u)
270     {
271         devs.emplace_back(&(*devices++)->cast<Device>());
272     }
273     return Object::Create<Program>(*this, std::move(devs), lengths, binaries, binaryStatus);
274 }
275 
createProgramWithBuiltInKernels(cl_uint numDevices,const cl_device_id * devices,const char * kernelNames)276 cl_program Context::createProgramWithBuiltInKernels(cl_uint numDevices,
277                                                     const cl_device_id *devices,
278                                                     const char *kernelNames)
279 {
280     DevicePtrs devs;
281     devs.reserve(numDevices);
282     while (numDevices-- != 0u)
283     {
284         devs.emplace_back(&(*devices++)->cast<Device>());
285     }
286     return Object::Create<Program>(*this, std::move(devs), kernelNames);
287 }
288 
linkProgram(cl_uint numDevices,const cl_device_id * deviceList,const char * options,cl_uint numInputPrograms,const cl_program * inputPrograms,ProgramCB pfnNotify,void * userData)289 cl_program Context::linkProgram(cl_uint numDevices,
290                                 const cl_device_id *deviceList,
291                                 const char *options,
292                                 cl_uint numInputPrograms,
293                                 const cl_program *inputPrograms,
294                                 ProgramCB pfnNotify,
295                                 void *userData)
296 {
297     DevicePtrs devices;
298     devices.reserve(numDevices);
299     while (numDevices-- != 0u)
300     {
301         devices.emplace_back(&(*deviceList++)->cast<Device>());
302     }
303     ProgramPtrs programs;
304     programs.reserve(numInputPrograms);
305     while (numInputPrograms-- != 0u)
306     {
307         programs.emplace_back(&(*inputPrograms++)->cast<Program>());
308     }
309     return Object::Create<Program>(*this, devices, options, programs, pfnNotify, userData);
310 }
311 
createUserEvent()312 cl_event Context::createUserEvent()
313 {
314     return Object::Create<Event>(*this);
315 }
316 
waitForEvents(cl_uint numEvents,const cl_event * eventList)317 angle::Result Context::waitForEvents(cl_uint numEvents, const cl_event *eventList)
318 {
319     return mImpl->waitForEvents(Event::Cast(numEvents, eventList));
320 }
321 
322 Context::~Context() = default;
323 
ErrorCallback(const char * errinfo,const void * privateInfo,size_t cb,void * userData)324 void Context::ErrorCallback(const char *errinfo, const void *privateInfo, size_t cb, void *userData)
325 {
326     Context *const context = static_cast<Context *>(userData);
327     if (!Context::IsValid(context))
328     {
329         WARN() << "Context error for invalid context";
330         return;
331     }
332     if (context->mNotify != nullptr)
333     {
334         context->mNotify(errinfo, privateInfo, cb, context->mUserData);
335     }
336 }
337 
Context(Platform & platform,PropArray && properties,DevicePtrs && devices,ContextErrorCB notify,void * userData,bool userSync)338 Context::Context(Platform &platform,
339                  PropArray &&properties,
340                  DevicePtrs &&devices,
341                  ContextErrorCB notify,
342                  void *userData,
343                  bool userSync)
344     : mPlatform(platform),
345       mProperties(std::move(properties)),
346       mNotify(notify),
347       mUserData(userData),
348       mImpl(nullptr),
349       mDevices(std::move(devices))
350 {
351     ANGLE_CL_IMPL_TRY(platform.getImpl().createContext(*this, mDevices, userSync, &mImpl));
352 }
353 
Context(Platform & platform,PropArray && properties,DeviceType deviceType,ContextErrorCB notify,void * userData,bool userSync)354 Context::Context(Platform &platform,
355                  PropArray &&properties,
356                  DeviceType deviceType,
357                  ContextErrorCB notify,
358                  void *userData,
359                  bool userSync)
360     : mPlatform(platform),
361       mProperties(std::move(properties)),
362       mNotify(notify),
363       mUserData(userData),
364       mImpl(nullptr)
365 {
366     if (!IsError(platform.getImpl().createContextFromType(*this, deviceType, userSync, &mImpl)))
367     {
368         ANGLE_CL_IMPL_TRY(mImpl->getDevices(&mDevices));
369     }
370 }
371 
372 }  // namespace cl
373