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 @@ ...@@ -24,6 +24,11 @@
namespace cl namespace cl
{ {
using ContextErrorCB = void(CL_CALLBACK *)(const char *errinfo,
const void *private_info,
size_t cb,
void *user_data);
template <typename CLObjectType> template <typename CLObjectType>
struct Dispatch struct Dispatch
{ {
......
...@@ -7,9 +7,127 @@ ...@@ -7,9 +7,127 @@
#include "libANGLE/CLContext.h" #include "libANGLE/CLContext.h"
#include "libANGLE/CLPlatform.h"
#include <cstring>
namespace cl 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 } // namespace cl
...@@ -9,7 +9,11 @@ ...@@ -9,7 +9,11 @@
#ifndef LIBANGLE_CLCONTEXT_H_ #ifndef LIBANGLE_CLCONTEXT_H_
#define 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 namespace cl
{ {
...@@ -17,10 +21,64 @@ namespace cl ...@@ -17,10 +21,64 @@ namespace cl
class Context final : public _cl_context, public Object class Context final : public _cl_context, public Object
{ {
public: public:
Context(const cl_icd_dispatch &dispatch); using Ptr = std::unique_ptr<Context>;
~Context() = default; 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 } // namespace cl
#endif // LIBANGLE_CLCONTEXT_H_ #endif // LIBANGLE_CLCONTEXT_H_
...@@ -9,6 +9,8 @@ ...@@ -9,6 +9,8 @@
#include "libANGLE/CLPlatform.h" #include "libANGLE/CLPlatform.h"
#include <cstring>
namespace cl namespace cl
{ {
...@@ -202,7 +204,7 @@ cl_int Device::getInfo(DeviceInfo name, size_t valueSize, void *value, size_t *v ...@@ -202,7 +204,7 @@ cl_int Device::getInfo(DeviceInfo name, size_t valueSize, void *value, size_t *v
sizeof(decltype(mInfo.mMaxWorkItemSizes)::value_type); sizeof(decltype(mInfo.mMaxWorkItemSizes)::value_type);
break; break;
case DeviceInfo::ILsWithVersion: case DeviceInfo::ILsWithVersion:
if (!mInfo.mIsSupportedILsWithVersion) if (mInfo.mVersion < CL_MAKE_VERSION(3, 0, 0))
{ {
return CL_INVALID_VALUE; return CL_INVALID_VALUE;
} }
...@@ -211,7 +213,7 @@ cl_int Device::getInfo(DeviceInfo name, size_t valueSize, void *value, size_t *v ...@@ -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); mInfo.mILsWithVersion.size() * sizeof(decltype(mInfo.mILsWithVersion)::value_type);
break; break;
case DeviceInfo::BuiltInKernelsWithVersion: case DeviceInfo::BuiltInKernelsWithVersion:
if (!mInfo.mIsSupportedBuiltInKernelsWithVersion) if (mInfo.mVersion < CL_MAKE_VERSION(3, 0, 0))
{ {
return CL_INVALID_VALUE; return CL_INVALID_VALUE;
} }
...@@ -220,7 +222,7 @@ cl_int Device::getInfo(DeviceInfo name, size_t valueSize, void *value, size_t *v ...@@ -220,7 +222,7 @@ cl_int Device::getInfo(DeviceInfo name, size_t valueSize, void *value, size_t *v
sizeof(decltype(mInfo.mBuiltInKernelsWithVersion)::value_type); sizeof(decltype(mInfo.mBuiltInKernelsWithVersion)::value_type);
break; break;
case DeviceInfo::OpenCL_C_AllVersions: case DeviceInfo::OpenCL_C_AllVersions:
if (!mInfo.mIsSupportedOpenCL_C_AllVersions) if (mInfo.mVersion < CL_MAKE_VERSION(3, 0, 0))
{ {
return CL_INVALID_VALUE; return CL_INVALID_VALUE;
} }
...@@ -229,7 +231,7 @@ cl_int Device::getInfo(DeviceInfo name, size_t valueSize, void *value, size_t *v ...@@ -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); sizeof(decltype(mInfo.mOpenCL_C_AllVersions)::value_type);
break; break;
case DeviceInfo::OpenCL_C_Features: case DeviceInfo::OpenCL_C_Features:
if (!mInfo.mIsSupportedOpenCL_C_Features) if (mInfo.mVersion < CL_MAKE_VERSION(3, 0, 0))
{ {
return CL_INVALID_VALUE; return CL_INVALID_VALUE;
} }
...@@ -242,7 +244,7 @@ cl_int Device::getInfo(DeviceInfo name, size_t valueSize, void *value, size_t *v ...@@ -242,7 +244,7 @@ cl_int Device::getInfo(DeviceInfo name, size_t valueSize, void *value, size_t *v
copySize = mInfo.mExtensions.length() + 1u; copySize = mInfo.mExtensions.length() + 1u;
break; break;
case DeviceInfo::ExtensionsWithVersion: case DeviceInfo::ExtensionsWithVersion:
if (!mInfo.mIsSupportedExtensionsWithVersion) if (mInfo.mVersion < CL_MAKE_VERSION(3, 0, 0))
{ {
return CL_INVALID_VALUE; return CL_INVALID_VALUE;
} }
...@@ -251,11 +253,19 @@ cl_int Device::getInfo(DeviceInfo name, size_t valueSize, void *value, size_t *v ...@@ -251,11 +253,19 @@ cl_int Device::getInfo(DeviceInfo name, size_t valueSize, void *value, size_t *v
sizeof(decltype(mInfo.mExtensionsWithVersion)::value_type); sizeof(decltype(mInfo.mExtensionsWithVersion)::value_type);
break; break;
case DeviceInfo::PartitionProperties: case DeviceInfo::PartitionProperties:
if (mInfo.mVersion < CL_MAKE_VERSION(1, 2, 0))
{
return CL_INVALID_VALUE;
}
copyValue = mInfo.mPartitionProperties.data(); copyValue = mInfo.mPartitionProperties.data();
copySize = mInfo.mPartitionProperties.size() * copySize = mInfo.mPartitionProperties.size() *
sizeof(decltype(mInfo.mPartitionProperties)::value_type); sizeof(decltype(mInfo.mPartitionProperties)::value_type);
break; break;
case DeviceInfo::PartitionType: case DeviceInfo::PartitionType:
if (mInfo.mVersion < CL_MAKE_VERSION(1, 2, 0))
{
return CL_INVALID_VALUE;
}
copyValue = mInfo.mPartitionType.data(); copyValue = mInfo.mPartitionType.data();
copySize = copySize =
mInfo.mPartitionType.size() * sizeof(decltype(mInfo.mPartitionType)::value_type); 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 ...@@ -268,10 +278,18 @@ cl_int Device::getInfo(DeviceInfo name, size_t valueSize, void *value, size_t *v
copySize = sizeof(valPointer); copySize = sizeof(valPointer);
break; break;
case DeviceInfo::ParentDevice: case DeviceInfo::ParentDevice:
if (mInfo.mVersion < CL_MAKE_VERSION(1, 2, 0))
{
return CL_INVALID_VALUE;
}
copyValue = &mParent; copyValue = &mParent;
copySize = sizeof(mParent); copySize = sizeof(mParent);
break; break;
case DeviceInfo::ReferenceCount: case DeviceInfo::ReferenceCount:
if (mInfo.mVersion < CL_MAKE_VERSION(1, 2, 0))
{
return CL_INVALID_VALUE;
}
copyValue = getRefCountPtr(); copyValue = getRefCountPtr();
copySize = sizeof(*getRefCountPtr()); copySize = sizeof(*getRefCountPtr());
break; break;
...@@ -312,27 +330,39 @@ cl_int Device::createSubDevices(const cl_device_partition_property *properties, ...@@ -312,27 +330,39 @@ cl_int Device::createSubDevices(const cl_device_partition_property *properties,
{ {
numDevices = 0u; numDevices = 0u;
} }
rx::CLDeviceImpl::InitList initList; rx::CLDeviceImpl::PtrList ptrList;
const cl_int result = mImpl->createSubDevices(properties, numDevices, initList, numDevicesRet); const cl_int result = mImpl->createSubDevices(properties, numDevices, ptrList, numDevicesRet);
if (result == CL_SUCCESS) if (result == CL_SUCCESS)
{ {
while (!initList.empty()) while (!ptrList.empty())
{
rx::CLDeviceImpl::Info info = ptrList.front()->createInfo();
if (!info.isValid())
{ {
mSubDevices.emplace_back(new Device(mPlatform, this, initList.front())); 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(); *devices++ = mSubDevices.back().get();
initList.pop_front();
} }
} }
return result; return result;
} }
Device::PtrList Device::CreateDevices(Platform &platform, rx::CLDeviceImpl::InitList &&initList) Device::PtrList Device::CreateDevices(Platform &platform, rx::CLDeviceImpl::PtrList &&implList)
{ {
PtrList devices; PtrList devices;
while (!initList.empty()) while (!implList.empty())
{ {
devices.emplace_back(new Device(platform, nullptr, initList.front())); rx::CLDeviceImpl::Info info = implList.front()->createInfo();
initList.pop_front(); 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; return devices;
} }
...@@ -345,12 +375,15 @@ bool Device::IsValid(const Device *device) ...@@ -345,12 +375,15 @@ bool Device::IsValid(const Device *device)
}) != platforms.cend(); }) != 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()), : _cl_device_id(platform.getDispatch()),
mPlatform(platform), mPlatform(platform),
mParent(parent), mParent(parent),
mImpl(std::move(initData.first)), mImpl(std::move(impl)),
mInfo(std::move(initData.second)) mInfo(std::move(info))
{} {}
void Device::destroySubDevice(Device *device) void Device::destroySubDevice(Device *device)
......
...@@ -10,6 +10,7 @@ ...@@ -10,6 +10,7 @@
#define LIBANGLE_CLDEVICE_H_ #define LIBANGLE_CLDEVICE_H_
#include "libANGLE/CLObject.h" #include "libANGLE/CLObject.h"
#include "libANGLE/CLRefPointer.h"
#include "libANGLE/renderer/CLDeviceImpl.h" #include "libANGLE/renderer/CLDeviceImpl.h"
namespace cl namespace cl
...@@ -20,14 +21,16 @@ class Device final : public _cl_device_id, public Object ...@@ -20,14 +21,16 @@ class Device final : public _cl_device_id, public Object
public: public:
using Ptr = std::unique_ptr<Device>; using Ptr = std::unique_ptr<Device>;
using PtrList = std::list<Ptr>; using PtrList = std::list<Ptr>;
using RefPtr = RefPointer<Device>;
using RefList = std::vector<RefPtr>;
~Device(); ~Device();
Platform &getPlatform() const; Platform &getPlatform() const noexcept;
bool isRoot() const; bool isRoot() const noexcept;
bool hasSubDevice(const Device *device) const; bool hasSubDevice(const Device *device) const;
void retain(); void retain() noexcept;
bool release(); bool release();
cl_int getInfoULong(DeviceInfo name, cl_ulong *value) const; cl_int getInfoULong(DeviceInfo name, cl_ulong *value) const;
...@@ -38,13 +41,16 @@ class Device final : public _cl_device_id, public Object ...@@ -38,13 +41,16 @@ class Device final : public _cl_device_id, public Object
Device **devices, Device **devices,
cl_uint *numDevicesRet); 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 IsValid(const Device *device);
static bool IsValidType(cl_device_type type); static bool IsValidType(cl_device_type type);
private: 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); void destroySubDevice(Device *device);
...@@ -54,14 +60,16 @@ class Device final : public _cl_device_id, public Object ...@@ -54,14 +60,16 @@ class Device final : public _cl_device_id, public Object
const rx::CLDeviceImpl::Info mInfo; const rx::CLDeviceImpl::Info mInfo;
PtrList mSubDevices; PtrList mSubDevices;
friend class Platform;
}; };
inline Platform &Device::getPlatform() const inline Platform &Device::getPlatform() const noexcept
{ {
return mPlatform; return mPlatform;
} }
inline bool Device::isRoot() const inline bool Device::isRoot() const noexcept
{ {
return mParent == nullptr; return mParent == nullptr;
} }
...@@ -73,7 +81,7 @@ inline bool Device::hasSubDevice(const Device *device) const ...@@ -73,7 +81,7 @@ inline bool Device::hasSubDevice(const Device *device) const
}) != mSubDevices.cend(); }) != mSubDevices.cend();
} }
inline void Device::retain() inline void Device::retain() noexcept
{ {
if (!isRoot()) if (!isRoot())
{ {
......
...@@ -20,17 +20,28 @@ class Object ...@@ -20,17 +20,28 @@ class Object
public: public:
// This class cannot be virtual as its derived classes need to have standard layout // This class cannot be virtual as its derived classes need to have standard layout
Object() = default; Object() = default;
~Object() { ASSERT(mRefCount == 0u); }
~Object()
{
if (mRefCount != 0u)
{
WARN() << "Deleted object with references";
}
}
cl_uint getRefCount() { return mRefCount; } cl_uint getRefCount() { return mRefCount; }
const cl_uint *getRefCountPtr() { return &mRefCount; } const cl_uint *getRefCountPtr() { return &mRefCount; }
protected: protected:
void addRef() { ++mRefCount; } void addRef() noexcept { ++mRefCount; }
bool removeRef() bool removeRef()
{ {
ASSERT(mRefCount > 0u); if (mRefCount == 0u)
{
WARN() << "Unreferenced object without references";
return true;
}
return --mRefCount == 0u; return --mRefCount == 0u;
} }
......
...@@ -30,7 +30,33 @@ Platform::~Platform() ...@@ -30,7 +30,33 @@ Platform::~Platform()
removeRef(); 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; const void *copyValue = nullptr;
size_t copySize = 0u; size_t copySize = 0u;
...@@ -46,6 +72,10 @@ cl_int Platform::getInfo(PlatformInfo name, size_t valueSize, void *value, size_ ...@@ -46,6 +72,10 @@ cl_int Platform::getInfo(PlatformInfo name, size_t valueSize, void *value, size_
copySize = mInfo.mVersionStr.length() + 1u; copySize = mInfo.mVersionStr.length() + 1u;
break; break;
case PlatformInfo::NumericVersion: case PlatformInfo::NumericVersion:
if (mInfo.mVersion < CL_MAKE_VERSION(3, 0, 0))
{
return CL_INVALID_VALUE;
}
copyValue = &mInfo.mVersion; copyValue = &mInfo.mVersion;
copySize = sizeof(mInfo.mVersion); copySize = sizeof(mInfo.mVersion);
break; break;
...@@ -62,7 +92,7 @@ cl_int Platform::getInfo(PlatformInfo name, size_t valueSize, void *value, size_ ...@@ -62,7 +92,7 @@ cl_int Platform::getInfo(PlatformInfo name, size_t valueSize, void *value, size_
copySize = mInfo.mExtensions.length() + 1u; copySize = mInfo.mExtensions.length() + 1u;
break; break;
case PlatformInfo::ExtensionsWithVersion: case PlatformInfo::ExtensionsWithVersion:
if (mInfo.mExtensionsWithVersion.empty()) if (mInfo.mVersion < CL_MAKE_VERSION(3, 0, 0))
{ {
return CL_INVALID_VALUE; return CL_INVALID_VALUE;
} }
...@@ -71,6 +101,10 @@ cl_int Platform::getInfo(PlatformInfo name, size_t valueSize, void *value, size_ ...@@ -71,6 +101,10 @@ cl_int Platform::getInfo(PlatformInfo name, size_t valueSize, void *value, size_
sizeof(decltype(mInfo.mExtensionsWithVersion)::value_type); sizeof(decltype(mInfo.mExtensionsWithVersion)::value_type);
break; break;
case PlatformInfo::HostTimerResolution: case PlatformInfo::HostTimerResolution:
if (mInfo.mVersion < CL_MAKE_VERSION(2, 1, 0))
{
return CL_INVALID_VALUE;
}
copyValue = &mInfo.mHostTimerRes; copyValue = &mInfo.mHostTimerRes;
copySize = sizeof(mInfo.mHostTimerRes); copySize = sizeof(mInfo.mHostTimerRes);
break; break;
...@@ -93,9 +127,9 @@ cl_int Platform::getInfo(PlatformInfo name, size_t valueSize, void *value, size_ ...@@ -93,9 +127,9 @@ cl_int Platform::getInfo(PlatformInfo name, size_t valueSize, void *value, size_
std::memcpy(value, copyValue, copySize); std::memcpy(value, copyValue, copySize);
} }
} }
if (sizeRet != nullptr) if (valueSizeRet != nullptr)
{ {
*sizeRet = copySize; *valueSizeRet = copySize;
} }
return CL_SUCCESS; return CL_SUCCESS;
} }
...@@ -126,27 +160,96 @@ cl_int Platform::getDeviceIDs(cl_device_type deviceType, ...@@ -126,27 +160,96 @@ cl_int Platform::getDeviceIDs(cl_device_type deviceType,
return found == 0u ? CL_DEVICE_NOT_FOUND : CL_SUCCESS; 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, void Platform::CreatePlatform(const cl_icd_dispatch &dispatch,
rx::CLPlatformImpl::InitData &initData) rx::CLPlatformImpl::InitData &initData)
{ {
rx::CLDeviceImpl::InitList deviceInitList = initData.first->getDevices(); Ptr platform(new Platform(dispatch, initData));
if (!deviceInitList.empty()) 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, Platform::Platform(const cl_icd_dispatch &dispatch, rx::CLPlatformImpl::InitData &initData)
rx::CLPlatformImpl::InitData &initData,
rx::CLDeviceImpl::InitList &&deviceInitList)
: _cl_platform_id(dispatch), : _cl_platform_id(dispatch),
mImpl(std::move(initData.first)), mImpl(std::move(std::get<0>(initData))),
mInfo(std::move(initData.second)), mInfo(std::move(std::get<1>(initData))),
mDevices(Device::CreateDevices(*this, std::move(deviceInitList))) mDevices(Device::CreateDevices(*this, std::move(std::get<2>(initData))))
{ {
ASSERT(isCompatible(this)); 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::kVendor[];
constexpr char Platform::kIcdSuffix[]; constexpr char Platform::kIcdSuffix[];
......
...@@ -9,6 +9,7 @@ ...@@ -9,6 +9,7 @@
#ifndef LIBANGLE_CLPLATFORM_H_ #ifndef LIBANGLE_CLPLATFORM_H_
#define LIBANGLE_CLPLATFORM_H_ #define LIBANGLE_CLPLATFORM_H_
#include "libANGLE/CLContext.h"
#include "libANGLE/CLDevice.h" #include "libANGLE/CLDevice.h"
#include "libANGLE/renderer/CLPlatformImpl.h" #include "libANGLE/renderer/CLPlatformImpl.h"
...@@ -27,14 +28,32 @@ class Platform final : public _cl_platform_id, public Object ...@@ -27,14 +28,32 @@ class Platform final : public _cl_platform_id, public Object
bool hasDevice(const Device *device) const; bool hasDevice(const Device *device) const;
const Device::PtrList &getDevices() 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_int getDeviceIDs(cl_device_type deviceType,
cl_uint numEntries, cl_uint numEntries,
Device **devices, Device **devices,
cl_uint *numDevices) const; 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, static void CreatePlatform(const cl_icd_dispatch &dispatch,
rx::CLPlatformImpl::InitData &initData); rx::CLPlatformImpl::InitData &initData);
static const PtrList &GetPlatforms(); static const PtrList &GetPlatforms();
...@@ -45,9 +64,15 @@ class Platform final : public _cl_platform_id, public Object ...@@ -45,9 +64,15 @@ class Platform final : public _cl_platform_id, public Object
static constexpr const char *GetVendor(); static constexpr const char *GetVendor();
private: private:
Platform(const cl_icd_dispatch &dispatch, Platform(const cl_icd_dispatch &dispatch, rx::CLPlatformImpl::InitData &initData);
rx::CLPlatformImpl::InitData &initData,
rx::CLDeviceImpl::InitList &&deviceInitList); rx::CLContextImpl::Ptr createContext(const Device::RefList &devices,
ContextErrorCB notify,
void *userData,
bool userSync,
cl_int *errcodeRet);
void destroyContext(Context *context);
static PtrList &GetList(); static PtrList &GetList();
...@@ -55,8 +80,12 @@ class Platform final : public _cl_platform_id, public Object ...@@ -55,8 +80,12 @@ class Platform final : public _cl_platform_id, public Object
const rx::CLPlatformImpl::Info mInfo; const rx::CLPlatformImpl::Info mInfo;
const Device::PtrList mDevices; const Device::PtrList mDevices;
Context::PtrList mContexts;
static constexpr char kVendor[] = "ANGLE"; static constexpr char kVendor[] = "ANGLE";
static constexpr char kIcdSuffix[] = "ANGLE"; static constexpr char kIcdSuffix[] = "ANGLE";
friend class Context;
}; };
inline bool Platform::hasDevice(const Device *device) const inline bool Platform::hasDevice(const Device *device) const
...@@ -71,6 +100,13 @@ inline const Device::PtrList &Platform::getDevices() const ...@@ -71,6 +100,13 @@ inline const Device::PtrList &Platform::getDevices() const
return mDevices; 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() inline Platform::PtrList &Platform::GetList()
{ {
static angle::base::NoDestructor<PtrList> sList; 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 @@ ...@@ -3,13 +3,12 @@
// Use of this source code is governed by a BSD-style license that can be // Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file. // found in the LICENSE file.
// //
// CLContextImpl.h: Defines the abstract rx::CLContextImpl class. // CLContextImpl.h: Defines the abstract rx::CLContextImpl class.
#ifndef LIBANGLE_RENDERER_CLCONTEXTIMPL_H_ #ifndef LIBANGLE_RENDERER_CLCONTEXTIMPL_H_
#define LIBANGLE_RENDERER_CLCONTEXTIMPL_H_ #define LIBANGLE_RENDERER_CLCONTEXTIMPL_H_
#include "libANGLE/renderer/CLtypes.h" #include "libANGLE/renderer/CLDeviceImpl.h"
namespace rx namespace rx
{ {
...@@ -17,10 +16,30 @@ namespace rx ...@@ -17,10 +16,30 @@ namespace rx
class CLContextImpl : angle::NonCopyable class CLContextImpl : angle::NonCopyable
{ {
public: public:
CLContextImpl() {} using Ptr = std::unique_ptr<CLContextImpl>;
virtual ~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 } // namespace rx
#endif // LIBANGLE_RENDERER_CLCONTEXTIMPL_H_ #endif // LIBANGLE_RENDERER_CLCONTEXTIMPL_H_
...@@ -7,6 +7,8 @@ ...@@ -7,6 +7,8 @@
#include "libANGLE/renderer/CLDeviceImpl.h" #include "libANGLE/renderer/CLDeviceImpl.h"
#include "libANGLE/Debug.h"
namespace rx namespace rx
{ {
...@@ -18,14 +20,24 @@ CLDeviceImpl::Info::Info(Info &&) = default; ...@@ -18,14 +20,24 @@ CLDeviceImpl::Info::Info(Info &&) = default;
CLDeviceImpl::Info &CLDeviceImpl::Info::operator=(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: if (mParent != nullptr)
// "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 auto it = std::find(mParent->mSubDevices.cbegin(), mParent->mSubDevices.cend(), this);
// Custom devices are currently not supported by ANGLE back ends. if (it != mParent->mSubDevices.cend())
return mMaxWorkItemSizes.size() >= 3u && mMaxWorkItemSizes[0] >= 1u && {
mMaxWorkItemSizes[1] >= 1u && mMaxWorkItemSizes[2] >= 1u; mParent->mSubDevices.erase(it);
}
else
{
ERR() << "Sub-device not in parent's list";
}
}
} }
} // namespace rx } // namespace rx
...@@ -27,8 +27,9 @@ class CLDeviceImpl : angle::NonCopyable ...@@ -27,8 +27,9 @@ class CLDeviceImpl : angle::NonCopyable
Info(Info &&); Info(Info &&);
Info &operator=(Info &&); Info &operator=(Info &&);
bool isValid() const; bool isValid() const { return mVersion != 0u; }
cl_version mVersion = 0u;
std::vector<size_t> mMaxWorkItemSizes; std::vector<size_t> mMaxWorkItemSizes;
NameVersionVector mILsWithVersion; NameVersionVector mILsWithVersion;
NameVersionVector mBuiltInKernelsWithVersion; NameVersionVector mBuiltInKernelsWithVersion;
...@@ -38,20 +39,22 @@ class CLDeviceImpl : angle::NonCopyable ...@@ -38,20 +39,22 @@ class CLDeviceImpl : angle::NonCopyable
NameVersionVector mExtensionsWithVersion; NameVersionVector mExtensionsWithVersion;
std::vector<cl_device_partition_property> mPartitionProperties; std::vector<cl_device_partition_property> mPartitionProperties;
std::vector<cl_device_partition_property> mPartitionType; 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 Ptr = std::unique_ptr<CLDeviceImpl>;
using InitData = std::pair<Ptr, Info>; using PtrList = std::list<Ptr>;
using InitList = std::list<InitData>; 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 Info createInfo() const = 0;
virtual ~CLDeviceImpl() = default;
virtual cl_int getInfoUInt(cl::DeviceInfo name, cl_uint *value) 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; virtual cl_int getInfoULong(cl::DeviceInfo name, cl_ulong *value) const = 0;
...@@ -61,8 +64,14 @@ class CLDeviceImpl : angle::NonCopyable ...@@ -61,8 +64,14 @@ class CLDeviceImpl : angle::NonCopyable
virtual cl_int createSubDevices(const cl_device_partition_property *properties, virtual cl_int createSubDevices(const cl_device_partition_property *properties,
cl_uint numDevices, cl_uint numDevices,
InitList &deviceInitList, PtrList &implList,
cl_uint *numDevicesRet) = 0; cl_uint *numDevicesRet) = 0;
protected:
CLPlatformImpl &mPlatform;
CLDeviceImpl *const mParent;
List mSubDevices;
}; };
} // namespace rx } // namespace rx
......
...@@ -18,9 +18,8 @@ CLPlatformImpl::Info::Info(Info &&) = default; ...@@ -18,9 +18,8 @@ CLPlatformImpl::Info::Info(Info &&) = default;
CLPlatformImpl::Info &CLPlatformImpl::Info::operator=(Info &&) = default; CLPlatformImpl::Info &CLPlatformImpl::Info::operator=(Info &&) = default;
bool CLPlatformImpl::Info::isValid() const CLPlatformImpl::CLPlatformImpl(CLDeviceImpl::List &&devices) : mDevices(std::move(devices)) {}
{
return !mProfile.empty(); CLPlatformImpl::~CLPlatformImpl() = default;
}
} // namespace rx } // namespace rx
...@@ -8,8 +8,11 @@ ...@@ -8,8 +8,11 @@
#ifndef LIBANGLE_RENDERER_CLPLATFORMIMPL_H_ #ifndef LIBANGLE_RENDERER_CLPLATFORMIMPL_H_
#define LIBANGLE_RENDERER_CLPLATFORMIMPL_H_ #define LIBANGLE_RENDERER_CLPLATFORMIMPL_H_
#include "libANGLE/renderer/CLContextImpl.h"
#include "libANGLE/renderer/CLDeviceImpl.h" #include "libANGLE/renderer/CLDeviceImpl.h"
#include <tuple>
namespace rx namespace rx
{ {
...@@ -27,27 +30,51 @@ class CLPlatformImpl : angle::NonCopyable ...@@ -27,27 +30,51 @@ class CLPlatformImpl : angle::NonCopyable
Info(Info &&); Info(Info &&);
Info &operator=(Info &&); Info &operator=(Info &&);
bool isValid() const; bool isValid() const { return mVersion != 0u; }
std::string mProfile; std::string mProfile;
std::string mVersionStr; std::string mVersionStr;
cl_version mVersion; cl_version mVersion = 0u;
std::string mName; std::string mName;
std::string mExtensions; std::string mExtensions;
NameVersionVector mExtensionsWithVersion; NameVersionVector mExtensionsWithVersion;
cl_ulong mHostTimerRes; cl_ulong mHostTimerRes = 0u;
}; };
using Ptr = std::unique_ptr<CLPlatformImpl>; 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>; using InitList = std::list<InitData>;
CLPlatformImpl() = default; explicit CLPlatformImpl(CLDeviceImpl::List &&devices);
virtual ~CLPlatformImpl() = default; 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 } // namespace rx
#endif // LIBANGLE_RENDERER_CLPLATFORMIMPL_H_ #endif // LIBANGLE_RENDERER_CLPLATFORMIMPL_H_
...@@ -15,6 +15,7 @@ _cl_backend_sources = [ ...@@ -15,6 +15,7 @@ _cl_backend_sources = [
"CLDeviceCL.h", "CLDeviceCL.h",
"CLPlatformCL.cpp", "CLPlatformCL.cpp",
"CLPlatformCL.h", "CLPlatformCL.h",
"cl_types.h",
"cl_util.cpp", "cl_util.cpp",
"cl_util.h", "cl_util.h",
] ]
......
...@@ -3,17 +3,27 @@ ...@@ -3,17 +3,27 @@
// Use of this source code is governed by a BSD-style license that can be // Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file. // found in the LICENSE file.
// //
// CLContextCL.cpp: // CLContextCL.cpp: Implements the class methods for CLContextCL.
// Implements the class methods for CLContextCL.
//
#include "libANGLE/renderer/cl/CLContextCL.h" #include "libANGLE/renderer/cl/CLContextCL.h"
#include "libANGLE/renderer/cl/CLPlatformCL.h"
#include "libANGLE/Debug.h"
namespace rx 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 } // namespace rx
...@@ -3,13 +3,13 @@ ...@@ -3,13 +3,13 @@
// Use of this source code is governed by a BSD-style license that can be // Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file. // found in the LICENSE file.
// //
// CLContextCL.h: // CLContextCL.h: Defines the class interface for CLContextCL, implementing CLContextImpl.
// Defines the class interface for CLContextCL, implementing CLContextImpl.
//
#ifndef LIBANGLE_RENDERER_CL_CLCONTEXTCL_H_ #ifndef LIBANGLE_RENDERER_CL_CLCONTEXTCL_H_
#define LIBANGLE_RENDERER_CL_CLCONTEXTCL_H_ #define LIBANGLE_RENDERER_CL_CLCONTEXTCL_H_
#include "libANGLE/renderer/cl/cl_types.h"
#include "libANGLE/renderer/CLContextImpl.h" #include "libANGLE/renderer/CLContextImpl.h"
namespace rx namespace rx
...@@ -18,8 +18,11 @@ namespace rx ...@@ -18,8 +18,11 @@ namespace rx
class CLContextCL : public CLContextImpl class CLContextCL : public CLContextImpl
{ {
public: public:
CLContextCL(); CLContextCL(CLPlatformCL &platform, CLDeviceImpl::List &&devices, cl_context context);
~CLContextCL() override; ~CLContextCL() override;
private:
const cl_context mContext;
}; };
} // namespace rx } // namespace rx
......
...@@ -7,6 +7,7 @@ ...@@ -7,6 +7,7 @@
#include "libANGLE/renderer/cl/CLDeviceCL.h" #include "libANGLE/renderer/cl/CLDeviceCL.h"
#include "libANGLE/renderer/cl/CLPlatformCL.h"
#include "libANGLE/renderer/cl/cl_util.h" #include "libANGLE/renderer/cl/cl_util.h"
#include "libANGLE/Debug.h" #include "libANGLE/Debug.h"
...@@ -14,6 +15,34 @@ ...@@ -14,6 +15,34 @@
namespace rx namespace rx
{ {
namespace
{
// Object information is queried in OpenCL by providing allocated memory into which the requested
// data is copied. If the size of the data is unknown, it can be queried first with an additional
// call to the same function, but without requesting the data itself. This function provides the
// functionality to request and validate the size and the data.
template <typename T>
bool GetDeviceInfo(cl_device_id device, cl::DeviceInfo name, std::vector<T> &vector)
{
size_t size = 0u;
if (device->getDispatch().clGetDeviceInfo(device, cl::ToCLenum(name), 0u, nullptr, &size) ==
CL_SUCCESS &&
(size % sizeof(T)) == 0u) // size has to be a multiple of the data type
{
vector.resize(size / sizeof(T));
if (device->getDispatch().clGetDeviceInfo(device, cl::ToCLenum(name), size, vector.data(),
nullptr) == CL_SUCCESS)
{
return true;
}
}
ERR() << "Failed to query CL device info for " << name;
return false;
}
} // namespace
CLDeviceCL::~CLDeviceCL() CLDeviceCL::~CLDeviceCL()
{ {
if (mVersion >= CL_MAKE_VERSION(1, 2, 0) && if (mVersion >= CL_MAKE_VERSION(1, 2, 0) &&
...@@ -23,6 +52,58 @@ CLDeviceCL::~CLDeviceCL() ...@@ -23,6 +52,58 @@ CLDeviceCL::~CLDeviceCL()
} }
} }
CLDeviceImpl::Info CLDeviceCL::createInfo() const
{
Info info;
info.mVersion = mVersion;
std::vector<char> valString;
if (!GetDeviceInfo(mDevice, cl::DeviceInfo::Extensions, valString))
{
return Info{};
}
info.mExtensions.assign(valString.data());
RemoveUnsupportedCLExtensions(info.mExtensions);
if (!GetDeviceInfo(mDevice, cl::DeviceInfo::MaxWorkItemSizes, info.mMaxWorkItemSizes))
{
return Info{};
}
// 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 this back end.
if (info.mMaxWorkItemSizes.size() < 3u || info.mMaxWorkItemSizes[0] == 0u ||
info.mMaxWorkItemSizes[1] == 0u || info.mMaxWorkItemSizes[2] == 0u)
{
ERR() << "Invalid CL_DEVICE_MAX_WORK_ITEM_SIZES";
return Info{};
}
if (mVersion >= CL_MAKE_VERSION(1, 2, 0) &&
(!GetDeviceInfo(mDevice, cl::DeviceInfo::PartitionProperties, info.mPartitionProperties) ||
!GetDeviceInfo(mDevice, cl::DeviceInfo::PartitionType, info.mPartitionType)))
{
return Info{};
}
if (mVersion >= CL_MAKE_VERSION(3, 0, 0) &&
(!GetDeviceInfo(mDevice, cl::DeviceInfo::ILsWithVersion, info.mILsWithVersion) ||
!GetDeviceInfo(mDevice, cl::DeviceInfo::BuiltInKernelsWithVersion,
info.mBuiltInKernelsWithVersion) ||
!GetDeviceInfo(mDevice, cl::DeviceInfo::OpenCL_C_AllVersions,
info.mOpenCL_C_AllVersions) ||
!GetDeviceInfo(mDevice, cl::DeviceInfo::OpenCL_C_Features, info.mOpenCL_C_Features) ||
!GetDeviceInfo(mDevice, cl::DeviceInfo::ExtensionsWithVersion,
info.mExtensionsWithVersion)))
{
return Info{};
}
RemoveUnsupportedCLExtensions(info.mExtensionsWithVersion);
return info;
}
cl_int CLDeviceCL::getInfoUInt(cl::DeviceInfo name, cl_uint *value) const cl_int CLDeviceCL::getInfoUInt(cl::DeviceInfo name, cl_uint *value) const
{ {
return mDevice->getDispatch().clGetDeviceInfo(mDevice, cl::ToCLenum(name), sizeof(*value), return mDevice->getDispatch().clGetDeviceInfo(mDevice, cl::ToCLenum(name), sizeof(*value),
...@@ -54,7 +135,7 @@ cl_int CLDeviceCL::getInfoString(cl::DeviceInfo name, size_t size, char *value) ...@@ -54,7 +135,7 @@ cl_int CLDeviceCL::getInfoString(cl::DeviceInfo name, size_t size, char *value)
cl_int CLDeviceCL::createSubDevices(const cl_device_partition_property *properties, cl_int CLDeviceCL::createSubDevices(const cl_device_partition_property *properties,
cl_uint numDevices, cl_uint numDevices,
InitList &deviceInitList, PtrList &implList,
cl_uint *numDevicesRet) cl_uint *numDevicesRet)
{ {
if (mVersion < CL_MAKE_VERSION(1, 2, 0)) if (mVersion < CL_MAKE_VERSION(1, 2, 0))
...@@ -66,6 +147,7 @@ cl_int CLDeviceCL::createSubDevices(const cl_device_partition_property *properti ...@@ -66,6 +147,7 @@ cl_int CLDeviceCL::createSubDevices(const cl_device_partition_property *properti
return mDevice->getDispatch().clCreateSubDevices(mDevice, properties, 0u, nullptr, return mDevice->getDispatch().clCreateSubDevices(mDevice, properties, 0u, nullptr,
numDevicesRet); numDevicesRet);
} }
std::vector<cl_device_id> devices(numDevices, nullptr); std::vector<cl_device_id> devices(numDevices, nullptr);
const cl_int result = mDevice->getDispatch().clCreateSubDevices(mDevice, properties, numDevices, const cl_int result = mDevice->getDispatch().clCreateSubDevices(mDevice, properties, numDevices,
devices.data(), nullptr); devices.data(), nullptr);
...@@ -73,154 +155,44 @@ cl_int CLDeviceCL::createSubDevices(const cl_device_partition_property *properti ...@@ -73,154 +155,44 @@ cl_int CLDeviceCL::createSubDevices(const cl_device_partition_property *properti
{ {
for (cl_device_id device : devices) for (cl_device_id device : devices)
{ {
CLDeviceImpl::Ptr impl(CLDeviceCL::Create(device)); implList.emplace_back(CLDeviceCL::Create(getPlatform<CLPlatformCL>(), this, device));
CLDeviceImpl::Info info = CLDeviceCL::GetInfo(device); if (!implList.back())
if (impl && info.isValid())
{
deviceInitList.emplace_back(std::move(impl), std::move(info));
}
}
if (deviceInitList.size() != devices.size())
{ {
implList.clear();
return CL_INVALID_VALUE; return CL_INVALID_VALUE;
} }
mSubDevices.emplace_back(implList.back().get());
}
} }
return result; return result;
} }
#define ANGLE_GET_INFO_SIZE(name, size_ret) \ CLDeviceCL *CLDeviceCL::Create(CLPlatformCL &platform, CLDeviceCL *parent, cl_device_id device)
device->getDispatch().clGetDeviceInfo(device, name, 0u, nullptr, size_ret)
#define ANGLE_GET_INFO_SIZE_RET(name, size_ret) \
do \
{ \
if (ANGLE_GET_INFO_SIZE(name, size_ret) != CL_SUCCESS) \
{ \
ERR() << "Failed to query CL device info for " << name; \
return info; \
} \
} while (0)
#define ANGLE_GET_INFO(name, size, param) \
device->getDispatch().clGetDeviceInfo(device, name, size, param, nullptr)
#define ANGLE_GET_INFO_RET(name, size, param) \
do \
{ \
if (ANGLE_GET_INFO(name, size, param) != CL_SUCCESS) \
{ \
ERR() << "Failed to query CL device info for " << name; \
return Info{}; \
} \
} while (0)
CLDeviceCL *CLDeviceCL::Create(cl_device_id device)
{ {
size_t valueSize = 0u; size_t valueSize = 0u;
if (ANGLE_GET_INFO_SIZE(CL_DEVICE_VERSION, &valueSize) == CL_SUCCESS) if (device->getDispatch().clGetDeviceInfo(device, CL_DEVICE_VERSION, 0u, nullptr, &valueSize) ==
CL_SUCCESS)
{ {
std::vector<char> valString(valueSize, '\0'); std::vector<char> valString(valueSize, '\0');
if (ANGLE_GET_INFO(CL_DEVICE_VERSION, valueSize, valString.data()) == CL_SUCCESS) if (device->getDispatch().clGetDeviceInfo(device, CL_DEVICE_VERSION, valueSize,
valString.data(), nullptr) == CL_SUCCESS)
{ {
const cl_version version = ExtractCLVersion(valString.data()); const cl_version version = ExtractCLVersion(valString.data());
if (version != 0u) if (version != 0u)
{ {
return new CLDeviceCL(device, version); return new CLDeviceCL(platform, parent, device, version);
} }
} }
} }
ERR() << "Failed to query version for device";
return nullptr; return nullptr;
} }
CLDeviceImpl::Info CLDeviceCL::GetInfo(cl_device_id device) CLDeviceCL::CLDeviceCL(CLPlatformCL &platform,
{ CLDeviceCL *parent,
Info info; cl_device_id device,
size_t valueSize = 0u; cl_version version)
std::vector<char> valString; : CLDeviceImpl(platform, parent), mDevice(device), mVersion(version)
if (ANGLE_GET_INFO_SIZE(CL_DEVICE_ILS_WITH_VERSION, &valueSize) == CL_SUCCESS &&
(valueSize % sizeof(decltype(info.mILsWithVersion)::value_type)) == 0u)
{
info.mILsWithVersion.resize(valueSize / sizeof(decltype(info.mILsWithVersion)::value_type));
ANGLE_GET_INFO_RET(CL_DEVICE_ILS_WITH_VERSION, valueSize, info.mILsWithVersion.data());
info.mIsSupportedILsWithVersion = true;
}
if (ANGLE_GET_INFO_SIZE(CL_DEVICE_BUILT_IN_KERNELS_WITH_VERSION, &valueSize) == CL_SUCCESS &&
(valueSize % sizeof(decltype(info.mBuiltInKernelsWithVersion)::value_type)) == 0u)
{
info.mBuiltInKernelsWithVersion.resize(
valueSize / sizeof(decltype(info.mBuiltInKernelsWithVersion)::value_type));
ANGLE_GET_INFO_RET(CL_DEVICE_BUILT_IN_KERNELS_WITH_VERSION, valueSize,
info.mBuiltInKernelsWithVersion.data());
info.mIsSupportedBuiltInKernelsWithVersion = true;
}
if (ANGLE_GET_INFO_SIZE(CL_DEVICE_OPENCL_C_ALL_VERSIONS, &valueSize) == CL_SUCCESS &&
(valueSize % sizeof(decltype(info.mOpenCL_C_AllVersions)::value_type)) == 0u)
{
info.mOpenCL_C_AllVersions.resize(valueSize /
sizeof(decltype(info.mOpenCL_C_AllVersions)::value_type));
ANGLE_GET_INFO_RET(CL_DEVICE_OPENCL_C_ALL_VERSIONS, valueSize,
info.mOpenCL_C_AllVersions.data());
info.mIsSupportedOpenCL_C_AllVersions = true;
}
if (ANGLE_GET_INFO_SIZE(CL_DEVICE_OPENCL_C_FEATURES, &valueSize) == CL_SUCCESS &&
(valueSize % sizeof(decltype(info.mOpenCL_C_Features)::value_type)) == 0u)
{
info.mOpenCL_C_Features.resize(valueSize /
sizeof(decltype(info.mOpenCL_C_Features)::value_type));
ANGLE_GET_INFO_RET(CL_DEVICE_OPENCL_C_FEATURES, valueSize, info.mOpenCL_C_Features.data());
info.mIsSupportedOpenCL_C_Features = true;
}
ANGLE_GET_INFO_SIZE_RET(CL_DEVICE_EXTENSIONS, &valueSize);
valString.resize(valueSize, '\0');
ANGLE_GET_INFO_RET(CL_DEVICE_EXTENSIONS, valueSize, valString.data());
info.mExtensions.assign(valString.data());
RemoveUnsupportedCLExtensions(info.mExtensions);
if (ANGLE_GET_INFO_SIZE(CL_DEVICE_EXTENSIONS_WITH_VERSION, &valueSize) == CL_SUCCESS &&
(valueSize % sizeof(decltype(info.mExtensionsWithVersion)::value_type)) == 0u)
{
info.mExtensionsWithVersion.resize(
valueSize / sizeof(decltype(info.mExtensionsWithVersion)::value_type));
ANGLE_GET_INFO_RET(CL_DEVICE_EXTENSIONS_WITH_VERSION, valueSize,
info.mExtensionsWithVersion.data());
RemoveUnsupportedCLExtensions(info.mExtensionsWithVersion);
info.mIsSupportedExtensionsWithVersion = true;
}
if (ANGLE_GET_INFO_SIZE(CL_DEVICE_PARTITION_PROPERTIES, &valueSize) == CL_SUCCESS &&
(valueSize % sizeof(decltype(info.mPartitionProperties)::value_type)) == 0u)
{
info.mPartitionProperties.resize(valueSize /
sizeof(decltype(info.mPartitionProperties)::value_type));
ANGLE_GET_INFO_RET(CL_DEVICE_PARTITION_PROPERTIES, valueSize,
info.mPartitionProperties.data());
}
if (ANGLE_GET_INFO_SIZE(CL_DEVICE_PARTITION_TYPE, &valueSize) == CL_SUCCESS &&
(valueSize % sizeof(decltype(info.mPartitionType)::value_type)) == 0u)
{
info.mPartitionType.resize(valueSize / sizeof(decltype(info.mPartitionType)::value_type));
ANGLE_GET_INFO_RET(CL_DEVICE_PARTITION_TYPE, valueSize, info.mPartitionType.data());
}
// Get this last, so the info is invalid if anything before fails
cl_uint maxWorkItemDims = 0u;
ANGLE_GET_INFO_RET(CL_DEVICE_MAX_WORK_ITEM_DIMENSIONS, sizeof(maxWorkItemDims),
&maxWorkItemDims);
info.mMaxWorkItemSizes.resize(maxWorkItemDims, 0u);
ANGLE_GET_INFO_RET(CL_DEVICE_MAX_WORK_ITEM_SIZES,
maxWorkItemDims * sizeof(decltype(info.mMaxWorkItemSizes)::value_type),
info.mMaxWorkItemSizes.data());
return info;
}
CLDeviceCL::CLDeviceCL(cl_device_id device, cl_version version) : mDevice(device), mVersion(version)
{} {}
} // namespace rx } // namespace rx
...@@ -8,6 +8,8 @@ ...@@ -8,6 +8,8 @@
#ifndef LIBANGLE_RENDERER_CL_CLDEVICECL_H_ #ifndef LIBANGLE_RENDERER_CL_CLDEVICECL_H_
#define LIBANGLE_RENDERER_CL_CLDEVICECL_H_ #define LIBANGLE_RENDERER_CL_CLDEVICECL_H_
#include "libANGLE/renderer/cl/cl_types.h"
#include "libANGLE/renderer/CLDeviceImpl.h" #include "libANGLE/renderer/CLDeviceImpl.h"
namespace rx namespace rx
...@@ -20,6 +22,8 @@ class CLDeviceCL : public CLDeviceImpl ...@@ -20,6 +22,8 @@ class CLDeviceCL : public CLDeviceImpl
cl_device_id getNative(); cl_device_id getNative();
Info createInfo() const override;
cl_int getInfoUInt(cl::DeviceInfo name, cl_uint *value) 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 getInfoULong(cl::DeviceInfo name, cl_ulong *value) const override;
cl_int getInfoSizeT(cl::DeviceInfo name, size_t *value) const override; cl_int getInfoSizeT(cl::DeviceInfo name, size_t *value) const override;
...@@ -28,14 +32,13 @@ class CLDeviceCL : public CLDeviceImpl ...@@ -28,14 +32,13 @@ class CLDeviceCL : public CLDeviceImpl
cl_int createSubDevices(const cl_device_partition_property *properties, cl_int createSubDevices(const cl_device_partition_property *properties,
cl_uint numDevices, cl_uint numDevices,
InitList &deviceInitList, PtrList &implList,
cl_uint *numDevicesRet) override; cl_uint *numDevicesRet) override;
static CLDeviceCL *Create(cl_device_id device); static CLDeviceCL *Create(CLPlatformCL &platform, CLDeviceCL *parent, cl_device_id device);
static Info GetInfo(cl_device_id device);
private: 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_device_id mDevice;
const cl_version mVersion; const cl_version mVersion;
......
...@@ -7,6 +7,7 @@ ...@@ -7,6 +7,7 @@
#include "libANGLE/renderer/cl/CLPlatformCL.h" #include "libANGLE/renderer/cl/CLPlatformCL.h"
#include "libANGLE/renderer/cl/CLContextCL.h"
#include "libANGLE/renderer/cl/CLDeviceCL.h" #include "libANGLE/renderer/cl/CLDeviceCL.h"
#include "libANGLE/renderer/cl/cl_util.h" #include "libANGLE/renderer/cl/cl_util.h"
...@@ -23,44 +24,160 @@ extern "C" { ...@@ -23,44 +24,160 @@ extern "C" {
namespace rx namespace rx
{ {
CLPlatformCL::~CLPlatformCL() = default; namespace
{
CLDeviceImpl::InitList CLPlatformCL::getDevices() CLDeviceImpl::List CreateDevices(CLPlatformCL &platform,
cl_platform_id native,
CLDeviceImpl::PtrList &implPtrList)
{ {
CLDeviceImpl::InitList initList; CLDeviceImpl::List implList;
// Fetch all regular devices. This does not include CL_DEVICE_TYPE_CUSTOM, which are not // Fetch all regular devices. This does not include CL_DEVICE_TYPE_CUSTOM, which are not
// supported by the CL pass-through back end because they have no standard feature set. // supported by the CL pass-through back end because they have no standard feature set.
// This makes them unreliable for the purpose of this back end. // This makes them unreliable for the purpose of this back end.
cl_uint numDevices = 0u; cl_uint numDevices = 0u;
if (mPlatform->getDispatch().clGetDeviceIDs(mPlatform, CL_DEVICE_TYPE_ALL, 0u, nullptr, if (native->getDispatch().clGetDeviceIDs(native, CL_DEVICE_TYPE_ALL, 0u, nullptr,
&numDevices) == CL_SUCCESS) &numDevices) == CL_SUCCESS)
{ {
std::vector<cl_device_id> devices(numDevices, nullptr); std::vector<cl_device_id> devices(numDevices, nullptr);
if (mPlatform->getDispatch().clGetDeviceIDs(mPlatform, CL_DEVICE_TYPE_ALL, numDevices, if (native->getDispatch().clGetDeviceIDs(native, CL_DEVICE_TYPE_ALL, numDevices,
devices.data(), nullptr) == CL_SUCCESS) devices.data(), nullptr) == CL_SUCCESS)
{ {
for (cl_device_id device : devices) for (cl_device_id device : devices)
{ {
CLDeviceImpl::Ptr impl(CLDeviceCL::Create(device)); CLDeviceImpl::Ptr impl(CLDeviceCL::Create(platform, nullptr, device));
CLDeviceImpl::Info info = CLDeviceCL::GetInfo(device); if (!impl)
if (impl && info.isValid())
{ {
initList.emplace_back(std::move(impl), std::move(info)); implList.clear();
implPtrList.clear();
break;
} }
implList.emplace_back(impl.get());
implPtrList.emplace_back(std::move(impl));
} }
} }
else }
if (implList.empty())
{ {
ERR() << "Failed to query CL devices"; ERR() << "Failed to query CL devices";
} }
return implList;
}
std::string GetPlatformString(cl_platform_id platform, cl::PlatformInfo name)
{
size_t size = 0u;
if (platform->getDispatch().clGetPlatformInfo(platform, cl::ToCLenum(name), 0u, nullptr,
&size) == CL_SUCCESS)
{
std::vector<char> str(size, '\0');
if (platform->getDispatch().clGetPlatformInfo(platform, cl::ToCLenum(name), size,
str.data(), nullptr) == CL_SUCCESS)
{
return std::string(str.data());
}
}
ERR() << "Failed to query CL platform info for " << name;
return std::string{};
}
} // namespace
CLPlatformCL::~CLPlatformCL() = default;
CLContextImpl::Ptr CLPlatformCL::createContext(CLDeviceImpl::List &&deviceImplList,
cl::ContextErrorCB notify,
void *userData,
bool userSync,
cl_int *errcodeRet)
{
cl_context_properties properties[] = {
CL_CONTEXT_PLATFORM, reinterpret_cast<cl_context_properties>(mPlatform),
userSync && mVersion >= CL_MAKE_VERSION(1, 2, 0) ? CL_CONTEXT_INTEROP_USER_SYNC : 0,
CL_TRUE, 0};
std::vector<cl_device_id> devices;
for (CLDeviceImpl *deviceImpl : deviceImplList)
{
devices.emplace_back(static_cast<CLDeviceCL *>(deviceImpl)->getNative());
}
CLContextImpl::Ptr contextImpl;
cl_context context =
mPlatform->getDispatch().clCreateContext(properties, static_cast<cl_uint>(devices.size()),
devices.data(), notify, userData, errcodeRet);
if (context != nullptr)
{
contextImpl.reset(new CLContextCL(*this, std::move(deviceImplList), context));
mContexts.emplace_back(contextImpl.get());
}
return contextImpl;
}
CLContextImpl::Ptr CLPlatformCL::createContextFromType(cl_device_type deviceType,
cl::ContextErrorCB notify,
void *userData,
bool userSync,
cl_int *errcodeRet)
{
cl_context_properties properties[] = {
CL_CONTEXT_PLATFORM, reinterpret_cast<cl_context_properties>(mPlatform),
userSync && mVersion >= CL_MAKE_VERSION(1, 2, 0) ? CL_CONTEXT_INTEROP_USER_SYNC : 0,
CL_TRUE, 0};
cl_context context = mPlatform->getDispatch().clCreateContextFromType(
properties, deviceType, notify, userData, errcodeRet);
if (context == nullptr)
{
return CLContextImpl::Ptr{};
}
size_t valueSize = 0u;
cl_int result = context->getDispatch().clGetContextInfo(context, CL_CONTEXT_DEVICES, 0u,
nullptr, &valueSize);
if (result == CL_SUCCESS && (valueSize % sizeof(cl_device_id)) == 0u)
{
std::vector<cl_device_id> devices(valueSize / sizeof(cl_device_id), nullptr);
result = context->getDispatch().clGetContextInfo(context, CL_CONTEXT_DEVICES, valueSize,
devices.data(), nullptr);
if (result == CL_SUCCESS)
{
CLDeviceImpl::List deviceImplList;
for (cl_device_id device : devices)
{
auto it = mDevices.cbegin();
while (it != mDevices.cend() &&
static_cast<CLDeviceCL *>(*it)->getNative() != device)
{
++it;
}
if (it != mDevices.cend())
{
deviceImplList.emplace_back(*it);
} }
else else
{ {
ERR() << "Failed to query CL devices"; ERR() << "Device not found in platform list";
}
}
if (deviceImplList.size() == devices.size())
{
CLContextImpl::Ptr contextImpl(
new CLContextCL(*this, std::move(deviceImplList), context));
mContexts.emplace_back(contextImpl.get());
return contextImpl;
}
result = CL_INVALID_VALUE;
}
} }
return initList; context->getDispatch().clReleaseContext(context);
if (errcodeRet != nullptr)
{
*errcodeRet = result;
}
return CLContextImpl::Ptr{};
} }
CLPlatformCL::InitList CLPlatformCL::GetPlatforms(bool isIcd) CLPlatformCL::InitList CLPlatformCL::GetPlatforms(bool isIcd)
...@@ -97,14 +214,25 @@ CLPlatformCL::InitList CLPlatformCL::GetPlatforms(bool isIcd) ...@@ -97,14 +214,25 @@ CLPlatformCL::InitList CLPlatformCL::GetPlatforms(bool isIcd)
Info info = GetInfo(vendorIt->platform); Info info = GetInfo(vendorIt->platform);
if (info.isValid()) if (info.isValid())
{ {
initList.emplace_back(new CLPlatformCL(vendorIt->platform), std::move(info)); CLDeviceImpl::PtrList devices;
Ptr platform(new CLPlatformCL(vendorIt->platform, info.mVersion, devices));
if (!devices.empty())
{
initList.emplace_back(std::move(platform), std::move(info), std::move(devices));
}
} }
} }
} }
return initList; return initList;
} }
CLPlatformCL::CLPlatformCL(cl_platform_id platform) : mPlatform(platform) {} CLPlatformCL::CLPlatformCL(cl_platform_id platform,
cl_version version,
CLDeviceImpl::PtrList &devices)
: CLPlatformImpl(CreateDevices(*this, platform, devices)),
mPlatform(platform),
mVersion(version)
{}
#define ANGLE_GET_INFO_SIZE(name, size_ret) \ #define ANGLE_GET_INFO_SIZE(name, size_ret) \
platform->getDispatch().clGetPlatformInfo(platform, name, 0u, nullptr, size_ret) platform->getDispatch().clGetPlatformInfo(platform, name, 0u, nullptr, size_ret)
...@@ -134,10 +262,6 @@ CLPlatformCL::CLPlatformCL(cl_platform_id platform) : mPlatform(platform) {} ...@@ -134,10 +262,6 @@ CLPlatformCL::CLPlatformCL(cl_platform_id platform) : mPlatform(platform) {}
CLPlatformImpl::Info CLPlatformCL::GetInfo(cl_platform_id platform) CLPlatformImpl::Info CLPlatformCL::GetInfo(cl_platform_id platform)
{ {
Info info;
size_t valueSize = 0u;
std::vector<char> valString;
// Verify that the platform is valid // Verify that the platform is valid
if (platform == nullptr || platform->getDispatch().clGetPlatformIDs == nullptr || if (platform == nullptr || platform->getDispatch().clGetPlatformIDs == nullptr ||
platform->getDispatch().clGetPlatformInfo == nullptr || platform->getDispatch().clGetPlatformInfo == nullptr ||
...@@ -206,49 +330,70 @@ CLPlatformImpl::Info CLPlatformCL::GetInfo(cl_platform_id platform) ...@@ -206,49 +330,70 @@ CLPlatformImpl::Info CLPlatformCL::GetInfo(cl_platform_id platform)
platform->getDispatch().clGetExtensionFunctionAddress == nullptr) platform->getDispatch().clGetExtensionFunctionAddress == nullptr)
{ {
ERR() << "Missing entry points for OpenCL 1.0"; ERR() << "Missing entry points for OpenCL 1.0";
return info; return Info{};
}
// Fetch common platform info
Info info;
const std::string vendor = GetPlatformString(platform, cl::PlatformInfo::Vendor);
info.mProfile = GetPlatformString(platform, cl::PlatformInfo::Profile);
info.mVersionStr = GetPlatformString(platform, cl::PlatformInfo::Version);
info.mName = GetPlatformString(platform, cl::PlatformInfo::Name);
info.mExtensions = GetPlatformString(platform, cl::PlatformInfo::Extensions);
if (vendor.empty() || info.mProfile.empty() || info.mVersionStr.empty() || info.mName.empty() ||
info.mExtensions.empty())
{
return Info{};
} }
// Skip ANGLE CL implementation to prevent passthrough loop // Skip ANGLE CL implementation to prevent passthrough loop
ANGLE_GET_INFO_SIZE_RET(CL_PLATFORM_VENDOR, &valueSize); if (vendor.compare(cl::Platform::GetVendor()) == 0)
valString.resize(valueSize, '\0');
ANGLE_GET_INFO_RET(CL_PLATFORM_VENDOR, valueSize, valString.data());
if (std::string(valString.data()).compare(cl::Platform::GetVendor()) == 0)
{ {
ERR() << "Tried to create CL pass-through back end for ANGLE library"; ERR() << "Tried to create CL pass-through back end for ANGLE library";
return info; return Info{};
} }
// Skip platform if it is not ICD compatible // Skip platform if it is not ICD compatible
ANGLE_GET_INFO_SIZE_RET(CL_PLATFORM_EXTENSIONS, &valueSize);
valString.resize(valueSize, '\0');
ANGLE_GET_INFO_RET(CL_PLATFORM_EXTENSIONS, valueSize, valString.data());
info.mExtensions.assign(valString.data());
RemoveUnsupportedCLExtensions(info.mExtensions);
if (info.mExtensions.find("cl_khr_icd") == std::string::npos) if (info.mExtensions.find("cl_khr_icd") == std::string::npos)
{ {
WARN() << "CL platform is not ICD compatible"; WARN() << "CL platform is not ICD compatible";
return info; return Info{};
} }
// Fetch common platform info
ANGLE_GET_INFO_SIZE_RET(CL_PLATFORM_VERSION, &valueSize);
valString.resize(valueSize, '\0');
ANGLE_GET_INFO_RET(CL_PLATFORM_VERSION, valueSize, valString.data());
info.mVersionStr.assign(valString.data());
info.mVersionStr += " (ANGLE " ANGLE_VERSION_STRING ")";
const cl_version version = ExtractCLVersion(info.mVersionStr); const cl_version version = ExtractCLVersion(info.mVersionStr);
if (version == 0u) if (version == 0u)
{ {
return info; return Info{};
}
// Customize version string and name, and remove unsupported extensions
info.mVersionStr += " (ANGLE " ANGLE_VERSION_STRING ")";
info.mName.insert(0u, "ANGLE pass-through -> ");
RemoveUnsupportedCLExtensions(info.mExtensions);
if (version >= CL_MAKE_VERSION(2, 1, 0) &&
platform->getDispatch().clGetPlatformInfo(platform, CL_PLATFORM_HOST_TIMER_RESOLUTION,
sizeof(info.mHostTimerRes), &info.mHostTimerRes,
nullptr) != CL_SUCCESS)
{
ERR() << "Failed to query CL platform info for CL_PLATFORM_HOST_TIMER_RESOLUTION";
return Info{};
} }
if (ANGLE_GET_INFO(CL_PLATFORM_NUMERIC_VERSION, sizeof(info.mVersion), &info.mVersion) != if (version < CL_MAKE_VERSION(3, 0, 0))
CL_SUCCESS)
{ {
info.mVersion = version; info.mVersion = version;
} }
else
{
if (platform->getDispatch().clGetPlatformInfo(platform, CL_PLATFORM_NUMERIC_VERSION,
sizeof(info.mVersion), &info.mVersion,
nullptr) != CL_SUCCESS)
{
ERR() << "Failed to query CL platform info for CL_PLATFORM_NUMERIC_VERSION";
return Info{};
}
else if (CL_VERSION_MAJOR(info.mVersion) != CL_VERSION_MAJOR(version) || else if (CL_VERSION_MAJOR(info.mVersion) != CL_VERSION_MAJOR(version) ||
CL_VERSION_MINOR(info.mVersion) != CL_VERSION_MINOR(version)) CL_VERSION_MINOR(info.mVersion) != CL_VERSION_MINOR(version))
{ {
...@@ -257,25 +402,26 @@ CLPlatformImpl::Info CLPlatformCL::GetInfo(cl_platform_id platform) ...@@ -257,25 +402,26 @@ CLPlatformImpl::Info CLPlatformCL::GetInfo(cl_platform_id platform)
<< " does not match version string: " << info.mVersionStr; << " does not match version string: " << info.mVersionStr;
} }
ANGLE_GET_INFO_SIZE_RET(CL_PLATFORM_NAME, &valueSize); size_t valueSize = 0u;
valString.resize(valueSize, '\0'); if (platform->getDispatch().clGetPlatformInfo(platform, CL_PLATFORM_EXTENSIONS_WITH_VERSION,
ANGLE_GET_INFO_RET(CL_PLATFORM_NAME, valueSize, valString.data()); 0u, nullptr, &valueSize) != CL_SUCCESS ||
info.mName.assign("ANGLE pass-through -> "); (valueSize % sizeof(decltype(info.mExtensionsWithVersion)::value_type)) != 0u)
info.mName += valString.data();
if (ANGLE_GET_INFO_SIZE(CL_PLATFORM_EXTENSIONS_WITH_VERSION, &valueSize) == CL_SUCCESS &&
(valueSize % sizeof(decltype(info.mExtensionsWithVersion)::value_type)) == 0u)
{ {
ERR() << "Failed to query CL platform info for CL_PLATFORM_EXTENSIONS_WITH_VERSION";
return Info{};
}
info.mExtensionsWithVersion.resize( info.mExtensionsWithVersion.resize(
valueSize / sizeof(decltype(info.mExtensionsWithVersion)::value_type)); valueSize / sizeof(decltype(info.mExtensionsWithVersion)::value_type));
ANGLE_GET_INFO_RET(CL_PLATFORM_EXTENSIONS_WITH_VERSION, valueSize, if (platform->getDispatch().clGetPlatformInfo(platform, CL_PLATFORM_EXTENSIONS_WITH_VERSION,
info.mExtensionsWithVersion.data()); valueSize, info.mExtensionsWithVersion.data(),
nullptr) != CL_SUCCESS)
{
ERR() << "Failed to query CL platform info for CL_PLATFORM_EXTENSIONS_WITH_VERSION";
return Info{};
}
RemoveUnsupportedCLExtensions(info.mExtensionsWithVersion); RemoveUnsupportedCLExtensions(info.mExtensionsWithVersion);
} }
ANGLE_GET_INFO(CL_PLATFORM_HOST_TIMER_RESOLUTION, sizeof(info.mHostTimerRes),
&info.mHostTimerRes);
if (info.mVersion >= CL_MAKE_VERSION(1, 1, 0) && if (info.mVersion >= CL_MAKE_VERSION(1, 1, 0) &&
(platform->getDispatch().clSetEventCallback == nullptr || (platform->getDispatch().clSetEventCallback == nullptr ||
platform->getDispatch().clCreateSubBuffer == nullptr || platform->getDispatch().clCreateSubBuffer == nullptr ||
...@@ -360,12 +506,6 @@ CLPlatformImpl::Info CLPlatformCL::GetInfo(cl_platform_id platform) ...@@ -360,12 +506,6 @@ CLPlatformImpl::Info CLPlatformCL::GetInfo(cl_platform_id platform)
return info; return info;
} }
// Get this last, so the info is invalid if anything before fails
ANGLE_GET_INFO_SIZE_RET(CL_PLATFORM_PROFILE, &valueSize);
valString.resize(valueSize, '\0');
ANGLE_GET_INFO_RET(CL_PLATFORM_PROFILE, valueSize, valString.data());
info.mProfile.assign(valString.data());
return info; return info;
} }
......
...@@ -20,16 +20,29 @@ class CLPlatformCL : public CLPlatformImpl ...@@ -20,16 +20,29 @@ class CLPlatformCL : public CLPlatformImpl
cl_platform_id getNative(); 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); static InitList GetPlatforms(bool isIcd);
private: 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); static Info GetInfo(cl_platform_id platform);
const cl_platform_id mPlatform; const cl_platform_id mPlatform;
const cl_version mVersion;
friend class CLContextCL;
}; };
inline cl_platform_id CLPlatformCL::getNative() 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) { ...@@ -111,6 +111,7 @@ if (angle_enable_cl) {
"CLDeviceVk.h", "CLDeviceVk.h",
"CLPlatformVk.cpp", "CLPlatformVk.cpp",
"CLPlatformVk.h", "CLPlatformVk.h",
"cl_types.h",
] ]
} }
......
...@@ -3,16 +3,18 @@ ...@@ -3,16 +3,18 @@
// Use of this source code is governed by a BSD-style license that can be // Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file. // found in the LICENSE file.
// //
// CLContextVk.cpp: // CLContextVk.cpp: Implements the class methods for CLContextVk.
// Implements the class methods for CLContextVk.
//
#include "libANGLE/renderer/vulkan/CLContextVk.h" #include "libANGLE/renderer/vulkan/CLContextVk.h"
#include "libANGLE/renderer/vulkan/CLPlatformVk.h"
namespace rx namespace rx
{ {
CLContextVk::CLContextVk() {} CLContextVk::CLContextVk(CLPlatformVk &platform, CLDeviceImpl::List &&devices)
: CLContextImpl(platform, std::move(devices))
{}
CLContextVk::~CLContextVk() = default; CLContextVk::~CLContextVk() = default;
......
...@@ -3,13 +3,13 @@ ...@@ -3,13 +3,13 @@
// Use of this source code is governed by a BSD-style license that can be // Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file. // found in the LICENSE file.
// //
// CLContextVk.h: // CLContextVk.h: Defines the class interface for CLContextVk, implementing CLContextImpl.
// Defines the class interface for CLContextVk, implementing CLContextImpl.
//
#ifndef LIBANGLE_RENDERER_VULKAN_CLCONTEXTVK_H_ #ifndef LIBANGLE_RENDERER_VULKAN_CLCONTEXTVK_H_
#define LIBANGLE_RENDERER_VULKAN_CLCONTEXTVK_H_ #define LIBANGLE_RENDERER_VULKAN_CLCONTEXTVK_H_
#include "libANGLE/renderer/vulkan/cl_types.h"
#include "libANGLE/renderer/CLContextImpl.h" #include "libANGLE/renderer/CLContextImpl.h"
namespace rx namespace rx
...@@ -18,7 +18,7 @@ namespace rx ...@@ -18,7 +18,7 @@ namespace rx
class CLContextVk : public CLContextImpl class CLContextVk : public CLContextImpl
{ {
public: public:
CLContextVk(); CLContextVk(CLPlatformVk &platform, CLDeviceImpl::List &&devices);
~CLContextVk() override; ~CLContextVk() override;
}; };
......
...@@ -7,13 +7,22 @@ ...@@ -7,13 +7,22 @@
#include "libANGLE/renderer/vulkan/CLDeviceVk.h" #include "libANGLE/renderer/vulkan/CLDeviceVk.h"
#include "libANGLE/renderer/vulkan/CLPlatformVk.h"
namespace rx namespace rx
{ {
CLDeviceVk::CLDeviceVk() = default; CLDeviceVk::CLDeviceVk(CLPlatformVk &platform, CLDeviceVk *parent) : CLDeviceImpl(platform, parent)
{}
CLDeviceVk::~CLDeviceVk() = default; CLDeviceVk::~CLDeviceVk() = default;
CLDeviceImpl::Info CLDeviceVk::createInfo() const
{
CLDeviceImpl::Info info;
return info;
}
cl_int CLDeviceVk::getInfoUInt(cl::DeviceInfo name, cl_uint *value) const cl_int CLDeviceVk::getInfoUInt(cl::DeviceInfo name, cl_uint *value) const
{ {
return CL_INVALID_VALUE; return CL_INVALID_VALUE;
...@@ -41,16 +50,10 @@ cl_int CLDeviceVk::getInfoString(cl::DeviceInfo name, size_t size, char *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_int CLDeviceVk::createSubDevices(const cl_device_partition_property *properties,
cl_uint numDevices, cl_uint numDevices,
InitList &deviceInitList, PtrList &deviceImplList,
cl_uint *numDevicesRet) cl_uint *numDevicesRet)
{ {
return CL_INVALID_VALUE; return CL_INVALID_VALUE;
} }
CLDeviceImpl::Info CLDeviceVk::GetInfo()
{
CLDeviceImpl::Info info;
return info;
}
} // namespace rx } // namespace rx
...@@ -8,6 +8,8 @@ ...@@ -8,6 +8,8 @@
#ifndef LIBANGLE_RENDERER_VULKAN_CLDEVICEVK_H_ #ifndef LIBANGLE_RENDERER_VULKAN_CLDEVICEVK_H_
#define LIBANGLE_RENDERER_VULKAN_CLDEVICEVK_H_ #define LIBANGLE_RENDERER_VULKAN_CLDEVICEVK_H_
#include "libANGLE/renderer/vulkan/cl_types.h"
#include "libANGLE/renderer/CLDeviceImpl.h" #include "libANGLE/renderer/CLDeviceImpl.h"
namespace rx namespace rx
...@@ -16,9 +18,11 @@ namespace rx ...@@ -16,9 +18,11 @@ namespace rx
class CLDeviceVk : public CLDeviceImpl class CLDeviceVk : public CLDeviceImpl
{ {
public: public:
CLDeviceVk(); CLDeviceVk(CLPlatformVk &platform, CLDeviceVk *parent);
~CLDeviceVk() override; ~CLDeviceVk() override;
Info createInfo() const override;
cl_int getInfoUInt(cl::DeviceInfo name, cl_uint *value) 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 getInfoULong(cl::DeviceInfo name, cl_ulong *value) const override;
cl_int getInfoSizeT(cl::DeviceInfo name, size_t *value) const override; cl_int getInfoSizeT(cl::DeviceInfo name, size_t *value) const override;
...@@ -27,10 +31,8 @@ class CLDeviceVk : public CLDeviceImpl ...@@ -27,10 +31,8 @@ class CLDeviceVk : public CLDeviceImpl
cl_int createSubDevices(const cl_device_partition_property *properties, cl_int createSubDevices(const cl_device_partition_property *properties,
cl_uint numDevices, cl_uint numDevices,
InitList &deviceInitList, PtrList &deviceImplList,
cl_uint *numDevicesRet) override; cl_uint *numDevicesRet) override;
static Info GetInfo();
}; };
} // namespace rx } // namespace rx
......
...@@ -31,19 +31,35 @@ std::string CreateExtensionString(const NameVersionVector &extList) ...@@ -31,19 +31,35 @@ std::string CreateExtensionString(const NameVersionVector &extList)
} }
return extensions; 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; 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; CLContextImpl::Ptr contextImpl;
CLDeviceImpl::Info info = CLDeviceVk::GetInfo(); return contextImpl;
if (info.isValid()) }
{
initList.emplace_back(new CLDeviceVk(), std::move(info)); CLContextImpl::Ptr CLPlatformVk::createContextFromType(cl_device_type deviceType,
} cl::ContextErrorCB notify,
return initList; void *userData,
bool userSync,
cl_int *errcodeRet)
{
CLContextImpl::Ptr contextImpl;
return contextImpl;
} }
CLPlatformVk::InitList CLPlatformVk::GetPlatforms() CLPlatformVk::InitList CLPlatformVk::GetPlatforms()
...@@ -62,7 +78,15 @@ CLPlatformVk::InitList CLPlatformVk::GetPlatforms() ...@@ -62,7 +78,15 @@ CLPlatformVk::InitList CLPlatformVk::GetPlatforms()
info.mHostTimerRes = 0u; info.mHostTimerRes = 0u;
InitList initList; 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; return initList;
} }
...@@ -74,6 +98,8 @@ const std::string &CLPlatformVk::GetVersionString() ...@@ -74,6 +98,8 @@ const std::string &CLPlatformVk::GetVersionString()
return *sVersion; return *sVersion;
} }
CLPlatformVk::CLPlatformVk() = default; CLPlatformVk::CLPlatformVk(CLDeviceImpl::PtrList &devices)
: CLPlatformImpl(CreateDevices(*this, devices))
{}
} // namespace rx } // namespace rx
...@@ -20,14 +20,24 @@ class CLPlatformVk : public CLPlatformImpl ...@@ -20,14 +20,24 @@ class CLPlatformVk : public CLPlatformImpl
public: public:
~CLPlatformVk() override; ~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 InitList GetPlatforms();
static constexpr cl_version GetVersion(); static constexpr cl_version GetVersion();
static const std::string &GetVersionString(); static const std::string &GetVersionString();
private: private:
CLPlatformVk(); explicit CLPlatformVk(CLDeviceImpl::PtrList &devices);
}; };
constexpr cl_version CLPlatformVk::GetVersion() 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 @@ ...@@ -7,8 +7,66 @@
#include "libANGLE/validationCL_autogen.h" #include "libANGLE/validationCL_autogen.h"
#define ANGLE_ERROR_RETURN(error, ret) \
if (errcode_ret != nullptr) \
{ \
*errcode_ret = error; \
} \
return ret
namespace cl 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 1.0
cl_int ValidateGetPlatformIDs(cl_uint num_entries, cl_int ValidateGetPlatformIDs(cl_uint num_entries,
Platform *const *platforms, Platform *const *platforms,
...@@ -80,7 +138,7 @@ cl_int ValidateGetDeviceInfo(const Device *device, ...@@ -80,7 +138,7 @@ cl_int ValidateGetDeviceInfo(const Device *device,
bool ValidateCreateContext(const cl_context_properties *properties, bool ValidateCreateContext(const cl_context_properties *properties,
cl_uint num_devices, cl_uint num_devices,
Device *const *devicesPacked, Device *const *devices,
void(CL_CALLBACK *pfn_notify)(const char *errinfo, void(CL_CALLBACK *pfn_notify)(const char *errinfo,
const void *private_info, const void *private_info,
size_t cb, size_t cb,
...@@ -88,6 +146,23 @@ bool ValidateCreateContext(const cl_context_properties *properties, ...@@ -88,6 +146,23 @@ bool ValidateCreateContext(const cl_context_properties *properties,
const void *user_data, const void *user_data,
cl_int *errcode_ret) 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; return true;
} }
...@@ -100,25 +175,47 @@ bool ValidateCreateContextFromType(const cl_context_properties *properties, ...@@ -100,25 +175,47 @@ bool ValidateCreateContextFromType(const cl_context_properties *properties,
const void *user_data, const void *user_data,
cl_int *errcode_ret) 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; 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, cl_int ValidateGetContextInfo(const Context *context,
ContextInfo param_namePacked, ContextInfo param_name,
size_t param_value_size, size_t param_value_size,
const void *param_value, const void *param_value,
const size_t *param_value_size_ret) 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; return CL_SUCCESS;
} }
......
...@@ -462,6 +462,7 @@ libangle_cl_headers = [ ...@@ -462,6 +462,7 @@ libangle_cl_headers = [
"src/libANGLE/CLObject.h", "src/libANGLE/CLObject.h",
"src/libANGLE/CLPlatform.h", "src/libANGLE/CLPlatform.h",
"src/libANGLE/CLProgram.h", "src/libANGLE/CLProgram.h",
"src/libANGLE/CLRefPointer.h",
"src/libANGLE/CLSampler.h", "src/libANGLE/CLSampler.h",
"src/libANGLE/CLtypes.h", "src/libANGLE/CLtypes.h",
"src/libANGLE/renderer/CLContextImpl.h", "src/libANGLE/renderer/CLContextImpl.h",
...@@ -482,6 +483,7 @@ libangle_cl_sources = [ ...@@ -482,6 +483,7 @@ libangle_cl_sources = [
"src/libANGLE/CLPlatform.cpp", "src/libANGLE/CLPlatform.cpp",
"src/libANGLE/CLProgram.cpp", "src/libANGLE/CLProgram.cpp",
"src/libANGLE/CLSampler.cpp", "src/libANGLE/CLSampler.cpp",
"src/libANGLE/renderer/CLContextImpl.cpp",
"src/libANGLE/renderer/CLDeviceImpl.cpp", "src/libANGLE/renderer/CLDeviceImpl.cpp",
"src/libANGLE/renderer/CLPlatformImpl.cpp", "src/libANGLE/renderer/CLPlatformImpl.cpp",
"src/libANGLE/validationCL.cpp", "src/libANGLE/validationCL.cpp",
......
...@@ -85,6 +85,41 @@ cl_int GetPlatforms(cl_uint num_entries, Platform **platforms, cl_uint *num_plat ...@@ -85,6 +85,41 @@ cl_int GetPlatforms(cl_uint num_entries, Platform **platforms, cl_uint *num_plat
return CL_SUCCESS; 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 } // anonymous namespace
cl_int IcdGetPlatformIDsKHR(cl_uint num_entries, Platform **platforms, cl_uint *num_platforms) cl_int IcdGetPlatformIDsKHR(cl_uint num_entries, Platform **platforms, cl_uint *num_platforms)
...@@ -175,8 +210,15 @@ Context *CreateContext(const cl_context_properties *properties, ...@@ -175,8 +210,15 @@ Context *CreateContext(const cl_context_properties *properties,
void *user_data, void *user_data,
cl_int *errcode_ret) cl_int *errcode_ret)
{ {
WARN_NOT_SUPPORTED(CreateContext); Platform *platform = nullptr;
return 0; 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, Context *CreateContextFromType(const cl_context_properties *properties,
...@@ -188,20 +230,27 @@ Context *CreateContextFromType(const cl_context_properties *properties, ...@@ -188,20 +230,27 @@ Context *CreateContextFromType(const cl_context_properties *properties,
void *user_data, void *user_data,
cl_int *errcode_ret) cl_int *errcode_ret)
{ {
WARN_NOT_SUPPORTED(CreateContextFromType); Platform *platform = nullptr;
return 0; 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) cl_int RetainContext(Context *context)
{ {
WARN_NOT_SUPPORTED(RetainContext); context->retain();
return 0; return CL_SUCCESS;
} }
cl_int ReleaseContext(Context *context) cl_int ReleaseContext(Context *context)
{ {
WARN_NOT_SUPPORTED(ReleaseContext); context->release();
return 0; return CL_SUCCESS;
} }
cl_int GetContextInfo(Context *context, cl_int GetContextInfo(Context *context,
...@@ -210,8 +259,7 @@ cl_int GetContextInfo(Context *context, ...@@ -210,8 +259,7 @@ cl_int GetContextInfo(Context *context,
void *param_value, void *param_value,
size_t *param_value_size_ret) size_t *param_value_size_ret)
{ {
WARN_NOT_SUPPORTED(GetContextInfo); return context->getInfo(param_name, param_value_size, param_value, param_value_size_ret);
return 0;
} }
cl_int SetContextDestructorCallback(Context *context, 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