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