| // | |
| // 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. | |
| // | |
| // CLEvent.cpp: Implements the cl::Event class. | |
| #include "libANGLE/CLEvent.h" | |
| #include "libANGLE/CLCommandQueue.h" | |
| #include "libANGLE/CLContext.h" | |
| #include "libANGLE/cl_utils.h" | |
| #include <cstring> | |
| namespace cl | |
| { | |
| angle::Result Event::setUserEventStatus(cl_int executionStatus) | |
| { | |
| ANGLE_TRY(mImpl->setUserEventStatus(executionStatus)); | |
| mStatusWasChanged = true; | |
| return angle::Result::Continue; | |
| } | |
| angle::Result Event::getInfo(EventInfo name, | |
| size_t valueSize, | |
| void *value, | |
| size_t *valueSizeRet) const | |
| { | |
| cl_int execStatus = 0; | |
| cl_uint valUInt = 0u; | |
| void *valPointer = nullptr; | |
| const void *copyValue = nullptr; | |
| size_t copySize = 0u; | |
| switch (name) | |
| { | |
| case EventInfo::CommandQueue: | |
| valPointer = CommandQueue::CastNative(mCommandQueue.get()); | |
| copyValue = &valPointer; | |
| copySize = sizeof(valPointer); | |
| break; | |
| case EventInfo::CommandType: | |
| copyValue = &mCommandType; | |
| copySize = sizeof(mCommandType); | |
| break; | |
| case EventInfo::ReferenceCount: | |
| valUInt = getRefCount(); | |
| copyValue = &valUInt; | |
| copySize = sizeof(valUInt); | |
| break; | |
| case EventInfo::CommandExecutionStatus: | |
| { | |
| ANGLE_TRY(mImpl->getCommandExecutionStatus(execStatus)); | |
| copyValue = &execStatus; | |
| copySize = sizeof(execStatus); | |
| break; | |
| } | |
| case EventInfo::Context: | |
| valPointer = mContext->getNative(); | |
| copyValue = &valPointer; | |
| copySize = sizeof(valPointer); | |
| break; | |
| default: | |
| ANGLE_CL_RETURN_ERROR(CL_INVALID_VALUE); | |
| } | |
| if (value != nullptr) | |
| { | |
| // CL_INVALID_VALUE if size in bytes specified by param_value_size is < size of return type | |
| // as described in the Event Queries table and param_value is not NULL. | |
| if (valueSize < copySize) | |
| { | |
| ANGLE_CL_RETURN_ERROR(CL_INVALID_VALUE); | |
| } | |
| if (copyValue != nullptr) | |
| { | |
| std::memcpy(value, copyValue, copySize); | |
| } | |
| } | |
| if (valueSizeRet != nullptr) | |
| { | |
| *valueSizeRet = copySize; | |
| } | |
| return angle::Result::Continue; | |
| } | |
| angle::Result Event::setCallback(cl_int commandExecCallbackType, EventCB pfnNotify, void *userData) | |
| { | |
| auto callbacks = mCallbacks.synchronize(); | |
| // Spec mentions that the callback will be called when the execution status of the event is | |
| // equal to past the status specified by commandExecCallbackType | |
| cl_int currentStatus; | |
| ANGLE_TRY(mImpl->getCommandExecutionStatus(currentStatus)); | |
| if (currentStatus <= commandExecCallbackType) | |
| { | |
| pfnNotify(this, commandExecCallbackType, userData); | |
| return angle::Result::Continue; | |
| } | |
| // Only when required register a single callback with the back end for each callback type. | |
| if ((*callbacks)[commandExecCallbackType].empty()) | |
| { | |
| ANGLE_TRY(mImpl->setCallback(*this, commandExecCallbackType)); | |
| // This event has to be retained until the callback is called. | |
| retain(); | |
| } | |
| (*callbacks)[commandExecCallbackType].emplace_back(pfnNotify, userData); | |
| return angle::Result::Continue; | |
| } | |
| angle::Result Event::getProfilingInfo(ProfilingInfo name, | |
| size_t valueSize, | |
| void *value, | |
| size_t *valueSizeRet) | |
| { | |
| return mImpl->getProfilingInfo(name, valueSize, value, valueSizeRet); | |
| } | |
| angle::Result Event::initBackend(const rx::CLEventImpl::CreateFunc &createFunc) | |
| { | |
| if (isUserEvent()) | |
| { | |
| return mContext->getImpl().createUserEvent(*this, &mImpl); | |
| } | |
| else | |
| { | |
| mImpl = createFunc(*this); | |
| if (mImpl == nullptr) | |
| { | |
| ANGLE_CL_RETURN_ERROR(CL_OUT_OF_HOST_MEMORY); | |
| } | |
| return mImpl->onEventCreate(); | |
| } | |
| } | |
| Event::~Event() = default; | |
| void Event::callback(cl_int commandStatus) | |
| { | |
| ASSERT(commandStatus >= 0 && commandStatus < 3); | |
| const Callbacks callbacks = std::move(mCallbacks->at(commandStatus)); | |
| for (const CallbackData &data : callbacks) | |
| { | |
| data.first(this, commandStatus, data.second); | |
| } | |
| // This event can be released after the callback was called. | |
| if (release()) | |
| { | |
| delete this; | |
| } | |
| } | |
| EventPtrs Event::Cast(cl_uint numEvents, const cl_event *eventList) | |
| { | |
| EventPtrs events; | |
| events.reserve(numEvents); | |
| while (numEvents-- != 0u) | |
| { | |
| events.emplace_back(&(*eventList++)->cast<Event>()); | |
| } | |
| return events; | |
| } | |
| Event::Event(Context &context) : mContext(&context), mCommandType(CL_COMMAND_USER), mImpl(nullptr) | |
| { | |
| ANGLE_CL_IMPL_TRY(context.getImpl().createUserEvent(*this, &mImpl)); | |
| } | |
| Event::Event(CommandQueue &queue, cl_command_type commandType) | |
| : mContext(&queue.getContext()), | |
| mCommandQueue(&queue), | |
| mCommandType(commandType), | |
| mImpl(nullptr) | |
| {} | |
| } // namespace cl |