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