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
break;
case ContextInfo::Devices:
static_assert(sizeof(decltype(mDevices)::value_type) == sizeof(Device *),
"DeviceRefList has wrong element size");
"DeviceRefs has wrong element size");
copyValue = mDevices.data();
copySize = mDevices.size() * sizeof(decltype(mDevices)::value_type);
break;
......@@ -261,7 +261,7 @@ cl_program Context::createProgramWithBinary(cl_uint numDevices,
cl_int *binaryStatus,
cl_int &errorCode)
{
DeviceRefList refDevices;
DeviceRefs refDevices;
Binaries binaryVec;
while (numDevices-- != 0u)
{
......@@ -278,7 +278,7 @@ cl_program Context::createProgramWithBuiltInKernels(cl_uint numDevices,
const char *kernelNames,
cl_int &errorCode)
{
DeviceRefList refDevices;
DeviceRefs refDevices;
while (numDevices-- != 0u)
{
refDevices.emplace_back(static_cast<Device *>(*devices++));
......@@ -318,7 +318,7 @@ void Context::ErrorCallback(const char *errinfo, const void *privateInfo, size_t
Context::Context(Platform &platform,
PropArray &&properties,
DeviceRefList &&devices,
DeviceRefs &&devices,
ContextErrorCB notify,
void *userData,
bool userSync,
......@@ -345,7 +345,7 @@ Context::Context(Platform &platform,
mNotify(notify),
mUserData(userData),
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)
......
......@@ -29,7 +29,7 @@ class Context final : public _cl_context, public Object
const Platform &getPlatform() const noexcept;
bool hasDevice(const _cl_device_id *device) const;
const DeviceRefList &getDevices() const;
const DeviceRefs &getDevices() const;
bool supportsImages() const;
bool supportsIL() const;
......@@ -39,6 +39,7 @@ class Context final : public _cl_context, public Object
bool hasMemory(const _cl_mem *memory) const;
bool hasSampler(const _cl_sampler *sampler) const;
bool hasProgram(const _cl_program *program) const;
bool hasKernel(const _cl_kernel *kernel) const;
void retain() noexcept;
bool release();
......@@ -122,7 +123,7 @@ class Context final : public _cl_context, public Object
private:
Context(Platform &platform,
PropArray &&properties,
DeviceRefList &&devices,
DeviceRefs &&devices,
ContextErrorCB notify,
void *userData,
bool userSync,
......@@ -151,7 +152,7 @@ class Context final : public _cl_context, public Object
const ContextErrorCB mNotify;
void *const mUserData;
const rx::CLContextImpl::Ptr mImpl;
const DeviceRefList mDevices;
const DeviceRefs mDevices;
CommandQueue::PtrList mCommandQueues;
Memory::PtrList mMemories;
......@@ -178,7 +179,7 @@ inline bool Context::hasDevice(const _cl_device_id *device) const
}) != mDevices.cend();
}
inline const DeviceRefList &Context::getDevices() const
inline const DeviceRefs &Context::getDevices() const
{
return mDevices;
}
......@@ -232,6 +233,13 @@ inline bool Context::hasProgram(const _cl_program *program) const
}) != 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
{
addRef();
......
......@@ -97,7 +97,7 @@ inline bool Device::isRoot() const noexcept
template <typename T>
inline T &Device::getImpl() const
{
return static_cast<T>(*mImpl);
return static_cast<T &>(*mImpl);
}
inline const rx::CLDeviceImpl::Info &Device::getInfo() const
......
......@@ -7,9 +7,242 @@
#include "libANGLE/CLKernel.h"
#include "libANGLE/CLPlatform.h"
#include "libANGLE/CLProgram.h"
#include <cstring>
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
......@@ -9,6 +9,7 @@
#define LIBANGLE_CLKERNEL_H_
#include "libANGLE/CLObject.h"
#include "libANGLE/renderer/CLKernelImpl.h"
namespace cl
{
......@@ -16,10 +17,69 @@ namespace cl
class Kernel final : public _cl_kernel, public Object
{
public:
Kernel(const cl_icd_dispatch &dispatch);
~Kernel() override = default;
using PtrList = std::list<KernelPtr>;
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
#endif // LIBANGLE_CLKERNEL_H_
......@@ -207,7 +207,7 @@ cl_context Platform::CreateContext(const cl_context_properties *properties,
bool userSync = false;
Context::PropArray propArray = ParseContextProperties(properties, platform, userSync);
ASSERT(platform != nullptr);
DeviceRefList refDevices;
DeviceRefs refDevices;
while (numDevices-- != 0u)
{
refDevices.emplace_back(static_cast<Device *>(*devices++));
......
......@@ -36,6 +36,7 @@ class Platform final : public _cl_platform_id, public Object
bool hasMemory(const _cl_mem *memory) const;
bool hasSampler(const _cl_sampler *sampler) 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;
......@@ -149,6 +150,13 @@ inline bool Platform::hasProgram(const _cl_program *program) const
}) != 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()
{
static angle::base::NoDestructor<PtrList> sList;
......
......@@ -10,6 +10,8 @@
#include "libANGLE/CLContext.h"
#include "libANGLE/CLPlatform.h"
#include <cstring>
namespace cl
{
......@@ -27,7 +29,8 @@ bool Program::release()
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,
"OpenCL type mismatch");
......@@ -56,7 +59,7 @@ cl_int Program::getInfo(ProgramInfo name, size_t valueSize, void *value, size_t
break;
case ProgramInfo::Devices:
static_assert(sizeof(decltype(mDevices)::value_type) == sizeof(Device *),
"DeviceRefList has wrong element size");
"DeviceRefs has wrong element size");
copyValue = mDevices.data();
copySize = mDevices.size() * sizeof(decltype(mDevices)::value_type);
break;
......@@ -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);
break;
case ProgramInfo::NumKernels:
copyValue = &mNumKernels;
copySize = sizeof(mNumKernels);
break;
case ProgramInfo::KernelNames:
copyValue = mKernelNames.c_str();
copySize = mKernelNames.length() + 1u;
break;
case ProgramInfo::ScopeGlobalCtorsPresent:
valUInt = CL_FALSE;
copyValue = &valUInt;
copySize = sizeof(valUInt);
break;
case ProgramInfo::ScopeGlobalDtorsPresent:
valUInt = CL_FALSE;
copyValue = &valUInt;
copySize = sizeof(valUInt);
break;
default:
return CL_INVALID_VALUE;
}
......@@ -116,6 +133,47 @@ cl_int Program::getInfo(ProgramInfo name, size_t valueSize, void *value, size_t
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)
{
const Platform::PtrList &platforms = Platform::GetPlatforms();
......@@ -142,7 +200,7 @@ Program::Program(Context &context, const void *il, size_t length, cl_int &errorC
{}
Program::Program(Context &context,
DeviceRefList &&devices,
DeviceRefs &&devices,
Binaries &&binaries,
cl_int *binaryStatus,
cl_int &errorCode)
......@@ -154,10 +212,7 @@ Program::Program(Context &context,
mBinaries(std::move(binaries))
{}
Program::Program(Context &context,
DeviceRefList &&devices,
const char *kernelNames,
cl_int &errorCode)
Program::Program(Context &context, DeviceRefs &&devices, const char *kernelNames, cl_int &errorCode)
: _cl_program(context.getDispatch()),
mContext(&context),
mDevices(std::move(devices)),
......@@ -165,4 +220,32 @@ Program::Program(Context &context,
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
......@@ -8,7 +8,7 @@
#ifndef LIBANGLE_CLPROGRAM_H_
#define LIBANGLE_CLPROGRAM_H_
#include "libANGLE/CLObject.h"
#include "libANGLE/CLKernel.h"
#include "libANGLE/renderer/CLProgramImpl.h"
namespace cl
......@@ -21,14 +21,22 @@ class Program final : public _cl_program, public Object
~Program() override;
Context &getContext();
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;
bool release();
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);
private:
......@@ -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,
DeviceRefList &&devices,
DeviceRefs &&devices,
Binaries &&binaries,
cl_int *binaryStatus,
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 DeviceRefList mDevices;
const DeviceRefs mDevices;
const std::string mIL;
const rx::CLProgramImpl::Ptr mImpl;
const std::string mSource;
Binaries mBinaries;
size_t mNumKernels;
std::string mKernelNames;
Kernel::PtrList mKernels;
friend class Context;
friend class Kernel;
};
inline Context &Program::getContext()
{
return *mContext;
}
inline const Context &Program::getContext() const
{
return *mContext;
}
inline const DeviceRefList &Program::getDevices() const
inline const DeviceRefs &Program::getDevices() const
{
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
{
addRef();
......
......@@ -52,9 +52,10 @@ using SamplerPtr = std::unique_ptr<Sampler>;
using ContextRefPtr = RefPointer<Context>;
using DeviceRefPtr = RefPointer<Device>;
using MemoryRefPtr = RefPointer<Memory>;
using ProgramRefPtr = RefPointer<Program>;
using DevicePtrList = std::list<DevicePtr>;
using DeviceRefList = std::vector<DeviceRefPtr>;
using DeviceRefs = std::vector<DeviceRefPtr>;
using Binary = std::vector<unsigned char>;
using Binaries = std::vector<Binary>;
......
......@@ -25,7 +25,7 @@ class CLContextImpl : angle::NonCopyable
CLContextImpl(const cl::Context &context);
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,
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
virtual cl::DevicePtrList createDevices(cl::Platform &platform) const = 0;
virtual CLContextImpl::Ptr createContext(cl::Context &context,
const cl::DeviceRefList &devices,
const cl::DeviceRefs &devices,
bool userSync,
cl_int &errorCode) = 0;
......
......@@ -8,7 +8,7 @@
#ifndef LIBANGLE_RENDERER_CLPROGRAMIMPL_H_
#define LIBANGLE_RENDERER_CLPROGRAMIMPL_H_
#include "libANGLE/renderer/CLtypes.h"
#include "libANGLE/renderer/CLKernelImpl.h"
namespace rx
{
......@@ -23,6 +23,12 @@ class CLProgramImpl : angle::NonCopyable
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:
const cl::Program &mProgram;
};
......
......@@ -15,6 +15,8 @@ _cl_backend_sources = [
"CLContextCL.h",
"CLDeviceCL.cpp",
"CLDeviceCL.h",
"CLKernelCL.cpp",
"CLKernelCL.h",
"CLMemoryCL.cpp",
"CLMemoryCL.h",
"CLPlatformCL.cpp",
......
......@@ -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;
errorCode = mNative->getDispatch().clGetContextInfo(mNative, CL_CONTEXT_DEVICES, 0u, nullptr,
......@@ -52,12 +52,12 @@ cl::DeviceRefList CLContextCL::getDevices(cl_int &errorCode) const
if (errorCode == CL_SUCCESS)
{
const cl::DevicePtrList &platformDevices = mContext.getPlatform().getDevices();
cl::DeviceRefList devices;
cl::DeviceRefs devices;
for (cl_device_id nativeDevice : nativeDevices)
{
auto it = platformDevices.cbegin();
while (it != platformDevices.cend() &&
(*it)->getImpl<CLDeviceCL &>().getNative() != nativeDevice)
(*it)->getImpl<CLDeviceCL>().getNative() != nativeDevice)
{
++it;
}
......@@ -70,20 +70,20 @@ cl::DeviceRefList CLContextCL::getDevices(cl_int &errorCode) const
ASSERT(false);
errorCode = CL_INVALID_DEVICE;
ERR() << "Device not found in platform list";
return cl::DeviceRefList{};
return cl::DeviceRefs{};
}
}
return devices;
}
}
return cl::DeviceRefList{};
return cl::DeviceRefs{};
}
CLCommandQueueImpl::Ptr CLContextCL::createCommandQueue(const cl::CommandQueue &commandQueue,
cl_int &errorCode)
{
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;
if (!device.isVersionOrNewer(2u, 0u))
{
......@@ -238,7 +238,7 @@ CLProgramImpl::Ptr CLContextCL::createProgramWithBinary(const cl::Program &progr
std::vector<cl_device_id> nativeDevices;
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<const unsigned char *> nativeBinaries;
......@@ -261,7 +261,7 @@ CLProgramImpl::Ptr CLContextCL::createProgramWithBuiltInKernels(const cl::Progra
std::vector<cl_device_id> nativeDevices;
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(
mNative, static_cast<cl_uint>(nativeDevices.size()), nativeDevices.data(), kernel_names,
......
......@@ -21,7 +21,7 @@ class CLContextCL : public CLContextImpl
CLContextCL(const cl::Context &context, cl_context native);
~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,
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
}
CLContextImpl::Ptr CLPlatformCL::createContext(cl::Context &context,
const cl::DeviceRefList &devices,
const cl::DeviceRefs &devices,
bool userSync,
cl_int &errorCode)
{
......@@ -382,7 +382,7 @@ CLContextImpl::Ptr CLPlatformCL::createContext(cl::Context &context,
std::vector<cl_device_id> nativeDevices;
for (const cl::DeviceRefPtr &device : devices)
{
nativeDevices.emplace_back(device->getImpl<CLDeviceCL &>().getNative());
nativeDevices.emplace_back(device->getImpl<CLDeviceCL>().getNative());
}
CLContextImpl::Ptr contextImpl;
......
......@@ -24,7 +24,7 @@ class CLPlatformCL : public CLPlatformImpl
cl::DevicePtrList createDevices(cl::Platform &platform) const override;
CLContextImpl::Ptr createContext(cl::Context &context,
const cl::DeviceRefList &devices,
const cl::DeviceRefs &devices,
bool userSync,
cl_int &errorCode) override;
......
......@@ -7,6 +7,10 @@
#include "libANGLE/renderer/cl/CLProgramCL.h"
#include "libANGLE/renderer/cl/CLKernelCL.h"
#include "libANGLE/CLKernel.h"
#include "libANGLE/CLProgram.h"
#include "libANGLE/Debug.h"
namespace rx
......@@ -45,4 +49,47 @@ std::string CLProgramCL::getSource(cl_int &errorCode) const
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
......@@ -23,6 +23,12 @@ class CLProgramCL : public CLProgramImpl
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:
const cl_program mNative;
};
......
......@@ -111,6 +111,8 @@ if (angle_enable_cl) {
"CLContextVk.h",
"CLDeviceVk.cpp",
"CLDeviceVk.h",
"CLKernelVk.cpp",
"CLKernelVk.h",
"CLMemoryVk.cpp",
"CLMemoryVk.h",
"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
}
CLContextImpl::Ptr CLPlatformVk::createContext(cl::Context &context,
const cl::DeviceRefList &devices,
const cl::DeviceRefs &devices,
bool userSync,
cl_int &errorCode)
{
......
......@@ -22,7 +22,7 @@ class CLPlatformVk : public CLPlatformImpl
cl::DevicePtrList createDevices(cl::Platform &platform) const override;
CLContextImpl::Ptr createContext(cl::Context &context,
const cl::DeviceRefList &devices,
const cl::DeviceRefs &devices,
bool userSync,
cl_int &errorCode) override;
......
......@@ -858,6 +858,18 @@ cl_int ValidateGetProgramBuildInfo(cl_program program,
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;
}
......@@ -866,17 +878,25 @@ cl_int ValidateCreateKernelsInProgram(cl_program program,
const cl_kernel *kernels,
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;
}
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)
{
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,
......@@ -893,6 +913,30 @@ cl_int ValidateGetKernelInfo(cl_kernel kernel,
const void *param_value,
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;
}
......@@ -903,6 +947,58 @@ cl_int ValidateGetKernelWorkGroupInfo(cl_kernel kernel,
const void *param_value,
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;
}
......@@ -1590,7 +1686,7 @@ cl_int ValidateCreateImage(cl_context context,
// 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.
const DeviceRefList &devices = ctx.getDevices();
const DeviceRefs &devices = ctx.getDevices();
if (std::find_if(devices.cbegin(), devices.cend(), [&](const DeviceRefPtr &ptr) {
switch (image_desc->image_type)
{
......@@ -1719,6 +1815,31 @@ cl_int ValidateGetKernelArgInfo(cl_kernel kernel,
const void *param_value,
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;
}
......
......@@ -472,6 +472,7 @@ libangle_cl_headers = [
"src/libANGLE/renderer/CLCommandQueueImpl.h",
"src/libANGLE/renderer/CLContextImpl.h",
"src/libANGLE/renderer/CLDeviceImpl.h",
"src/libANGLE/renderer/CLKernelImpl.h",
"src/libANGLE/renderer/CLMemoryImpl.h",
"src/libANGLE/renderer/CLPlatformImpl.h",
"src/libANGLE/renderer/CLProgramImpl.h",
......@@ -498,6 +499,7 @@ libangle_cl_sources = [
"src/libANGLE/renderer/CLCommandQueueImpl.cpp",
"src/libANGLE/renderer/CLContextImpl.cpp",
"src/libANGLE/renderer/CLDeviceImpl.cpp",
"src/libANGLE/renderer/CLKernelImpl.cpp",
"src/libANGLE/renderer/CLMemoryImpl.cpp",
"src/libANGLE/renderer/CLPlatformImpl.cpp",
"src/libANGLE/renderer/CLProgramImpl.cpp",
......
......@@ -504,8 +504,7 @@ cl_int GetProgramBuildInfo(cl_program program,
cl_kernel CreateKernel(cl_program program, const char *kernel_name, cl_int &errorCode)
{
WARN_NOT_SUPPORTED(CreateKernel);
return 0;
return static_cast<Program *>(program)->createKernel(kernel_name, errorCode);
}
cl_int CreateKernelsInProgram(cl_program program,
......@@ -513,8 +512,7 @@ cl_int CreateKernelsInProgram(cl_program program,
cl_kernel *kernels,
cl_uint *num_kernels_ret)
{
WARN_NOT_SUPPORTED(CreateKernelsInProgram);
return 0;
return static_cast<Program *>(program)->createKernels(num_kernels, kernels, num_kernels_ret);
}
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)
{
WARN_NOT_SUPPORTED(RetainKernel);
return 0;
static_cast<Kernel *>(kernel)->retain();
return CL_SUCCESS;
}
cl_int ReleaseKernel(cl_kernel kernel)
{
WARN_NOT_SUPPORTED(ReleaseKernel);
return 0;
static_cast<Kernel *>(kernel)->release();
return CL_SUCCESS;
}
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,
void *param_value,
size_t *param_value_size_ret)
{
WARN_NOT_SUPPORTED(GetKernelInfo);
return 0;
return static_cast<Kernel *>(kernel)->getInfo(param_name, param_value_size, param_value,
param_value_size_ret);
}
cl_int GetKernelArgInfo(cl_kernel kernel,
......@@ -573,8 +571,8 @@ cl_int GetKernelArgInfo(cl_kernel kernel,
void *param_value,
size_t *param_value_size_ret)
{
WARN_NOT_SUPPORTED(GetKernelArgInfo);
return 0;
return static_cast<Kernel *>(kernel)->getArgInfo(arg_index, param_name, param_value_size,
param_value, param_value_size_ret);
}
cl_int GetKernelWorkGroupInfo(cl_kernel kernel,
......@@ -584,8 +582,8 @@ cl_int GetKernelWorkGroupInfo(cl_kernel kernel,
void *param_value,
size_t *param_value_size_ret)
{
WARN_NOT_SUPPORTED(GetKernelWorkGroupInfo);
return 0;
return static_cast<Kernel *>(kernel)->getWorkGroupInfo(device, param_name, param_value_size,
param_value, param_value_size_ret);
}
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