blob: d9b8d516d3b26986f5545f9d17dd10e7ae552bbc [file] [log] [blame]
//
// 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