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 ®ion,
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 ®ion,
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 ®ion,
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 ®ion,
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 ®ion,
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 ®ion,
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 ®ion,
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 ®ion,
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 ®ion,
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 ®ion,
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