Commit 076974a9 by John Plate Committed by Angle LUCI CQ

CL: event creation for front end & passthrough

Add event object to back end and implement creation and info query. Bug: angleproject:6001 Change-Id: Id4951b726b66afa289fafe1a716a7cfdb6f5826d Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/2925477 Commit-Queue: John Plate <jplate@google.com> Reviewed-by: 's avatarJamie Madill <jmadill@chromium.org> Reviewed-by: 's avatarCody Northrop <cnorthrop@google.com>
parent d7aa0130
......@@ -29,6 +29,8 @@ using ContextErrorCB = void(CL_CALLBACK *)(const char *errinfo,
size_t cb,
void *user_data);
using EventCB = void(CL_CALLBACK *)(cl_event event, cl_int event_command_status, void *user_data);
template <typename CLObjectType>
struct Dispatch
{
......
......@@ -20,7 +20,8 @@ cl_mem Buffer::createSubBuffer(MemFlags flags,
cl_int &errorCode)
{
const cl_buffer_region &region = *static_cast<const cl_buffer_region *>(createInfo);
return mContext->createMemory(new Buffer(*this, flags, region.origin, region.size, errorCode));
return mContext->createMemory(new Buffer(*this, flags, region.origin, region.size, errorCode),
errorCode);
}
Buffer::Buffer(Context &context,
......
......@@ -50,7 +50,7 @@ inline cl_mem_object_type Buffer::getType() const
inline bool Buffer::isSubBuffer() const
{
return mParent.isValid();
return mParent != nullptr;
}
inline bool Buffer::isRegionValid(const cl_buffer_region &region) const
......
......@@ -85,7 +85,7 @@ cl_command_queue Context::createCommandQueue(cl_device_id device,
cl_int &errorCode)
{
return createCommandQueue(
new CommandQueue(*this, *static_cast<Device *>(device), properties, errorCode));
new CommandQueue(*this, *static_cast<Device *>(device), properties, errorCode), errorCode);
}
cl_command_queue Context::createCommandQueueWithProperties(cl_device_id device,
......@@ -116,7 +116,8 @@ cl_command_queue Context::createCommandQueueWithProperties(cl_device_id device,
propArray.insert(propArray.cend(), properties, propIt);
}
return createCommandQueue(new CommandQueue(*this, *static_cast<Device *>(device),
std::move(propArray), props, size, errorCode));
std::move(propArray), props, size, errorCode),
errorCode);
}
cl_mem Context::createBuffer(const cl_mem_properties *properties,
......@@ -125,7 +126,7 @@ cl_mem Context::createBuffer(const cl_mem_properties *properties,
void *hostPtr,
cl_int &errorCode)
{
return createMemory(new Buffer(*this, {}, flags, size, hostPtr, errorCode));
return createMemory(new Buffer(*this, {}, flags, size, hostPtr, errorCode), errorCode);
}
cl_mem Context::createImage(const cl_mem_properties *properties,
......@@ -140,7 +141,8 @@ cl_mem Context::createImage(const cl_mem_properties *properties,
desc->image_depth, desc->image_array_size, desc->image_row_pitch,
desc->image_slice_pitch, desc->num_mip_levels, desc->num_samples};
return createMemory(new Image(*this, {}, flags, *format, imageDesc,
static_cast<Memory *>(desc->buffer), hostPtr, errorCode));
static_cast<Memory *>(desc->buffer), hostPtr, errorCode),
errorCode);
}
cl_mem Context::createImage2D(MemFlags flags,
......@@ -154,7 +156,7 @@ cl_mem Context::createImage2D(MemFlags flags,
const ImageDescriptor imageDesc = {
CL_MEM_OBJECT_IMAGE2D, width, height, 0u, 0u, rowPitch, 0u, 0u, 0u};
return createMemory(
new Image(*this, {}, flags, *format, imageDesc, nullptr, hostPtr, errorCode));
new Image(*this, {}, flags, *format, imageDesc, nullptr, hostPtr, errorCode), errorCode);
}
cl_mem Context::createImage3D(MemFlags flags,
......@@ -170,7 +172,7 @@ cl_mem Context::createImage3D(MemFlags flags,
const ImageDescriptor imageDesc = {
CL_MEM_OBJECT_IMAGE3D, width, height, depth, 0u, rowPitch, slicePitch, 0u, 0u};
return createMemory(
new Image(*this, {}, flags, *format, imageDesc, nullptr, hostPtr, errorCode));
new Image(*this, {}, flags, *format, imageDesc, nullptr, hostPtr, errorCode), errorCode);
}
cl_sampler Context::createSampler(cl_bool normalizedCoords,
......@@ -179,7 +181,7 @@ cl_sampler Context::createSampler(cl_bool normalizedCoords,
cl_int &errorCode)
{
return createSampler(
new Sampler(*this, {}, normalizedCoords, addressingMode, filterMode, errorCode));
new Sampler(*this, {}, normalizedCoords, addressingMode, filterMode, errorCode), errorCode);
}
cl_sampler Context::createSamplerWithProperties(const cl_sampler_properties *properties,
......@@ -215,7 +217,8 @@ cl_sampler Context::createSamplerWithProperties(const cl_sampler_properties *pro
}
return createSampler(new Sampler(*this, std::move(propArray), normalizedCoords, addressingMode,
filterMode, errorCode));
filterMode, errorCode),
errorCode);
}
cl_program Context::createProgramWithSource(cl_uint count,
......@@ -246,12 +249,12 @@ cl_program Context::createProgramWithSource(cl_uint count,
++lengths;
}
}
return createProgram(new Program(*this, std::move(source), errorCode));
return createProgram(new Program(*this, std::move(source), errorCode), errorCode);
}
cl_program Context::createProgramWithIL(const void *il, size_t length, cl_int &errorCode)
{
return createProgram(new Program(*this, il, length, errorCode));
return createProgram(new Program(*this, il, length, errorCode), errorCode);
}
cl_program Context::createProgramWithBinary(cl_uint numDevices,
......@@ -270,7 +273,8 @@ cl_program Context::createProgramWithBinary(cl_uint numDevices,
std::memcpy(binaryVec.back().data(), *binaries++, binaryVec.back().size());
}
return createProgram(
new Program(*this, std::move(refDevices), std::move(binaryVec), binaryStatus, errorCode));
new Program(*this, std::move(refDevices), std::move(binaryVec), binaryStatus, errorCode),
errorCode);
}
cl_program Context::createProgramWithBuiltInKernels(cl_uint numDevices,
......@@ -283,7 +287,24 @@ cl_program Context::createProgramWithBuiltInKernels(cl_uint numDevices,
{
refDevices.emplace_back(static_cast<Device *>(*devices++));
}
return createProgram(new Program(*this, std::move(refDevices), kernelNames, errorCode));
return createProgram(new Program(*this, std::move(refDevices), kernelNames, errorCode),
errorCode);
}
cl_event Context::createUserEvent(cl_int &errorCode)
{
return createEvent(new Event(*this, errorCode), errorCode);
}
cl_int Context::waitForEvents(cl_uint numEvents, const cl_event *eventList)
{
EventRefs events;
events.reserve(numEvents);
while (numEvents-- != 0u)
{
events.emplace_back(static_cast<Event *>(*eventList++));
}
return mImpl->waitForEvents(events);
}
bool Context::IsValid(const _cl_context *context)
......@@ -348,10 +369,10 @@ Context::Context(Platform &platform,
mDevices(mImpl ? mImpl->getDevices(errorCode) : DeviceRefs{})
{}
cl_command_queue Context::createCommandQueue(CommandQueue *commandQueue)
cl_command_queue Context::createCommandQueue(CommandQueue *commandQueue, cl_int errorCode)
{
mCommandQueues.emplace_back(commandQueue);
if (!mCommandQueues.back()->mImpl)
if (errorCode != CL_SUCCESS)
{
mCommandQueues.back()->release();
return nullptr;
......@@ -359,10 +380,10 @@ cl_command_queue Context::createCommandQueue(CommandQueue *commandQueue)
return mCommandQueues.back().get();
}
cl_mem Context::createMemory(Memory *memory)
cl_mem Context::createMemory(Memory *memory, cl_int errorCode)
{
mMemories.emplace_back(memory);
if (!mMemories.back()->mImpl || mMemories.back()->mSize == 0u)
if (errorCode != CL_SUCCESS)
{
mMemories.back()->release();
return nullptr;
......@@ -370,10 +391,10 @@ cl_mem Context::createMemory(Memory *memory)
return mMemories.back().get();
}
cl_sampler Context::createSampler(Sampler *sampler)
cl_sampler Context::createSampler(Sampler *sampler, cl_int errorCode)
{
mSamplers.emplace_back(sampler);
if (!mSamplers.back()->mImpl)
if (errorCode != CL_SUCCESS)
{
mSamplers.back()->release();
return nullptr;
......@@ -381,10 +402,10 @@ cl_sampler Context::createSampler(Sampler *sampler)
return mSamplers.back().get();
}
cl_program Context::createProgram(Program *program)
cl_program Context::createProgram(Program *program, cl_int errorCode)
{
mPrograms.emplace_back(program);
if (!mPrograms.back()->mImpl)
if (errorCode != CL_SUCCESS)
{
mPrograms.back()->release();
return nullptr;
......@@ -392,6 +413,17 @@ cl_program Context::createProgram(Program *program)
return mPrograms.back().get();
}
cl_event Context::createEvent(Event *event, cl_int errorCode)
{
mEvents.emplace_back(event);
if (errorCode != CL_SUCCESS)
{
mEvents.back()->release();
return nullptr;
}
return mEvents.back().get();
}
void Context::destroyCommandQueue(CommandQueue *commandQueue)
{
auto commandQueueIt = mCommandQueues.cbegin();
......@@ -460,4 +492,21 @@ void Context::destroyProgram(Program *program)
}
}
void Context::destroyEvent(Event *event)
{
auto eventIt = mEvents.cbegin();
while (eventIt != mEvents.cend() && eventIt->get() != event)
{
++eventIt;
}
if (eventIt != mEvents.cend())
{
mEvents.erase(eventIt);
}
else
{
ERR() << "Event not found";
}
}
} // namespace cl
......@@ -11,6 +11,7 @@
#include "libANGLE/CLCommandQueue.h"
#include "libANGLE/CLDevice.h"
#include "libANGLE/CLEvent.h"
#include "libANGLE/CLMemory.h"
#include "libANGLE/CLProgram.h"
#include "libANGLE/CLSampler.h"
......@@ -40,6 +41,9 @@ class Context final : public _cl_context, public Object
bool hasSampler(const _cl_sampler *sampler) const;
bool hasProgram(const _cl_program *program) const;
bool hasKernel(const _cl_kernel *kernel) const;
bool hasEvent(const _cl_event *event) const;
EventRefPtr findEvent(const EventPredicate &eventPredicate) const;
void retain() noexcept;
bool release();
......@@ -112,6 +116,10 @@ class Context final : public _cl_context, public Object
const char *kernelNames,
cl_int &errorCode);
cl_event createUserEvent(cl_int &errorCode);
cl_int waitForEvents(cl_uint numEvents, const cl_event *eventList);
static bool IsValid(const _cl_context *context);
static bool IsValidAndVersionOrNewer(const _cl_context *context, cl_uint major, cl_uint minor);
......@@ -137,15 +145,17 @@ class Context final : public _cl_context, public Object
bool userSync,
cl_int &errorCode);
cl_command_queue createCommandQueue(CommandQueue *commandQueue);
cl_mem createMemory(Memory *memory);
cl_sampler createSampler(Sampler *sampler);
cl_program createProgram(Program *program);
cl_command_queue createCommandQueue(CommandQueue *commandQueue, cl_int errorCode);
cl_mem createMemory(Memory *memory, cl_int errorCode);
cl_sampler createSampler(Sampler *sampler, cl_int errorCode);
cl_program createProgram(Program *program, cl_int errorCode);
cl_event createEvent(Event *event, cl_int errorCode);
void destroyCommandQueue(CommandQueue *commandQueue);
void destroyMemory(Memory *memory);
void destroySampler(Sampler *sampler);
void destroyProgram(Program *program);
void destroyEvent(Event *event);
Platform &mPlatform;
const PropArray mProperties;
......@@ -158,9 +168,11 @@ class Context final : public _cl_context, public Object
Memory::PtrList mMemories;
Sampler::PtrList mSamplers;
Program::PtrList mPrograms;
Event::PtrList mEvents;
friend class Buffer;
friend class CommandQueue;
friend class Event;
friend class Memory;
friend class Platform;
friend class Program;
......@@ -240,6 +252,18 @@ inline bool Context::hasKernel(const _cl_kernel *kernel) const
}) != mPrograms.cend();
}
inline bool Context::hasEvent(const _cl_event *event) const
{
return std::find_if(mEvents.cbegin(), mEvents.cend(),
[=](const EventPtr &ptr) { return ptr.get() == event; }) != mEvents.cend();
}
inline EventRefPtr Context::findEvent(const EventPredicate &eventPredicate) const
{
const auto eventIt = std::find_if(mEvents.cbegin(), mEvents.cend(), eventPredicate);
return EventRefPtr(eventIt != mEvents.cend() ? eventIt->get() : nullptr);
}
inline void Context::retain() noexcept
{
addRef();
......
......@@ -7,9 +7,143 @@
#include "libANGLE/CLEvent.h"
#include "libANGLE/CLContext.h"
#include "libANGLE/CLPlatform.h"
#include <cstring>
namespace cl
{
Event::Event(const cl_icd_dispatch &dispatch) : _cl_event(dispatch) {}
Event::~Event() = default;
bool Event::release()
{
const bool released = removeRef();
if (released)
{
mContext->destroyEvent(this);
}
return released;
}
void Event::callback(cl_int commandStatus)
{
ASSERT(commandStatus >= 0 && commandStatus < 3);
for (const CallbackData &data : mCallbacks[commandStatus])
{
data.first(this, commandStatus, data.second);
}
}
cl_int Event::setUserEventStatus(cl_int executionStatus)
{
const cl_int errorCode = mImpl->setUserEventStatus(executionStatus);
if (errorCode == CL_SUCCESS)
{
mStatusWasChanged = true;
}
return errorCode;
}
cl_int Event::getInfo(EventInfo name, size_t valueSize, void *value, size_t *valueSizeRet) const
{
cl_int execStatus = 0;
void *valPointer = nullptr;
const void *copyValue = nullptr;
size_t copySize = 0u;
switch (name)
{
case EventInfo::CommandQueue:
valPointer = static_cast<cl_command_queue>(mCommandQueue.get());
copyValue = &valPointer;
copySize = sizeof(valPointer);
break;
case EventInfo::CommandType:
copyValue = &mCommandType;
copySize = sizeof(mCommandType);
break;
case EventInfo::ReferenceCount:
copyValue = getRefCountPtr();
copySize = sizeof(*getRefCountPtr());
break;
case EventInfo::CommandExecutionStatus:
{
const cl_int errorCode = mImpl->getCommandExecutionStatus(execStatus);
if (errorCode != CL_SUCCESS)
{
return errorCode;
}
copyValue = &execStatus;
copySize = sizeof(execStatus);
break;
}
case EventInfo::Context:
valPointer = static_cast<cl_context>(mContext.get());
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 described in the Event Queries table and param_value is not NULL.
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 Event::setCallback(cl_int commandExecCallbackType, EventCB pfnNotify, void *userData)
{
// Only when required register a single callback with the back end for each callback type.
if (mCallbacks[commandExecCallbackType].empty())
{
const cl_int errorCode = mImpl->setCallback(commandExecCallbackType);
if (errorCode != CL_SUCCESS)
{
return errorCode;
}
}
mCallbacks[commandExecCallbackType].emplace_back(pfnNotify, userData);
return CL_SUCCESS;
}
bool Event::IsValid(const _cl_event *event)
{
const Platform::PtrList &platforms = Platform::GetPlatforms();
return std::find_if(platforms.cbegin(), platforms.cend(), [=](const PlatformPtr &platform) {
return platform->hasEvent(event);
}) != platforms.cend();
}
bool Event::IsValidAndVersionOrNewer(const _cl_event *event, cl_uint major, cl_uint minor)
{
const Platform::PtrList &platforms = Platform::GetPlatforms();
return std::find_if(platforms.cbegin(), platforms.cend(), [=](const PlatformPtr &platform) {
return platform->isVersionOrNewer(major, minor) && platform->hasEvent(event);
}) != platforms.cend();
}
Event::Event(Context &context, cl_int &errorCode)
: _cl_event(context.getDispatch()),
mContext(&context),
mImpl(context.mImpl->createUserEvent(*this, errorCode)),
mCommandType(CL_COMMAND_USER)
{}
} // namespace cl
......@@ -10,6 +10,9 @@
#define LIBANGLE_CLEVENT_H_
#include "libANGLE/CLObject.h"
#include "libANGLE/renderer/CLEventImpl.h"
#include <array>
namespace cl
{
......@@ -17,10 +20,89 @@ namespace cl
class Event final : public _cl_event, public Object
{
public:
Event(const cl_icd_dispatch &dispatch);
~Event() override = default;
using PtrList = std::list<EventPtr>;
~Event() override;
Context &getContext();
const Context &getContext() const;
const CommandQueueRefPtr &getCommandQueue() const;
cl_command_type getCommandType() const;
bool wasStatusChanged() const;
template <typename T>
T &getImpl() const;
void retain() noexcept;
bool release();
void callback(cl_int commandStatus);
cl_int setUserEventStatus(cl_int executionStatus);
cl_int getInfo(EventInfo name, size_t valueSize, void *value, size_t *valueSizeRet) const;
cl_int setCallback(cl_int commandExecCallbackType, EventCB pfnNotify, void *userData);
static bool IsValid(const _cl_event *event);
static bool IsValidAndVersionOrNewer(const _cl_event *event, cl_uint major, cl_uint minor);
private:
using CallbackData = std::pair<EventCB, void *>;
Event(Context &context, cl_int &errorCode);
const ContextRefPtr mContext;
const CommandQueueRefPtr mCommandQueue;
const rx::CLEventImpl::Ptr mImpl;
const cl_command_type mCommandType;
bool mStatusWasChanged = false;
// Create separate storage for each possible callback type.
static_assert(CL_COMPLETE == 0 && CL_RUNNING == 1 && CL_SUBMITTED == 2,
"OpenCL command execution status values are not as assumed");
std::array<std::vector<CallbackData>, 3u> mCallbacks;
friend class Context;
};
inline Context &Event::getContext()
{
return *mContext;
}
inline const Context &Event::getContext() const
{
return *mContext;
}
inline const CommandQueueRefPtr &Event::getCommandQueue() const
{
return mCommandQueue;
}
inline cl_command_type Event::getCommandType() const
{
return mCommandType;
}
inline bool Event::wasStatusChanged() const
{
return mStatusWasChanged;
}
template <typename T>
inline T &Event::getImpl() const
{
return static_cast<T &>(*mImpl);
}
inline void Event::retain() noexcept
{
addRef();
}
} // namespace cl
#endif // LIBANGLE_CLEVENT_H_
......@@ -212,9 +212,10 @@ cl_context Platform::CreateContext(const cl_context_properties *properties,
{
refDevices.emplace_back(static_cast<Device *>(*devices++));
}
return platform->createContext(new Context(*platform, std::move(propArray),
std::move(refDevices), notify, userData, userSync,
errorCode));
return platform->createContext(
new Context(*platform, std::move(propArray), std::move(refDevices), notify, userData,
userSync, errorCode),
errorCode);
}
cl_context Platform::CreateContextFromType(const cl_context_properties *properties,
......@@ -228,7 +229,8 @@ cl_context Platform::CreateContextFromType(const cl_context_properties *properti
Context::PropArray propArray = ParseContextProperties(properties, platform, userSync);
ASSERT(platform != nullptr);
return platform->createContext(new Context(*platform, std::move(propArray), deviceType, notify,
userData, userSync, errorCode));
userData, userSync, errorCode),
errorCode);
}
Platform::Platform(const cl_icd_dispatch &dispatch, const CreateImplFunc &createImplFunc)
......@@ -238,10 +240,10 @@ Platform::Platform(const cl_icd_dispatch &dispatch, const CreateImplFunc &create
mDevices(mImpl->createDevices(*this))
{}
cl_context Platform::createContext(Context *context)
cl_context Platform::createContext(Context *context, cl_int errorCode)
{
mContexts.emplace_back(context);
if (!mContexts.back()->mImpl || mContexts.back()->mDevices.empty())
if (errorCode != CL_SUCCESS)
{
mContexts.back()->release();
return nullptr;
......
......@@ -37,6 +37,9 @@ class Platform final : public _cl_platform_id, public Object
bool hasSampler(const _cl_sampler *sampler) const;
bool hasProgram(const _cl_program *program) const;
bool hasKernel(const _cl_kernel *kernel) const;
bool hasEvent(const _cl_event *event) const;
EventRefPtr findEvent(const EventPredicate &eventPredicate) const;
cl_int getInfo(PlatformInfo name, size_t valueSize, void *value, size_t *valueSizeRet) const;
......@@ -71,12 +74,14 @@ class Platform final : public _cl_platform_id, public Object
static bool IsValid(const _cl_platform_id *platform);
static bool IsValidOrDefault(const _cl_platform_id *platform);
static EventRefPtr FindEvent(const EventPredicate &eventPredicate);
static constexpr const char *GetVendor();
private:
Platform(const cl_icd_dispatch &dispatch, const CreateImplFunc &createImplFunc);
cl_context createContext(Context *context);
cl_context createContext(Context *context, cl_int errorCode);
void destroyContext(Context *context);
static PtrList &GetList();
......@@ -157,6 +162,24 @@ inline bool Platform::hasKernel(const _cl_kernel *kernel) const
}) != mContexts.cend();
}
inline bool Platform::hasEvent(const _cl_event *event) const
{
return std::find_if(mContexts.cbegin(), mContexts.cend(), [=](const ContextPtr &ptr) {
return ptr->hasEvent(event);
}) != mContexts.cend();
}
inline EventRefPtr Platform::findEvent(const EventPredicate &eventPredicate) const
{
EventRefPtr event;
auto contextIt = mContexts.cbegin();
while (contextIt != mContexts.cend() && event == nullptr)
{
event = (*contextIt++)->findEvent(eventPredicate);
}
return event;
}
inline Platform::PtrList &Platform::GetList()
{
static angle::base::NoDestructor<PtrList> sList;
......@@ -193,6 +216,17 @@ inline bool Platform::IsValidOrDefault(const _cl_platform_id *platform)
return platform != nullptr ? IsValid(platform) : GetDefault() != nullptr;
}
inline EventRefPtr Platform::FindEvent(const EventPredicate &eventPredicate)
{
EventRefPtr event;
auto platformIt = GetPlatforms().cbegin();
while (platformIt != GetPlatforms().cend() && event == nullptr)
{
event = (*platformIt++)->findEvent(eventPredicate);
}
return event;
}
constexpr const char *Platform::GetVendor()
{
return kVendor;
......
......@@ -135,13 +135,13 @@ cl_int Program::getInfo(ProgramInfo name, size_t valueSize, void *value, size_t
cl_kernel Program::createKernel(const char *kernel_name, cl_int &errorCode)
{
return createKernel(new Kernel(*this, kernel_name, errorCode));
return createKernel(new Kernel(*this, kernel_name, errorCode), errorCode);
}
cl_int Program::createKernel(const Kernel::CreateImplFunc &createImplFunc)
{
cl_int errorCode = CL_SUCCESS;
createKernel(new Kernel(*this, createImplFunc, errorCode));
createKernel(new Kernel(*this, createImplFunc, errorCode), errorCode);
return errorCode;
}
......@@ -220,10 +220,10 @@ Program::Program(Context &context, DeviceRefs &&devices, const char *kernelNames
mSource(mImpl ? mImpl->getSource(errorCode) : std::string{})
{}
cl_kernel Program::createKernel(Kernel *kernel)
cl_kernel Program::createKernel(Kernel *kernel, cl_int errorCode)
{
mKernels.emplace_back(kernel);
if (!mKernels.back()->mImpl)
if (errorCode != CL_SUCCESS)
{
mKernels.back()->release();
return nullptr;
......
......@@ -51,7 +51,7 @@ class Program final : public _cl_program, public Object
Program(Context &context, DeviceRefs &&devices, const char *kernelNames, cl_int &errorCode);
cl_kernel createKernel(Kernel *kernel);
cl_kernel createKernel(Kernel *kernel, cl_int errorCode);
void destroyKernel(Kernel *kernel);
......
......@@ -41,10 +41,10 @@ class RefPointer
return *this;
}
RefPointer(RefPointer &&other) noexcept : mCLObject(nullptr) { other.swap(*this); }
RefPointer(RefPointer &&other) noexcept : mCLObject(nullptr) { this->swap(other); }
RefPointer &operator=(RefPointer &&other)
{
other.swap(this);
this->swap(other);
return *this;
}
......@@ -72,7 +72,6 @@ class RefPointer
T *operator->() const { return mCLObject; }
T &operator*() const { return *mCLObject; }
bool isValid() const { return mCLObject != nullptr; }
T *get() const { return mCLObject; }
explicit operator bool() const { return mCLObject != nullptr; }
......@@ -104,6 +103,30 @@ void swap(RefPointer<T> &left, RefPointer<T> &right)
left.swap(right);
}
template <typename T>
bool operator==(const RefPointer<T> &ptr, nullptr_t) noexcept
{
return ptr.get() == nullptr;
}
template <typename T>
bool operator==(nullptr_t, const RefPointer<T> &ptr) noexcept
{
return ptr.get() == nullptr;
}
template <typename T>
bool operator!=(const RefPointer<T> &ptr, nullptr_t) noexcept
{
return ptr.get() != nullptr;
}
template <typename T>
bool operator!=(nullptr_t, const RefPointer<T> &ptr) noexcept
{
return ptr.get() != nullptr;
}
} // namespace cl
#endif // LIBANGLE_CLREFPOINTER_H_
......@@ -49,17 +49,23 @@ using PlatformPtr = std::unique_ptr<Platform>;
using ProgramPtr = std::unique_ptr<Program>;
using SamplerPtr = std::unique_ptr<Sampler>;
using ContextRefPtr = RefPointer<Context>;
using DeviceRefPtr = RefPointer<Device>;
using MemoryRefPtr = RefPointer<Memory>;
using ProgramRefPtr = RefPointer<Program>;
using CommandQueueRefPtr = RefPointer<CommandQueue>;
using ContextRefPtr = RefPointer<Context>;
using DeviceRefPtr = RefPointer<Device>;
using EventRefPtr = RefPointer<Event>;
using MemoryRefPtr = RefPointer<Memory>;
using ProgramRefPtr = RefPointer<Program>;
using DevicePtrList = std::list<DevicePtr>;
using DeviceRefs = std::vector<DeviceRefPtr>;
using DeviceRefs = std::vector<DeviceRefPtr>;
using EventRefs = std::vector<EventRefPtr>;
using Binary = std::vector<unsigned char>;
using Binaries = std::vector<Binary>;
using EventPredicate = std::function<bool(const EventPtr &)>;
struct ImageDescriptor
{
cl_mem_object_type type;
......
......@@ -10,6 +10,7 @@
#include "libANGLE/renderer/CLCommandQueueImpl.h"
#include "libANGLE/renderer/CLDeviceImpl.h"
#include "libANGLE/renderer/CLEventImpl.h"
#include "libANGLE/renderer/CLMemoryImpl.h"
#include "libANGLE/renderer/CLProgramImpl.h"
#include "libANGLE/renderer/CLSamplerImpl.h"
......@@ -61,6 +62,10 @@ class CLContextImpl : angle::NonCopyable
const char *kernel_names,
cl_int &errorCode) = 0;
virtual CLEventImpl::Ptr createUserEvent(const cl::Event &event, cl_int &errorCode) = 0;
virtual cl_int waitForEvents(const cl::EventRefs &events) = 0;
protected:
const cl::Context &mContext;
};
......
//
// 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.
//
// CLEventImpl.cpp: Implements the class methods for CLEventImpl.
#include "libANGLE/renderer/CLEventImpl.h"
namespace rx
{
CLEventImpl::CLEventImpl(const cl::Event &event) : mEvent(event) {}
CLEventImpl::~CLEventImpl() = default;
} // namespace rx
//
// 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.
//
// CLEventImpl.h: Defines the abstract rx::CLEventImpl class.
#ifndef LIBANGLE_RENDERER_CLEVENTIMPL_H_
#define LIBANGLE_RENDERER_CLEVENTIMPL_H_
#include "libANGLE/renderer/CLtypes.h"
namespace rx
{
class CLEventImpl : angle::NonCopyable
{
public:
using Ptr = std::unique_ptr<CLEventImpl>;
CLEventImpl(const cl::Event &event);
virtual ~CLEventImpl();
virtual cl_int getCommandExecutionStatus(cl_int &executionStatus) = 0;
virtual cl_int setUserEventStatus(cl_int executionStatus) = 0;
virtual cl_int setCallback(cl_int commandExecCallbackType) = 0;
protected:
const cl::Event &mEvent;
};
} // namespace rx
#endif // LIBANGLE_RENDERER_CLEVENTIMPL_H_
......@@ -15,6 +15,8 @@ _cl_backend_sources = [
"CLContextCL.h",
"CLDeviceCL.cpp",
"CLDeviceCL.h",
"CLEventCL.cpp",
"CLEventCL.h",
"CLKernelCL.cpp",
"CLKernelCL.h",
"CLMemoryCL.cpp",
......
......@@ -9,6 +9,7 @@
#include "libANGLE/renderer/cl/CLCommandQueueCL.h"
#include "libANGLE/renderer/cl/CLDeviceCL.h"
#include "libANGLE/renderer/cl/CLEventCL.h"
#include "libANGLE/renderer/cl/CLMemoryCL.h"
#include "libANGLE/renderer/cl/CLProgramCL.h"
#include "libANGLE/renderer/cl/CLSamplerCL.h"
......@@ -17,6 +18,7 @@
#include "libANGLE/CLCommandQueue.h"
#include "libANGLE/CLContext.h"
#include "libANGLE/CLDevice.h"
#include "libANGLE/CLEvent.h"
#include "libANGLE/CLImage.h"
#include "libANGLE/CLMemory.h"
#include "libANGLE/CLPlatform.h"
......@@ -270,4 +272,22 @@ CLProgramImpl::Ptr CLContextCL::createProgramWithBuiltInKernels(const cl::Progra
: nullptr);
}
CLEventImpl::Ptr CLContextCL::createUserEvent(const cl::Event &event, cl_int &errorCode)
{
const cl_event nativeEvent = mNative->getDispatch().clCreateUserEvent(mNative, &errorCode);
return CLEventImpl::Ptr(nativeEvent != nullptr ? new CLEventCL(event, nativeEvent) : nullptr);
}
cl_int CLContextCL::waitForEvents(const cl::EventRefs &events)
{
std::vector<cl_event> nativeEvents;
nativeEvents.reserve(events.size());
for (const cl::EventRefPtr &event : events)
{
nativeEvents.emplace_back(event->getImpl<CLEventCL>().getNative());
}
return mNative->getDispatch().clWaitForEvents(static_cast<cl_uint>(nativeEvents.size()),
nativeEvents.data());
}
} // namespace rx
......@@ -57,6 +57,10 @@ class CLContextCL : public CLContextImpl
const char *kernel_names,
cl_int &errorCode) override;
CLEventImpl::Ptr createUserEvent(const cl::Event &event, cl_int &errorCode) override;
cl_int waitForEvents(const cl::EventRefs &events) override;
private:
const cl_context mNative;
};
......
//
// 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.
//
// CLEventCL.cpp: Implements the class methods for CLEventCL.
#include "libANGLE/renderer/cl/CLEventCL.h"
#include "libANGLE/CLPlatform.h"
#include "libANGLE/Debug.h"
namespace rx
{
CLEventCL::CLEventCL(const cl::Event &event, cl_event native) : CLEventImpl(event), mNative(native)
{}
CLEventCL::~CLEventCL()
{
if (mNative->getDispatch().clReleaseEvent(mNative) != CL_SUCCESS)
{
ERR() << "Error while releasing CL event";
}
}
cl_int CLEventCL::getCommandExecutionStatus(cl_int &executionStatus)
{
return mNative->getDispatch().clGetEventInfo(mNative, CL_EVENT_COMMAND_EXECUTION_STATUS,
sizeof(executionStatus), &executionStatus,
nullptr);
}
cl_int CLEventCL::setUserEventStatus(cl_int executionStatus)
{
return mNative->getDispatch().clSetUserEventStatus(mNative, executionStatus);
}
cl_int CLEventCL::setCallback(cl_int commandExecCallbackType)
{
return mNative->getDispatch().clSetEventCallback(mNative, commandExecCallbackType, Callback,
nullptr);
}
void CLEventCL::Callback(cl_event event, cl_int commandStatus, void *userData)
{
const cl::EventRefPtr evt = cl::Platform::FindEvent(
[=](const cl::EventPtr &ptr) { return ptr->getImpl<CLEventCL>().getNative() == event; });
if (evt)
{
evt->callback(commandStatus);
}
else
{
WARN() << "Callback event not found";
}
}
} // namespace rx
//
// 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.
//
// CLEventCL.h: Defines the class interface for CLEventCL, implementing CLEventImpl.
#ifndef LIBANGLE_RENDERER_CL_CLEVENTCL_H_
#define LIBANGLE_RENDERER_CL_CLEVENTCL_H_
#include "libANGLE/renderer/cl/cl_types.h"
#include "libANGLE/renderer/CLEventImpl.h"
namespace rx
{
class CLEventCL : public CLEventImpl
{
public:
CLEventCL(const cl::Event &event, cl_event native);
~CLEventCL() override;
cl_event getNative();
cl_int getCommandExecutionStatus(cl_int &executionStatus) override;
cl_int setUserEventStatus(cl_int executionStatus) override;
cl_int setCallback(cl_int commandExecCallbackType) override;
private:
static void CL_CALLBACK Callback(cl_event event, cl_int commandStatus, void *userData);
const cl_event mNative;
};
inline cl_event CLEventCL::getNative()
{
return mNative;
}
} // namespace rx
#endif // LIBANGLE_RENDERER_CL_CLEVENTCL_H_
......@@ -111,6 +111,8 @@ if (angle_enable_cl) {
"CLContextVk.h",
"CLDeviceVk.cpp",
"CLDeviceVk.h",
"CLEventVk.cpp",
"CLEventVk.h",
"CLKernelVk.cpp",
"CLKernelVk.h",
"CLMemoryVk.cpp",
......
//
// 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.
//
// CLEventVk.cpp: Implements the class methods for CLEventVk.
#include "libANGLE/renderer/vulkan/CLEventVk.h"
namespace rx
{
CLEventVk::CLEventVk(const cl::Event &event) : CLEventImpl(event) {}
CLEventVk::~CLEventVk() = default;
} // namespace rx
//
// 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.
//
// CLEventVk.h: Defines the class interface for CLEventVk, implementing CLEventImpl.
#ifndef LIBANGLE_RENDERER_VULKAN_CLEVENTVK_H_
#define LIBANGLE_RENDERER_VULKAN_CLEVENTVK_H_
#include "libANGLE/renderer/vulkan/cl_types.h"
#include "libANGLE/renderer/CLEventImpl.h"
namespace rx
{
class CLEventVk : public CLEventImpl
{
public:
CLEventVk(const cl::Event &event);
~CLEventVk() override;
};
} // namespace rx
#endif // LIBANGLE_RENDERER_VULKAN_CLEVENTVK_H_
......@@ -1004,6 +1004,33 @@ cl_int ValidateGetKernelWorkGroupInfo(cl_kernel kernel,
cl_int ValidateWaitForEvents(cl_uint num_events, const cl_event *event_list)
{
// CL_INVALID_VALUE if num_events is zero or event_list is NULL.
if (num_events == 0u || event_list == nullptr)
{
return CL_INVALID_VALUE;
}
const Context *context = nullptr;
while (num_events-- != 0u)
{
// CL_INVALID_EVENT if event objects specified in event_list are not valid event objects.
if (!Event::IsValid(*event_list))
{
return CL_INVALID_EVENT;
}
// CL_INVALID_CONTEXT if events specified in event_list do not belong to the same context.
const Context *eventContext = &static_cast<const Event *>(*event_list++)->getContext();
if (context == nullptr)
{
context = eventContext;
}
else if (context != eventContext)
{
return CL_INVALID_CONTEXT;
}
}
return CL_SUCCESS;
}
......@@ -1013,17 +1040,39 @@ cl_int ValidateGetEventInfo(cl_event event,
const void *param_value,
const size_t *param_value_size_ret)
{
// CL_INVALID_EVENT if event is a not a valid event object.
if (!Event::IsValid(event))
{
return CL_INVALID_EVENT;
}
// CL_INVALID_VALUE if param_name is not valid.
const cl_version version =
static_cast<const Event *>(event)->getContext().getPlatform().getInfo().mVersion;
switch (param_name)
{
case EventInfo::Context:
ANGLE_VALIDATE_VERSION(1, 1);
break;
case EventInfo::InvalidEnum:
return CL_INVALID_VALUE;
default:
break;
}
return CL_SUCCESS;
}
cl_int ValidateRetainEvent(cl_event event)
{
return CL_SUCCESS;
// CL_INVALID_EVENT if event is not a valid event object.
return Event::IsValid(event) ? CL_SUCCESS : CL_INVALID_EVENT;
}
cl_int ValidateReleaseEvent(cl_event event)
{
return CL_SUCCESS;
// CL_INVALID_EVENT if event is not a valid event object.
return Event::IsValid(event) ? CL_SUCCESS : CL_INVALID_EVENT;
}
cl_int ValidateGetEventProfilingInfo(cl_event event,
......@@ -1443,11 +1492,36 @@ cl_int ValidateSetMemObjectDestructorCallback(cl_mem memobj,
cl_int ValidateCreateUserEvent(cl_context context)
{
return CL_SUCCESS;
// CL_INVALID_CONTEXT if context is not a valid context.
return Context::IsValidAndVersionOrNewer(context, 1u, 1u) ? CL_SUCCESS : CL_INVALID_CONTEXT;
}
cl_int ValidateSetUserEventStatus(cl_event event, cl_int execution_status)
{
// CL_INVALID_EVENT if event is not a valid user event object.
if (!Event::IsValidAndVersionOrNewer(event, 1u, 1u))
{
return CL_INVALID_EVENT;
}
const Event &evt = *static_cast<Event *>(event);
if (evt.getCommandType() != CL_COMMAND_USER)
{
return CL_INVALID_EVENT;
}
// CL_INVALID_VALUE if the execution_status is not CL_COMPLETE or a negative integer value.
if (execution_status != CL_COMPLETE && execution_status >= 0)
{
return CL_INVALID_VALUE;
}
// CL_INVALID_OPERATION if the execution_status for event has already been changed
// by a previous call to clSetUserEventStatus.
if (evt.wasStatusChanged())
{
return CL_INVALID_OPERATION;
}
return CL_SUCCESS;
}
......@@ -1458,6 +1532,21 @@ cl_int ValidateSetEventCallback(cl_event event,
void *user_data),
const void *user_data)
{
// CL_INVALID_EVENT if event is not a valid event object.
if (!Event::IsValidAndVersionOrNewer(event, 1u, 1u))
{
return CL_INVALID_EVENT;
}
// CL_INVALID_VALUE if pfn_event_notify is NULL
// or if command_exec_callback_type is not CL_SUBMITTED, CL_RUNNING, or CL_COMPLETE.
if (pfn_notify == nullptr ||
(command_exec_callback_type != CL_SUBMITTED && command_exec_callback_type != CL_RUNNING &&
command_exec_callback_type != CL_COMPLETE))
{
return CL_INVALID_VALUE;
}
return CL_SUCCESS;
}
......
......@@ -472,6 +472,7 @@ libangle_cl_headers = [
"src/libANGLE/renderer/CLCommandQueueImpl.h",
"src/libANGLE/renderer/CLContextImpl.h",
"src/libANGLE/renderer/CLDeviceImpl.h",
"src/libANGLE/renderer/CLEventImpl.h",
"src/libANGLE/renderer/CLKernelImpl.h",
"src/libANGLE/renderer/CLMemoryImpl.h",
"src/libANGLE/renderer/CLPlatformImpl.h",
......@@ -499,6 +500,7 @@ libangle_cl_sources = [
"src/libANGLE/renderer/CLCommandQueueImpl.cpp",
"src/libANGLE/renderer/CLContextImpl.cpp",
"src/libANGLE/renderer/CLDeviceImpl.cpp",
"src/libANGLE/renderer/CLEventImpl.cpp",
"src/libANGLE/renderer/CLKernelImpl.cpp",
"src/libANGLE/renderer/CLMemoryImpl.cpp",
"src/libANGLE/renderer/CLPlatformImpl.cpp",
......
......@@ -601,8 +601,7 @@ cl_int GetKernelSubGroupInfo(cl_kernel kernel,
cl_int WaitForEvents(cl_uint num_events, const cl_event *event_list)
{
WARN_NOT_SUPPORTED(WaitForEvents);
return 0;
return static_cast<Event *>(*event_list)->getContext().waitForEvents(num_events, event_list);
}
cl_int GetEventInfo(cl_event event,
......@@ -611,32 +610,30 @@ cl_int GetEventInfo(cl_event event,
void *param_value,
size_t *param_value_size_ret)
{
WARN_NOT_SUPPORTED(GetEventInfo);
return 0;
return static_cast<Event *>(event)->getInfo(param_name, param_value_size, param_value,
param_value_size_ret);
}
cl_event CreateUserEvent(cl_context context, cl_int &errorCode)
{
WARN_NOT_SUPPORTED(CreateUserEvent);
return 0;
return static_cast<Context *>(context)->createUserEvent(errorCode);
}
cl_int RetainEvent(cl_event event)
{
WARN_NOT_SUPPORTED(RetainEvent);
return 0;
static_cast<Event *>(event)->retain();
return CL_SUCCESS;
}
cl_int ReleaseEvent(cl_event event)
{
WARN_NOT_SUPPORTED(ReleaseEvent);
return 0;
static_cast<Event *>(event)->release();
return CL_SUCCESS;
}
cl_int SetUserEventStatus(cl_event event, cl_int execution_status)
{
WARN_NOT_SUPPORTED(SetUserEventStatus);
return 0;
return static_cast<Event *>(event)->setUserEventStatus(execution_status);
}
cl_int SetEventCallback(cl_event event,
......@@ -646,8 +643,8 @@ cl_int SetEventCallback(cl_event event,
void *user_data),
void *user_data)
{
WARN_NOT_SUPPORTED(SetEventCallback);
return 0;
return static_cast<Event *>(event)->setCallback(command_exec_callback_type, pfn_notify,
user_data);
}
cl_int GetEventProfilingInfo(cl_event event,
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment