// // Copyright 2021 The ANGLE Project Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. // // CLCommandQueue.cpp: Implements the cl::CommandQueue class. #include "libANGLE/CLCommandQueue.h" #include "libANGLE/CLBuffer.h" #include "libANGLE/CLContext.h" #include "libANGLE/CLDevice.h" #include "libANGLE/CLEvent.h" #include "libANGLE/CLImage.h" #include "libANGLE/CLKernel.h" #include "libANGLE/CLMemory.h" #include namespace cl { namespace { void CheckCreateEvent(CommandQueue &queue, cl_command_type commandType, const rx::CLEventImpl::CreateFunc &createFunc, cl_event *event, cl_int &errorCode) { if (errorCode == CL_SUCCESS && event != nullptr) { ASSERT(createFunc); *event = Object::Create(errorCode, queue, commandType, createFunc); } } } // namespace cl_int CommandQueue::getInfo(CommandQueueInfo name, size_t valueSize, void *value, size_t *valueSizeRet) const { cl_command_queue_properties properties = 0u; cl_uint valUInt = 0u; void *valPointer = nullptr; const void *copyValue = nullptr; size_t copySize = 0u; switch (name) { case CommandQueueInfo::Context: valPointer = mContext->getNative(); copyValue = &valPointer; copySize = sizeof(valPointer); break; case CommandQueueInfo::Device: valPointer = mDevice->getNative(); copyValue = &valPointer; copySize = sizeof(valPointer); break; case CommandQueueInfo::ReferenceCount: valUInt = getRefCount(); copyValue = &valUInt; copySize = sizeof(valUInt); break; case CommandQueueInfo::Properties: properties = mProperties->get(); copyValue = &properties; copySize = sizeof(properties); break; case CommandQueueInfo::PropertiesArray: copyValue = mPropArray.data(); copySize = mPropArray.size() * sizeof(decltype(mPropArray)::value_type); break; case CommandQueueInfo::Size: copyValue = &mSize; copySize = sizeof(mSize); break; case CommandQueueInfo::DeviceDefault: valPointer = CommandQueue::CastNative(*mDevice->mDefaultCommandQueue); copyValue = &valPointer; copySize = sizeof(valPointer); break; default: return CL_INVALID_VALUE; } if (value != nullptr) { // CL_INVALID_VALUE if size in bytes specified by param_value_size is < size of return type // as specified in the Command Queue Parameter table, and param_value is not a NULL value. if (valueSize < copySize) { return CL_INVALID_VALUE; } if (copyValue != nullptr) { std::memcpy(value, copyValue, copySize); } } if (valueSizeRet != nullptr) { *valueSizeRet = copySize; } return CL_SUCCESS; } cl_int CommandQueue::setProperty(CommandQueueProperties properties, cl_bool enable, cl_command_queue_properties *oldProperties) { auto props = mProperties.synchronize(); if (oldProperties != nullptr) { *oldProperties = props->get(); } ANGLE_CL_TRY(mImpl->setProperty(properties, enable)); if (enable == CL_FALSE) { props->clear(properties); } else { props->set(properties); } return CL_SUCCESS; } cl_int CommandQueue::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) { const Buffer &buf = buffer->cast(); const bool blocking = blockingRead != CL_FALSE; const EventPtrs waitEvents = Event::Cast(numEventsInWaitList, eventWaitList); rx::CLEventImpl::CreateFunc eventCreateFunc; rx::CLEventImpl::CreateFunc *const eventCreateFuncPtr = event != nullptr ? &eventCreateFunc : nullptr; cl_int errorCode = mImpl->enqueueReadBuffer(buf, blocking, offset, size, ptr, waitEvents, eventCreateFuncPtr); CheckCreateEvent(*this, CL_COMMAND_READ_BUFFER, eventCreateFunc, event, errorCode); return errorCode; } cl_int CommandQueue::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) { const Buffer &buf = buffer->cast(); const bool blocking = blockingWrite != CL_FALSE; const EventPtrs waitEvents = Event::Cast(numEventsInWaitList, eventWaitList); rx::CLEventImpl::CreateFunc eventCreateFunc; rx::CLEventImpl::CreateFunc *const eventCreateFuncPtr = event != nullptr ? &eventCreateFunc : nullptr; cl_int errorCode = mImpl->enqueueWriteBuffer(buf, blocking, offset, size, ptr, waitEvents, eventCreateFuncPtr); CheckCreateEvent(*this, CL_COMMAND_WRITE_BUFFER, eventCreateFunc, event, errorCode); return errorCode; } cl_int CommandQueue::enqueueReadBufferRect(cl_mem buffer, cl_bool blockingRead, const size_t *bufferOrigin, const size_t *hostOrigin, const size_t *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) { const Buffer &buf = buffer->cast(); const bool blocking = blockingRead != CL_FALSE; const EventPtrs waitEvents = Event::Cast(numEventsInWaitList, eventWaitList); rx::CLEventImpl::CreateFunc eventCreateFunc; rx::CLEventImpl::CreateFunc *const eventCreateFuncPtr = event != nullptr ? &eventCreateFunc : nullptr; cl_int errorCode = mImpl->enqueueReadBufferRect( buf, blocking, bufferOrigin, hostOrigin, region, bufferRowPitch, bufferSlicePitch, hostRowPitch, hostSlicePitch, ptr, waitEvents, eventCreateFuncPtr); CheckCreateEvent(*this, CL_COMMAND_READ_BUFFER_RECT, eventCreateFunc, event, errorCode); return errorCode; } cl_int CommandQueue::enqueueWriteBufferRect(cl_mem buffer, cl_bool blockingWrite, const size_t *bufferOrigin, const size_t *hostOrigin, const size_t *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) { const Buffer &buf = buffer->cast(); const bool blocking = blockingWrite != CL_FALSE; const EventPtrs waitEvents = Event::Cast(numEventsInWaitList, eventWaitList); rx::CLEventImpl::CreateFunc eventCreateFunc; rx::CLEventImpl::CreateFunc *const eventCreateFuncPtr = event != nullptr ? &eventCreateFunc : nullptr; cl_int errorCode = mImpl->enqueueWriteBufferRect( buf, blocking, bufferOrigin, hostOrigin, region, bufferRowPitch, bufferSlicePitch, hostRowPitch, hostSlicePitch, ptr, waitEvents, eventCreateFuncPtr); CheckCreateEvent(*this, CL_COMMAND_WRITE_BUFFER_RECT, eventCreateFunc, event, errorCode); return errorCode; } cl_int CommandQueue::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) { const Buffer &src = srcBuffer->cast(); const Buffer &dst = dstBuffer->cast(); const EventPtrs waitEvents = Event::Cast(numEventsInWaitList, eventWaitList); rx::CLEventImpl::CreateFunc eventCreateFunc; rx::CLEventImpl::CreateFunc *const eventCreateFuncPtr = event != nullptr ? &eventCreateFunc : nullptr; cl_int errorCode = mImpl->enqueueCopyBuffer(src, dst, srcOffset, dstOffset, size, waitEvents, eventCreateFuncPtr); CheckCreateEvent(*this, CL_COMMAND_COPY_BUFFER, eventCreateFunc, event, errorCode); return errorCode; } cl_int CommandQueue::enqueueCopyBufferRect(cl_mem srcBuffer, cl_mem dstBuffer, const size_t *srcOrigin, const size_t *dstOrigin, const size_t *region, size_t srcRowPitch, size_t srcSlicePitch, size_t dstRowPitch, size_t dstSlicePitch, cl_uint numEventsInWaitList, const cl_event *eventWaitList, cl_event *event) { const Buffer &src = srcBuffer->cast(); const Buffer &dst = dstBuffer->cast(); const EventPtrs waitEvents = Event::Cast(numEventsInWaitList, eventWaitList); rx::CLEventImpl::CreateFunc eventCreateFunc; rx::CLEventImpl::CreateFunc *const eventCreateFuncPtr = event != nullptr ? &eventCreateFunc : nullptr; cl_int errorCode = mImpl->enqueueCopyBufferRect(src, dst, srcOrigin, dstOrigin, region, srcRowPitch, srcSlicePitch, dstRowPitch, dstSlicePitch, waitEvents, eventCreateFuncPtr); CheckCreateEvent(*this, CL_COMMAND_COPY_BUFFER_RECT, eventCreateFunc, event, errorCode); return errorCode; } cl_int CommandQueue::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) { const Buffer &buf = buffer->cast(); const EventPtrs waitEvents = Event::Cast(numEventsInWaitList, eventWaitList); rx::CLEventImpl::CreateFunc eventCreateFunc; rx::CLEventImpl::CreateFunc *const eventCreateFuncPtr = event != nullptr ? &eventCreateFunc : nullptr; cl_int errorCode = mImpl->enqueueFillBuffer(buf, pattern, patternSize, offset, size, waitEvents, eventCreateFuncPtr); CheckCreateEvent(*this, CL_COMMAND_FILL_BUFFER, eventCreateFunc, event, errorCode); return errorCode; } void *CommandQueue::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, cl_int &errorCode) { const Buffer &buf = buffer->cast(); const bool blocking = blockingMap != CL_FALSE; const EventPtrs waitEvents = Event::Cast(numEventsInWaitList, eventWaitList); rx::CLEventImpl::CreateFunc eventCreateFunc; rx::CLEventImpl::CreateFunc *const eventCreateFuncPtr = event != nullptr ? &eventCreateFunc : nullptr; void *const map = mImpl->enqueueMapBuffer(buf, blocking, mapFlags, offset, size, waitEvents, eventCreateFuncPtr, errorCode); CheckCreateEvent(*this, CL_COMMAND_MAP_BUFFER, eventCreateFunc, event, errorCode); return map; } cl_int CommandQueue::enqueueReadImage(cl_mem image, cl_bool blockingRead, const size_t *origin, const size_t *region, size_t rowPitch, size_t slicePitch, void *ptr, cl_uint numEventsInWaitList, const cl_event *eventWaitList, cl_event *event) { const Image &img = image->cast(); const bool blocking = blockingRead != CL_FALSE; const EventPtrs waitEvents = Event::Cast(numEventsInWaitList, eventWaitList); rx::CLEventImpl::CreateFunc eventCreateFunc; rx::CLEventImpl::CreateFunc *const eventCreateFuncPtr = event != nullptr ? &eventCreateFunc : nullptr; cl_int errorCode = mImpl->enqueueReadImage(img, blocking, origin, region, rowPitch, slicePitch, ptr, waitEvents, eventCreateFuncPtr); CheckCreateEvent(*this, CL_COMMAND_READ_IMAGE, eventCreateFunc, event, errorCode); return errorCode; } cl_int CommandQueue::enqueueWriteImage(cl_mem image, cl_bool blockingWrite, const size_t *origin, const size_t *region, size_t inputRowPitch, size_t inputSlicePitch, const void *ptr, cl_uint numEventsInWaitList, const cl_event *eventWaitList, cl_event *event) { const Image &img = image->cast(); const bool blocking = blockingWrite != CL_FALSE; const EventPtrs waitEvents = Event::Cast(numEventsInWaitList, eventWaitList); rx::CLEventImpl::CreateFunc eventCreateFunc; rx::CLEventImpl::CreateFunc *const eventCreateFuncPtr = event != nullptr ? &eventCreateFunc : nullptr; cl_int errorCode = mImpl->enqueueWriteImage(img, blocking, origin, region, inputRowPitch, inputSlicePitch, ptr, waitEvents, eventCreateFuncPtr); CheckCreateEvent(*this, CL_COMMAND_WRITE_IMAGE, eventCreateFunc, event, errorCode); return errorCode; } cl_int CommandQueue::enqueueCopyImage(cl_mem srcImage, cl_mem dstImage, const size_t *srcOrigin, const size_t *dstOrigin, const size_t *region, cl_uint numEventsInWaitList, const cl_event *eventWaitList, cl_event *event) { const Image &src = srcImage->cast(); const Image &dst = dstImage->cast(); const EventPtrs waitEvents = Event::Cast(numEventsInWaitList, eventWaitList); rx::CLEventImpl::CreateFunc eventCreateFunc; rx::CLEventImpl::CreateFunc *const eventCreateFuncPtr = event != nullptr ? &eventCreateFunc : nullptr; cl_int errorCode = mImpl->enqueueCopyImage(src, dst, srcOrigin, dstOrigin, region, waitEvents, eventCreateFuncPtr); CheckCreateEvent(*this, CL_COMMAND_COPY_IMAGE, eventCreateFunc, event, errorCode); return errorCode; } cl_int CommandQueue::enqueueFillImage(cl_mem image, const void *fillColor, const size_t *origin, const size_t *region, cl_uint numEventsInWaitList, const cl_event *eventWaitList, cl_event *event) { const Image &img = image->cast(); const EventPtrs waitEvents = Event::Cast(numEventsInWaitList, eventWaitList); rx::CLEventImpl::CreateFunc eventCreateFunc; rx::CLEventImpl::CreateFunc *const eventCreateFuncPtr = event != nullptr ? &eventCreateFunc : nullptr; cl_int errorCode = mImpl->enqueueFillImage(img, fillColor, origin, region, waitEvents, eventCreateFuncPtr); CheckCreateEvent(*this, CL_COMMAND_FILL_IMAGE, eventCreateFunc, event, errorCode); return errorCode; } cl_int CommandQueue::enqueueCopyImageToBuffer(cl_mem srcImage, cl_mem dstBuffer, const size_t *srcOrigin, const size_t *region, size_t dstOffset, cl_uint numEventsInWaitList, const cl_event *eventWaitList, cl_event *event) { const Image &src = srcImage->cast(); const Buffer &dst = dstBuffer->cast(); const EventPtrs waitEvents = Event::Cast(numEventsInWaitList, eventWaitList); rx::CLEventImpl::CreateFunc eventCreateFunc; rx::CLEventImpl::CreateFunc *const eventCreateFuncPtr = event != nullptr ? &eventCreateFunc : nullptr; cl_int errorCode = mImpl->enqueueCopyImageToBuffer(src, dst, srcOrigin, region, dstOffset, waitEvents, eventCreateFuncPtr); CheckCreateEvent(*this, CL_COMMAND_COPY_IMAGE_TO_BUFFER, eventCreateFunc, event, errorCode); return errorCode; } cl_int CommandQueue::enqueueCopyBufferToImage(cl_mem srcBuffer, cl_mem dstImage, size_t srcOffset, const size_t *dstOrigin, const size_t *region, cl_uint numEventsInWaitList, const cl_event *eventWaitList, cl_event *event) { const Buffer &src = srcBuffer->cast(); const Image &dst = dstImage->cast(); const EventPtrs waitEvents = Event::Cast(numEventsInWaitList, eventWaitList); rx::CLEventImpl::CreateFunc eventCreateFunc; rx::CLEventImpl::CreateFunc *const eventCreateFuncPtr = event != nullptr ? &eventCreateFunc : nullptr; cl_int errorCode = mImpl->enqueueCopyBufferToImage(src, dst, srcOffset, dstOrigin, region, waitEvents, eventCreateFuncPtr); CheckCreateEvent(*this, CL_COMMAND_COPY_BUFFER_TO_IMAGE, eventCreateFunc, event, errorCode); return errorCode; } void *CommandQueue::enqueueMapImage(cl_mem image, cl_bool blockingMap, MapFlags mapFlags, const size_t *origin, const size_t *region, size_t *imageRowPitch, size_t *imageSlicePitch, cl_uint numEventsInWaitList, const cl_event *eventWaitList, cl_event *event, cl_int &errorCode) { const Image &img = image->cast(); const bool blocking = blockingMap != CL_FALSE; const EventPtrs waitEvents = Event::Cast(numEventsInWaitList, eventWaitList); rx::CLEventImpl::CreateFunc eventCreateFunc; rx::CLEventImpl::CreateFunc *const eventCreateFuncPtr = event != nullptr ? &eventCreateFunc : nullptr; void *const map = mImpl->enqueueMapImage(img, blocking, mapFlags, origin, region, imageRowPitch, imageSlicePitch, waitEvents, eventCreateFuncPtr, errorCode); CheckCreateEvent(*this, CL_COMMAND_MAP_IMAGE, eventCreateFunc, event, errorCode); return map; } cl_int CommandQueue::enqueueUnmapMemObject(cl_mem memobj, void *mappedPtr, cl_uint numEventsInWaitList, const cl_event *eventWaitList, cl_event *event) { const Memory &memory = memobj->cast(); const EventPtrs waitEvents = Event::Cast(numEventsInWaitList, eventWaitList); rx::CLEventImpl::CreateFunc eventCreateFunc; rx::CLEventImpl::CreateFunc *const eventCreateFuncPtr = event != nullptr ? &eventCreateFunc : nullptr; cl_int errorCode = mImpl->enqueueUnmapMemObject(memory, mappedPtr, waitEvents, eventCreateFuncPtr); CheckCreateEvent(*this, CL_COMMAND_UNMAP_MEM_OBJECT, eventCreateFunc, event, errorCode); return errorCode; } cl_int CommandQueue::enqueueMigrateMemObjects(cl_uint numMemObjects, const cl_mem *memObjects, MemMigrationFlags flags, cl_uint numEventsInWaitList, const cl_event *eventWaitList, cl_event *event) { MemoryPtrs memories; memories.reserve(numMemObjects); while (numMemObjects-- != 0u) { memories.emplace_back(&(*memObjects++)->cast()); } const EventPtrs waitEvents = Event::Cast(numEventsInWaitList, eventWaitList); rx::CLEventImpl::CreateFunc eventCreateFunc; rx::CLEventImpl::CreateFunc *const eventCreateFuncPtr = event != nullptr ? &eventCreateFunc : nullptr; cl_int errorCode = mImpl->enqueueMigrateMemObjects(memories, flags, waitEvents, eventCreateFuncPtr); CheckCreateEvent(*this, CL_COMMAND_MIGRATE_MEM_OBJECTS, eventCreateFunc, event, errorCode); return errorCode; } cl_int CommandQueue::enqueueNDRangeKernel(cl_kernel kernel, cl_uint workDim, const size_t *globalWorkOffset, const size_t *globalWorkSize, const size_t *localWorkSize, cl_uint numEventsInWaitList, const cl_event *eventWaitList, cl_event *event) { const Kernel &krnl = kernel->cast(); const EventPtrs waitEvents = Event::Cast(numEventsInWaitList, eventWaitList); rx::CLEventImpl::CreateFunc eventCreateFunc; rx::CLEventImpl::CreateFunc *const eventCreateFuncPtr = event != nullptr ? &eventCreateFunc : nullptr; cl_int errorCode = mImpl->enqueueNDRangeKernel(krnl, workDim, globalWorkOffset, globalWorkSize, localWorkSize, waitEvents, eventCreateFuncPtr); CheckCreateEvent(*this, CL_COMMAND_NDRANGE_KERNEL, eventCreateFunc, event, errorCode); return errorCode; } cl_int CommandQueue::enqueueTask(cl_kernel kernel, cl_uint numEventsInWaitList, const cl_event *eventWaitList, cl_event *event) { const Kernel &krnl = kernel->cast(); const EventPtrs waitEvents = Event::Cast(numEventsInWaitList, eventWaitList); rx::CLEventImpl::CreateFunc eventCreateFunc; rx::CLEventImpl::CreateFunc *const eventCreateFuncPtr = event != nullptr ? &eventCreateFunc : nullptr; cl_int errorCode = mImpl->enqueueTask(krnl, waitEvents, eventCreateFuncPtr); CheckCreateEvent(*this, CL_COMMAND_TASK, eventCreateFunc, event, errorCode); return errorCode; } cl_int CommandQueue::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) { std::vector funcArgs; BufferPtrs buffers; std::vector offsets; if (numMemObjects != 0u) { // If argument memory block contains memory objects, make a copy. funcArgs.resize(cbArgs); std::memcpy(funcArgs.data(), args, cbArgs); buffers.reserve(numMemObjects); offsets.reserve(numMemObjects); while (numMemObjects-- != 0u) { buffers.emplace_back(&(*memList++)->cast()); // Calc memory offset of cl_mem object in args. offsets.emplace_back(static_cast(*argsMemLoc++) - static_cast(args)); // Fetch location of cl_mem object in copied function argument memory block. void *loc = &funcArgs[offsets.back()]; // Cast cl_mem object to cl::Buffer pointer in place. *reinterpret_cast(loc) = &(*reinterpret_cast(loc))->cast(); } // Use copied argument memory block. args = funcArgs.data(); } const EventPtrs waitEvents = Event::Cast(numEventsInWaitList, eventWaitList); rx::CLEventImpl::CreateFunc eventCreateFunc; rx::CLEventImpl::CreateFunc *const eventCreateFuncPtr = event != nullptr ? &eventCreateFunc : nullptr; cl_int errorCode = mImpl->enqueueNativeKernel(userFunc, args, cbArgs, buffers, offsets, waitEvents, eventCreateFuncPtr); CheckCreateEvent(*this, CL_COMMAND_NATIVE_KERNEL, eventCreateFunc, event, errorCode); return errorCode; } cl_int CommandQueue::enqueueMarkerWithWaitList(cl_uint numEventsInWaitList, const cl_event *eventWaitList, cl_event *event) { const EventPtrs waitEvents = Event::Cast(numEventsInWaitList, eventWaitList); rx::CLEventImpl::CreateFunc eventCreateFunc; rx::CLEventImpl::CreateFunc *const eventCreateFuncPtr = event != nullptr ? &eventCreateFunc : nullptr; cl_int errorCode = mImpl->enqueueMarkerWithWaitList(waitEvents, eventCreateFuncPtr); CheckCreateEvent(*this, CL_COMMAND_MARKER, eventCreateFunc, event, errorCode); return errorCode; } cl_int CommandQueue::enqueueMarker(cl_event *event) { rx::CLEventImpl::CreateFunc eventCreateFunc; cl_int errorCode = mImpl->enqueueMarker(eventCreateFunc); CheckCreateEvent(*this, CL_COMMAND_MARKER, eventCreateFunc, event, errorCode); return errorCode; } cl_int CommandQueue::enqueueWaitForEvents(cl_uint numEvents, const cl_event *eventList) { return mImpl->enqueueWaitForEvents(Event::Cast(numEvents, eventList)); } cl_int CommandQueue::enqueueBarrierWithWaitList(cl_uint numEventsInWaitList, const cl_event *eventWaitList, cl_event *event) { const EventPtrs waitEvents = Event::Cast(numEventsInWaitList, eventWaitList); rx::CLEventImpl::CreateFunc eventCreateFunc; rx::CLEventImpl::CreateFunc *const eventCreateFuncPtr = event != nullptr ? &eventCreateFunc : nullptr; cl_int errorCode = mImpl->enqueueBarrierWithWaitList(waitEvents, eventCreateFuncPtr); CheckCreateEvent(*this, CL_COMMAND_BARRIER, eventCreateFunc, event, errorCode); return errorCode; } cl_int CommandQueue::enqueueBarrier() { return mImpl->enqueueBarrier(); } cl_int CommandQueue::flush() { return mImpl->flush(); } cl_int CommandQueue::finish() { return mImpl->finish(); } CommandQueue::~CommandQueue() { auto queue = mDevice->mDefaultCommandQueue.synchronize(); if (*queue == this) { *queue = nullptr; } } size_t CommandQueue::getDeviceIndex() const { return std::find(mContext->getDevices().cbegin(), mContext->getDevices().cend(), mDevice) - mContext->getDevices().cbegin(); } CommandQueue::CommandQueue(Context &context, Device &device, PropArray &&propArray, CommandQueueProperties properties, cl_uint size, cl_int &errorCode) : mContext(&context), mDevice(&device), mPropArray(std::move(propArray)), mProperties(properties), mSize(size), mImpl(context.getImpl().createCommandQueue(*this, errorCode)) { if (mProperties->isSet(CL_QUEUE_ON_DEVICE_DEFAULT)) { *mDevice->mDefaultCommandQueue = this; } } CommandQueue::CommandQueue(Context &context, Device &device, CommandQueueProperties properties, cl_int &errorCode) : mContext(&context), mDevice(&device), mProperties(properties), mImpl(context.getImpl().createCommandQueue(*this, errorCode)) {} } // namespace cl