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