• 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 // 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 &region,
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 &region,
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 &region,
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 &region,
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 &region,
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 &region,
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 &region,
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 &region,
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 &region,
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 &region,
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