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