Commit 48b835cf by John Plate Committed by Commit Bot

CL: Implement context for front end and passthrough

Bug: angleproject:5904 Change-Id: I23b764bba87be3a51a1b5b44b13968fc572efde9 Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/2883773Reviewed-by: 's avatarJamie Madill <jmadill@chromium.org> Reviewed-by: 's avatarCody Northrop <cnorthrop@google.com> Commit-Queue: John Plate <jplate@google.com>
parent 39ee3640
......@@ -24,6 +24,11 @@
namespace cl
{
using ContextErrorCB = void(CL_CALLBACK *)(const char *errinfo,
const void *private_info,
size_t cb,
void *user_data);
template <typename CLObjectType>
struct Dispatch
{
......
......@@ -7,9 +7,127 @@
#include "libANGLE/CLContext.h"
#include "libANGLE/CLPlatform.h"
#include <cstring>
namespace cl
{
Context::Context(const cl_icd_dispatch &dispatch) : _cl_context(dispatch) {}
Context::~Context() = default;
bool Context::release()
{
const bool released = removeRef();
if (released)
{
mPlatform.destroyContext(this);
}
return released;
}
cl_int Context::getInfo(ContextInfo name, size_t valueSize, void *value, size_t *valueSizeRet)
{
cl_uint numDevices = 0u;
const void *copyValue = nullptr;
size_t copySize = 0u;
switch (name)
{
case ContextInfo::ReferenceCount:
copyValue = getRefCountPtr();
copySize = sizeof(*getRefCountPtr());
break;
case ContextInfo::NumDevices:
numDevices = static_cast<decltype(numDevices)>(mDevices.size());
copyValue = &numDevices;
copySize = sizeof(numDevices);
break;
case ContextInfo::Devices:
static_assert(sizeof(decltype(mDevices)::value_type) == sizeof(Device *),
"Device::RefList has wrong element size");
copyValue = mDevices.data();
copySize = mDevices.size() * sizeof(decltype(mDevices)::value_type);
break;
case ContextInfo::Properties:
copyValue = mProperties.data();
copySize = mProperties.size() * sizeof(decltype(mProperties)::value_type);
break;
default:
return CL_INVALID_VALUE;
}
if (value != nullptr)
{
if (valueSize < copySize)
{
return CL_INVALID_VALUE;
}
if (copyValue != nullptr)
{
std::memcpy(value, copyValue, copySize);
}
}
if (valueSizeRet != nullptr)
{
*valueSizeRet = copySize;
}
return CL_SUCCESS;
}
bool Context::IsValid(const Context *context)
{
const Platform::PtrList &platforms = Platform::GetPlatforms();
return std::find_if(platforms.cbegin(), platforms.cend(), [=](const Platform::Ptr &platform) {
return platform->hasContext(context);
}) != platforms.cend();
}
Context::Context(Platform &platform,
PropArray &&properties,
Device::RefList &&devices,
ContextErrorCB notify,
void *userData,
bool userSync,
cl_int *errcodeRet)
: _cl_context(platform.getDispatch()),
mPlatform(platform),
mImpl(platform.createContext(devices, ErrorCallback, this, userSync, errcodeRet)),
mProperties(std::move(properties)),
mDevices(std::move(devices)),
mNotify(notify),
mUserData(userData)
{}
Context::Context(Platform &platform,
PropArray &&properties,
cl_device_type deviceType,
ContextErrorCB notify,
void *userData,
bool userSync,
cl_int *errcodeRet)
: _cl_context(platform.getDispatch()),
mPlatform(platform),
mImpl(platform.mImpl
->createContextFromType(deviceType, ErrorCallback, this, userSync, errcodeRet)),
mProperties(std::move(properties)),
mDevices(mImpl ? platform.mapDevices(mImpl->getDevices()) : Device::RefList{}),
mNotify(notify),
mUserData(userData)
{}
void Context::ErrorCallback(const char *errinfo, const void *privateInfo, size_t cb, void *userData)
{
Context *const context = static_cast<Context *>(userData);
if (!Context::IsValid(context))
{
WARN() << "Context error for invalid context";
return;
}
if (context->mNotify != nullptr)
{
context->mNotify(errinfo, privateInfo, cb, context->mUserData);
}
}
} // namespace cl
......@@ -9,7 +9,11 @@
#ifndef LIBANGLE_CLCONTEXT_H_
#define LIBANGLE_CLCONTEXT_H_
#include "libANGLE/CLObject.h"
#include "libANGLE/CLDevice.h"
#include "libANGLE/CLRefPointer.h"
#include "libANGLE/renderer/CLContextImpl.h"
#include <list>
namespace cl
{
......@@ -17,10 +21,64 @@ namespace cl
class Context final : public _cl_context, public Object
{
public:
Context(const cl_icd_dispatch &dispatch);
~Context() = default;
using Ptr = std::unique_ptr<Context>;
using PtrList = std::list<Ptr>;
using RefPtr = RefPointer<Context>;
using PropArray = std::vector<cl_context_properties>;
~Context();
Platform &getPlatform() const noexcept;
void retain() noexcept;
bool release();
cl_int getInfo(ContextInfo name, size_t valueSize, void *value, size_t *valueSizeRet);
static bool IsValid(const Context *context);
private:
Context(Platform &platform,
PropArray &&properties,
Device::RefList &&devices,
ContextErrorCB notify,
void *userData,
bool userSync,
cl_int *errcodeRet);
Context(Platform &platform,
PropArray &&properties,
cl_device_type deviceType,
ContextErrorCB notify,
void *userData,
bool userSync,
cl_int *errcodeRet);
static void CL_CALLBACK ErrorCallback(const char *errinfo,
const void *privateInfo,
size_t cb,
void *userData);
Platform &mPlatform;
const rx::CLContextImpl::Ptr mImpl;
const PropArray mProperties;
const Device::RefList mDevices;
const ContextErrorCB mNotify;
void *const mUserData;
friend class Platform;
};
inline Platform &Context::getPlatform() const noexcept
{
return mPlatform;
}
inline void Context::retain() noexcept
{
addRef();
}
} // namespace cl
#endif // LIBANGLE_CLCONTEXT_H_
......@@ -9,6 +9,8 @@
#include "libANGLE/CLPlatform.h"
#include <cstring>
namespace cl
{
......@@ -202,7 +204,7 @@ cl_int Device::getInfo(DeviceInfo name, size_t valueSize, void *value, size_t *v
sizeof(decltype(mInfo.mMaxWorkItemSizes)::value_type);
break;
case DeviceInfo::ILsWithVersion:
if (!mInfo.mIsSupportedILsWithVersion)
if (mInfo.mVersion < CL_MAKE_VERSION(3, 0, 0))
{
return CL_INVALID_VALUE;
}
......@@ -211,7 +213,7 @@ cl_int Device::getInfo(DeviceInfo name, size_t valueSize, void *value, size_t *v
mInfo.mILsWithVersion.size() * sizeof(decltype(mInfo.mILsWithVersion)::value_type);
break;
case DeviceInfo::BuiltInKernelsWithVersion:
if (!mInfo.mIsSupportedBuiltInKernelsWithVersion)
if (mInfo.mVersion < CL_MAKE_VERSION(3, 0, 0))
{
return CL_INVALID_VALUE;
}
......@@ -220,7 +222,7 @@ cl_int Device::getInfo(DeviceInfo name, size_t valueSize, void *value, size_t *v
sizeof(decltype(mInfo.mBuiltInKernelsWithVersion)::value_type);
break;
case DeviceInfo::OpenCL_C_AllVersions:
if (!mInfo.mIsSupportedOpenCL_C_AllVersions)
if (mInfo.mVersion < CL_MAKE_VERSION(3, 0, 0))
{
return CL_INVALID_VALUE;
}
......@@ -229,7 +231,7 @@ cl_int Device::getInfo(DeviceInfo name, size_t valueSize, void *value, size_t *v
sizeof(decltype(mInfo.mOpenCL_C_AllVersions)::value_type);
break;
case DeviceInfo::OpenCL_C_Features:
if (!mInfo.mIsSupportedOpenCL_C_Features)
if (mInfo.mVersion < CL_MAKE_VERSION(3, 0, 0))
{
return CL_INVALID_VALUE;
}
......@@ -242,7 +244,7 @@ cl_int Device::getInfo(DeviceInfo name, size_t valueSize, void *value, size_t *v
copySize = mInfo.mExtensions.length() + 1u;
break;
case DeviceInfo::ExtensionsWithVersion:
if (!mInfo.mIsSupportedExtensionsWithVersion)
if (mInfo.mVersion < CL_MAKE_VERSION(3, 0, 0))
{
return CL_INVALID_VALUE;
}
......@@ -251,11 +253,19 @@ cl_int Device::getInfo(DeviceInfo name, size_t valueSize, void *value, size_t *v
sizeof(decltype(mInfo.mExtensionsWithVersion)::value_type);
break;
case DeviceInfo::PartitionProperties:
if (mInfo.mVersion < CL_MAKE_VERSION(1, 2, 0))
{
return CL_INVALID_VALUE;
}
copyValue = mInfo.mPartitionProperties.data();
copySize = mInfo.mPartitionProperties.size() *
sizeof(decltype(mInfo.mPartitionProperties)::value_type);
break;
case DeviceInfo::PartitionType:
if (mInfo.mVersion < CL_MAKE_VERSION(1, 2, 0))
{
return CL_INVALID_VALUE;
}
copyValue = mInfo.mPartitionType.data();
copySize =
mInfo.mPartitionType.size() * sizeof(decltype(mInfo.mPartitionType)::value_type);
......@@ -268,10 +278,18 @@ cl_int Device::getInfo(DeviceInfo name, size_t valueSize, void *value, size_t *v
copySize = sizeof(valPointer);
break;
case DeviceInfo::ParentDevice:
if (mInfo.mVersion < CL_MAKE_VERSION(1, 2, 0))
{
return CL_INVALID_VALUE;
}
copyValue = &mParent;
copySize = sizeof(mParent);
break;
case DeviceInfo::ReferenceCount:
if (mInfo.mVersion < CL_MAKE_VERSION(1, 2, 0))
{
return CL_INVALID_VALUE;
}
copyValue = getRefCountPtr();
copySize = sizeof(*getRefCountPtr());
break;
......@@ -312,27 +330,39 @@ cl_int Device::createSubDevices(const cl_device_partition_property *properties,
{
numDevices = 0u;
}
rx::CLDeviceImpl::InitList initList;
const cl_int result = mImpl->createSubDevices(properties, numDevices, initList, numDevicesRet);
rx::CLDeviceImpl::PtrList ptrList;
const cl_int result = mImpl->createSubDevices(properties, numDevices, ptrList, numDevicesRet);
if (result == CL_SUCCESS)
{
while (!initList.empty())
while (!ptrList.empty())
{
mSubDevices.emplace_back(new Device(mPlatform, this, initList.front()));
rx::CLDeviceImpl::Info info = ptrList.front()->createInfo();
if (!info.isValid())
{
return CL_INVALID_VALUE;
}
mSubDevices.emplace_back(
new Device(mPlatform, this, std::move(ptrList.front()), std::move(info)));
ptrList.pop_front();
*devices++ = mSubDevices.back().get();
initList.pop_front();
}
}
return result;
}
Device::PtrList Device::CreateDevices(Platform &platform, rx::CLDeviceImpl::InitList &&initList)
Device::PtrList Device::CreateDevices(Platform &platform, rx::CLDeviceImpl::PtrList &&implList)
{
PtrList devices;
while (!initList.empty())
while (!implList.empty())
{
devices.emplace_back(new Device(platform, nullptr, initList.front()));
initList.pop_front();
rx::CLDeviceImpl::Info info = implList.front()->createInfo();
if (!info.isValid())
{
return Device::PtrList{};
}
devices.emplace_back(
new Device(platform, nullptr, std::move(implList.front()), std::move(info)));
implList.pop_front();
}
return devices;
}
......@@ -345,12 +375,15 @@ bool Device::IsValid(const Device *device)
}) != platforms.cend();
}
Device::Device(Platform &platform, Device *parent, rx::CLDeviceImpl::InitData &initData)
Device::Device(Platform &platform,
Device *parent,
rx::CLDeviceImpl::Ptr &&impl,
rx::CLDeviceImpl::Info &&info)
: _cl_device_id(platform.getDispatch()),
mPlatform(platform),
mParent(parent),
mImpl(std::move(initData.first)),
mInfo(std::move(initData.second))
mImpl(std::move(impl)),
mInfo(std::move(info))
{}
void Device::destroySubDevice(Device *device)
......
......@@ -10,6 +10,7 @@
#define LIBANGLE_CLDEVICE_H_
#include "libANGLE/CLObject.h"
#include "libANGLE/CLRefPointer.h"
#include "libANGLE/renderer/CLDeviceImpl.h"
namespace cl
......@@ -20,14 +21,16 @@ class Device final : public _cl_device_id, public Object
public:
using Ptr = std::unique_ptr<Device>;
using PtrList = std::list<Ptr>;
using RefPtr = RefPointer<Device>;
using RefList = std::vector<RefPtr>;
~Device();
Platform &getPlatform() const;
bool isRoot() const;
Platform &getPlatform() const noexcept;
bool isRoot() const noexcept;
bool hasSubDevice(const Device *device) const;
void retain();
void retain() noexcept;
bool release();
cl_int getInfoULong(DeviceInfo name, cl_ulong *value) const;
......@@ -38,13 +41,16 @@ class Device final : public _cl_device_id, public Object
Device **devices,
cl_uint *numDevicesRet);
static PtrList CreateDevices(Platform &platform, rx::CLDeviceImpl::InitList &&initList);
static PtrList CreateDevices(Platform &platform, rx::CLDeviceImpl::PtrList &&implList);
static bool IsValid(const Device *device);
static bool IsValidType(cl_device_type type);
private:
Device(Platform &platform, Device *parent, rx::CLDeviceImpl::InitData &initData);
Device(Platform &platform,
Device *parent,
rx::CLDeviceImpl::Ptr &&impl,
rx::CLDeviceImpl::Info &&info);
void destroySubDevice(Device *device);
......@@ -54,14 +60,16 @@ class Device final : public _cl_device_id, public Object
const rx::CLDeviceImpl::Info mInfo;
PtrList mSubDevices;
friend class Platform;
};
inline Platform &Device::getPlatform() const
inline Platform &Device::getPlatform() const noexcept
{
return mPlatform;
}
inline bool Device::isRoot() const
inline bool Device::isRoot() const noexcept
{
return mParent == nullptr;
}
......@@ -73,7 +81,7 @@ inline bool Device::hasSubDevice(const Device *device) const
}) != mSubDevices.cend();
}
inline void Device::retain()
inline void Device::retain() noexcept
{
if (!isRoot())
{
......
......@@ -20,17 +20,28 @@ class Object
public:
// This class cannot be virtual as its derived classes need to have standard layout
Object() = default;
~Object() { ASSERT(mRefCount == 0u); }
~Object()
{
if (mRefCount != 0u)
{
WARN() << "Deleted object with references";
}
}
cl_uint getRefCount() { return mRefCount; }
const cl_uint *getRefCountPtr() { return &mRefCount; }
protected:
void addRef() { ++mRefCount; }
void addRef() noexcept { ++mRefCount; }
bool removeRef()
{
ASSERT(mRefCount > 0u);
if (mRefCount == 0u)
{
WARN() << "Unreferenced object without references";
return true;
}
return --mRefCount == 0u;
}
......
......@@ -30,7 +30,33 @@ Platform::~Platform()
removeRef();
}
cl_int Platform::getInfo(PlatformInfo name, size_t valueSize, void *value, size_t *sizeRet)
Device::RefList Platform::mapDevices(const rx::CLDeviceImpl::List &deviceImplList) const
{
Device::RefList devices;
for (rx::CLDeviceImpl *impl : deviceImplList)
{
auto it = mDevices.cbegin();
while (it != mDevices.cend() && (*it)->mImpl.get() != impl)
{
++it;
}
if (it != mDevices.cend())
{
devices.emplace_back(it->get());
}
else
{
ERR() << "Device not found in platform list";
}
}
if (devices.size() != deviceImplList.size())
{
devices.clear();
}
return devices;
}
cl_int Platform::getInfo(PlatformInfo name, size_t valueSize, void *value, size_t *valueSizeRet)
{
const void *copyValue = nullptr;
size_t copySize = 0u;
......@@ -46,6 +72,10 @@ cl_int Platform::getInfo(PlatformInfo name, size_t valueSize, void *value, size_
copySize = mInfo.mVersionStr.length() + 1u;
break;
case PlatformInfo::NumericVersion:
if (mInfo.mVersion < CL_MAKE_VERSION(3, 0, 0))
{
return CL_INVALID_VALUE;
}
copyValue = &mInfo.mVersion;
copySize = sizeof(mInfo.mVersion);
break;
......@@ -62,7 +92,7 @@ cl_int Platform::getInfo(PlatformInfo name, size_t valueSize, void *value, size_
copySize = mInfo.mExtensions.length() + 1u;
break;
case PlatformInfo::ExtensionsWithVersion:
if (mInfo.mExtensionsWithVersion.empty())
if (mInfo.mVersion < CL_MAKE_VERSION(3, 0, 0))
{
return CL_INVALID_VALUE;
}
......@@ -71,6 +101,10 @@ cl_int Platform::getInfo(PlatformInfo name, size_t valueSize, void *value, size_
sizeof(decltype(mInfo.mExtensionsWithVersion)::value_type);
break;
case PlatformInfo::HostTimerResolution:
if (mInfo.mVersion < CL_MAKE_VERSION(2, 1, 0))
{
return CL_INVALID_VALUE;
}
copyValue = &mInfo.mHostTimerRes;
copySize = sizeof(mInfo.mHostTimerRes);
break;
......@@ -93,9 +127,9 @@ cl_int Platform::getInfo(PlatformInfo name, size_t valueSize, void *value, size_
std::memcpy(value, copyValue, copySize);
}
}
if (sizeRet != nullptr)
if (valueSizeRet != nullptr)
{
*sizeRet = copySize;
*valueSizeRet = copySize;
}
return CL_SUCCESS;
}
......@@ -126,27 +160,96 @@ cl_int Platform::getDeviceIDs(cl_device_type deviceType,
return found == 0u ? CL_DEVICE_NOT_FOUND : CL_SUCCESS;
}
Context *Platform::createContext(Context::PropArray &&properties,
cl_uint numDevices,
Device *const *devices,
ContextErrorCB notify,
void *userData,
bool userSync,
cl_int *errcodeRet)
{
Device::RefList refDevices;
while (numDevices-- != 0u)
{
refDevices.emplace_back(*devices++);
}
mContexts.emplace_back(new Context(*this, std::move(properties), std::move(refDevices), notify,
userData, userSync, errcodeRet));
if (!mContexts.back()->mImpl)
{
mContexts.back()->release();
return nullptr;
}
return mContexts.back().get();
}
Context *Platform::createContextFromType(Context::PropArray &&properties,
cl_device_type deviceType,
ContextErrorCB notify,
void *userData,
bool userSync,
cl_int *errcodeRet)
{
mContexts.emplace_back(new Context(*this, std::move(properties), deviceType, notify, userData,
userSync, errcodeRet));
if (!mContexts.back()->mImpl || mContexts.back()->mDevices.empty())
{
mContexts.back()->release();
return nullptr;
}
return mContexts.back().get();
}
void Platform::CreatePlatform(const cl_icd_dispatch &dispatch,
rx::CLPlatformImpl::InitData &initData)
{
rx::CLDeviceImpl::InitList deviceInitList = initData.first->getDevices();
if (!deviceInitList.empty())
Ptr platform(new Platform(dispatch, initData));
if (!platform->mDevices.empty())
{
GetList().emplace_back(new Platform(dispatch, initData, std::move(deviceInitList)));
GetList().emplace_back(std::move(platform));
}
}
Platform::Platform(const cl_icd_dispatch &dispatch,
rx::CLPlatformImpl::InitData &initData,
rx::CLDeviceImpl::InitList &&deviceInitList)
Platform::Platform(const cl_icd_dispatch &dispatch, rx::CLPlatformImpl::InitData &initData)
: _cl_platform_id(dispatch),
mImpl(std::move(initData.first)),
mInfo(std::move(initData.second)),
mDevices(Device::CreateDevices(*this, std::move(deviceInitList)))
mImpl(std::move(std::get<0>(initData))),
mInfo(std::move(std::get<1>(initData))),
mDevices(Device::CreateDevices(*this, std::move(std::get<2>(initData))))
{
ASSERT(isCompatible(this));
}
rx::CLContextImpl::Ptr Platform::createContext(const Device::RefList &devices,
ContextErrorCB notify,
void *userData,
bool userSync,
cl_int *errcodeRet)
{
rx::CLDeviceImpl::List deviceImplList;
for (const Device::RefPtr &device : devices)
{
deviceImplList.emplace_back(device->mImpl.get());
}
return mImpl->createContext(std::move(deviceImplList), notify, userData, userSync, errcodeRet);
}
void Platform::destroyContext(Context *context)
{
auto contextIt = mContexts.cbegin();
while (contextIt != mContexts.cend() && contextIt->get() != context)
{
++contextIt;
}
if (contextIt != mContexts.cend())
{
mContexts.erase(contextIt);
}
else
{
ERR() << "Context not found";
}
}
constexpr char Platform::kVendor[];
constexpr char Platform::kIcdSuffix[];
......
......@@ -9,6 +9,7 @@
#ifndef LIBANGLE_CLPLATFORM_H_
#define LIBANGLE_CLPLATFORM_H_
#include "libANGLE/CLContext.h"
#include "libANGLE/CLDevice.h"
#include "libANGLE/renderer/CLPlatformImpl.h"
......@@ -27,14 +28,32 @@ class Platform final : public _cl_platform_id, public Object
bool hasDevice(const Device *device) const;
const Device::PtrList &getDevices() const;
Device::RefList mapDevices(const rx::CLDeviceImpl::List &deviceImplList) const;
cl_int getInfo(PlatformInfo name, size_t valueSize, void *value, size_t *sizeRet);
bool hasContext(const Context *context) const;
cl_int getInfo(PlatformInfo name, size_t valueSize, void *value, size_t *valueSizeRet);
cl_int getDeviceIDs(cl_device_type deviceType,
cl_uint numEntries,
Device **devices,
cl_uint *numDevices) const;
Context *createContext(Context::PropArray &&properties,
cl_uint numDevices,
Device *const *devices,
ContextErrorCB notify,
void *userData,
bool userSync,
cl_int *errcodeRet);
Context *createContextFromType(Context::PropArray &&properties,
cl_device_type deviceType,
ContextErrorCB notify,
void *userData,
bool userSync,
cl_int *errcodeRet);
static void CreatePlatform(const cl_icd_dispatch &dispatch,
rx::CLPlatformImpl::InitData &initData);
static const PtrList &GetPlatforms();
......@@ -45,9 +64,15 @@ class Platform final : public _cl_platform_id, public Object
static constexpr const char *GetVendor();
private:
Platform(const cl_icd_dispatch &dispatch,
rx::CLPlatformImpl::InitData &initData,
rx::CLDeviceImpl::InitList &&deviceInitList);
Platform(const cl_icd_dispatch &dispatch, rx::CLPlatformImpl::InitData &initData);
rx::CLContextImpl::Ptr createContext(const Device::RefList &devices,
ContextErrorCB notify,
void *userData,
bool userSync,
cl_int *errcodeRet);
void destroyContext(Context *context);
static PtrList &GetList();
......@@ -55,8 +80,12 @@ class Platform final : public _cl_platform_id, public Object
const rx::CLPlatformImpl::Info mInfo;
const Device::PtrList mDevices;
Context::PtrList mContexts;
static constexpr char kVendor[] = "ANGLE";
static constexpr char kIcdSuffix[] = "ANGLE";
friend class Context;
};
inline bool Platform::hasDevice(const Device *device) const
......@@ -71,6 +100,13 @@ inline const Device::PtrList &Platform::getDevices() const
return mDevices;
}
inline bool Platform::hasContext(const Context *context) const
{
return std::find_if(mContexts.cbegin(), mContexts.cend(), [=](const Context::Ptr &ptr) {
return ptr.get() == context;
}) != mContexts.cend();
}
inline Platform::PtrList &Platform::GetList()
{
static angle::base::NoDestructor<PtrList> sList;
......
//
// 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.
//
// CLRefPointer.h: A non-owning intrinsic reference counting smart pointer for CL objects.
#ifndef LIBANGLE_CLREFPOINTER_H_
#define LIBANGLE_CLREFPOINTER_H_
#include "libANGLE/CLtypes.h"
#include "libANGLE/Debug.h"
#include <algorithm>
namespace cl
{
template <typename T>
class RefPointer
{
public:
RefPointer() noexcept : mCLObject(nullptr) {}
explicit RefPointer(T *object) noexcept : mCLObject(object)
{
if (mCLObject != nullptr)
{
mCLObject->retain();
}
}
~RefPointer()
{
if (mCLObject != nullptr)
{
mCLObject->release();
}
}
RefPointer(std::nullptr_t) noexcept : mCLObject(nullptr) {}
RefPointer &operator=(std::nullptr_t)
{
reset();
return *this;
}
RefPointer(RefPointer &&other) noexcept : mCLObject(nullptr) { other.swap(*this); }
RefPointer &operator=(RefPointer &&other)
{
other.swap(this);
return *this;
}
RefPointer(const RefPointer<T> &other) : mCLObject(other.mCLObject)
{
if (mCLObject != nullptr)
{
mCLObject->retain();
}
}
RefPointer &operator=(const RefPointer<T> &other)
{
if (this != &other)
{
reset();
mCLObject = other.mCLObject;
if (mCLObject != nullptr)
{
mCLObject->retain();
}
}
return *this;
}
T *operator->() const { return mCLObject; }
T &operator*() const { return *mCLObject; }
T *get() const { return mCLObject; }
explicit operator bool() const { return mCLObject != nullptr; }
T *release() noexcept
{
T *const object = mCLObject;
mCLObject = nullptr;
return object;
}
void swap(RefPointer &other) noexcept { std::swap(mCLObject, other.mCLObject); }
void reset()
{
if (mCLObject != nullptr)
{
T *const object = release();
object->release();
}
}
private:
T *mCLObject;
};
template <typename T>
void swap(RefPointer<T> &left, RefPointer<T> &right)
{
left.swap(right);
}
} // namespace cl
#endif // LIBANGLE_CLREFPOINTER_H_
//
// 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.
//
// CLContextImpl.cpp: Implements the class methods for CLContextImpl.
#include "libANGLE/renderer/CLContextImpl.h"
#include "libANGLE/renderer/CLPlatformImpl.h"
#include "libANGLE/Debug.h"
namespace rx
{
CLContextImpl::CLContextImpl(CLPlatformImpl &platform, CLDeviceImpl::List &&devices)
: mPlatform(platform), mDevices(std::move(devices))
{}
CLContextImpl::~CLContextImpl()
{
auto it = std::find(mPlatform.mContexts.cbegin(), mPlatform.mContexts.cend(), this);
if (it != mPlatform.mContexts.cend())
{
mPlatform.mContexts.erase(it);
}
else
{
ERR() << "Context not in platform's list";
}
}
} // namespace rx
......@@ -3,13 +3,12 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//
// CLContextImpl.h: Defines the abstract rx::CLContextImpl class.
#ifndef LIBANGLE_RENDERER_CLCONTEXTIMPL_H_
#define LIBANGLE_RENDERER_CLCONTEXTIMPL_H_
#include "libANGLE/renderer/CLtypes.h"
#include "libANGLE/renderer/CLDeviceImpl.h"
namespace rx
{
......@@ -17,10 +16,30 @@ namespace rx
class CLContextImpl : angle::NonCopyable
{
public:
CLContextImpl() {}
virtual ~CLContextImpl() {}
using Ptr = std::unique_ptr<CLContextImpl>;
using List = std::list<CLContextImpl *>;
CLContextImpl(CLPlatformImpl &platform, CLDeviceImpl::List &&devices);
virtual ~CLContextImpl();
template <typename T>
T &getPlatform() const
{
return static_cast<T &>(mPlatform);
}
const CLDeviceImpl::List &getDevices() const;
protected:
CLPlatformImpl &mPlatform;
const CLDeviceImpl::List mDevices;
};
inline const CLDeviceImpl::List &CLContextImpl::getDevices() const
{
return mDevices;
}
} // namespace rx
#endif // LIBANGLE_RENDERER_CLCONTEXTIMPL_H_
......@@ -7,6 +7,8 @@
#include "libANGLE/renderer/CLDeviceImpl.h"
#include "libANGLE/Debug.h"
namespace rx
{
......@@ -18,14 +20,24 @@ CLDeviceImpl::Info::Info(Info &&) = default;
CLDeviceImpl::Info &CLDeviceImpl::Info::operator=(Info &&) = default;
bool CLDeviceImpl::Info::isValid() const
CLDeviceImpl::CLDeviceImpl(CLPlatformImpl &platform, CLDeviceImpl *parent)
: mPlatform(platform), mParent(parent)
{}
CLDeviceImpl::~CLDeviceImpl()
{
// From the OpenCL specification for info name CL_DEVICE_MAX_WORK_ITEM_SIZES:
// "The minimum value is (1, 1, 1) for devices that are not of type CL_DEVICE_TYPE_CUSTOM."
// https://www.khronos.org/registry/OpenCL/specs/3.0-unified/html/OpenCL_API.html#clGetDeviceInfo
// Custom devices are currently not supported by ANGLE back ends.
return mMaxWorkItemSizes.size() >= 3u && mMaxWorkItemSizes[0] >= 1u &&
mMaxWorkItemSizes[1] >= 1u && mMaxWorkItemSizes[2] >= 1u;
if (mParent != nullptr)
{
auto it = std::find(mParent->mSubDevices.cbegin(), mParent->mSubDevices.cend(), this);
if (it != mParent->mSubDevices.cend())
{
mParent->mSubDevices.erase(it);
}
else
{
ERR() << "Sub-device not in parent's list";
}
}
}
} // namespace rx
......@@ -27,8 +27,9 @@ class CLDeviceImpl : angle::NonCopyable
Info(Info &&);
Info &operator=(Info &&);
bool isValid() const;
bool isValid() const { return mVersion != 0u; }
cl_version mVersion = 0u;
std::vector<size_t> mMaxWorkItemSizes;
NameVersionVector mILsWithVersion;
NameVersionVector mBuiltInKernelsWithVersion;
......@@ -38,20 +39,22 @@ class CLDeviceImpl : angle::NonCopyable
NameVersionVector mExtensionsWithVersion;
std::vector<cl_device_partition_property> mPartitionProperties;
std::vector<cl_device_partition_property> mPartitionType;
bool mIsSupportedILsWithVersion = false;
bool mIsSupportedBuiltInKernelsWithVersion = false;
bool mIsSupportedOpenCL_C_AllVersions = false;
bool mIsSupportedOpenCL_C_Features = false;
bool mIsSupportedExtensionsWithVersion = false;
};
using Ptr = std::unique_ptr<CLDeviceImpl>;
using InitData = std::pair<Ptr, Info>;
using InitList = std::list<InitData>;
using Ptr = std::unique_ptr<CLDeviceImpl>;
using PtrList = std::list<Ptr>;
using List = std::list<CLDeviceImpl *>;
CLDeviceImpl(CLPlatformImpl &platform, CLDeviceImpl *parent);
virtual ~CLDeviceImpl();
template <typename T>
T &getPlatform() const
{
return static_cast<T &>(mPlatform);
}
CLDeviceImpl() = default;
virtual ~CLDeviceImpl() = default;
virtual Info createInfo() const = 0;
virtual cl_int getInfoUInt(cl::DeviceInfo name, cl_uint *value) const = 0;
virtual cl_int getInfoULong(cl::DeviceInfo name, cl_ulong *value) const = 0;
......@@ -61,8 +64,14 @@ class CLDeviceImpl : angle::NonCopyable
virtual cl_int createSubDevices(const cl_device_partition_property *properties,
cl_uint numDevices,
InitList &deviceInitList,
PtrList &implList,
cl_uint *numDevicesRet) = 0;
protected:
CLPlatformImpl &mPlatform;
CLDeviceImpl *const mParent;
List mSubDevices;
};
} // namespace rx
......
......@@ -18,9 +18,8 @@ CLPlatformImpl::Info::Info(Info &&) = default;
CLPlatformImpl::Info &CLPlatformImpl::Info::operator=(Info &&) = default;
bool CLPlatformImpl::Info::isValid() const
{
return !mProfile.empty();
}
CLPlatformImpl::CLPlatformImpl(CLDeviceImpl::List &&devices) : mDevices(std::move(devices)) {}
CLPlatformImpl::~CLPlatformImpl() = default;
} // namespace rx
......@@ -8,8 +8,11 @@
#ifndef LIBANGLE_RENDERER_CLPLATFORMIMPL_H_
#define LIBANGLE_RENDERER_CLPLATFORMIMPL_H_
#include "libANGLE/renderer/CLContextImpl.h"
#include "libANGLE/renderer/CLDeviceImpl.h"
#include <tuple>
namespace rx
{
......@@ -27,27 +30,51 @@ class CLPlatformImpl : angle::NonCopyable
Info(Info &&);
Info &operator=(Info &&);
bool isValid() const;
bool isValid() const { return mVersion != 0u; }
std::string mProfile;
std::string mVersionStr;
cl_version mVersion;
cl_version mVersion = 0u;
std::string mName;
std::string mExtensions;
NameVersionVector mExtensionsWithVersion;
cl_ulong mHostTimerRes;
cl_ulong mHostTimerRes = 0u;
};
using Ptr = std::unique_ptr<CLPlatformImpl>;
using InitData = std::pair<Ptr, Info>;
using InitData = std::tuple<Ptr, Info, CLDeviceImpl::PtrList>;
using InitList = std::list<InitData>;
CLPlatformImpl() = default;
virtual ~CLPlatformImpl() = default;
explicit CLPlatformImpl(CLDeviceImpl::List &&devices);
virtual ~CLPlatformImpl();
const CLDeviceImpl::List &getDevices() const;
virtual CLContextImpl::Ptr createContext(CLDeviceImpl::List &&devices,
cl::ContextErrorCB notify,
void *userData,
bool userSync,
cl_int *errcodeRet) = 0;
virtual CLContextImpl::Ptr createContextFromType(cl_device_type deviceType,
cl::ContextErrorCB notify,
void *userData,
bool userSync,
cl_int *errcodeRet) = 0;
virtual CLDeviceImpl::InitList getDevices() = 0;
protected:
const CLDeviceImpl::List mDevices;
CLContextImpl::List mContexts;
friend class CLContextImpl;
};
inline const CLDeviceImpl::List &CLPlatformImpl::getDevices() const
{
return mDevices;
}
} // namespace rx
#endif // LIBANGLE_RENDERER_CLPLATFORMIMPL_H_
......@@ -15,6 +15,7 @@ _cl_backend_sources = [
"CLDeviceCL.h",
"CLPlatformCL.cpp",
"CLPlatformCL.h",
"cl_types.h",
"cl_util.cpp",
"cl_util.h",
]
......
......@@ -3,17 +3,27 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//
// CLContextCL.cpp:
// Implements the class methods for CLContextCL.
//
// CLContextCL.cpp: Implements the class methods for CLContextCL.
#include "libANGLE/renderer/cl/CLContextCL.h"
#include "libANGLE/renderer/cl/CLPlatformCL.h"
#include "libANGLE/Debug.h"
namespace rx
{
CLContextCL::CLContextCL() {}
CLContextCL::CLContextCL(CLPlatformCL &platform, CLDeviceImpl::List &&devices, cl_context context)
: CLContextImpl(platform, std::move(devices)), mContext(context)
{}
CLContextCL::~CLContextCL() {}
CLContextCL::~CLContextCL()
{
if (mContext->getDispatch().clReleaseContext(mContext) != CL_SUCCESS)
{
ERR() << "Error while releasing CL context";
}
}
} // namespace rx
......@@ -3,13 +3,13 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//
// CLContextCL.h:
// Defines the class interface for CLContextCL, implementing CLContextImpl.
//
// CLContextCL.h: Defines the class interface for CLContextCL, implementing CLContextImpl.
#ifndef LIBANGLE_RENDERER_CL_CLCONTEXTCL_H_
#define LIBANGLE_RENDERER_CL_CLCONTEXTCL_H_
#include "libANGLE/renderer/cl/cl_types.h"
#include "libANGLE/renderer/CLContextImpl.h"
namespace rx
......@@ -18,8 +18,11 @@ namespace rx
class CLContextCL : public CLContextImpl
{
public:
CLContextCL();
CLContextCL(CLPlatformCL &platform, CLDeviceImpl::List &&devices, cl_context context);
~CLContextCL() override;
private:
const cl_context mContext;
};
} // namespace rx
......
......@@ -8,6 +8,8 @@
#ifndef LIBANGLE_RENDERER_CL_CLDEVICECL_H_
#define LIBANGLE_RENDERER_CL_CLDEVICECL_H_
#include "libANGLE/renderer/cl/cl_types.h"
#include "libANGLE/renderer/CLDeviceImpl.h"
namespace rx
......@@ -20,6 +22,8 @@ class CLDeviceCL : public CLDeviceImpl
cl_device_id getNative();
Info createInfo() const override;
cl_int getInfoUInt(cl::DeviceInfo name, cl_uint *value) const override;
cl_int getInfoULong(cl::DeviceInfo name, cl_ulong *value) const override;
cl_int getInfoSizeT(cl::DeviceInfo name, size_t *value) const override;
......@@ -28,14 +32,13 @@ class CLDeviceCL : public CLDeviceImpl
cl_int createSubDevices(const cl_device_partition_property *properties,
cl_uint numDevices,
InitList &deviceInitList,
PtrList &implList,
cl_uint *numDevicesRet) override;
static CLDeviceCL *Create(cl_device_id device);
static Info GetInfo(cl_device_id device);
static CLDeviceCL *Create(CLPlatformCL &platform, CLDeviceCL *parent, cl_device_id device);
private:
CLDeviceCL(cl_device_id device, cl_version version);
CLDeviceCL(CLPlatformCL &platform, CLDeviceCL *parent, cl_device_id device, cl_version version);
const cl_device_id mDevice;
const cl_version mVersion;
......
......@@ -20,16 +20,29 @@ class CLPlatformCL : public CLPlatformImpl
cl_platform_id getNative();
CLDeviceImpl::InitList getDevices() override;
CLContextImpl::Ptr createContext(CLDeviceImpl::List &&deviceImplList,
cl::ContextErrorCB notify,
void *userData,
bool userSync,
cl_int *errcodeRet) override;
CLContextImpl::Ptr createContextFromType(cl_device_type deviceType,
cl::ContextErrorCB notify,
void *userData,
bool userSync,
cl_int *errcodeRet) override;
static InitList GetPlatforms(bool isIcd);
private:
explicit CLPlatformCL(cl_platform_id platform);
CLPlatformCL(cl_platform_id platform, cl_version version, CLDeviceImpl::PtrList &devices);
static Info GetInfo(cl_platform_id platform);
const cl_platform_id mPlatform;
const cl_version mVersion;
friend class CLContextCL;
};
inline cl_platform_id CLPlatformCL::getNative()
......
//
// 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.
//
// cl_types.h: Defines common types for the OpenCL pass-through back end.
#ifndef LIBANGLE_RENDERER_CL_CL_TYPES_H_
#define LIBANGLE_RENDERER_CL_CL_TYPES_H_
#include "libANGLE/renderer/CLtypes.h"
namespace rx
{
class CLContextCL;
class CLDeviceCL;
class CLPlatformCL;
} // namespace rx
#endif // LIBANGLE_RENDERER_CL_CL_TYPES_H_
......@@ -111,6 +111,7 @@ if (angle_enable_cl) {
"CLDeviceVk.h",
"CLPlatformVk.cpp",
"CLPlatformVk.h",
"cl_types.h",
]
}
......
......@@ -3,16 +3,18 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//
// CLContextVk.cpp:
// Implements the class methods for CLContextVk.
//
// CLContextVk.cpp: Implements the class methods for CLContextVk.
#include "libANGLE/renderer/vulkan/CLContextVk.h"
#include "libANGLE/renderer/vulkan/CLPlatformVk.h"
namespace rx
{
CLContextVk::CLContextVk() {}
CLContextVk::CLContextVk(CLPlatformVk &platform, CLDeviceImpl::List &&devices)
: CLContextImpl(platform, std::move(devices))
{}
CLContextVk::~CLContextVk() = default;
......
......@@ -3,13 +3,13 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//
// CLContextVk.h:
// Defines the class interface for CLContextVk, implementing CLContextImpl.
//
// CLContextVk.h: Defines the class interface for CLContextVk, implementing CLContextImpl.
#ifndef LIBANGLE_RENDERER_VULKAN_CLCONTEXTVK_H_
#define LIBANGLE_RENDERER_VULKAN_CLCONTEXTVK_H_
#include "libANGLE/renderer/vulkan/cl_types.h"
#include "libANGLE/renderer/CLContextImpl.h"
namespace rx
......@@ -18,7 +18,7 @@ namespace rx
class CLContextVk : public CLContextImpl
{
public:
CLContextVk();
CLContextVk(CLPlatformVk &platform, CLDeviceImpl::List &&devices);
~CLContextVk() override;
};
......
......@@ -7,13 +7,22 @@
#include "libANGLE/renderer/vulkan/CLDeviceVk.h"
#include "libANGLE/renderer/vulkan/CLPlatformVk.h"
namespace rx
{
CLDeviceVk::CLDeviceVk() = default;
CLDeviceVk::CLDeviceVk(CLPlatformVk &platform, CLDeviceVk *parent) : CLDeviceImpl(platform, parent)
{}
CLDeviceVk::~CLDeviceVk() = default;
CLDeviceImpl::Info CLDeviceVk::createInfo() const
{
CLDeviceImpl::Info info;
return info;
}
cl_int CLDeviceVk::getInfoUInt(cl::DeviceInfo name, cl_uint *value) const
{
return CL_INVALID_VALUE;
......@@ -41,16 +50,10 @@ cl_int CLDeviceVk::getInfoString(cl::DeviceInfo name, size_t size, char *value)
cl_int CLDeviceVk::createSubDevices(const cl_device_partition_property *properties,
cl_uint numDevices,
InitList &deviceInitList,
PtrList &deviceImplList,
cl_uint *numDevicesRet)
{
return CL_INVALID_VALUE;
}
CLDeviceImpl::Info CLDeviceVk::GetInfo()
{
CLDeviceImpl::Info info;
return info;
}
} // namespace rx
......@@ -8,6 +8,8 @@
#ifndef LIBANGLE_RENDERER_VULKAN_CLDEVICEVK_H_
#define LIBANGLE_RENDERER_VULKAN_CLDEVICEVK_H_
#include "libANGLE/renderer/vulkan/cl_types.h"
#include "libANGLE/renderer/CLDeviceImpl.h"
namespace rx
......@@ -16,9 +18,11 @@ namespace rx
class CLDeviceVk : public CLDeviceImpl
{
public:
CLDeviceVk();
CLDeviceVk(CLPlatformVk &platform, CLDeviceVk *parent);
~CLDeviceVk() override;
Info createInfo() const override;
cl_int getInfoUInt(cl::DeviceInfo name, cl_uint *value) const override;
cl_int getInfoULong(cl::DeviceInfo name, cl_ulong *value) const override;
cl_int getInfoSizeT(cl::DeviceInfo name, size_t *value) const override;
......@@ -27,10 +31,8 @@ class CLDeviceVk : public CLDeviceImpl
cl_int createSubDevices(const cl_device_partition_property *properties,
cl_uint numDevices,
InitList &deviceInitList,
PtrList &deviceImplList,
cl_uint *numDevicesRet) override;
static Info GetInfo();
};
} // namespace rx
......
......@@ -31,19 +31,35 @@ std::string CreateExtensionString(const NameVersionVector &extList)
}
return extensions;
}
} // anonymous namespace
CLDeviceImpl::List CreateDevices(CLPlatformVk &platform, CLDeviceImpl::PtrList &implList)
{
implList.emplace_back(new CLDeviceVk(platform, nullptr));
return CLDeviceImpl::List(1u, implList.back().get());
}
} // namespace
CLPlatformVk::~CLPlatformVk() = default;
CLDeviceImpl::InitList CLPlatformVk::getDevices()
CLContextImpl::Ptr CLPlatformVk::createContext(CLDeviceImpl::List &&deviceImplList,
cl::ContextErrorCB notify,
void *userData,
bool userSync,
cl_int *errcodeRet)
{
CLDeviceImpl::InitList initList;
CLDeviceImpl::Info info = CLDeviceVk::GetInfo();
if (info.isValid())
{
initList.emplace_back(new CLDeviceVk(), std::move(info));
}
return initList;
CLContextImpl::Ptr contextImpl;
return contextImpl;
}
CLContextImpl::Ptr CLPlatformVk::createContextFromType(cl_device_type deviceType,
cl::ContextErrorCB notify,
void *userData,
bool userSync,
cl_int *errcodeRet)
{
CLContextImpl::Ptr contextImpl;
return contextImpl;
}
CLPlatformVk::InitList CLPlatformVk::GetPlatforms()
......@@ -62,7 +78,15 @@ CLPlatformVk::InitList CLPlatformVk::GetPlatforms()
info.mHostTimerRes = 0u;
InitList initList;
initList.emplace_back(new CLPlatformVk, std::move(info));
if (info.isValid())
{
CLDeviceImpl::PtrList devices;
Ptr platform(new CLPlatformVk(devices));
if (!devices.empty())
{
initList.emplace_back(std::move(platform), std::move(info), std::move(devices));
}
}
return initList;
}
......@@ -74,6 +98,8 @@ const std::string &CLPlatformVk::GetVersionString()
return *sVersion;
}
CLPlatformVk::CLPlatformVk() = default;
CLPlatformVk::CLPlatformVk(CLDeviceImpl::PtrList &devices)
: CLPlatformImpl(CreateDevices(*this, devices))
{}
} // namespace rx
......@@ -20,14 +20,24 @@ class CLPlatformVk : public CLPlatformImpl
public:
~CLPlatformVk() override;
CLDeviceImpl::InitList getDevices() override;
CLContextImpl::Ptr createContext(CLDeviceImpl::List &&deviceImplList,
cl::ContextErrorCB notify,
void *userData,
bool userSync,
cl_int *errcodeRet) override;
CLContextImpl::Ptr createContextFromType(cl_device_type deviceType,
cl::ContextErrorCB notify,
void *userData,
bool userSync,
cl_int *errcodeRet) override;
static InitList GetPlatforms();
static constexpr cl_version GetVersion();
static const std::string &GetVersionString();
private:
CLPlatformVk();
explicit CLPlatformVk(CLDeviceImpl::PtrList &devices);
};
constexpr cl_version CLPlatformVk::GetVersion()
......
//
// 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.
//
// cl_types.h: Defines common types for the OpenCL Vulkan back end.
#ifndef LIBANGLE_RENDERER_VULKAN_CL_TYPES_H_
#define LIBANGLE_RENDERER_VULKAN_CL_TYPES_H_
#include "libANGLE/renderer/CLtypes.h"
namespace rx
{
class CLContextVk;
class CLDeviceVk;
class CLPlatformVk;
} // namespace rx
#endif // LIBANGLE_RENDERER_VULKAN_CL_TYPES_H_
......@@ -7,8 +7,66 @@
#include "libANGLE/validationCL_autogen.h"
#define ANGLE_ERROR_RETURN(error, ret) \
if (errcode_ret != nullptr) \
{ \
*errcode_ret = error; \
} \
return ret
namespace cl
{
namespace
{
Platform *ValidateContextProperties(const cl_context_properties *properties, cl_int *errcode_ret)
{
Platform *platform = nullptr;
bool hasUserSync = false;
if (properties != nullptr)
{
while (*properties != 0)
{
switch (*properties++)
{
case CL_CONTEXT_PLATFORM:
if (platform != nullptr)
{
ANGLE_ERROR_RETURN(CL_INVALID_PROPERTY, nullptr);
}
platform = reinterpret_cast<Platform *>(*properties++);
if (!Platform::IsValid(platform))
{
ANGLE_ERROR_RETURN(CL_INVALID_PLATFORM, nullptr);
}
break;
case CL_CONTEXT_INTEROP_USER_SYNC:
if (hasUserSync || (*properties != CL_FALSE && *properties != CL_TRUE))
{
ANGLE_ERROR_RETURN(CL_INVALID_PROPERTY, nullptr);
}
++properties;
hasUserSync = true;
break;
default:
ANGLE_ERROR_RETURN(CL_INVALID_PROPERTY, nullptr);
}
}
}
if (platform == nullptr)
{
platform = Platform::GetDefault();
if (platform == nullptr)
{
ANGLE_ERROR_RETURN(CL_INVALID_PLATFORM, nullptr);
}
}
return platform;
}
} // namespace
// CL 1.0
cl_int ValidateGetPlatformIDs(cl_uint num_entries,
Platform *const *platforms,
......@@ -80,7 +138,7 @@ cl_int ValidateGetDeviceInfo(const Device *device,
bool ValidateCreateContext(const cl_context_properties *properties,
cl_uint num_devices,
Device *const *devicesPacked,
Device *const *devices,
void(CL_CALLBACK *pfn_notify)(const char *errinfo,
const void *private_info,
size_t cb,
......@@ -88,6 +146,23 @@ bool ValidateCreateContext(const cl_context_properties *properties,
const void *user_data,
cl_int *errcode_ret)
{
Platform *platform = ValidateContextProperties(properties, errcode_ret);
if (platform == nullptr)
{
return false;
}
if (num_devices == 0u || devices == nullptr || (pfn_notify == nullptr && user_data != nullptr))
{
ANGLE_ERROR_RETURN(CL_INVALID_VALUE, false);
}
while (num_devices-- > 0u)
{
if (!platform->hasDevice(*devices++))
{
ANGLE_ERROR_RETURN(CL_INVALID_DEVICE, false);
}
}
return true;
}
......@@ -100,25 +175,47 @@ bool ValidateCreateContextFromType(const cl_context_properties *properties,
const void *user_data,
cl_int *errcode_ret)
{
Platform *platform = ValidateContextProperties(properties, errcode_ret);
if (platform == nullptr)
{
return false;
}
if (!Device::IsValidType(device_type))
{
ANGLE_ERROR_RETURN(CL_INVALID_DEVICE_TYPE, false);
}
if (pfn_notify == nullptr && user_data != nullptr)
{
ANGLE_ERROR_RETURN(CL_INVALID_VALUE, false);
}
return true;
}
cl_int ValidateRetainContext(const Context *contextPacked)
cl_int ValidateRetainContext(const Context *context)
{
return CL_SUCCESS;
return Context::IsValid(context) ? CL_SUCCESS : CL_INVALID_CONTEXT;
}
cl_int ValidateReleaseContext(const Context *contextPacked)
cl_int ValidateReleaseContext(const Context *context)
{
return CL_SUCCESS;
return Context::IsValid(context) ? CL_SUCCESS : CL_INVALID_CONTEXT;
}
cl_int ValidateGetContextInfo(const Context *contextPacked,
ContextInfo param_namePacked,
cl_int ValidateGetContextInfo(const Context *context,
ContextInfo param_name,
size_t param_value_size,
const void *param_value,
const size_t *param_value_size_ret)
{
if (!Context::IsValid(context))
{
return CL_INVALID_CONTEXT;
}
if (param_name == ContextInfo::InvalidEnum ||
(param_value_size == 0u && param_value != nullptr))
{
return CL_INVALID_VALUE;
}
return CL_SUCCESS;
}
......
......@@ -462,6 +462,7 @@ libangle_cl_headers = [
"src/libANGLE/CLObject.h",
"src/libANGLE/CLPlatform.h",
"src/libANGLE/CLProgram.h",
"src/libANGLE/CLRefPointer.h",
"src/libANGLE/CLSampler.h",
"src/libANGLE/CLtypes.h",
"src/libANGLE/renderer/CLContextImpl.h",
......@@ -482,6 +483,7 @@ libangle_cl_sources = [
"src/libANGLE/CLPlatform.cpp",
"src/libANGLE/CLProgram.cpp",
"src/libANGLE/CLSampler.cpp",
"src/libANGLE/renderer/CLContextImpl.cpp",
"src/libANGLE/renderer/CLDeviceImpl.cpp",
"src/libANGLE/renderer/CLPlatformImpl.cpp",
"src/libANGLE/validationCL.cpp",
......
......@@ -85,6 +85,41 @@ cl_int GetPlatforms(cl_uint num_entries, Platform **platforms, cl_uint *num_plat
return CL_SUCCESS;
}
Context::PropArray ParseContextProperties(const cl_context_properties *properties,
Platform *&platform,
bool &userSync)
{
Context::PropArray propArray;
if (properties != nullptr)
{
// Count the trailing zero
size_t propSize = 1u;
const cl_context_properties *propIt = properties;
while (*propIt != 0)
{
++propSize;
switch (*propIt++)
{
case CL_CONTEXT_PLATFORM:
platform = reinterpret_cast<Platform *>(*propIt++);
++propSize;
break;
case CL_CONTEXT_INTEROP_USER_SYNC:
userSync = *propIt++ != CL_FALSE;
++propSize;
break;
}
}
propArray.reserve(propSize);
propArray.insert(propArray.cend(), properties, properties + propSize);
}
if (platform == nullptr)
{
platform = Platform::GetDefault();
}
return propArray;
}
} // anonymous namespace
cl_int IcdGetPlatformIDsKHR(cl_uint num_entries, Platform **platforms, cl_uint *num_platforms)
......@@ -175,8 +210,15 @@ Context *CreateContext(const cl_context_properties *properties,
void *user_data,
cl_int *errcode_ret)
{
WARN_NOT_SUPPORTED(CreateContext);
return 0;
Platform *platform = nullptr;
bool userSync = false;
Context::PropArray propArray = ParseContextProperties(properties, platform, userSync);
if (platform == nullptr)
{
return nullptr;
}
return platform->createContext(std::move(propArray), num_devices, devices, pfn_notify,
user_data, userSync, errcode_ret);
}
Context *CreateContextFromType(const cl_context_properties *properties,
......@@ -188,20 +230,27 @@ Context *CreateContextFromType(const cl_context_properties *properties,
void *user_data,
cl_int *errcode_ret)
{
WARN_NOT_SUPPORTED(CreateContextFromType);
return 0;
Platform *platform = nullptr;
bool userSync = false;
Context::PropArray propArray = ParseContextProperties(properties, platform, userSync);
if (platform == nullptr)
{
return nullptr;
}
return platform->createContextFromType(std::move(propArray), device_type, pfn_notify, user_data,
userSync, errcode_ret);
}
cl_int RetainContext(Context *context)
{
WARN_NOT_SUPPORTED(RetainContext);
return 0;
context->retain();
return CL_SUCCESS;
}
cl_int ReleaseContext(Context *context)
{
WARN_NOT_SUPPORTED(ReleaseContext);
return 0;
context->release();
return CL_SUCCESS;
}
cl_int GetContextInfo(Context *context,
......@@ -210,8 +259,7 @@ cl_int GetContextInfo(Context *context,
void *param_value,
size_t *param_value_size_ret)
{
WARN_NOT_SUPPORTED(GetContextInfo);
return 0;
return context->getInfo(param_name, param_value_size, param_value, param_value_size_ret);
}
cl_int SetContextDestructorCallback(Context *context,
......
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