Commit 9459456b by John Plate Committed by Angle LUCI CQ

CL: kernel creation for front end & passthrough

Add kernel object to back end and implement creation and info query. Bug: angleproject:6001 Change-Id: I6e3fdd2b35d7e73ed56144dc938bf21436d3559f Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/2922150 Commit-Queue: John Plate <jplate@google.com> Reviewed-by: 's avatarJamie Madill <jmadill@chromium.org> Reviewed-by: 's avatarCody Northrop <cnorthrop@google.com>
parent 4a697276
...@@ -47,7 +47,7 @@ cl_int Context::getInfo(ContextInfo name, size_t valueSize, void *value, size_t ...@@ -47,7 +47,7 @@ cl_int Context::getInfo(ContextInfo name, size_t valueSize, void *value, size_t
break; break;
case ContextInfo::Devices: case ContextInfo::Devices:
static_assert(sizeof(decltype(mDevices)::value_type) == sizeof(Device *), static_assert(sizeof(decltype(mDevices)::value_type) == sizeof(Device *),
"DeviceRefList has wrong element size"); "DeviceRefs has wrong element size");
copyValue = mDevices.data(); copyValue = mDevices.data();
copySize = mDevices.size() * sizeof(decltype(mDevices)::value_type); copySize = mDevices.size() * sizeof(decltype(mDevices)::value_type);
break; break;
...@@ -261,7 +261,7 @@ cl_program Context::createProgramWithBinary(cl_uint numDevices, ...@@ -261,7 +261,7 @@ cl_program Context::createProgramWithBinary(cl_uint numDevices,
cl_int *binaryStatus, cl_int *binaryStatus,
cl_int &errorCode) cl_int &errorCode)
{ {
DeviceRefList refDevices; DeviceRefs refDevices;
Binaries binaryVec; Binaries binaryVec;
while (numDevices-- != 0u) while (numDevices-- != 0u)
{ {
...@@ -278,7 +278,7 @@ cl_program Context::createProgramWithBuiltInKernels(cl_uint numDevices, ...@@ -278,7 +278,7 @@ cl_program Context::createProgramWithBuiltInKernels(cl_uint numDevices,
const char *kernelNames, const char *kernelNames,
cl_int &errorCode) cl_int &errorCode)
{ {
DeviceRefList refDevices; DeviceRefs refDevices;
while (numDevices-- != 0u) while (numDevices-- != 0u)
{ {
refDevices.emplace_back(static_cast<Device *>(*devices++)); refDevices.emplace_back(static_cast<Device *>(*devices++));
...@@ -318,7 +318,7 @@ void Context::ErrorCallback(const char *errinfo, const void *privateInfo, size_t ...@@ -318,7 +318,7 @@ void Context::ErrorCallback(const char *errinfo, const void *privateInfo, size_t
Context::Context(Platform &platform, Context::Context(Platform &platform,
PropArray &&properties, PropArray &&properties,
DeviceRefList &&devices, DeviceRefs &&devices,
ContextErrorCB notify, ContextErrorCB notify,
void *userData, void *userData,
bool userSync, bool userSync,
...@@ -345,7 +345,7 @@ Context::Context(Platform &platform, ...@@ -345,7 +345,7 @@ Context::Context(Platform &platform,
mNotify(notify), mNotify(notify),
mUserData(userData), mUserData(userData),
mImpl(platform.mImpl->createContextFromType(*this, deviceType, userSync, errorCode)), mImpl(platform.mImpl->createContextFromType(*this, deviceType, userSync, errorCode)),
mDevices(mImpl ? mImpl->getDevices(errorCode) : DeviceRefList{}) mDevices(mImpl ? mImpl->getDevices(errorCode) : DeviceRefs{})
{} {}
cl_command_queue Context::createCommandQueue(CommandQueue *commandQueue) cl_command_queue Context::createCommandQueue(CommandQueue *commandQueue)
......
...@@ -29,7 +29,7 @@ class Context final : public _cl_context, public Object ...@@ -29,7 +29,7 @@ class Context final : public _cl_context, public Object
const Platform &getPlatform() const noexcept; const Platform &getPlatform() const noexcept;
bool hasDevice(const _cl_device_id *device) const; bool hasDevice(const _cl_device_id *device) const;
const DeviceRefList &getDevices() const; const DeviceRefs &getDevices() const;
bool supportsImages() const; bool supportsImages() const;
bool supportsIL() const; bool supportsIL() const;
...@@ -39,6 +39,7 @@ class Context final : public _cl_context, public Object ...@@ -39,6 +39,7 @@ class Context final : public _cl_context, public Object
bool hasMemory(const _cl_mem *memory) const; bool hasMemory(const _cl_mem *memory) const;
bool hasSampler(const _cl_sampler *sampler) const; bool hasSampler(const _cl_sampler *sampler) const;
bool hasProgram(const _cl_program *program) const; bool hasProgram(const _cl_program *program) const;
bool hasKernel(const _cl_kernel *kernel) const;
void retain() noexcept; void retain() noexcept;
bool release(); bool release();
...@@ -122,7 +123,7 @@ class Context final : public _cl_context, public Object ...@@ -122,7 +123,7 @@ class Context final : public _cl_context, public Object
private: private:
Context(Platform &platform, Context(Platform &platform,
PropArray &&properties, PropArray &&properties,
DeviceRefList &&devices, DeviceRefs &&devices,
ContextErrorCB notify, ContextErrorCB notify,
void *userData, void *userData,
bool userSync, bool userSync,
...@@ -151,7 +152,7 @@ class Context final : public _cl_context, public Object ...@@ -151,7 +152,7 @@ class Context final : public _cl_context, public Object
const ContextErrorCB mNotify; const ContextErrorCB mNotify;
void *const mUserData; void *const mUserData;
const rx::CLContextImpl::Ptr mImpl; const rx::CLContextImpl::Ptr mImpl;
const DeviceRefList mDevices; const DeviceRefs mDevices;
CommandQueue::PtrList mCommandQueues; CommandQueue::PtrList mCommandQueues;
Memory::PtrList mMemories; Memory::PtrList mMemories;
...@@ -178,7 +179,7 @@ inline bool Context::hasDevice(const _cl_device_id *device) const ...@@ -178,7 +179,7 @@ inline bool Context::hasDevice(const _cl_device_id *device) const
}) != mDevices.cend(); }) != mDevices.cend();
} }
inline const DeviceRefList &Context::getDevices() const inline const DeviceRefs &Context::getDevices() const
{ {
return mDevices; return mDevices;
} }
...@@ -232,6 +233,13 @@ inline bool Context::hasProgram(const _cl_program *program) const ...@@ -232,6 +233,13 @@ inline bool Context::hasProgram(const _cl_program *program) const
}) != mPrograms.cend(); }) != mPrograms.cend();
} }
inline bool Context::hasKernel(const _cl_kernel *kernel) const
{
return std::find_if(mPrograms.cbegin(), mPrograms.cend(), [=](const ProgramPtr &ptr) {
return ptr->hasKernel(kernel);
}) != mPrograms.cend();
}
inline void Context::retain() noexcept inline void Context::retain() noexcept
{ {
addRef(); addRef();
......
...@@ -97,7 +97,7 @@ inline bool Device::isRoot() const noexcept ...@@ -97,7 +97,7 @@ inline bool Device::isRoot() const noexcept
template <typename T> template <typename T>
inline T &Device::getImpl() const inline T &Device::getImpl() const
{ {
return static_cast<T>(*mImpl); return static_cast<T &>(*mImpl);
} }
inline const rx::CLDeviceImpl::Info &Device::getInfo() const inline const rx::CLDeviceImpl::Info &Device::getInfo() const
......
...@@ -7,9 +7,242 @@ ...@@ -7,9 +7,242 @@
#include "libANGLE/CLKernel.h" #include "libANGLE/CLKernel.h"
#include "libANGLE/CLPlatform.h"
#include "libANGLE/CLProgram.h"
#include <cstring>
namespace cl namespace cl
{ {
Kernel::Kernel(const cl_icd_dispatch &dispatch) : _cl_kernel(dispatch) {} Kernel::~Kernel() = default;
bool Kernel::release()
{
const bool released = removeRef();
if (released)
{
mProgram->destroyKernel(this);
}
return released;
}
cl_int Kernel::getInfo(KernelInfo name, size_t valueSize, void *value, size_t *valueSizeRet) const
{
void *valPointer = nullptr;
const void *copyValue = nullptr;
size_t copySize = 0u;
switch (name)
{
case KernelInfo::FunctionName:
copyValue = mInfo.mFunctionName.c_str();
copySize = mInfo.mFunctionName.length() + 1u;
break;
case KernelInfo::NumArgs:
copyValue = &mInfo.mNumArgs;
copySize = sizeof(mInfo.mNumArgs);
break;
case KernelInfo::ReferenceCount:
copyValue = getRefCountPtr();
copySize = sizeof(*getRefCountPtr());
break;
case KernelInfo::Context:
valPointer = static_cast<cl_context>(&mProgram->getContext());
copyValue = &valPointer;
copySize = sizeof(valPointer);
break;
case KernelInfo::Program:
valPointer = static_cast<cl_program>(mProgram.get());
copyValue = &valPointer;
copySize = sizeof(valPointer);
break;
case KernelInfo::Attributes:
copyValue = mInfo.mAttributes.c_str();
copySize = mInfo.mAttributes.length() + 1u;
break;
default:
return CL_INVALID_VALUE;
}
if (value != nullptr)
{
// CL_INVALID_VALUE if size in bytes specified by param_value_size is < size of return type
// as described in the Kernel Object Queries table and param_value is not NULL.
if (valueSize < copySize)
{
return CL_INVALID_VALUE;
}
if (copyValue != nullptr)
{
std::memcpy(value, copyValue, copySize);
}
}
if (valueSizeRet != nullptr)
{
*valueSizeRet = copySize;
}
return CL_SUCCESS;
}
cl_int Kernel::getWorkGroupInfo(cl_device_id device,
KernelWorkGroupInfo name,
size_t valueSize,
void *value,
size_t *valueSizeRet) const
{
size_t index = 0u;
if (device != nullptr)
{
const DeviceRefs &devices = mProgram->getContext().getDevices();
while (index < devices.size() && devices[index].get() != device)
{
++index;
}
if (index == devices.size())
{
return CL_INVALID_DEVICE;
}
}
const rx::CLKernelImpl::WorkGroupInfo &info = mInfo.mWorkGroups[index];
const void *copyValue = nullptr;
size_t copySize = 0u;
switch (name)
{
case KernelWorkGroupInfo::GlobalWorkSize:
copyValue = &info.mGlobalWorkSize;
copySize = sizeof(info.mGlobalWorkSize);
break;
case KernelWorkGroupInfo::WorkGroupSize:
copyValue = &info.mWorkGroupSize;
copySize = sizeof(info.mWorkGroupSize);
break;
case KernelWorkGroupInfo::CompileWorkGroupSize:
copyValue = &info.mCompileWorkGroupSize;
copySize = sizeof(info.mCompileWorkGroupSize);
break;
case KernelWorkGroupInfo::LocalMemSize:
copyValue = &info.mLocalMemSize;
copySize = sizeof(info.mLocalMemSize);
break;
case KernelWorkGroupInfo::PreferredWorkGroupSizeMultiple:
copyValue = &info.mPrefWorkGroupSizeMultiple;
copySize = sizeof(info.mPrefWorkGroupSizeMultiple);
break;
case KernelWorkGroupInfo::PrivateMemSize:
copyValue = &info.mPrivateMemSize;
copySize = sizeof(info.mPrivateMemSize);
break;
default:
return CL_INVALID_VALUE;
}
if (value != nullptr)
{
// CL_INVALID_VALUE if size in bytes specified by param_value_size is < size of return type
// as described in the Kernel Object Device Queries table and param_value is not NULL.
if (valueSize < copySize)
{
return CL_INVALID_VALUE;
}
if (copyValue != nullptr)
{
std::memcpy(value, copyValue, copySize);
}
}
if (valueSizeRet != nullptr)
{
*valueSizeRet = copySize;
}
return CL_SUCCESS;
}
cl_int Kernel::getArgInfo(cl_uint argIndex,
KernelArgInfo name,
size_t valueSize,
void *value,
size_t *valueSizeRet) const
{
const rx::CLKernelImpl::ArgInfo &info = mInfo.mArgs[argIndex];
const void *copyValue = nullptr;
size_t copySize = 0u;
switch (name)
{
case KernelArgInfo::AddressQualifier:
copyValue = &info.mAddressQualifier;
copySize = sizeof(info.mAddressQualifier);
break;
case KernelArgInfo::AccessQualifier:
copyValue = &info.mAccessQualifier;
copySize = sizeof(info.mAccessQualifier);
break;
case KernelArgInfo::TypeName:
copyValue = info.mTypeName.c_str();
copySize = info.mTypeName.length() + 1u;
break;
case KernelArgInfo::TypeQualifier:
copyValue = &info.mTypeQualifier;
copySize = sizeof(info.mTypeQualifier);
break;
case KernelArgInfo::Name:
copyValue = info.mName.c_str();
copySize = info.mName.length() + 1u;
break;
default:
return CL_INVALID_VALUE;
}
if (value != nullptr)
{
// CL_INVALID_VALUE if size in bytes specified by param_value size is < size of return type
// as described in the Kernel Argument Queries table and param_value is not NULL.
if (valueSize < copySize)
{
return CL_INVALID_VALUE;
}
if (copyValue != nullptr)
{
std::memcpy(value, copyValue, copySize);
}
}
if (valueSizeRet != nullptr)
{
*valueSizeRet = copySize;
}
return CL_SUCCESS;
}
bool Kernel::IsValid(const _cl_kernel *kernel)
{
const Platform::PtrList &platforms = Platform::GetPlatforms();
return std::find_if(platforms.cbegin(), platforms.cend(), [=](const PlatformPtr &platform) {
return platform->hasKernel(kernel);
}) != platforms.cend();
}
bool Kernel::IsValidAndVersionOrNewer(const _cl_kernel *kernel, cl_uint major, cl_uint minor)
{
const Platform::PtrList &platforms = Platform::GetPlatforms();
return std::find_if(platforms.cbegin(), platforms.cend(), [=](const PlatformPtr &platform) {
return platform->isVersionOrNewer(major, minor) && platform->hasKernel(kernel);
}) != platforms.cend();
}
Kernel::Kernel(Program &program, const char *name, cl_int &errorCode)
: _cl_kernel(program.getDispatch()),
mProgram(&program),
mImpl(program.mImpl->createKernel(*this, name, errorCode)),
mInfo(mImpl ? mImpl->createInfo(errorCode) : rx::CLKernelImpl::Info{})
{}
Kernel::Kernel(Program &program, const CreateImplFunc &createImplFunc, cl_int &errorCode)
: _cl_kernel(program.getDispatch()),
mProgram(&program),
mImpl(createImplFunc(*this)),
mInfo(mImpl->createInfo(errorCode))
{}
} // namespace cl } // namespace cl
...@@ -9,6 +9,7 @@ ...@@ -9,6 +9,7 @@
#define LIBANGLE_CLKERNEL_H_ #define LIBANGLE_CLKERNEL_H_
#include "libANGLE/CLObject.h" #include "libANGLE/CLObject.h"
#include "libANGLE/renderer/CLKernelImpl.h"
namespace cl namespace cl
{ {
...@@ -16,10 +17,69 @@ namespace cl ...@@ -16,10 +17,69 @@ namespace cl
class Kernel final : public _cl_kernel, public Object class Kernel final : public _cl_kernel, public Object
{ {
public: public:
Kernel(const cl_icd_dispatch &dispatch); using PtrList = std::list<KernelPtr>;
~Kernel() override = default; using CreateImplFunc = std::function<rx::CLKernelImpl::Ptr(const cl::Kernel &)>;
~Kernel() override;
const Program &getProgram() const;
const rx::CLKernelImpl::Info &getInfo() const;
template <typename T>
T &getImpl() const;
void retain() noexcept;
bool release();
cl_int getInfo(KernelInfo name, size_t valueSize, void *value, size_t *valueSizeRet) const;
cl_int getWorkGroupInfo(cl_device_id device,
KernelWorkGroupInfo name,
size_t valueSize,
void *value,
size_t *valueSizeRet) const;
cl_int getArgInfo(cl_uint argIndex,
KernelArgInfo name,
size_t valueSize,
void *value,
size_t *valueSizeRet) const;
static bool IsValid(const _cl_kernel *kernel);
static bool IsValidAndVersionOrNewer(const _cl_kernel *kernel, cl_uint major, cl_uint minor);
private:
Kernel(Program &program, const char *name, cl_int &errorCode);
Kernel(Program &program, const CreateImplFunc &createImplFunc, cl_int &errorCode);
const ProgramRefPtr mProgram;
const rx::CLKernelImpl::Ptr mImpl;
const rx::CLKernelImpl::Info mInfo;
friend class Program;
}; };
inline const Program &Kernel::getProgram() const
{
return *mProgram;
}
inline const rx::CLKernelImpl::Info &Kernel::getInfo() const
{
return mInfo;
}
template <typename T>
inline T &Kernel::getImpl() const
{
return static_cast<T &>(*mImpl);
}
inline void Kernel::retain() noexcept
{
addRef();
}
} // namespace cl } // namespace cl
#endif // LIBANGLE_CLKERNEL_H_ #endif // LIBANGLE_CLKERNEL_H_
...@@ -207,7 +207,7 @@ cl_context Platform::CreateContext(const cl_context_properties *properties, ...@@ -207,7 +207,7 @@ cl_context Platform::CreateContext(const cl_context_properties *properties,
bool userSync = false; bool userSync = false;
Context::PropArray propArray = ParseContextProperties(properties, platform, userSync); Context::PropArray propArray = ParseContextProperties(properties, platform, userSync);
ASSERT(platform != nullptr); ASSERT(platform != nullptr);
DeviceRefList refDevices; DeviceRefs refDevices;
while (numDevices-- != 0u) while (numDevices-- != 0u)
{ {
refDevices.emplace_back(static_cast<Device *>(*devices++)); refDevices.emplace_back(static_cast<Device *>(*devices++));
......
...@@ -36,6 +36,7 @@ class Platform final : public _cl_platform_id, public Object ...@@ -36,6 +36,7 @@ class Platform final : public _cl_platform_id, public Object
bool hasMemory(const _cl_mem *memory) const; bool hasMemory(const _cl_mem *memory) const;
bool hasSampler(const _cl_sampler *sampler) const; bool hasSampler(const _cl_sampler *sampler) const;
bool hasProgram(const _cl_program *program) const; bool hasProgram(const _cl_program *program) const;
bool hasKernel(const _cl_kernel *kernel) const;
cl_int getInfo(PlatformInfo name, size_t valueSize, void *value, size_t *valueSizeRet) const; cl_int getInfo(PlatformInfo name, size_t valueSize, void *value, size_t *valueSizeRet) const;
...@@ -149,6 +150,13 @@ inline bool Platform::hasProgram(const _cl_program *program) const ...@@ -149,6 +150,13 @@ inline bool Platform::hasProgram(const _cl_program *program) const
}) != mContexts.cend(); }) != mContexts.cend();
} }
inline bool Platform::hasKernel(const _cl_kernel *kernel) const
{
return std::find_if(mContexts.cbegin(), mContexts.cend(), [=](const ContextPtr &ptr) {
return ptr->hasKernel(kernel);
}) != mContexts.cend();
}
inline Platform::PtrList &Platform::GetList() inline Platform::PtrList &Platform::GetList()
{ {
static angle::base::NoDestructor<PtrList> sList; static angle::base::NoDestructor<PtrList> sList;
......
...@@ -10,6 +10,8 @@ ...@@ -10,6 +10,8 @@
#include "libANGLE/CLContext.h" #include "libANGLE/CLContext.h"
#include "libANGLE/CLPlatform.h" #include "libANGLE/CLPlatform.h"
#include <cstring>
namespace cl namespace cl
{ {
...@@ -27,7 +29,8 @@ bool Program::release() ...@@ -27,7 +29,8 @@ bool Program::release()
cl_int Program::getInfo(ProgramInfo name, size_t valueSize, void *value, size_t *valueSizeRet) const cl_int Program::getInfo(ProgramInfo name, size_t valueSize, void *value, size_t *valueSizeRet) const
{ {
static_assert(std::is_same<cl_uint, cl_addressing_mode>::value && static_assert(std::is_same<cl_uint, cl_bool>::value &&
std::is_same<cl_uint, cl_addressing_mode>::value &&
std::is_same<cl_uint, cl_filter_mode>::value, std::is_same<cl_uint, cl_filter_mode>::value,
"OpenCL type mismatch"); "OpenCL type mismatch");
...@@ -56,7 +59,7 @@ cl_int Program::getInfo(ProgramInfo name, size_t valueSize, void *value, size_t ...@@ -56,7 +59,7 @@ cl_int Program::getInfo(ProgramInfo name, size_t valueSize, void *value, size_t
break; break;
case ProgramInfo::Devices: case ProgramInfo::Devices:
static_assert(sizeof(decltype(mDevices)::value_type) == sizeof(Device *), static_assert(sizeof(decltype(mDevices)::value_type) == sizeof(Device *),
"DeviceRefList has wrong element size"); "DeviceRefs has wrong element size");
copyValue = mDevices.data(); copyValue = mDevices.data();
copySize = mDevices.size() * sizeof(decltype(mDevices)::value_type); copySize = mDevices.size() * sizeof(decltype(mDevices)::value_type);
break; break;
...@@ -89,9 +92,23 @@ cl_int Program::getInfo(ProgramInfo name, size_t valueSize, void *value, size_t ...@@ -89,9 +92,23 @@ cl_int Program::getInfo(ProgramInfo name, size_t valueSize, void *value, size_t
copySize = binaries.size() * sizeof(decltype(binaries)::value_type); copySize = binaries.size() * sizeof(decltype(binaries)::value_type);
break; break;
case ProgramInfo::NumKernels: case ProgramInfo::NumKernels:
copyValue = &mNumKernels;
copySize = sizeof(mNumKernels);
break;
case ProgramInfo::KernelNames: case ProgramInfo::KernelNames:
copyValue = mKernelNames.c_str();
copySize = mKernelNames.length() + 1u;
break;
case ProgramInfo::ScopeGlobalCtorsPresent: case ProgramInfo::ScopeGlobalCtorsPresent:
valUInt = CL_FALSE;
copyValue = &valUInt;
copySize = sizeof(valUInt);
break;
case ProgramInfo::ScopeGlobalDtorsPresent: case ProgramInfo::ScopeGlobalDtorsPresent:
valUInt = CL_FALSE;
copyValue = &valUInt;
copySize = sizeof(valUInt);
break;
default: default:
return CL_INVALID_VALUE; return CL_INVALID_VALUE;
} }
...@@ -116,6 +133,47 @@ cl_int Program::getInfo(ProgramInfo name, size_t valueSize, void *value, size_t ...@@ -116,6 +133,47 @@ cl_int Program::getInfo(ProgramInfo name, size_t valueSize, void *value, size_t
return CL_SUCCESS; return CL_SUCCESS;
} }
cl_kernel Program::createKernel(const char *kernel_name, cl_int &errorCode)
{
return createKernel(new Kernel(*this, kernel_name, errorCode));
}
cl_int Program::createKernel(const Kernel::CreateImplFunc &createImplFunc)
{
cl_int errorCode = CL_SUCCESS;
createKernel(new Kernel(*this, createImplFunc, errorCode));
return errorCode;
}
cl_int Program::createKernels(cl_uint numKernels, cl_kernel *kernels, cl_uint *numKernelsRet)
{
cl_int errorCode = mImpl->createKernels(*this);
if (errorCode == CL_SUCCESS)
{
// CL_INVALID_VALUE if kernels is not NULL and
// num_kernels is less than the number of kernels in program.
if (kernels != nullptr && numKernels < mKernels.size())
{
errorCode = CL_INVALID_VALUE;
}
else
{
if (kernels != nullptr)
{
for (const KernelPtr &kernel : mKernels)
{
*kernels++ = kernel.get();
}
}
if (numKernelsRet != nullptr)
{
*numKernelsRet = static_cast<cl_uint>(mKernels.size());
}
}
}
return errorCode;
}
bool Program::IsValid(const _cl_program *program) bool Program::IsValid(const _cl_program *program)
{ {
const Platform::PtrList &platforms = Platform::GetPlatforms(); const Platform::PtrList &platforms = Platform::GetPlatforms();
...@@ -142,7 +200,7 @@ Program::Program(Context &context, const void *il, size_t length, cl_int &errorC ...@@ -142,7 +200,7 @@ Program::Program(Context &context, const void *il, size_t length, cl_int &errorC
{} {}
Program::Program(Context &context, Program::Program(Context &context,
DeviceRefList &&devices, DeviceRefs &&devices,
Binaries &&binaries, Binaries &&binaries,
cl_int *binaryStatus, cl_int *binaryStatus,
cl_int &errorCode) cl_int &errorCode)
...@@ -154,10 +212,7 @@ Program::Program(Context &context, ...@@ -154,10 +212,7 @@ Program::Program(Context &context,
mBinaries(std::move(binaries)) mBinaries(std::move(binaries))
{} {}
Program::Program(Context &context, Program::Program(Context &context, DeviceRefs &&devices, const char *kernelNames, cl_int &errorCode)
DeviceRefList &&devices,
const char *kernelNames,
cl_int &errorCode)
: _cl_program(context.getDispatch()), : _cl_program(context.getDispatch()),
mContext(&context), mContext(&context),
mDevices(std::move(devices)), mDevices(std::move(devices)),
...@@ -165,4 +220,32 @@ Program::Program(Context &context, ...@@ -165,4 +220,32 @@ Program::Program(Context &context,
mSource(mImpl ? mImpl->getSource(errorCode) : std::string{}) mSource(mImpl ? mImpl->getSource(errorCode) : std::string{})
{} {}
cl_kernel Program::createKernel(Kernel *kernel)
{
mKernels.emplace_back(kernel);
if (!mKernels.back()->mImpl)
{
mKernels.back()->release();
return nullptr;
}
return mKernels.back().get();
}
void Program::destroyKernel(Kernel *kernel)
{
auto kernelIt = mKernels.cbegin();
while (kernelIt != mKernels.cend() && kernelIt->get() != kernel)
{
++kernelIt;
}
if (kernelIt != mKernels.cend())
{
mKernels.erase(kernelIt);
}
else
{
ERR() << "Kernel not found";
}
}
} // namespace cl } // namespace cl
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
#ifndef LIBANGLE_CLPROGRAM_H_ #ifndef LIBANGLE_CLPROGRAM_H_
#define LIBANGLE_CLPROGRAM_H_ #define LIBANGLE_CLPROGRAM_H_
#include "libANGLE/CLObject.h" #include "libANGLE/CLKernel.h"
#include "libANGLE/renderer/CLProgramImpl.h" #include "libANGLE/renderer/CLProgramImpl.h"
namespace cl namespace cl
...@@ -21,14 +21,22 @@ class Program final : public _cl_program, public Object ...@@ -21,14 +21,22 @@ class Program final : public _cl_program, public Object
~Program() override; ~Program() override;
Context &getContext();
const Context &getContext() const; const Context &getContext() const;
const DeviceRefList &getDevices() const; const DeviceRefs &getDevices() const;
const Kernel::PtrList &getKernels() const;
bool hasKernel(const _cl_kernel *kernel) const;
void retain() noexcept; void retain() noexcept;
bool release(); bool release();
cl_int getInfo(ProgramInfo name, size_t valueSize, void *value, size_t *valueSizeRet) const; cl_int getInfo(ProgramInfo name, size_t valueSize, void *value, size_t *valueSizeRet) const;
cl_kernel createKernel(const char *kernel_name, cl_int &errorCode);
cl_int createKernel(const Kernel::CreateImplFunc &createImplFunc);
cl_int createKernels(cl_uint numKernels, cl_kernel *kernels, cl_uint *numKernelsRet);
static bool IsValid(const _cl_program *program); static bool IsValid(const _cl_program *program);
private: private:
...@@ -36,34 +44,59 @@ class Program final : public _cl_program, public Object ...@@ -36,34 +44,59 @@ class Program final : public _cl_program, public Object
Program(Context &context, const void *il, size_t length, cl_int &errorCode); Program(Context &context, const void *il, size_t length, cl_int &errorCode);
Program(Context &context, Program(Context &context,
DeviceRefList &&devices, DeviceRefs &&devices,
Binaries &&binaries, Binaries &&binaries,
cl_int *binaryStatus, cl_int *binaryStatus,
cl_int &errorCode); cl_int &errorCode);
Program(Context &context, DeviceRefList &&devices, const char *kernelNames, cl_int &errorCode); Program(Context &context, DeviceRefs &&devices, const char *kernelNames, cl_int &errorCode);
cl_kernel createKernel(Kernel *kernel);
void destroyKernel(Kernel *kernel);
const ContextRefPtr mContext; const ContextRefPtr mContext;
const DeviceRefList mDevices; const DeviceRefs mDevices;
const std::string mIL; const std::string mIL;
const rx::CLProgramImpl::Ptr mImpl; const rx::CLProgramImpl::Ptr mImpl;
const std::string mSource; const std::string mSource;
Binaries mBinaries; Binaries mBinaries;
size_t mNumKernels;
std::string mKernelNames;
Kernel::PtrList mKernels;
friend class Context; friend class Context;
friend class Kernel;
}; };
inline Context &Program::getContext()
{
return *mContext;
}
inline const Context &Program::getContext() const inline const Context &Program::getContext() const
{ {
return *mContext; return *mContext;
} }
inline const DeviceRefList &Program::getDevices() const inline const DeviceRefs &Program::getDevices() const
{ {
return mDevices; return mDevices;
} }
inline const Kernel::PtrList &Program::getKernels() const
{
return mKernels;
}
inline bool Program::hasKernel(const _cl_kernel *kernel) const
{
return std::find_if(mKernels.cbegin(), mKernels.cend(), [=](const KernelPtr &ptr) {
return ptr.get() == kernel;
}) != mKernels.cend();
}
inline void Program::retain() noexcept inline void Program::retain() noexcept
{ {
addRef(); addRef();
......
...@@ -52,9 +52,10 @@ using SamplerPtr = std::unique_ptr<Sampler>; ...@@ -52,9 +52,10 @@ using SamplerPtr = std::unique_ptr<Sampler>;
using ContextRefPtr = RefPointer<Context>; using ContextRefPtr = RefPointer<Context>;
using DeviceRefPtr = RefPointer<Device>; using DeviceRefPtr = RefPointer<Device>;
using MemoryRefPtr = RefPointer<Memory>; using MemoryRefPtr = RefPointer<Memory>;
using ProgramRefPtr = RefPointer<Program>;
using DevicePtrList = std::list<DevicePtr>; using DevicePtrList = std::list<DevicePtr>;
using DeviceRefList = std::vector<DeviceRefPtr>; using DeviceRefs = std::vector<DeviceRefPtr>;
using Binary = std::vector<unsigned char>; using Binary = std::vector<unsigned char>;
using Binaries = std::vector<Binary>; using Binaries = std::vector<Binary>;
......
...@@ -25,7 +25,7 @@ class CLContextImpl : angle::NonCopyable ...@@ -25,7 +25,7 @@ class CLContextImpl : angle::NonCopyable
CLContextImpl(const cl::Context &context); CLContextImpl(const cl::Context &context);
virtual ~CLContextImpl(); virtual ~CLContextImpl();
virtual cl::DeviceRefList getDevices(cl_int &errorCode) const = 0; virtual cl::DeviceRefs getDevices(cl_int &errorCode) const = 0;
virtual CLCommandQueueImpl::Ptr createCommandQueue(const cl::CommandQueue &commandQueue, virtual CLCommandQueueImpl::Ptr createCommandQueue(const cl::CommandQueue &commandQueue,
cl_int &errorCode) = 0; cl_int &errorCode) = 0;
......
//
// 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.
//
// CLKernelImpl.cpp: Implements the class methods for CLKernelImpl.
#include "libANGLE/renderer/CLKernelImpl.h"
namespace rx
{
CLKernelImpl::WorkGroupInfo::WorkGroupInfo() = default;
CLKernelImpl::WorkGroupInfo::~WorkGroupInfo() = default;
CLKernelImpl::WorkGroupInfo::WorkGroupInfo(WorkGroupInfo &&) = default;
CLKernelImpl::WorkGroupInfo &CLKernelImpl::WorkGroupInfo::operator=(WorkGroupInfo &&) = default;
CLKernelImpl::ArgInfo::ArgInfo() = default;
CLKernelImpl::ArgInfo::~ArgInfo() = default;
CLKernelImpl::ArgInfo::ArgInfo(ArgInfo &&) = default;
CLKernelImpl::ArgInfo &CLKernelImpl::ArgInfo::operator=(ArgInfo &&) = default;
CLKernelImpl::Info::Info() = default;
CLKernelImpl::Info::~Info() = default;
CLKernelImpl::Info::Info(Info &&) = default;
CLKernelImpl::Info &CLKernelImpl::Info::operator=(Info &&) = default;
CLKernelImpl::CLKernelImpl(const cl::Kernel &kernel) : mKernel(kernel) {}
CLKernelImpl::~CLKernelImpl() = default;
} // namespace rx
//
// Copyright 2021 The ANGLE Project Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//
// CLKernelImpl.h: Defines the abstract rx::CLKernelImpl class.
#ifndef LIBANGLE_RENDERER_CLKERNELIMPL_H_
#define LIBANGLE_RENDERER_CLKERNELIMPL_H_
#include "libANGLE/renderer/CLtypes.h"
namespace rx
{
class CLKernelImpl : angle::NonCopyable
{
public:
using Ptr = std::unique_ptr<CLKernelImpl>;
struct WorkGroupInfo
{
WorkGroupInfo();
~WorkGroupInfo();
WorkGroupInfo(const WorkGroupInfo &) = delete;
WorkGroupInfo &operator=(const WorkGroupInfo &) = delete;
WorkGroupInfo(WorkGroupInfo &&);
WorkGroupInfo &operator=(WorkGroupInfo &&);
size_t mGlobalWorkSize[3] = {};
size_t mWorkGroupSize = 0u;
size_t mCompileWorkGroupSize[3] = {};
cl_ulong mLocalMemSize = 0u;
size_t mPrefWorkGroupSizeMultiple = 0u;
cl_ulong mPrivateMemSize = 0u;
};
struct ArgInfo
{
ArgInfo();
~ArgInfo();
ArgInfo(const ArgInfo &) = delete;
ArgInfo &operator=(const ArgInfo &) = delete;
ArgInfo(ArgInfo &&);
ArgInfo &operator=(ArgInfo &&);
bool isAvailable() const { return !mName.empty(); }
cl_kernel_arg_address_qualifier mAddressQualifier = 0u;
cl_kernel_arg_access_qualifier mAccessQualifier = 0u;
std::string mTypeName;
cl_kernel_arg_type_qualifier mTypeQualifier = 0u;
std::string mName;
};
struct Info
{
Info();
~Info();
Info(const Info &) = delete;
Info &operator=(const Info &) = delete;
Info(Info &&);
Info &operator=(Info &&);
bool isValid() const { return !mFunctionName.empty(); }
std::string mFunctionName;
cl_uint mNumArgs = 0u;
std::string mAttributes;
std::vector<WorkGroupInfo> mWorkGroups;
std::vector<ArgInfo> mArgs;
};
CLKernelImpl(const cl::Kernel &kernel);
virtual ~CLKernelImpl();
virtual Info createInfo(cl_int &errorCode) const = 0;
protected:
const cl::Kernel &mKernel;
};
} // namespace rx
#endif // LIBANGLE_RENDERER_CLKERNELIMPL_H_
...@@ -51,7 +51,7 @@ class CLPlatformImpl : angle::NonCopyable ...@@ -51,7 +51,7 @@ class CLPlatformImpl : angle::NonCopyable
virtual cl::DevicePtrList createDevices(cl::Platform &platform) const = 0; virtual cl::DevicePtrList createDevices(cl::Platform &platform) const = 0;
virtual CLContextImpl::Ptr createContext(cl::Context &context, virtual CLContextImpl::Ptr createContext(cl::Context &context,
const cl::DeviceRefList &devices, const cl::DeviceRefs &devices,
bool userSync, bool userSync,
cl_int &errorCode) = 0; cl_int &errorCode) = 0;
......
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
#ifndef LIBANGLE_RENDERER_CLPROGRAMIMPL_H_ #ifndef LIBANGLE_RENDERER_CLPROGRAMIMPL_H_
#define LIBANGLE_RENDERER_CLPROGRAMIMPL_H_ #define LIBANGLE_RENDERER_CLPROGRAMIMPL_H_
#include "libANGLE/renderer/CLtypes.h" #include "libANGLE/renderer/CLKernelImpl.h"
namespace rx namespace rx
{ {
...@@ -23,6 +23,12 @@ class CLProgramImpl : angle::NonCopyable ...@@ -23,6 +23,12 @@ class CLProgramImpl : angle::NonCopyable
virtual std::string getSource(cl_int &errorCode) const = 0; virtual std::string getSource(cl_int &errorCode) const = 0;
virtual CLKernelImpl::Ptr createKernel(const cl::Kernel &kernel,
const char *name,
cl_int &errorCode) = 0;
virtual cl_int createKernels(cl::Program &program) = 0;
protected: protected:
const cl::Program &mProgram; const cl::Program &mProgram;
}; };
......
...@@ -15,6 +15,8 @@ _cl_backend_sources = [ ...@@ -15,6 +15,8 @@ _cl_backend_sources = [
"CLContextCL.h", "CLContextCL.h",
"CLDeviceCL.cpp", "CLDeviceCL.cpp",
"CLDeviceCL.h", "CLDeviceCL.h",
"CLKernelCL.cpp",
"CLKernelCL.h",
"CLMemoryCL.cpp", "CLMemoryCL.cpp",
"CLMemoryCL.h", "CLMemoryCL.h",
"CLPlatformCL.cpp", "CLPlatformCL.cpp",
......
...@@ -39,7 +39,7 @@ CLContextCL::~CLContextCL() ...@@ -39,7 +39,7 @@ CLContextCL::~CLContextCL()
} }
} }
cl::DeviceRefList CLContextCL::getDevices(cl_int &errorCode) const cl::DeviceRefs CLContextCL::getDevices(cl_int &errorCode) const
{ {
size_t valueSize = 0u; size_t valueSize = 0u;
errorCode = mNative->getDispatch().clGetContextInfo(mNative, CL_CONTEXT_DEVICES, 0u, nullptr, errorCode = mNative->getDispatch().clGetContextInfo(mNative, CL_CONTEXT_DEVICES, 0u, nullptr,
...@@ -52,12 +52,12 @@ cl::DeviceRefList CLContextCL::getDevices(cl_int &errorCode) const ...@@ -52,12 +52,12 @@ cl::DeviceRefList CLContextCL::getDevices(cl_int &errorCode) const
if (errorCode == CL_SUCCESS) if (errorCode == CL_SUCCESS)
{ {
const cl::DevicePtrList &platformDevices = mContext.getPlatform().getDevices(); const cl::DevicePtrList &platformDevices = mContext.getPlatform().getDevices();
cl::DeviceRefList devices; cl::DeviceRefs devices;
for (cl_device_id nativeDevice : nativeDevices) for (cl_device_id nativeDevice : nativeDevices)
{ {
auto it = platformDevices.cbegin(); auto it = platformDevices.cbegin();
while (it != platformDevices.cend() && while (it != platformDevices.cend() &&
(*it)->getImpl<CLDeviceCL &>().getNative() != nativeDevice) (*it)->getImpl<CLDeviceCL>().getNative() != nativeDevice)
{ {
++it; ++it;
} }
...@@ -70,20 +70,20 @@ cl::DeviceRefList CLContextCL::getDevices(cl_int &errorCode) const ...@@ -70,20 +70,20 @@ cl::DeviceRefList CLContextCL::getDevices(cl_int &errorCode) const
ASSERT(false); ASSERT(false);
errorCode = CL_INVALID_DEVICE; errorCode = CL_INVALID_DEVICE;
ERR() << "Device not found in platform list"; ERR() << "Device not found in platform list";
return cl::DeviceRefList{}; return cl::DeviceRefs{};
} }
} }
return devices; return devices;
} }
} }
return cl::DeviceRefList{}; return cl::DeviceRefs{};
} }
CLCommandQueueImpl::Ptr CLContextCL::createCommandQueue(const cl::CommandQueue &commandQueue, CLCommandQueueImpl::Ptr CLContextCL::createCommandQueue(const cl::CommandQueue &commandQueue,
cl_int &errorCode) cl_int &errorCode)
{ {
const cl::Device &device = commandQueue.getDevice(); const cl::Device &device = commandQueue.getDevice();
const cl_device_id nativeDevice = device.getImpl<CLDeviceCL &>().getNative(); const cl_device_id nativeDevice = device.getImpl<CLDeviceCL>().getNative();
cl_command_queue nativeQueue = nullptr; cl_command_queue nativeQueue = nullptr;
if (!device.isVersionOrNewer(2u, 0u)) if (!device.isVersionOrNewer(2u, 0u))
{ {
...@@ -238,7 +238,7 @@ CLProgramImpl::Ptr CLContextCL::createProgramWithBinary(const cl::Program &progr ...@@ -238,7 +238,7 @@ CLProgramImpl::Ptr CLContextCL::createProgramWithBinary(const cl::Program &progr
std::vector<cl_device_id> nativeDevices; std::vector<cl_device_id> nativeDevices;
for (const cl::DeviceRefPtr &device : program.getDevices()) for (const cl::DeviceRefPtr &device : program.getDevices())
{ {
nativeDevices.emplace_back(device->getImpl<CLDeviceCL &>().getNative()); nativeDevices.emplace_back(device->getImpl<CLDeviceCL>().getNative());
} }
std::vector<size_t> lengths; std::vector<size_t> lengths;
std::vector<const unsigned char *> nativeBinaries; std::vector<const unsigned char *> nativeBinaries;
...@@ -261,7 +261,7 @@ CLProgramImpl::Ptr CLContextCL::createProgramWithBuiltInKernels(const cl::Progra ...@@ -261,7 +261,7 @@ CLProgramImpl::Ptr CLContextCL::createProgramWithBuiltInKernels(const cl::Progra
std::vector<cl_device_id> nativeDevices; std::vector<cl_device_id> nativeDevices;
for (const cl::DeviceRefPtr &device : program.getDevices()) for (const cl::DeviceRefPtr &device : program.getDevices())
{ {
nativeDevices.emplace_back(device->getImpl<CLDeviceCL &>().getNative()); nativeDevices.emplace_back(device->getImpl<CLDeviceCL>().getNative());
} }
const cl_program nativeProgram = mNative->getDispatch().clCreateProgramWithBuiltInKernels( const cl_program nativeProgram = mNative->getDispatch().clCreateProgramWithBuiltInKernels(
mNative, static_cast<cl_uint>(nativeDevices.size()), nativeDevices.data(), kernel_names, mNative, static_cast<cl_uint>(nativeDevices.size()), nativeDevices.data(), kernel_names,
......
...@@ -21,7 +21,7 @@ class CLContextCL : public CLContextImpl ...@@ -21,7 +21,7 @@ class CLContextCL : public CLContextImpl
CLContextCL(const cl::Context &context, cl_context native); CLContextCL(const cl::Context &context, cl_context native);
~CLContextCL() override; ~CLContextCL() override;
cl::DeviceRefList getDevices(cl_int &errorCode) const override; cl::DeviceRefs getDevices(cl_int &errorCode) const override;
CLCommandQueueImpl::Ptr createCommandQueue(const cl::CommandQueue &commandQueue, CLCommandQueueImpl::Ptr createCommandQueue(const cl::CommandQueue &commandQueue,
cl_int &errorCode) override; cl_int &errorCode) override;
......
//
// 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.
//
// CLKernelCL.cpp: Implements the class methods for CLKernelCL.
#include "libANGLE/renderer/cl/CLKernelCL.h"
#include "libANGLE/renderer/cl/CLDeviceCL.h"
#include "libANGLE/CLContext.h"
#include "libANGLE/CLKernel.h"
#include "libANGLE/CLPlatform.h"
#include "libANGLE/CLProgram.h"
#include "libANGLE/Debug.h"
namespace rx
{
namespace
{
template <typename T>
bool GetWorkGroupInfo(cl_kernel kernel,
cl_device_id device,
cl::KernelWorkGroupInfo name,
T &value,
cl_int &errorCode)
{
errorCode = kernel->getDispatch().clGetKernelWorkGroupInfo(kernel, device, cl::ToCLenum(name),
sizeof(T), &value, nullptr);
return errorCode == CL_SUCCESS;
}
template <typename T>
bool GetArgInfo(cl_kernel kernel,
cl_uint index,
cl::KernelArgInfo name,
T &value,
cl_int &errorCode)
{
errorCode = kernel->getDispatch().clGetKernelArgInfo(kernel, index, cl::ToCLenum(name),
sizeof(T), &value, nullptr);
return errorCode == CL_SUCCESS || errorCode == CL_KERNEL_ARG_INFO_NOT_AVAILABLE;
}
template <typename T>
bool GetKernelInfo(cl_kernel kernel, cl::KernelInfo name, T &value, cl_int &errorCode)
{
errorCode = kernel->getDispatch().clGetKernelInfo(kernel, cl::ToCLenum(name), sizeof(T), &value,
nullptr);
return errorCode == CL_SUCCESS;
}
bool GetArgString(cl_kernel kernel,
cl_uint index,
cl::KernelArgInfo name,
std::string &string,
cl_int &errorCode)
{
size_t size = 0u;
errorCode = kernel->getDispatch().clGetKernelArgInfo(kernel, index, cl::ToCLenum(name), 0u,
nullptr, &size);
if (errorCode == CL_KERNEL_ARG_INFO_NOT_AVAILABLE)
{
return true;
}
else if (errorCode != CL_SUCCESS)
{
return false;
}
std::vector<char> valString(size, '\0');
errorCode = kernel->getDispatch().clGetKernelArgInfo(kernel, index, cl::ToCLenum(name), size,
valString.data(), nullptr);
if (errorCode != CL_SUCCESS)
{
return false;
}
string.assign(valString.data(), valString.size() - 1u);
return true;
}
bool GetKernelString(cl_kernel kernel, cl::KernelInfo name, std::string &string, cl_int &errorCode)
{
size_t size = 0u;
errorCode =
kernel->getDispatch().clGetKernelInfo(kernel, cl::ToCLenum(name), 0u, nullptr, &size);
if (errorCode != CL_SUCCESS)
{
return false;
}
std::vector<char> valString(size, '\0');
errorCode = kernel->getDispatch().clGetKernelInfo(kernel, cl::ToCLenum(name), size,
valString.data(), nullptr);
if (errorCode != CL_SUCCESS)
{
return false;
}
string.assign(valString.data(), valString.size() - 1u);
return true;
}
} // namespace
CLKernelCL::CLKernelCL(const cl::Kernel &kernel, cl_kernel native)
: CLKernelImpl(kernel), mNative(native)
{}
CLKernelCL::~CLKernelCL()
{
if (mNative->getDispatch().clReleaseKernel(mNative) != CL_SUCCESS)
{
ERR() << "Error while releasing CL kernel";
}
}
CLKernelImpl::Info CLKernelCL::createInfo(cl_int &errorCode) const
{
const cl::Context &ctx = mKernel.getProgram().getContext();
Info info;
if (!GetKernelString(mNative, cl::KernelInfo::FunctionName, info.mFunctionName, errorCode) ||
!GetKernelInfo(mNative, cl::KernelInfo::NumArgs, info.mNumArgs, errorCode) ||
(ctx.getPlatform().isVersionOrNewer(1u, 2u) &&
!GetKernelString(mNative, cl::KernelInfo::Attributes, info.mAttributes, errorCode)))
{
return Info{};
}
info.mWorkGroups.resize(ctx.getDevices().size());
for (size_t index = 0u; index < ctx.getDevices().size(); ++index)
{
const cl_device_id device = ctx.getDevices()[index]->getImpl<CLDeviceCL>().getNative();
WorkGroupInfo &workGroup = info.mWorkGroups[index];
if ((ctx.getPlatform().isVersionOrNewer(1u, 2u) &&
!GetWorkGroupInfo(mNative, device, cl::KernelWorkGroupInfo::GlobalWorkSize,
workGroup.mGlobalWorkSize, errorCode)) ||
!GetWorkGroupInfo(mNative, device, cl::KernelWorkGroupInfo::WorkGroupSize,
workGroup.mWorkGroupSize, errorCode) ||
!GetWorkGroupInfo(mNative, device, cl::KernelWorkGroupInfo::CompileWorkGroupSize,
workGroup.mCompileWorkGroupSize, errorCode) ||
!GetWorkGroupInfo(mNative, device, cl::KernelWorkGroupInfo::LocalMemSize,
workGroup.mLocalMemSize, errorCode) ||
!GetWorkGroupInfo(mNative, device,
cl::KernelWorkGroupInfo::PreferredWorkGroupSizeMultiple,
workGroup.mPrefWorkGroupSizeMultiple, errorCode) ||
!GetWorkGroupInfo(mNative, device, cl::KernelWorkGroupInfo::PrivateMemSize,
workGroup.mPrivateMemSize, errorCode))
{
return Info{};
}
}
info.mArgs.resize(info.mNumArgs);
if (ctx.getPlatform().isVersionOrNewer(1u, 2u))
{
for (cl_uint index = 0u; index < info.mNumArgs; ++index)
{
ArgInfo &arg = info.mArgs[index];
if (!GetArgInfo(mNative, index, cl::KernelArgInfo::AddressQualifier,
arg.mAddressQualifier, errorCode) ||
!GetArgInfo(mNative, index, cl::KernelArgInfo::AccessQualifier,
arg.mAccessQualifier, errorCode) ||
!GetArgString(mNative, index, cl::KernelArgInfo::TypeName, arg.mTypeName,
errorCode) ||
!GetArgInfo(mNative, index, cl::KernelArgInfo::TypeQualifier, arg.mTypeQualifier,
errorCode) ||
!GetArgString(mNative, index, cl::KernelArgInfo::Name, arg.mName, errorCode))
{
return Info{};
}
}
}
return info;
}
} // namespace rx
//
// Copyright 2021 The ANGLE Project Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//
// CLKernelCL.h: Defines the class interface for CLKernelCL, implementing CLKernelImpl.
#ifndef LIBANGLE_RENDERER_CL_CLKERNELCL_H_
#define LIBANGLE_RENDERER_CL_CLKERNELCL_H_
#include "libANGLE/renderer/cl/cl_types.h"
#include "libANGLE/renderer/CLKernelImpl.h"
namespace rx
{
class CLKernelCL : public CLKernelImpl
{
public:
CLKernelCL(const cl::Kernel &kernel, cl_kernel native);
~CLKernelCL() override;
cl_kernel getNative();
Info createInfo(cl_int &errorCode) const override;
private:
const cl_kernel mNative;
};
inline cl_kernel CLKernelCL::getNative()
{
return mNative;
}
} // namespace rx
#endif // LIBANGLE_RENDERER_CL_CLKERNELCL_H_
...@@ -370,7 +370,7 @@ cl::DevicePtrList CLPlatformCL::createDevices(cl::Platform &platform) const ...@@ -370,7 +370,7 @@ cl::DevicePtrList CLPlatformCL::createDevices(cl::Platform &platform) const
} }
CLContextImpl::Ptr CLPlatformCL::createContext(cl::Context &context, CLContextImpl::Ptr CLPlatformCL::createContext(cl::Context &context,
const cl::DeviceRefList &devices, const cl::DeviceRefs &devices,
bool userSync, bool userSync,
cl_int &errorCode) cl_int &errorCode)
{ {
...@@ -382,7 +382,7 @@ CLContextImpl::Ptr CLPlatformCL::createContext(cl::Context &context, ...@@ -382,7 +382,7 @@ CLContextImpl::Ptr CLPlatformCL::createContext(cl::Context &context,
std::vector<cl_device_id> nativeDevices; std::vector<cl_device_id> nativeDevices;
for (const cl::DeviceRefPtr &device : devices) for (const cl::DeviceRefPtr &device : devices)
{ {
nativeDevices.emplace_back(device->getImpl<CLDeviceCL &>().getNative()); nativeDevices.emplace_back(device->getImpl<CLDeviceCL>().getNative());
} }
CLContextImpl::Ptr contextImpl; CLContextImpl::Ptr contextImpl;
......
...@@ -24,7 +24,7 @@ class CLPlatformCL : public CLPlatformImpl ...@@ -24,7 +24,7 @@ class CLPlatformCL : public CLPlatformImpl
cl::DevicePtrList createDevices(cl::Platform &platform) const override; cl::DevicePtrList createDevices(cl::Platform &platform) const override;
CLContextImpl::Ptr createContext(cl::Context &context, CLContextImpl::Ptr createContext(cl::Context &context,
const cl::DeviceRefList &devices, const cl::DeviceRefs &devices,
bool userSync, bool userSync,
cl_int &errorCode) override; cl_int &errorCode) override;
......
...@@ -7,6 +7,10 @@ ...@@ -7,6 +7,10 @@
#include "libANGLE/renderer/cl/CLProgramCL.h" #include "libANGLE/renderer/cl/CLProgramCL.h"
#include "libANGLE/renderer/cl/CLKernelCL.h"
#include "libANGLE/CLKernel.h"
#include "libANGLE/CLProgram.h"
#include "libANGLE/Debug.h" #include "libANGLE/Debug.h"
namespace rx namespace rx
...@@ -45,4 +49,47 @@ std::string CLProgramCL::getSource(cl_int &errorCode) const ...@@ -45,4 +49,47 @@ std::string CLProgramCL::getSource(cl_int &errorCode) const
return std::string{}; return std::string{};
} }
CLKernelImpl::Ptr CLProgramCL::createKernel(const cl::Kernel &kernel,
const char *name,
cl_int &errorCode)
{
const cl_kernel nativeKernel = mNative->getDispatch().clCreateKernel(mNative, name, &errorCode);
return CLKernelImpl::Ptr(nativeKernel != nullptr ? new CLKernelCL(kernel, nativeKernel)
: nullptr);
}
cl_int CLProgramCL::createKernels(cl::Program &program)
{
cl_uint numKernels = 0u;
cl_int errorCode =
mNative->getDispatch().clCreateKernelsInProgram(mNative, 0u, nullptr, &numKernels);
if (errorCode == CL_SUCCESS)
{
std::vector<cl_kernel> nativeKernels(numKernels, nullptr);
errorCode = mNative->getDispatch().clCreateKernelsInProgram(mNative, numKernels,
nativeKernels.data(), nullptr);
if (errorCode == CL_SUCCESS)
{
for (cl_kernel nativeKernel : nativeKernels)
{
// Check that kernel has not already been created.
if (std::find_if(mProgram.getKernels().cbegin(), mProgram.getKernels().cend(),
[=](const cl::KernelPtr &ptr) {
return ptr->getImpl<CLKernelCL>().getNative() == nativeKernel;
}) == mProgram.getKernels().cend())
{
errorCode = program.createKernel([&](const cl::Kernel &kernel) {
return CLKernelImpl::Ptr(new CLKernelCL(kernel, nativeKernel));
});
if (errorCode != CL_SUCCESS)
{
break;
}
}
}
}
}
return errorCode;
}
} // namespace rx } // namespace rx
...@@ -23,6 +23,12 @@ class CLProgramCL : public CLProgramImpl ...@@ -23,6 +23,12 @@ class CLProgramCL : public CLProgramImpl
std::string getSource(cl_int &errorCode) const override; std::string getSource(cl_int &errorCode) const override;
CLKernelImpl::Ptr createKernel(const cl::Kernel &kernel,
const char *name,
cl_int &errorCode) override;
cl_int createKernels(cl::Program &program) override;
private: private:
const cl_program mNative; const cl_program mNative;
}; };
......
...@@ -111,6 +111,8 @@ if (angle_enable_cl) { ...@@ -111,6 +111,8 @@ if (angle_enable_cl) {
"CLContextVk.h", "CLContextVk.h",
"CLDeviceVk.cpp", "CLDeviceVk.cpp",
"CLDeviceVk.h", "CLDeviceVk.h",
"CLKernelVk.cpp",
"CLKernelVk.h",
"CLMemoryVk.cpp", "CLMemoryVk.cpp",
"CLMemoryVk.h", "CLMemoryVk.h",
"CLPlatformVk.cpp", "CLPlatformVk.cpp",
......
//
// Copyright 2021 The ANGLE Project Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//
// CLKernelVk.cpp: Implements the class methods for CLKernelVk.
#include "libANGLE/renderer/vulkan/CLKernelVk.h"
namespace rx
{
CLKernelVk::CLKernelVk(const cl::Kernel &kernel) : CLKernelImpl(kernel) {}
CLKernelVk::~CLKernelVk() = default;
} // namespace rx
//
// Copyright 2021 The ANGLE Project Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//
// CLKernelVk.h: Defines the class interface for CLKernelVk, implementing CLKernelImpl.
#ifndef LIBANGLE_RENDERER_VULKAN_CLKERNELVK_H_
#define LIBANGLE_RENDERER_VULKAN_CLKERNELVK_H_
#include "libANGLE/renderer/vulkan/cl_types.h"
#include "libANGLE/renderer/CLKernelImpl.h"
namespace rx
{
class CLKernelVk : public CLKernelImpl
{
public:
CLKernelVk(const cl::Kernel &kernel);
~CLKernelVk() override;
};
} // namespace rx
#endif // LIBANGLE_RENDERER_VULKAN_CLKERNELVK_H_
...@@ -72,7 +72,7 @@ cl::DevicePtrList CLPlatformVk::createDevices(cl::Platform &platform) const ...@@ -72,7 +72,7 @@ cl::DevicePtrList CLPlatformVk::createDevices(cl::Platform &platform) const
} }
CLContextImpl::Ptr CLPlatformVk::createContext(cl::Context &context, CLContextImpl::Ptr CLPlatformVk::createContext(cl::Context &context,
const cl::DeviceRefList &devices, const cl::DeviceRefs &devices,
bool userSync, bool userSync,
cl_int &errorCode) cl_int &errorCode)
{ {
......
...@@ -22,7 +22,7 @@ class CLPlatformVk : public CLPlatformImpl ...@@ -22,7 +22,7 @@ class CLPlatformVk : public CLPlatformImpl
cl::DevicePtrList createDevices(cl::Platform &platform) const override; cl::DevicePtrList createDevices(cl::Platform &platform) const override;
CLContextImpl::Ptr createContext(cl::Context &context, CLContextImpl::Ptr createContext(cl::Context &context,
const cl::DeviceRefList &devices, const cl::DeviceRefs &devices,
bool userSync, bool userSync,
cl_int &errorCode) override; cl_int &errorCode) override;
......
...@@ -858,6 +858,18 @@ cl_int ValidateGetProgramBuildInfo(cl_program program, ...@@ -858,6 +858,18 @@ cl_int ValidateGetProgramBuildInfo(cl_program program,
cl_int ValidateCreateKernel(cl_program program, const char *kernel_name) cl_int ValidateCreateKernel(cl_program program, const char *kernel_name)
{ {
// CL_INVALID_PROGRAM if program is not a valid program object.
if (!Program::IsValid(program))
{
return CL_INVALID_PROGRAM;
}
// CL_INVALID_VALUE if kernel_name is NULL.
if (kernel_name == nullptr)
{
return CL_INVALID_VALUE;
}
return CL_SUCCESS; return CL_SUCCESS;
} }
...@@ -866,17 +878,25 @@ cl_int ValidateCreateKernelsInProgram(cl_program program, ...@@ -866,17 +878,25 @@ cl_int ValidateCreateKernelsInProgram(cl_program program,
const cl_kernel *kernels, const cl_kernel *kernels,
const cl_uint *num_kernels_ret) const cl_uint *num_kernels_ret)
{ {
// CL_INVALID_PROGRAM if program is not a valid program object.
if (!Program::IsValid(program))
{
return CL_INVALID_PROGRAM;
}
return CL_SUCCESS; return CL_SUCCESS;
} }
cl_int ValidateRetainKernel(cl_kernel kernel) cl_int ValidateRetainKernel(cl_kernel kernel)
{ {
return CL_SUCCESS; // CL_INVALID_KERNEL if kernel is not a valid kernel object.
return Kernel::IsValid(kernel) ? CL_SUCCESS : CL_INVALID_KERNEL;
} }
cl_int ValidateReleaseKernel(cl_kernel kernel) cl_int ValidateReleaseKernel(cl_kernel kernel)
{ {
return CL_SUCCESS; // CL_INVALID_KERNEL if kernel is not a valid kernel object.
return Kernel::IsValid(kernel) ? CL_SUCCESS : CL_INVALID_KERNEL;
} }
cl_int ValidateSetKernelArg(cl_kernel kernel, cl_int ValidateSetKernelArg(cl_kernel kernel,
...@@ -893,6 +913,30 @@ cl_int ValidateGetKernelInfo(cl_kernel kernel, ...@@ -893,6 +913,30 @@ cl_int ValidateGetKernelInfo(cl_kernel kernel,
const void *param_value, const void *param_value,
const size_t *param_value_size_ret) const size_t *param_value_size_ret)
{ {
// CL_INVALID_KERNEL if kernel is a not a valid kernel object.
if (!Kernel::IsValid(kernel))
{
return CL_INVALID_KERNEL;
}
// CL_INVALID_VALUE if param_name is not valid.
const cl_version version = static_cast<const Kernel *>(kernel)
->getProgram()
.getContext()
.getPlatform()
.getInfo()
.mVersion;
switch (param_name)
{
case KernelInfo::Attributes:
ANGLE_VALIDATE_VERSION(1, 2);
break;
case KernelInfo::InvalidEnum:
return CL_INVALID_VALUE;
default:
break;
}
return CL_SUCCESS; return CL_SUCCESS;
} }
...@@ -903,6 +947,58 @@ cl_int ValidateGetKernelWorkGroupInfo(cl_kernel kernel, ...@@ -903,6 +947,58 @@ cl_int ValidateGetKernelWorkGroupInfo(cl_kernel kernel,
const void *param_value, const void *param_value,
const size_t *param_value_size_ret) const size_t *param_value_size_ret)
{ {
// CL_INVALID_KERNEL if kernel is a not a valid kernel object.
if (!Kernel::IsValid(kernel))
{
return CL_INVALID_KERNEL;
}
const Kernel &krnl = *static_cast<const Kernel *>(kernel);
const Device *dvc = nullptr;
if (device != nullptr)
{
// CL_INVALID_DEVICE if device is not in the list of devices associated with kernel ...
if (krnl.getProgram().getContext().hasDevice(device))
{
dvc = static_cast<const Device *>(device);
}
else
{
return CL_INVALID_DEVICE;
}
}
else
{
// or if device is NULL but there is more than one device associated with kernel.
if (krnl.getProgram().getContext().getDevices().size() == 1u)
{
dvc = krnl.getProgram().getContext().getDevices().front().get();
}
else
{
return CL_INVALID_DEVICE;
}
}
// CL_INVALID_VALUE if param_name is not valid.
const cl_version version = krnl.getProgram().getContext().getPlatform().getInfo().mVersion;
switch (param_name)
{
case KernelWorkGroupInfo::GlobalWorkSize:
ANGLE_VALIDATE_VERSION(1, 2);
// CL_INVALID_VALUE if param_name is CL_KERNEL_GLOBAL_WORK_SIZE and
// device is not a custom device and kernel is not a built-in kernel.
if (!dvc->supportsBuiltInKernel(krnl.getInfo().mFunctionName))
{
return CL_INVALID_VALUE;
}
break;
case KernelWorkGroupInfo::InvalidEnum:
return CL_INVALID_VALUE;
default:
break;
}
return CL_SUCCESS; return CL_SUCCESS;
} }
...@@ -1590,7 +1686,7 @@ cl_int ValidateCreateImage(cl_context context, ...@@ -1590,7 +1686,7 @@ cl_int ValidateCreateImage(cl_context context,
// CL_INVALID_IMAGE_SIZE if image dimensions specified in image_desc exceed the maximum // CL_INVALID_IMAGE_SIZE if image dimensions specified in image_desc exceed the maximum
// image dimensions described in the Device Queries table for all devices in context. // image dimensions described in the Device Queries table for all devices in context.
const DeviceRefList &devices = ctx.getDevices(); const DeviceRefs &devices = ctx.getDevices();
if (std::find_if(devices.cbegin(), devices.cend(), [&](const DeviceRefPtr &ptr) { if (std::find_if(devices.cbegin(), devices.cend(), [&](const DeviceRefPtr &ptr) {
switch (image_desc->image_type) switch (image_desc->image_type)
{ {
...@@ -1719,6 +1815,31 @@ cl_int ValidateGetKernelArgInfo(cl_kernel kernel, ...@@ -1719,6 +1815,31 @@ cl_int ValidateGetKernelArgInfo(cl_kernel kernel,
const void *param_value, const void *param_value,
const size_t *param_value_size_ret) const size_t *param_value_size_ret)
{ {
// CL_INVALID_KERNEL if kernel is a not a valid kernel object.
if (!Kernel::IsValidAndVersionOrNewer(kernel, 1u, 2u))
{
return CL_INVALID_KERNEL;
}
const Kernel &krnl = *static_cast<const Kernel *>(kernel);
// CL_INVALID_ARG_INDEX if arg_index is not a valid argument index.
if (arg_index >= krnl.getInfo().mArgs.size())
{
return CL_INVALID_ARG_INDEX;
}
// CL_KERNEL_ARG_INFO_NOT_AVAILABLE if the argument information is not available for kernel.
if (!krnl.getInfo().mArgs[arg_index].isAvailable())
{
return CL_KERNEL_ARG_INFO_NOT_AVAILABLE;
}
// CL_INVALID_VALUE if param_name is not valid.
if (param_name == KernelArgInfo::InvalidEnum)
{
return CL_INVALID_VALUE;
}
return CL_SUCCESS; return CL_SUCCESS;
} }
......
...@@ -472,6 +472,7 @@ libangle_cl_headers = [ ...@@ -472,6 +472,7 @@ libangle_cl_headers = [
"src/libANGLE/renderer/CLCommandQueueImpl.h", "src/libANGLE/renderer/CLCommandQueueImpl.h",
"src/libANGLE/renderer/CLContextImpl.h", "src/libANGLE/renderer/CLContextImpl.h",
"src/libANGLE/renderer/CLDeviceImpl.h", "src/libANGLE/renderer/CLDeviceImpl.h",
"src/libANGLE/renderer/CLKernelImpl.h",
"src/libANGLE/renderer/CLMemoryImpl.h", "src/libANGLE/renderer/CLMemoryImpl.h",
"src/libANGLE/renderer/CLPlatformImpl.h", "src/libANGLE/renderer/CLPlatformImpl.h",
"src/libANGLE/renderer/CLProgramImpl.h", "src/libANGLE/renderer/CLProgramImpl.h",
...@@ -498,6 +499,7 @@ libangle_cl_sources = [ ...@@ -498,6 +499,7 @@ libangle_cl_sources = [
"src/libANGLE/renderer/CLCommandQueueImpl.cpp", "src/libANGLE/renderer/CLCommandQueueImpl.cpp",
"src/libANGLE/renderer/CLContextImpl.cpp", "src/libANGLE/renderer/CLContextImpl.cpp",
"src/libANGLE/renderer/CLDeviceImpl.cpp", "src/libANGLE/renderer/CLDeviceImpl.cpp",
"src/libANGLE/renderer/CLKernelImpl.cpp",
"src/libANGLE/renderer/CLMemoryImpl.cpp", "src/libANGLE/renderer/CLMemoryImpl.cpp",
"src/libANGLE/renderer/CLPlatformImpl.cpp", "src/libANGLE/renderer/CLPlatformImpl.cpp",
"src/libANGLE/renderer/CLProgramImpl.cpp", "src/libANGLE/renderer/CLProgramImpl.cpp",
......
...@@ -504,8 +504,7 @@ cl_int GetProgramBuildInfo(cl_program program, ...@@ -504,8 +504,7 @@ cl_int GetProgramBuildInfo(cl_program program,
cl_kernel CreateKernel(cl_program program, const char *kernel_name, cl_int &errorCode) cl_kernel CreateKernel(cl_program program, const char *kernel_name, cl_int &errorCode)
{ {
WARN_NOT_SUPPORTED(CreateKernel); return static_cast<Program *>(program)->createKernel(kernel_name, errorCode);
return 0;
} }
cl_int CreateKernelsInProgram(cl_program program, cl_int CreateKernelsInProgram(cl_program program,
...@@ -513,8 +512,7 @@ cl_int CreateKernelsInProgram(cl_program program, ...@@ -513,8 +512,7 @@ cl_int CreateKernelsInProgram(cl_program program,
cl_kernel *kernels, cl_kernel *kernels,
cl_uint *num_kernels_ret) cl_uint *num_kernels_ret)
{ {
WARN_NOT_SUPPORTED(CreateKernelsInProgram); return static_cast<Program *>(program)->createKernels(num_kernels, kernels, num_kernels_ret);
return 0;
} }
cl_kernel CloneKernel(cl_kernel source_kernel, cl_int &errorCode) cl_kernel CloneKernel(cl_kernel source_kernel, cl_int &errorCode)
...@@ -525,14 +523,14 @@ cl_kernel CloneKernel(cl_kernel source_kernel, cl_int &errorCode) ...@@ -525,14 +523,14 @@ cl_kernel CloneKernel(cl_kernel source_kernel, cl_int &errorCode)
cl_int RetainKernel(cl_kernel kernel) cl_int RetainKernel(cl_kernel kernel)
{ {
WARN_NOT_SUPPORTED(RetainKernel); static_cast<Kernel *>(kernel)->retain();
return 0; return CL_SUCCESS;
} }
cl_int ReleaseKernel(cl_kernel kernel) cl_int ReleaseKernel(cl_kernel kernel)
{ {
WARN_NOT_SUPPORTED(ReleaseKernel); static_cast<Kernel *>(kernel)->release();
return 0; return CL_SUCCESS;
} }
cl_int SetKernelArg(cl_kernel kernel, cl_uint arg_index, size_t arg_size, const void *arg_value) cl_int SetKernelArg(cl_kernel kernel, cl_uint arg_index, size_t arg_size, const void *arg_value)
...@@ -562,8 +560,8 @@ cl_int GetKernelInfo(cl_kernel kernel, ...@@ -562,8 +560,8 @@ cl_int GetKernelInfo(cl_kernel kernel,
void *param_value, void *param_value,
size_t *param_value_size_ret) size_t *param_value_size_ret)
{ {
WARN_NOT_SUPPORTED(GetKernelInfo); return static_cast<Kernel *>(kernel)->getInfo(param_name, param_value_size, param_value,
return 0; param_value_size_ret);
} }
cl_int GetKernelArgInfo(cl_kernel kernel, cl_int GetKernelArgInfo(cl_kernel kernel,
...@@ -573,8 +571,8 @@ cl_int GetKernelArgInfo(cl_kernel kernel, ...@@ -573,8 +571,8 @@ cl_int GetKernelArgInfo(cl_kernel kernel,
void *param_value, void *param_value,
size_t *param_value_size_ret) size_t *param_value_size_ret)
{ {
WARN_NOT_SUPPORTED(GetKernelArgInfo); return static_cast<Kernel *>(kernel)->getArgInfo(arg_index, param_name, param_value_size,
return 0; param_value, param_value_size_ret);
} }
cl_int GetKernelWorkGroupInfo(cl_kernel kernel, cl_int GetKernelWorkGroupInfo(cl_kernel kernel,
...@@ -584,8 +582,8 @@ cl_int GetKernelWorkGroupInfo(cl_kernel kernel, ...@@ -584,8 +582,8 @@ cl_int GetKernelWorkGroupInfo(cl_kernel kernel,
void *param_value, void *param_value,
size_t *param_value_size_ret) size_t *param_value_size_ret)
{ {
WARN_NOT_SUPPORTED(GetKernelWorkGroupInfo); return static_cast<Kernel *>(kernel)->getWorkGroupInfo(device, param_name, param_value_size,
return 0; param_value, param_value_size_ret);
} }
cl_int GetKernelSubGroupInfo(cl_kernel kernel, cl_int GetKernelSubGroupInfo(cl_kernel kernel,
......
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