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
......
......@@ -7,6 +7,7 @@
#include "libANGLE/renderer/cl/CLDeviceCL.h"
#include "libANGLE/renderer/cl/CLPlatformCL.h"
#include "libANGLE/renderer/cl/cl_util.h"
#include "libANGLE/Debug.h"
......@@ -14,6 +15,34 @@
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()
{
if (mVersion >= CL_MAKE_VERSION(1, 2, 0) &&
......@@ -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
{
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)
cl_int CLDeviceCL::createSubDevices(const cl_device_partition_property *properties,
cl_uint numDevices,
InitList &deviceInitList,
PtrList &implList,
cl_uint *numDevicesRet)
{
if (mVersion < CL_MAKE_VERSION(1, 2, 0))
......@@ -66,6 +147,7 @@ cl_int CLDeviceCL::createSubDevices(const cl_device_partition_property *properti
return mDevice->getDispatch().clCreateSubDevices(mDevice, properties, 0u, nullptr,
numDevicesRet);
}
std::vector<cl_device_id> devices(numDevices, nullptr);
const cl_int result = mDevice->getDispatch().clCreateSubDevices(mDevice, properties, numDevices,
devices.data(), nullptr);
......@@ -73,154 +155,44 @@ cl_int CLDeviceCL::createSubDevices(const cl_device_partition_property *properti
{
for (cl_device_id device : devices)
{
CLDeviceImpl::Ptr impl(CLDeviceCL::Create(device));
CLDeviceImpl::Info info = CLDeviceCL::GetInfo(device);
if (impl && info.isValid())
implList.emplace_back(CLDeviceCL::Create(getPlatform<CLPlatformCL>(), this, device));
if (!implList.back())
{
deviceInitList.emplace_back(std::move(impl), std::move(info));
implList.clear();
return CL_INVALID_VALUE;
}
}
if (deviceInitList.size() != devices.size())
{
return CL_INVALID_VALUE;
mSubDevices.emplace_back(implList.back().get());
}
}
return result;
}
#define ANGLE_GET_INFO_SIZE(name, size_ret) \
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)
CLDeviceCL *CLDeviceCL::Create(CLPlatformCL &platform, CLDeviceCL *parent, cl_device_id device)
{
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');
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());
if (version != 0u)
{
return new CLDeviceCL(device, version);
return new CLDeviceCL(platform, parent, device, version);
}
}
}
ERR() << "Failed to query version for device";
return nullptr;
}
CLDeviceImpl::Info CLDeviceCL::GetInfo(cl_device_id device)
{
Info info;
size_t valueSize = 0u;
std::vector<char> valString;
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)
CLDeviceCL::CLDeviceCL(CLPlatformCL &platform,
CLDeviceCL *parent,
cl_device_id device,
cl_version version)
: CLDeviceImpl(platform, parent), mDevice(device), mVersion(version)
{}
} // 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;
......
......@@ -7,6 +7,7 @@
#include "libANGLE/renderer/cl/CLPlatformCL.h"
#include "libANGLE/renderer/cl/CLContextCL.h"
#include "libANGLE/renderer/cl/CLDeviceCL.h"
#include "libANGLE/renderer/cl/cl_util.h"
......@@ -23,44 +24,160 @@ extern "C" {
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
// 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.
cl_uint numDevices = 0u;
if (mPlatform->getDispatch().clGetDeviceIDs(mPlatform, CL_DEVICE_TYPE_ALL, 0u, nullptr,
&numDevices) == CL_SUCCESS)
if (native->getDispatch().clGetDeviceIDs(native, CL_DEVICE_TYPE_ALL, 0u, nullptr,
&numDevices) == CL_SUCCESS)
{
std::vector<cl_device_id> devices(numDevices, nullptr);
if (mPlatform->getDispatch().clGetDeviceIDs(mPlatform, CL_DEVICE_TYPE_ALL, numDevices,
devices.data(), nullptr) == CL_SUCCESS)
if (native->getDispatch().clGetDeviceIDs(native, CL_DEVICE_TYPE_ALL, numDevices,
devices.data(), nullptr) == CL_SUCCESS)
{
for (cl_device_id device : devices)
{
CLDeviceImpl::Ptr impl(CLDeviceCL::Create(device));
CLDeviceImpl::Info info = CLDeviceCL::GetInfo(device);
if (impl && info.isValid())
CLDeviceImpl::Ptr impl(CLDeviceCL::Create(platform, nullptr, device));
if (!impl)
{
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";
}
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)
{
ERR() << "Failed to query CL devices";
return std::string(str.data());
}
}
else
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)
{
ERR() << "Failed to query CL devices";
devices.emplace_back(static_cast<CLDeviceCL *>(deviceImpl)->getNative());
}
return initList;
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
{
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;
}
}
context->getDispatch().clReleaseContext(context);
if (errcodeRet != nullptr)
{
*errcodeRet = result;
}
return CLContextImpl::Ptr{};
}
CLPlatformCL::InitList CLPlatformCL::GetPlatforms(bool isIcd)
......@@ -97,14 +214,25 @@ CLPlatformCL::InitList CLPlatformCL::GetPlatforms(bool isIcd)
Info info = GetInfo(vendorIt->platform);
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;
}
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) \
platform->getDispatch().clGetPlatformInfo(platform, name, 0u, nullptr, size_ret)
......@@ -134,10 +262,6 @@ CLPlatformCL::CLPlatformCL(cl_platform_id platform) : mPlatform(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
if (platform == nullptr || platform->getDispatch().clGetPlatformIDs == nullptr ||
platform->getDispatch().clGetPlatformInfo == nullptr ||
......@@ -206,76 +330,98 @@ CLPlatformImpl::Info CLPlatformCL::GetInfo(cl_platform_id platform)
platform->getDispatch().clGetExtensionFunctionAddress == nullptr)
{
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
ANGLE_GET_INFO_SIZE_RET(CL_PLATFORM_VENDOR, &valueSize);
valString.resize(valueSize, '\0');
ANGLE_GET_INFO_RET(CL_PLATFORM_VENDOR, valueSize, valString.data());
if (std::string(valString.data()).compare(cl::Platform::GetVendor()) == 0)
if (vendor.compare(cl::Platform::GetVendor()) == 0)
{
ERR() << "Tried to create CL pass-through back end for ANGLE library";
return info;
return Info{};
}
// 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)
{
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);
if (version == 0u)
{
return info;
return Info{};
}
if (ANGLE_GET_INFO(CL_PLATFORM_NUMERIC_VERSION, sizeof(info.mVersion), &info.mVersion) !=
CL_SUCCESS)
// 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)
{
info.mVersion = version;
ERR() << "Failed to query CL platform info for CL_PLATFORM_HOST_TIMER_RESOLUTION";
return Info{};
}
else if (CL_VERSION_MAJOR(info.mVersion) != CL_VERSION_MAJOR(version) ||
CL_VERSION_MINOR(info.mVersion) != CL_VERSION_MINOR(version))
if (version < CL_MAKE_VERSION(3, 0, 0))
{
WARN() << "CL_PLATFORM_NUMERIC_VERSION = " << CL_VERSION_MAJOR(info.mVersion) << '.'
<< CL_VERSION_MINOR(info.mVersion)
<< " does not match version string: " << info.mVersionStr;
info.mVersion = version;
}
ANGLE_GET_INFO_SIZE_RET(CL_PLATFORM_NAME, &valueSize);
valString.resize(valueSize, '\0');
ANGLE_GET_INFO_RET(CL_PLATFORM_NAME, valueSize, valString.data());
info.mName.assign("ANGLE pass-through -> ");
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)
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) ||
CL_VERSION_MINOR(info.mVersion) != CL_VERSION_MINOR(version))
{
WARN() << "CL_PLATFORM_NUMERIC_VERSION = " << CL_VERSION_MAJOR(info.mVersion) << '.'
<< CL_VERSION_MINOR(info.mVersion)
<< " does not match version string: " << info.mVersionStr;
}
size_t valueSize = 0u;
if (platform->getDispatch().clGetPlatformInfo(platform, CL_PLATFORM_EXTENSIONS_WITH_VERSION,
0u, nullptr, &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(
valueSize / sizeof(decltype(info.mExtensionsWithVersion)::value_type));
ANGLE_GET_INFO_RET(CL_PLATFORM_EXTENSIONS_WITH_VERSION, valueSize,
info.mExtensionsWithVersion.data());
if (platform->getDispatch().clGetPlatformInfo(platform, CL_PLATFORM_EXTENSIONS_WITH_VERSION,
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);
}
ANGLE_GET_INFO(CL_PLATFORM_HOST_TIMER_RESOLUTION, sizeof(info.mHostTimerRes),
&info.mHostTimerRes);
if (info.mVersion >= CL_MAKE_VERSION(1, 1, 0) &&
(platform->getDispatch().clSetEventCallback == nullptr ||
platform->getDispatch().clCreateSubBuffer == nullptr ||
......@@ -360,12 +506,6 @@ CLPlatformImpl::Info CLPlatformCL::GetInfo(cl_platform_id platform)
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;
}
......
......@@ -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