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 // CLCommandQueue.cpp: Implements the cl::CommandQueue class.
7
8 #include "libANGLE/CLCommandQueue.h"
9
10 #include "libANGLE/CLBuffer.h"
11 #include "libANGLE/CLContext.h"
12 #include "libANGLE/CLDevice.h"
13 #include "libANGLE/CLEvent.h"
14 #include "libANGLE/CLImage.h"
15 #include "libANGLE/CLKernel.h"
16 #include "libANGLE/CLMemory.h"
17
18 #include <cstring>
19
20 namespace cl
21 {
22
23 namespace
24 {
25
CheckCreateEvent(CommandQueue & queue,cl_command_type commandType,const rx::CLEventImpl::CreateFunc & createFunc,cl_event * event)26 void CheckCreateEvent(CommandQueue &queue,
27 cl_command_type commandType,
28 const rx::CLEventImpl::CreateFunc &createFunc,
29 cl_event *event)
30 {
31 if (event != nullptr)
32 {
33 ASSERT(createFunc);
34 *event = Object::Create<Event>(queue, commandType, createFunc);
35 }
36 }
37
38 } // namespace
39
getInfo(CommandQueueInfo name,size_t valueSize,void * value,size_t * valueSizeRet) const40 angle::Result CommandQueue::getInfo(CommandQueueInfo name,
41 size_t valueSize,
42 void *value,
43 size_t *valueSizeRet) const
44 {
45 cl_command_queue_properties properties = 0u;
46 cl_uint valUInt = 0u;
47 void *valPointer = nullptr;
48 const void *copyValue = nullptr;
49 size_t copySize = 0u;
50
51 switch (name)
52 {
53 case CommandQueueInfo::Context:
54 valPointer = mContext->getNative();
55 copyValue = &valPointer;
56 copySize = sizeof(valPointer);
57 break;
58 case CommandQueueInfo::Device:
59 valPointer = mDevice->getNative();
60 copyValue = &valPointer;
61 copySize = sizeof(valPointer);
62 break;
63 case CommandQueueInfo::ReferenceCount:
64 valUInt = getRefCount();
65 copyValue = &valUInt;
66 copySize = sizeof(valUInt);
67 break;
68 case CommandQueueInfo::Properties:
69 properties = mProperties->get();
70 copyValue = &properties;
71 copySize = sizeof(properties);
72 break;
73 case CommandQueueInfo::PropertiesArray:
74 copyValue = mPropArray.data();
75 copySize = mPropArray.size() * sizeof(decltype(mPropArray)::value_type);
76 break;
77 case CommandQueueInfo::Size:
78 copyValue = &mSize;
79 copySize = sizeof(mSize);
80 break;
81 case CommandQueueInfo::DeviceDefault:
82 valPointer = CommandQueue::CastNative(*mDevice->mDefaultCommandQueue);
83 copyValue = &valPointer;
84 copySize = sizeof(valPointer);
85 break;
86 default:
87 ANGLE_CL_RETURN_ERROR(CL_INVALID_VALUE);
88 }
89
90 if (value != nullptr)
91 {
92 // CL_INVALID_VALUE if size in bytes specified by param_value_size is < size of return type
93 // as specified in the Command Queue Parameter table, and param_value is not a NULL value.
94 if (valueSize < copySize)
95 {
96 ANGLE_CL_RETURN_ERROR(CL_INVALID_VALUE);
97 }
98 if (copyValue != nullptr)
99 {
100 std::memcpy(value, copyValue, copySize);
101 }
102 }
103 if (valueSizeRet != nullptr)
104 {
105 *valueSizeRet = copySize;
106 }
107 return angle::Result::Continue;
108 }
109
setProperty(CommandQueueProperties properties,cl_bool enable,cl_command_queue_properties * oldProperties)110 angle::Result CommandQueue::setProperty(CommandQueueProperties properties,
111 cl_bool enable,
112 cl_command_queue_properties *oldProperties)
113 {
114 auto props = mProperties.synchronize();
115 if (oldProperties != nullptr)
116 {
117 *oldProperties = props->get();
118 }
119
120 ANGLE_TRY(mImpl->setProperty(properties, enable));
121
122 if (enable == CL_FALSE)
123 {
124 props->clear(properties);
125 }
126 else
127 {
128 props->set(properties);
129 }
130 return angle::Result::Continue;
131 }
132
enqueueReadBuffer(cl_mem buffer,cl_bool blockingRead,size_t offset,size_t size,void * ptr,cl_uint numEventsInWaitList,const cl_event * eventWaitList,cl_event * event)133 angle::Result CommandQueue::enqueueReadBuffer(cl_mem buffer,
134 cl_bool blockingRead,
135 size_t offset,
136 size_t size,
137 void *ptr,
138 cl_uint numEventsInWaitList,
139 const cl_event *eventWaitList,
140 cl_event *event)
141 {
142 const Buffer &buf = buffer->cast<Buffer>();
143 const bool blocking = blockingRead != CL_FALSE;
144 const EventPtrs waitEvents = Event::Cast(numEventsInWaitList, eventWaitList);
145 rx::CLEventImpl::CreateFunc eventCreateFunc;
146 rx::CLEventImpl::CreateFunc *const eventCreateFuncPtr =
147 event != nullptr ? &eventCreateFunc : nullptr;
148
149 ANGLE_TRY(
150 mImpl->enqueueReadBuffer(buf, blocking, offset, size, ptr, waitEvents, eventCreateFuncPtr));
151
152 CheckCreateEvent(*this, CL_COMMAND_READ_BUFFER, eventCreateFunc, event);
153 return angle::Result::Continue;
154 }
155
enqueueWriteBuffer(cl_mem buffer,cl_bool blockingWrite,size_t offset,size_t size,const void * ptr,cl_uint numEventsInWaitList,const cl_event * eventWaitList,cl_event * event)156 angle::Result CommandQueue::enqueueWriteBuffer(cl_mem buffer,
157 cl_bool blockingWrite,
158 size_t offset,
159 size_t size,
160 const void *ptr,
161 cl_uint numEventsInWaitList,
162 const cl_event *eventWaitList,
163 cl_event *event)
164 {
165 const Buffer &buf = buffer->cast<Buffer>();
166 const bool blocking = blockingWrite != CL_FALSE;
167 const EventPtrs waitEvents = Event::Cast(numEventsInWaitList, eventWaitList);
168 rx::CLEventImpl::CreateFunc eventCreateFunc;
169 rx::CLEventImpl::CreateFunc *const eventCreateFuncPtr =
170 event != nullptr ? &eventCreateFunc : nullptr;
171
172 ANGLE_TRY(mImpl->enqueueWriteBuffer(buf, blocking, offset, size, ptr, waitEvents,
173 eventCreateFuncPtr));
174
175 CheckCreateEvent(*this, CL_COMMAND_WRITE_BUFFER, eventCreateFunc, event);
176 return angle::Result::Continue;
177 }
178
enqueueReadBufferRect(cl_mem buffer,cl_bool blockingRead,const cl::MemOffsets & bufferOrigin,const cl::MemOffsets & hostOrigin,const cl::Coordinate & region,size_t bufferRowPitch,size_t bufferSlicePitch,size_t hostRowPitch,size_t hostSlicePitch,void * ptr,cl_uint numEventsInWaitList,const cl_event * eventWaitList,cl_event * event)179 angle::Result CommandQueue::enqueueReadBufferRect(cl_mem buffer,
180 cl_bool blockingRead,
181 const cl::MemOffsets &bufferOrigin,
182 const cl::MemOffsets &hostOrigin,
183 const cl::Coordinate ®ion,
184 size_t bufferRowPitch,
185 size_t bufferSlicePitch,
186 size_t hostRowPitch,
187 size_t hostSlicePitch,
188 void *ptr,
189 cl_uint numEventsInWaitList,
190 const cl_event *eventWaitList,
191 cl_event *event)
192 {
193 const Buffer &buf = buffer->cast<Buffer>();
194 const bool blocking = blockingRead != CL_FALSE;
195 const EventPtrs waitEvents = Event::Cast(numEventsInWaitList, eventWaitList);
196 rx::CLEventImpl::CreateFunc eventCreateFunc;
197 rx::CLEventImpl::CreateFunc *const eventCreateFuncPtr =
198 event != nullptr ? &eventCreateFunc : nullptr;
199
200 ANGLE_TRY(mImpl->enqueueReadBufferRect(buf, blocking, bufferOrigin, hostOrigin, region,
201 bufferRowPitch, bufferSlicePitch, hostRowPitch,
202 hostSlicePitch, ptr, waitEvents, eventCreateFuncPtr));
203
204 CheckCreateEvent(*this, CL_COMMAND_READ_BUFFER_RECT, eventCreateFunc, event);
205 return angle::Result::Continue;
206 }
207
enqueueWriteBufferRect(cl_mem buffer,cl_bool blockingWrite,const cl::MemOffsets & bufferOrigin,const cl::MemOffsets & hostOrigin,const cl::Coordinate & region,size_t bufferRowPitch,size_t bufferSlicePitch,size_t hostRowPitch,size_t hostSlicePitch,const void * ptr,cl_uint numEventsInWaitList,const cl_event * eventWaitList,cl_event * event)208 angle::Result CommandQueue::enqueueWriteBufferRect(cl_mem buffer,
209 cl_bool blockingWrite,
210 const cl::MemOffsets &bufferOrigin,
211 const cl::MemOffsets &hostOrigin,
212 const cl::Coordinate ®ion,
213 size_t bufferRowPitch,
214 size_t bufferSlicePitch,
215 size_t hostRowPitch,
216 size_t hostSlicePitch,
217 const void *ptr,
218 cl_uint numEventsInWaitList,
219 const cl_event *eventWaitList,
220 cl_event *event)
221 {
222 const Buffer &buf = buffer->cast<Buffer>();
223 const bool blocking = blockingWrite != CL_FALSE;
224 const EventPtrs waitEvents = Event::Cast(numEventsInWaitList, eventWaitList);
225 rx::CLEventImpl::CreateFunc eventCreateFunc;
226 rx::CLEventImpl::CreateFunc *const eventCreateFuncPtr =
227 event != nullptr ? &eventCreateFunc : nullptr;
228
229 ANGLE_TRY(mImpl->enqueueWriteBufferRect(buf, blocking, bufferOrigin, hostOrigin, region,
230 bufferRowPitch, bufferSlicePitch, hostRowPitch,
231 hostSlicePitch, ptr, waitEvents, eventCreateFuncPtr));
232
233 CheckCreateEvent(*this, CL_COMMAND_WRITE_BUFFER_RECT, eventCreateFunc, event);
234 return angle::Result::Continue;
235 }
236
enqueueCopyBuffer(cl_mem srcBuffer,cl_mem dstBuffer,size_t srcOffset,size_t dstOffset,size_t size,cl_uint numEventsInWaitList,const cl_event * eventWaitList,cl_event * event)237 angle::Result CommandQueue::enqueueCopyBuffer(cl_mem srcBuffer,
238 cl_mem dstBuffer,
239 size_t srcOffset,
240 size_t dstOffset,
241 size_t size,
242 cl_uint numEventsInWaitList,
243 const cl_event *eventWaitList,
244 cl_event *event)
245 {
246 const Buffer &src = srcBuffer->cast<Buffer>();
247 const Buffer &dst = dstBuffer->cast<Buffer>();
248 const EventPtrs waitEvents = Event::Cast(numEventsInWaitList, eventWaitList);
249 rx::CLEventImpl::CreateFunc eventCreateFunc;
250 rx::CLEventImpl::CreateFunc *const eventCreateFuncPtr =
251 event != nullptr ? &eventCreateFunc : nullptr;
252
253 ANGLE_TRY(mImpl->enqueueCopyBuffer(src, dst, srcOffset, dstOffset, size, waitEvents,
254 eventCreateFuncPtr));
255
256 CheckCreateEvent(*this, CL_COMMAND_COPY_BUFFER, eventCreateFunc, event);
257 return angle::Result::Continue;
258 }
259
enqueueCopyBufferRect(cl_mem srcBuffer,cl_mem dstBuffer,const cl::MemOffsets & srcOrigin,const cl::MemOffsets & dstOrigin,const cl::Coordinate & region,size_t srcRowPitch,size_t srcSlicePitch,size_t dstRowPitch,size_t dstSlicePitch,cl_uint numEventsInWaitList,const cl_event * eventWaitList,cl_event * event)260 angle::Result CommandQueue::enqueueCopyBufferRect(cl_mem srcBuffer,
261 cl_mem dstBuffer,
262 const cl::MemOffsets &srcOrigin,
263 const cl::MemOffsets &dstOrigin,
264 const cl::Coordinate ®ion,
265 size_t srcRowPitch,
266 size_t srcSlicePitch,
267 size_t dstRowPitch,
268 size_t dstSlicePitch,
269 cl_uint numEventsInWaitList,
270 const cl_event *eventWaitList,
271 cl_event *event)
272 {
273 const Buffer &src = srcBuffer->cast<Buffer>();
274 const Buffer &dst = dstBuffer->cast<Buffer>();
275 const EventPtrs waitEvents = Event::Cast(numEventsInWaitList, eventWaitList);
276 rx::CLEventImpl::CreateFunc eventCreateFunc;
277 rx::CLEventImpl::CreateFunc *const eventCreateFuncPtr =
278 event != nullptr ? &eventCreateFunc : nullptr;
279
280 ANGLE_TRY(mImpl->enqueueCopyBufferRect(src, dst, srcOrigin, dstOrigin, region, srcRowPitch,
281 srcSlicePitch, dstRowPitch, dstSlicePitch, waitEvents,
282 eventCreateFuncPtr));
283
284 CheckCreateEvent(*this, CL_COMMAND_COPY_BUFFER_RECT, eventCreateFunc, event);
285 return angle::Result::Continue;
286 }
287
enqueueFillBuffer(cl_mem buffer,const void * pattern,size_t patternSize,size_t offset,size_t size,cl_uint numEventsInWaitList,const cl_event * eventWaitList,cl_event * event)288 angle::Result CommandQueue::enqueueFillBuffer(cl_mem buffer,
289 const void *pattern,
290 size_t patternSize,
291 size_t offset,
292 size_t size,
293 cl_uint numEventsInWaitList,
294 const cl_event *eventWaitList,
295 cl_event *event)
296 {
297 const Buffer &buf = buffer->cast<Buffer>();
298 const EventPtrs waitEvents = Event::Cast(numEventsInWaitList, eventWaitList);
299 rx::CLEventImpl::CreateFunc eventCreateFunc;
300 rx::CLEventImpl::CreateFunc *const eventCreateFuncPtr =
301 event != nullptr ? &eventCreateFunc : nullptr;
302
303 ANGLE_TRY(mImpl->enqueueFillBuffer(buf, pattern, patternSize, offset, size, waitEvents,
304 eventCreateFuncPtr));
305
306 CheckCreateEvent(*this, CL_COMMAND_FILL_BUFFER, eventCreateFunc, event);
307 return angle::Result::Continue;
308 }
309
enqueueMapBuffer(cl_mem buffer,cl_bool blockingMap,MapFlags mapFlags,size_t offset,size_t size,cl_uint numEventsInWaitList,const cl_event * eventWaitList,cl_event * event,void * & mapPtr)310 angle::Result CommandQueue::enqueueMapBuffer(cl_mem buffer,
311 cl_bool blockingMap,
312 MapFlags mapFlags,
313 size_t offset,
314 size_t size,
315 cl_uint numEventsInWaitList,
316 const cl_event *eventWaitList,
317 cl_event *event,
318 void *&mapPtr)
319 {
320 const Buffer &buf = buffer->cast<Buffer>();
321 const bool blocking = blockingMap != CL_FALSE;
322 const EventPtrs waitEvents = Event::Cast(numEventsInWaitList, eventWaitList);
323 rx::CLEventImpl::CreateFunc eventCreateFunc;
324 rx::CLEventImpl::CreateFunc *const eventCreateFuncPtr =
325 event != nullptr ? &eventCreateFunc : nullptr;
326
327 ANGLE_TRY(mImpl->enqueueMapBuffer(buf, blocking, mapFlags, offset, size, waitEvents,
328 eventCreateFuncPtr, mapPtr));
329
330 CheckCreateEvent(*this, CL_COMMAND_MAP_BUFFER, eventCreateFunc, event);
331 return angle::Result::Continue;
332 }
333
enqueueReadImage(cl_mem image,cl_bool blockingRead,const cl::MemOffsets & origin,const cl::Coordinate & region,size_t rowPitch,size_t slicePitch,void * ptr,cl_uint numEventsInWaitList,const cl_event * eventWaitList,cl_event * event)334 angle::Result CommandQueue::enqueueReadImage(cl_mem image,
335 cl_bool blockingRead,
336 const cl::MemOffsets &origin,
337 const cl::Coordinate ®ion,
338 size_t rowPitch,
339 size_t slicePitch,
340 void *ptr,
341 cl_uint numEventsInWaitList,
342 const cl_event *eventWaitList,
343 cl_event *event)
344 {
345 const Image &img = image->cast<Image>();
346 const bool blocking = blockingRead != CL_FALSE;
347 const EventPtrs waitEvents = Event::Cast(numEventsInWaitList, eventWaitList);
348 rx::CLEventImpl::CreateFunc eventCreateFunc;
349 rx::CLEventImpl::CreateFunc *const eventCreateFuncPtr =
350 event != nullptr ? &eventCreateFunc : nullptr;
351
352 ANGLE_TRY(mImpl->enqueueReadImage(img, blocking, origin, region, rowPitch, slicePitch, ptr,
353 waitEvents, eventCreateFuncPtr));
354
355 CheckCreateEvent(*this, CL_COMMAND_READ_IMAGE, eventCreateFunc, event);
356 return angle::Result::Continue;
357 }
358
enqueueWriteImage(cl_mem image,cl_bool blockingWrite,const cl::MemOffsets & origin,const cl::Coordinate & region,size_t inputRowPitch,size_t inputSlicePitch,const void * ptr,cl_uint numEventsInWaitList,const cl_event * eventWaitList,cl_event * event)359 angle::Result CommandQueue::enqueueWriteImage(cl_mem image,
360 cl_bool blockingWrite,
361 const cl::MemOffsets &origin,
362 const cl::Coordinate ®ion,
363 size_t inputRowPitch,
364 size_t inputSlicePitch,
365 const void *ptr,
366 cl_uint numEventsInWaitList,
367 const cl_event *eventWaitList,
368 cl_event *event)
369 {
370 const Image &img = image->cast<Image>();
371 const bool blocking = blockingWrite != CL_FALSE;
372 const EventPtrs waitEvents = Event::Cast(numEventsInWaitList, eventWaitList);
373 rx::CLEventImpl::CreateFunc eventCreateFunc;
374 rx::CLEventImpl::CreateFunc *const eventCreateFuncPtr =
375 event != nullptr ? &eventCreateFunc : nullptr;
376
377 ANGLE_TRY(mImpl->enqueueWriteImage(img, blocking, origin, region, inputRowPitch,
378 inputSlicePitch, ptr, waitEvents, eventCreateFuncPtr));
379
380 CheckCreateEvent(*this, CL_COMMAND_WRITE_IMAGE, eventCreateFunc, event);
381 return angle::Result::Continue;
382 }
383
enqueueCopyImage(cl_mem srcImage,cl_mem dstImage,const cl::MemOffsets & srcOrigin,const cl::MemOffsets & dstOrigin,const cl::Coordinate & region,cl_uint numEventsInWaitList,const cl_event * eventWaitList,cl_event * event)384 angle::Result CommandQueue::enqueueCopyImage(cl_mem srcImage,
385 cl_mem dstImage,
386 const cl::MemOffsets &srcOrigin,
387 const cl::MemOffsets &dstOrigin,
388 const cl::Coordinate ®ion,
389 cl_uint numEventsInWaitList,
390 const cl_event *eventWaitList,
391 cl_event *event)
392 {
393 const Image &src = srcImage->cast<Image>();
394 const Image &dst = dstImage->cast<Image>();
395 const EventPtrs waitEvents = Event::Cast(numEventsInWaitList, eventWaitList);
396 rx::CLEventImpl::CreateFunc eventCreateFunc;
397 rx::CLEventImpl::CreateFunc *const eventCreateFuncPtr =
398 event != nullptr ? &eventCreateFunc : nullptr;
399
400 ANGLE_TRY(mImpl->enqueueCopyImage(src, dst, srcOrigin, dstOrigin, region, waitEvents,
401 eventCreateFuncPtr));
402
403 CheckCreateEvent(*this, CL_COMMAND_COPY_IMAGE, eventCreateFunc, event);
404 return angle::Result::Continue;
405 }
406
enqueueFillImage(cl_mem image,const void * fillColor,const cl::MemOffsets & origin,const cl::Coordinate & region,cl_uint numEventsInWaitList,const cl_event * eventWaitList,cl_event * event)407 angle::Result CommandQueue::enqueueFillImage(cl_mem image,
408 const void *fillColor,
409 const cl::MemOffsets &origin,
410 const cl::Coordinate ®ion,
411 cl_uint numEventsInWaitList,
412 const cl_event *eventWaitList,
413 cl_event *event)
414 {
415 const Image &img = image->cast<Image>();
416 const EventPtrs waitEvents = Event::Cast(numEventsInWaitList, eventWaitList);
417 rx::CLEventImpl::CreateFunc eventCreateFunc;
418 rx::CLEventImpl::CreateFunc *const eventCreateFuncPtr =
419 event != nullptr ? &eventCreateFunc : nullptr;
420
421 ANGLE_TRY(
422 mImpl->enqueueFillImage(img, fillColor, origin, region, waitEvents, eventCreateFuncPtr));
423
424 CheckCreateEvent(*this, CL_COMMAND_FILL_IMAGE, eventCreateFunc, event);
425 return angle::Result::Continue;
426 }
427
enqueueCopyImageToBuffer(cl_mem srcImage,cl_mem dstBuffer,const cl::MemOffsets & srcOrigin,const cl::Coordinate & region,size_t dstOffset,cl_uint numEventsInWaitList,const cl_event * eventWaitList,cl_event * event)428 angle::Result CommandQueue::enqueueCopyImageToBuffer(cl_mem srcImage,
429 cl_mem dstBuffer,
430 const cl::MemOffsets &srcOrigin,
431 const cl::Coordinate ®ion,
432 size_t dstOffset,
433 cl_uint numEventsInWaitList,
434 const cl_event *eventWaitList,
435 cl_event *event)
436 {
437 const Image &src = srcImage->cast<Image>();
438 const Buffer &dst = dstBuffer->cast<Buffer>();
439 const EventPtrs waitEvents = Event::Cast(numEventsInWaitList, eventWaitList);
440 rx::CLEventImpl::CreateFunc eventCreateFunc;
441 rx::CLEventImpl::CreateFunc *const eventCreateFuncPtr =
442 event != nullptr ? &eventCreateFunc : nullptr;
443
444 ANGLE_TRY(mImpl->enqueueCopyImageToBuffer(src, dst, srcOrigin, region, dstOffset, waitEvents,
445 eventCreateFuncPtr));
446
447 CheckCreateEvent(*this, CL_COMMAND_COPY_IMAGE_TO_BUFFER, eventCreateFunc, event);
448 return angle::Result::Continue;
449 }
450
enqueueCopyBufferToImage(cl_mem srcBuffer,cl_mem dstImage,size_t srcOffset,const cl::MemOffsets & dstOrigin,const cl::Coordinate & region,cl_uint numEventsInWaitList,const cl_event * eventWaitList,cl_event * event)451 angle::Result CommandQueue::enqueueCopyBufferToImage(cl_mem srcBuffer,
452 cl_mem dstImage,
453 size_t srcOffset,
454 const cl::MemOffsets &dstOrigin,
455 const cl::Coordinate ®ion,
456 cl_uint numEventsInWaitList,
457 const cl_event *eventWaitList,
458 cl_event *event)
459 {
460 const Buffer &src = srcBuffer->cast<Buffer>();
461 const Image &dst = dstImage->cast<Image>();
462 const EventPtrs waitEvents = Event::Cast(numEventsInWaitList, eventWaitList);
463 rx::CLEventImpl::CreateFunc eventCreateFunc;
464 rx::CLEventImpl::CreateFunc *const eventCreateFuncPtr =
465 event != nullptr ? &eventCreateFunc : nullptr;
466
467 ANGLE_TRY(mImpl->enqueueCopyBufferToImage(src, dst, srcOffset, dstOrigin, region, waitEvents,
468 eventCreateFuncPtr));
469
470 CheckCreateEvent(*this, CL_COMMAND_COPY_BUFFER_TO_IMAGE, eventCreateFunc, event);
471 return angle::Result::Continue;
472 }
473
enqueueMapImage(cl_mem image,cl_bool blockingMap,MapFlags mapFlags,const cl::MemOffsets & origin,const cl::Coordinate & region,size_t * imageRowPitch,size_t * imageSlicePitch,cl_uint numEventsInWaitList,const cl_event * eventWaitList,cl_event * event,void * & mapPtr)474 angle::Result CommandQueue::enqueueMapImage(cl_mem image,
475 cl_bool blockingMap,
476 MapFlags mapFlags,
477 const cl::MemOffsets &origin,
478 const cl::Coordinate ®ion,
479 size_t *imageRowPitch,
480 size_t *imageSlicePitch,
481 cl_uint numEventsInWaitList,
482 const cl_event *eventWaitList,
483 cl_event *event,
484 void *&mapPtr)
485 {
486 const Image &img = image->cast<Image>();
487 const bool blocking = blockingMap != CL_FALSE;
488 const EventPtrs waitEvents = Event::Cast(numEventsInWaitList, eventWaitList);
489 rx::CLEventImpl::CreateFunc eventCreateFunc;
490 rx::CLEventImpl::CreateFunc *const eventCreateFuncPtr =
491 event != nullptr ? &eventCreateFunc : nullptr;
492
493 ANGLE_TRY(mImpl->enqueueMapImage(img, blocking, mapFlags, origin, region, imageRowPitch,
494 imageSlicePitch, waitEvents, eventCreateFuncPtr, mapPtr));
495
496 CheckCreateEvent(*this, CL_COMMAND_MAP_IMAGE, eventCreateFunc, event);
497 return angle::Result::Continue;
498 }
499
enqueueUnmapMemObject(cl_mem memobj,void * mappedPtr,cl_uint numEventsInWaitList,const cl_event * eventWaitList,cl_event * event)500 angle::Result CommandQueue::enqueueUnmapMemObject(cl_mem memobj,
501 void *mappedPtr,
502 cl_uint numEventsInWaitList,
503 const cl_event *eventWaitList,
504 cl_event *event)
505 {
506 const Memory &memory = memobj->cast<Memory>();
507 const EventPtrs waitEvents = Event::Cast(numEventsInWaitList, eventWaitList);
508 rx::CLEventImpl::CreateFunc eventCreateFunc;
509 rx::CLEventImpl::CreateFunc *const eventCreateFuncPtr =
510 event != nullptr ? &eventCreateFunc : nullptr;
511
512 ANGLE_TRY(mImpl->enqueueUnmapMemObject(memory, mappedPtr, waitEvents, eventCreateFuncPtr));
513
514 CheckCreateEvent(*this, CL_COMMAND_UNMAP_MEM_OBJECT, eventCreateFunc, event);
515 return angle::Result::Continue;
516 }
517
enqueueMigrateMemObjects(cl_uint numMemObjects,const cl_mem * memObjects,MemMigrationFlags flags,cl_uint numEventsInWaitList,const cl_event * eventWaitList,cl_event * event)518 angle::Result CommandQueue::enqueueMigrateMemObjects(cl_uint numMemObjects,
519 const cl_mem *memObjects,
520 MemMigrationFlags flags,
521 cl_uint numEventsInWaitList,
522 const cl_event *eventWaitList,
523 cl_event *event)
524 {
525 MemoryPtrs memories;
526 memories.reserve(numMemObjects);
527 while (numMemObjects-- != 0u)
528 {
529 memories.emplace_back(&(*memObjects++)->cast<Memory>());
530 }
531 const EventPtrs waitEvents = Event::Cast(numEventsInWaitList, eventWaitList);
532 rx::CLEventImpl::CreateFunc eventCreateFunc;
533 rx::CLEventImpl::CreateFunc *const eventCreateFuncPtr =
534 event != nullptr ? &eventCreateFunc : nullptr;
535
536 ANGLE_TRY(mImpl->enqueueMigrateMemObjects(memories, flags, waitEvents, eventCreateFuncPtr));
537
538 CheckCreateEvent(*this, CL_COMMAND_MIGRATE_MEM_OBJECTS, eventCreateFunc, event);
539 return angle::Result::Continue;
540 }
541
enqueueNDRangeKernel(cl_kernel kernel,const NDRange & ndrange,cl_uint numEventsInWaitList,const cl_event * eventWaitList,cl_event * event)542 angle::Result CommandQueue::enqueueNDRangeKernel(cl_kernel kernel,
543 const NDRange &ndrange,
544 cl_uint numEventsInWaitList,
545 const cl_event *eventWaitList,
546 cl_event *event)
547 {
548 const Kernel &krnl = kernel->cast<Kernel>();
549 const EventPtrs waitEvents = Event::Cast(numEventsInWaitList, eventWaitList);
550 rx::CLEventImpl::CreateFunc eventCreateFunc;
551 rx::CLEventImpl::CreateFunc *const eventCreateFuncPtr =
552 event != nullptr ? &eventCreateFunc : nullptr;
553
554 ANGLE_TRY(mImpl->enqueueNDRangeKernel(krnl, ndrange, waitEvents, eventCreateFuncPtr));
555
556 CheckCreateEvent(*this, CL_COMMAND_NDRANGE_KERNEL, eventCreateFunc, event);
557 return angle::Result::Continue;
558 }
559
enqueueTask(cl_kernel kernel,cl_uint numEventsInWaitList,const cl_event * eventWaitList,cl_event * event)560 angle::Result CommandQueue::enqueueTask(cl_kernel kernel,
561 cl_uint numEventsInWaitList,
562 const cl_event *eventWaitList,
563 cl_event *event)
564 {
565 const Kernel &krnl = kernel->cast<Kernel>();
566 const EventPtrs waitEvents = Event::Cast(numEventsInWaitList, eventWaitList);
567 rx::CLEventImpl::CreateFunc eventCreateFunc;
568 rx::CLEventImpl::CreateFunc *const eventCreateFuncPtr =
569 event != nullptr ? &eventCreateFunc : nullptr;
570
571 ANGLE_TRY(mImpl->enqueueTask(krnl, waitEvents, eventCreateFuncPtr));
572
573 CheckCreateEvent(*this, CL_COMMAND_TASK, eventCreateFunc, event);
574 return angle::Result::Continue;
575 }
576
enqueueNativeKernel(UserFunc userFunc,void * args,size_t cbArgs,cl_uint numMemObjects,const cl_mem * memList,const void ** argsMemLoc,cl_uint numEventsInWaitList,const cl_event * eventWaitList,cl_event * event)577 angle::Result CommandQueue::enqueueNativeKernel(UserFunc userFunc,
578 void *args,
579 size_t cbArgs,
580 cl_uint numMemObjects,
581 const cl_mem *memList,
582 const void **argsMemLoc,
583 cl_uint numEventsInWaitList,
584 const cl_event *eventWaitList,
585 cl_event *event)
586 {
587 std::vector<unsigned char> funcArgs;
588 BufferPtrs buffers;
589 std::vector<size_t> offsets;
590 if (numMemObjects != 0u)
591 {
592 // If argument memory block contains memory objects, make a copy.
593 funcArgs.resize(cbArgs);
594 std::memcpy(funcArgs.data(), args, cbArgs);
595 buffers.reserve(numMemObjects);
596 offsets.reserve(numMemObjects);
597
598 while (numMemObjects-- != 0u)
599 {
600 buffers.emplace_back(&(*memList++)->cast<Buffer>());
601
602 // Calc memory offset of cl_mem object in args.
603 offsets.emplace_back(static_cast<const char *>(*argsMemLoc++) -
604 static_cast<const char *>(args));
605
606 // Fetch location of cl_mem object in copied function argument memory block.
607 void *loc = &funcArgs[offsets.back()];
608
609 // Cast cl_mem object to cl::Buffer pointer in place.
610 *reinterpret_cast<Buffer **>(loc) = &(*reinterpret_cast<cl_mem *>(loc))->cast<Buffer>();
611 }
612
613 // Use copied argument memory block.
614 args = funcArgs.data();
615 }
616
617 const EventPtrs waitEvents = Event::Cast(numEventsInWaitList, eventWaitList);
618 rx::CLEventImpl::CreateFunc eventCreateFunc;
619 rx::CLEventImpl::CreateFunc *const eventCreateFuncPtr =
620 event != nullptr ? &eventCreateFunc : nullptr;
621
622 ANGLE_TRY(mImpl->enqueueNativeKernel(userFunc, args, cbArgs, buffers, offsets, waitEvents,
623 eventCreateFuncPtr));
624
625 CheckCreateEvent(*this, CL_COMMAND_NATIVE_KERNEL, eventCreateFunc, event);
626 return angle::Result::Continue;
627 }
628
enqueueMarkerWithWaitList(cl_uint numEventsInWaitList,const cl_event * eventWaitList,cl_event * event)629 angle::Result CommandQueue::enqueueMarkerWithWaitList(cl_uint numEventsInWaitList,
630 const cl_event *eventWaitList,
631 cl_event *event)
632 {
633 const EventPtrs waitEvents = Event::Cast(numEventsInWaitList, eventWaitList);
634 rx::CLEventImpl::CreateFunc eventCreateFunc;
635 rx::CLEventImpl::CreateFunc *const eventCreateFuncPtr =
636 event != nullptr ? &eventCreateFunc : nullptr;
637
638 ANGLE_TRY(mImpl->enqueueMarkerWithWaitList(waitEvents, eventCreateFuncPtr));
639
640 CheckCreateEvent(*this, CL_COMMAND_MARKER, eventCreateFunc, event);
641 return angle::Result::Continue;
642 }
643
enqueueMarker(cl_event * event)644 angle::Result CommandQueue::enqueueMarker(cl_event *event)
645 {
646 rx::CLEventImpl::CreateFunc eventCreateFunc;
647
648 ANGLE_TRY(mImpl->enqueueMarker(eventCreateFunc));
649
650 CheckCreateEvent(*this, CL_COMMAND_MARKER, eventCreateFunc, event);
651 return angle::Result::Continue;
652 }
653
enqueueWaitForEvents(cl_uint numEvents,const cl_event * eventList)654 angle::Result CommandQueue::enqueueWaitForEvents(cl_uint numEvents, const cl_event *eventList)
655 {
656 return mImpl->enqueueWaitForEvents(Event::Cast(numEvents, eventList));
657 }
658
enqueueBarrierWithWaitList(cl_uint numEventsInWaitList,const cl_event * eventWaitList,cl_event * event)659 angle::Result CommandQueue::enqueueBarrierWithWaitList(cl_uint numEventsInWaitList,
660 const cl_event *eventWaitList,
661 cl_event *event)
662 {
663 const EventPtrs waitEvents = Event::Cast(numEventsInWaitList, eventWaitList);
664 rx::CLEventImpl::CreateFunc eventCreateFunc;
665 rx::CLEventImpl::CreateFunc *const eventCreateFuncPtr =
666 event != nullptr ? &eventCreateFunc : nullptr;
667
668 ANGLE_TRY(mImpl->enqueueBarrierWithWaitList(waitEvents, eventCreateFuncPtr));
669
670 CheckCreateEvent(*this, CL_COMMAND_BARRIER, eventCreateFunc, event);
671 return angle::Result::Continue;
672 }
673
enqueueBarrier()674 angle::Result CommandQueue::enqueueBarrier()
675 {
676 return mImpl->enqueueBarrier();
677 }
678
flush()679 angle::Result CommandQueue::flush()
680 {
681 return mImpl->flush();
682 }
683
finish()684 angle::Result CommandQueue::finish()
685 {
686 return mImpl->finish();
687 }
688
~CommandQueue()689 CommandQueue::~CommandQueue()
690 {
691 auto queue = mDevice->mDefaultCommandQueue.synchronize();
692 if (*queue == this)
693 {
694 *queue = nullptr;
695 }
696 }
697
getDeviceIndex() const698 size_t CommandQueue::getDeviceIndex() const
699 {
700 return std::find(mContext->getDevices().cbegin(), mContext->getDevices().cend(), mDevice) -
701 mContext->getDevices().cbegin();
702 }
703
CommandQueue(Context & context,Device & device,PropArray && propArray,CommandQueueProperties properties,cl_uint size)704 CommandQueue::CommandQueue(Context &context,
705 Device &device,
706 PropArray &&propArray,
707 CommandQueueProperties properties,
708 cl_uint size)
709 : mContext(&context),
710 mDevice(&device),
711 mPropArray(std::move(propArray)),
712 mProperties(properties),
713 mSize(size),
714 mImpl(nullptr)
715 {
716 ANGLE_CL_IMPL_TRY(context.getImpl().createCommandQueue(*this, &mImpl));
717 if (mProperties->isSet(CL_QUEUE_ON_DEVICE_DEFAULT))
718 {
719 *mDevice->mDefaultCommandQueue = this;
720 }
721 }
722
CommandQueue(Context & context,Device & device,CommandQueueProperties properties)723 CommandQueue::CommandQueue(Context &context, Device &device, CommandQueueProperties properties)
724 : mContext(&context), mDevice(&device), mProperties(properties), mImpl(nullptr)
725 {
726 ANGLE_CL_IMPL_TRY(context.getImpl().createCommandQueue(*this, &mImpl));
727 }
728
729 } // namespace cl
730