Commit 1aa88398 by John Plate Committed by Angle LUCI CQ

CL: program object creation for front end and pass-through

Add program object to back end and implement creation and info query. Bug: angleproject:6001 Change-Id: If94db8ab8b491e1ac21c767347cabb6f4f3b3cba Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/2912465Reviewed-by: 's avatarJamie Madill <jmadill@chromium.org> Reviewed-by: 's avatarCody Northrop <cnorthrop@google.com> Commit-Queue: John Plate <jplate@google.com>
parent a8d98fcf
......@@ -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 *),
"Device::RefList has wrong element size");
"DeviceRefList has wrong element size");
copyValue = mDevices.data();
copySize = mDevices.size() * sizeof(decltype(mDevices)::value_type);
break;
......@@ -220,6 +220,76 @@ cl_sampler Context::createSamplerWithProperties(const cl_sampler_properties *pro
errcodeRet);
}
cl_program Context::createProgramWithSource(cl_uint count,
const char **strings,
const size_t *lengths,
cl_int *errcodeRet)
{
std::string source;
if (lengths == nullptr)
{
while (count-- != 0u)
{
source.append(*strings++);
}
}
else
{
while (count-- != 0u)
{
if (*lengths != 0u)
{
source.append(*strings++, *lengths);
}
else
{
source.append(*strings++);
}
++lengths;
}
}
return createProgram(new Program(*this, std::move(source), errcodeRet), errcodeRet);
}
cl_program Context::createProgramWithIL(const void *il, size_t length, cl_int *errcodeRet)
{
return createProgram(new Program(*this, il, length, errcodeRet), errcodeRet);
}
cl_program Context::createProgramWithBinary(cl_uint numDevices,
const cl_device_id *devices,
const size_t *lengths,
const unsigned char **binaries,
cl_int *binaryStatus,
cl_int *errcodeRet)
{
DeviceRefList refDevices;
Binaries binaryVec;
while (numDevices-- != 0u)
{
refDevices.emplace_back(static_cast<Device *>(*devices++));
binaryVec.emplace_back(*lengths++);
std::memcpy(binaryVec.back().data(), *binaries++, binaryVec.back().size());
}
return createProgram(
new Program(*this, std::move(refDevices), std::move(binaryVec), binaryStatus, errcodeRet),
errcodeRet);
}
cl_program Context::createProgramWithBuiltInKernels(cl_uint numDevices,
const cl_device_id *devices,
const char *kernelNames,
cl_int *errcodeRet)
{
DeviceRefList refDevices;
while (numDevices-- != 0u)
{
refDevices.emplace_back(static_cast<Device *>(*devices++));
}
return createProgram(new Program(*this, std::move(refDevices), kernelNames, errcodeRet),
errcodeRet);
}
bool Context::IsValid(const _cl_context *context)
{
const Platform::PtrList &platforms = Platform::GetPlatforms();
......@@ -311,6 +381,21 @@ cl_sampler Context::createSampler(Sampler *sampler, cl_int *errcodeRet)
return mSamplers.back().get();
}
cl_program Context::createProgram(Program *program, cl_int *errcodeRet)
{
mPrograms.emplace_back(program);
if (!mPrograms.back()->mImpl)
{
mPrograms.back()->release();
return nullptr;
}
if (errcodeRet != nullptr)
{
*errcodeRet = CL_SUCCESS;
}
return mPrograms.back().get();
}
void Context::destroyCommandQueue(CommandQueue *commandQueue)
{
auto commandQueueIt = mCommandQueues.cbegin();
......@@ -362,6 +447,23 @@ void Context::destroySampler(Sampler *sampler)
}
}
void Context::destroyProgram(Program *program)
{
auto programIt = mPrograms.cbegin();
while (programIt != mPrograms.cend() && programIt->get() != program)
{
++programIt;
}
if (programIt != mPrograms.cend())
{
mPrograms.erase(programIt);
}
else
{
ERR() << "Program not found";
}
}
void Context::ErrorCallback(const char *errinfo, const void *privateInfo, size_t cb, void *userData)
{
Context *const context = static_cast<Context *>(userData);
......
......@@ -12,6 +12,7 @@
#include "libANGLE/CLCommandQueue.h"
#include "libANGLE/CLDevice.h"
#include "libANGLE/CLMemory.h"
#include "libANGLE/CLProgram.h"
#include "libANGLE/CLSampler.h"
#include "libANGLE/renderer/CLContextImpl.h"
......@@ -29,11 +30,15 @@ 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;
bool supportsImages() const;
bool supportsIL() const;
bool supportsBuiltInKernel(const std::string &name) const;
bool hasCommandQueue(const _cl_command_queue *commandQueue) const;
bool hasMemory(const _cl_mem *memory) const;
bool hasSampler(const _cl_sampler *sampler) const;
bool hasProgram(const _cl_program *program) const;
void retain() noexcept;
bool release();
......@@ -87,6 +92,25 @@ class Context final : public _cl_context, public Object
cl_sampler createSamplerWithProperties(const cl_sampler_properties *properties,
cl_int *errcodeRet);
cl_program createProgramWithSource(cl_uint count,
const char **strings,
const size_t *lengths,
cl_int *errcodeRet);
cl_program createProgramWithIL(const void *il, size_t length, cl_int *errcodeRet);
cl_program createProgramWithBinary(cl_uint numDevices,
const cl_device_id *devices,
const size_t *lengths,
const unsigned char **binaries,
cl_int *binaryStatus,
cl_int *errcodeRet);
cl_program createProgramWithBuiltInKernels(cl_uint numDevices,
const cl_device_id *devices,
const char *kernelNames,
cl_int *errcodeRet);
static bool IsValid(const _cl_context *context);
private:
......@@ -109,10 +133,12 @@ class Context final : public _cl_context, public Object
cl_command_queue createCommandQueue(CommandQueue *commandQueue, cl_int *errcodeRet);
cl_mem createMemory(Memory *memory, cl_int *errcodeRet);
cl_sampler createSampler(Sampler *sampler, cl_int *errcodeRet);
cl_program createProgram(Program *program, cl_int *errcodeRet);
void destroyCommandQueue(CommandQueue *commandQueue);
void destroyMemory(Memory *memory);
void destroySampler(Sampler *sampler);
void destroyProgram(Program *program);
static void CL_CALLBACK ErrorCallback(const char *errinfo,
const void *privateInfo,
......@@ -129,11 +155,13 @@ class Context final : public _cl_context, public Object
CommandQueue::PtrList mCommandQueues;
Memory::PtrList mMemories;
Sampler::PtrList mSamplers;
Program::PtrList mPrograms;
friend class Buffer;
friend class CommandQueue;
friend class Memory;
friend class Platform;
friend class Program;
friend class Sampler;
};
......@@ -161,6 +189,20 @@ inline bool Context::supportsImages() const
}) != mDevices.cend());
}
inline bool Context::supportsIL() const
{
return (std::find_if(mDevices.cbegin(), mDevices.cend(), [](const DeviceRefPtr &ptr) {
return !ptr->getInfo().mIL_Version.empty();
}) != mDevices.cend());
}
inline bool Context::supportsBuiltInKernel(const std::string &name) const
{
return (std::find_if(mDevices.cbegin(), mDevices.cend(), [&](const DeviceRefPtr &ptr) {
return ptr->supportsBuiltInKernel(name);
}) != mDevices.cend());
}
inline bool Context::hasCommandQueue(const _cl_command_queue *commandQueue) const
{
return std::find_if(mCommandQueues.cbegin(), mCommandQueues.cend(),
......@@ -182,6 +224,13 @@ inline bool Context::hasSampler(const _cl_sampler *sampler) const
}) != mSamplers.cend();
}
inline bool Context::hasProgram(const _cl_program *program) const
{
return std::find_if(mPrograms.cbegin(), mPrograms.cend(), [=](const ProgramPtr &ptr) {
return ptr.get() == program;
}) != mPrograms.cend();
}
inline void Context::retain() noexcept
{
addRef();
......
......@@ -22,6 +22,31 @@ Device::~Device()
}
}
bool Device::supportsBuiltInKernel(const std::string &name) const
{
if (name.empty() || mInfo.mBuiltInKernels.empty())
{
return false;
}
// Compare kernel name with all sub-strings terminated by semi-colon or end of string
std::string::size_type start = 0u;
do
{
std::string::size_type end = mInfo.mBuiltInKernels.find(';', start);
if (end == std::string::npos)
{
end = mInfo.mBuiltInKernels.length();
}
const std::string::size_type length = end - start;
if (length == name.length() && mInfo.mBuiltInKernels.compare(start, length, name) == 0)
{
return true;
}
start = end + 1u;
} while (start < mInfo.mBuiltInKernels.size());
return false;
}
bool Device::release()
{
if (isRoot())
......@@ -170,8 +195,6 @@ cl_int Device::getInfo(DeviceInfo name, size_t valueSize, void *value, size_t *v
break;
// Handle all string types
case DeviceInfo::IL_Version:
case DeviceInfo::BuiltInKernels:
case DeviceInfo::Name:
case DeviceInfo::Vendor:
case DeviceInfo::DriverVersion:
......@@ -207,11 +230,19 @@ cl_int Device::getInfo(DeviceInfo name, size_t valueSize, void *value, size_t *v
copyValue = &mInfo.mMaxMemAllocSize;
copySize = sizeof(mInfo.mMaxMemAllocSize);
break;
case DeviceInfo::IL_Version:
copyValue = mInfo.mIL_Version.c_str();
copySize = mInfo.mIL_Version.length() + 1u;
break;
case DeviceInfo::ILsWithVersion:
copyValue = mInfo.mILsWithVersion.data();
copySize =
mInfo.mILsWithVersion.size() * sizeof(decltype(mInfo.mILsWithVersion)::value_type);
break;
case DeviceInfo::BuiltInKernels:
copyValue = mInfo.mBuiltInKernels.c_str();
copySize = mInfo.mBuiltInKernels.length() + 1u;
break;
case DeviceInfo::BuiltInKernelsWithVersion:
copyValue = mInfo.mBuiltInKernelsWithVersion.data();
copySize = mInfo.mBuiltInKernelsWithVersion.size() *
......
......@@ -35,6 +35,8 @@ class Device final : public _cl_device_id, public Object
bool isVersionOrNewer(cl_uint major, cl_uint minor) const;
bool hasSubDevice(const _cl_device_id *device) const;
bool supportsBuiltInKernel(const std::string &name) const;
void retain() noexcept;
bool release();
......
......@@ -37,6 +37,7 @@ class Platform final : public _cl_platform_id, public Object
bool hasCommandQueue(const _cl_command_queue *commandQueue) const;
bool hasMemory(const _cl_mem *memory) const;
bool hasSampler(const _cl_sampler *sampler) const;
bool hasProgram(const _cl_program *program) const;
cl_int getInfo(PlatformInfo name, size_t valueSize, void *value, size_t *valueSizeRet) const;
......@@ -143,6 +144,13 @@ inline bool Platform::hasSampler(const _cl_sampler *sampler) const
}) != mContexts.cend();
}
inline bool Platform::hasProgram(const _cl_program *program) const
{
return std::find_if(mContexts.cbegin(), mContexts.cend(), [=](const ContextPtr &ptr) {
return ptr->hasProgram(program);
}) != mContexts.cend();
}
inline Platform::PtrList &Platform::GetList()
{
static angle::base::NoDestructor<PtrList> sList;
......
......@@ -7,9 +7,160 @@
#include "libANGLE/CLProgram.h"
#include "libANGLE/CLContext.h"
#include "libANGLE/CLPlatform.h"
namespace cl
{
Program::Program(const cl_icd_dispatch &dispatch) : _cl_program(dispatch) {}
Program::~Program() = default;
bool Program::release()
{
const bool released = removeRef();
if (released)
{
mContext->destroyProgram(this);
}
return released;
}
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 &&
std::is_same<cl_uint, cl_filter_mode>::value,
"OpenCL type mismatch");
std::vector<size_t> binarySizes;
std::vector<const unsigned char *> binaries;
cl_uint valUInt = 0u;
void *valPointer = nullptr;
const void *copyValue = nullptr;
size_t copySize = 0u;
switch (name)
{
case ProgramInfo::ReferenceCount:
copyValue = getRefCountPtr();
copySize = sizeof(*getRefCountPtr());
break;
case ProgramInfo::Context:
valPointer = static_cast<cl_context>(mContext.get());
copyValue = &valPointer;
copySize = sizeof(valPointer);
break;
case ProgramInfo::NumDevices:
valUInt = static_cast<decltype(valUInt)>(mDevices.size());
copyValue = &valUInt;
copySize = sizeof(valUInt);
break;
case ProgramInfo::Devices:
static_assert(sizeof(decltype(mDevices)::value_type) == sizeof(Device *),
"DeviceRefList has wrong element size");
copyValue = mDevices.data();
copySize = mDevices.size() * sizeof(decltype(mDevices)::value_type);
break;
case ProgramInfo::Source:
copyValue = mSource.c_str();
copySize = mSource.length() + 1u;
break;
case ProgramInfo::IL:
copyValue = mIL.c_str();
copySize = mIL.length() + 1u;
break;
case ProgramInfo::BinarySizes:
binarySizes.resize(mDevices.size(), 0u);
for (size_t index = 0u; index < binarySizes.size(); ++index)
{
binarySizes[index] = index < mBinaries.size() ? mBinaries[index].size() : 0u;
}
copyValue = binarySizes.data();
copySize = binarySizes.size() * sizeof(decltype(binarySizes)::value_type);
break;
case ProgramInfo::Binaries:
binaries.resize(mDevices.size(), nullptr);
for (size_t index = 0u; index < binaries.size(); ++index)
{
binaries[index] = index < mBinaries.size() && mBinaries[index].empty()
? mBinaries[index].data()
: nullptr;
}
copyValue = binaries.data();
copySize = binaries.size() * sizeof(decltype(binaries)::value_type);
break;
case ProgramInfo::NumKernels:
case ProgramInfo::KernelNames:
case ProgramInfo::ScopeGlobalCtorsPresent:
case ProgramInfo::ScopeGlobalDtorsPresent:
default:
return CL_INVALID_VALUE;
}
if (value != nullptr)
{
if (valueSize < copySize)
{
return CL_INVALID_VALUE;
}
if (copyValue != nullptr)
{
std::memcpy(value, copyValue, copySize);
}
}
if (valueSizeRet != nullptr)
{
*valueSizeRet = copySize;
}
return CL_SUCCESS;
}
bool Program::IsValid(const _cl_program *program)
{
const Platform::PtrList &platforms = Platform::GetPlatforms();
return std::find_if(platforms.cbegin(), platforms.cend(), [=](const PlatformPtr &platform) {
return platform->hasProgram(program);
}) != platforms.cend();
}
Program::Program(Context &context, std::string &&source, cl_int *errcodeRet)
: _cl_program(context.getDispatch()),
mContext(&context),
mDevices(context.getDevices()),
mImpl(context.mImpl->createProgramWithSource(*this, source, errcodeRet)),
mSource(std::move(source))
{}
Program::Program(Context &context, const void *il, size_t length, cl_int *errcodeRet)
: _cl_program(context.getDispatch()),
mContext(&context),
mDevices(context.getDevices()),
mIL(static_cast<const char *>(il), length),
mImpl(context.mImpl->createProgramWithIL(*this, il, length, errcodeRet)),
mSource(mImpl ? mImpl->getSource() : std::string{})
{}
Program::Program(Context &context,
DeviceRefList &&devices,
Binaries &&binaries,
cl_int *binaryStatus,
cl_int *errcodeRet)
: _cl_program(context.getDispatch()),
mContext(&context),
mDevices(std::move(devices)),
mImpl(context.mImpl->createProgramWithBinary(*this, binaries, binaryStatus, errcodeRet)),
mSource(mImpl ? mImpl->getSource() : std::string{}),
mBinaries(std::move(binaries))
{}
Program::Program(Context &context,
DeviceRefList &&devices,
const char *kernelNames,
cl_int *errcodeRet)
: _cl_program(context.getDispatch()),
mContext(&context),
mDevices(std::move(devices)),
mImpl(context.mImpl->createProgramWithBuiltInKernels(*this, kernelNames, errcodeRet)),
mSource(mImpl ? mImpl->getSource() : std::string{})
{}
} // namespace cl
......@@ -9,6 +9,7 @@
#define LIBANGLE_CLPROGRAM_H_
#include "libANGLE/CLObject.h"
#include "libANGLE/renderer/CLProgramImpl.h"
namespace cl
{
......@@ -16,10 +17,58 @@ namespace cl
class Program final : public _cl_program, public Object
{
public:
Program(const cl_icd_dispatch &dispatch);
~Program() override = default;
using PtrList = std::list<ProgramPtr>;
~Program() override;
const Context &getContext() const;
const DeviceRefList &getDevices() const;
void retain() noexcept;
bool release();
cl_int getInfo(ProgramInfo name, size_t valueSize, void *value, size_t *valueSizeRet) const;
static bool IsValid(const _cl_program *program);
private:
Program(Context &context, std::string &&source, cl_int *errcodeRet);
Program(Context &context, const void *il, size_t length, cl_int *errcodeRet);
Program(Context &context,
DeviceRefList &&devices,
Binaries &&binaries,
cl_int *binaryStatus,
cl_int *errcodeRet);
Program(Context &context, DeviceRefList &&devices, const char *kernelNames, cl_int *errcodeRet);
const ContextRefPtr mContext;
const DeviceRefList mDevices;
const std::string mIL;
const rx::CLProgramImpl::Ptr mImpl;
const std::string mSource;
Binaries mBinaries;
friend class Context;
};
inline const Context &Program::getContext() const
{
return *mContext;
}
inline const DeviceRefList &Program::getDevices() const
{
return mDevices;
}
inline void Program::retain() noexcept
{
addRef();
}
} // namespace cl
#endif // LIBANGLE_CLPROGRAM_H_
......@@ -54,6 +54,9 @@ using MemoryRefPtr = RefPointer<Memory>;
using DevicePtrList = std::list<DevicePtr>;
using DeviceRefList = std::vector<DeviceRefPtr>;
using Binary = std::vector<unsigned char>;
using Binaries = std::vector<Binary>;
struct ImageDescriptor
{
cl_mem_object_type type;
......
......@@ -11,6 +11,7 @@
#include "libANGLE/renderer/CLCommandQueueImpl.h"
#include "libANGLE/renderer/CLDeviceImpl.h"
#include "libANGLE/renderer/CLMemoryImpl.h"
#include "libANGLE/renderer/CLProgramImpl.h"
#include "libANGLE/renderer/CLSamplerImpl.h"
namespace rx
......@@ -42,6 +43,24 @@ class CLContextImpl : angle::NonCopyable
virtual CLSamplerImpl::Ptr createSampler(const cl::Sampler &sampler, cl_int *errcodeRet) = 0;
virtual CLProgramImpl::Ptr createProgramWithSource(const cl::Program &program,
const std::string &source,
cl_int *errcodeRet) = 0;
virtual CLProgramImpl::Ptr createProgramWithIL(const cl::Program &program,
const void *il,
size_t length,
cl_int *errcodeRet) = 0;
virtual CLProgramImpl::Ptr createProgramWithBinary(const cl::Program &program,
const cl::Binaries &binaries,
cl_int *binaryStatus,
cl_int *errcodeRet) = 0;
virtual CLProgramImpl::Ptr createProgramWithBuiltInKernels(const cl::Program &program,
const char *kernel_names,
cl_int *errcodeRet) = 0;
protected:
const cl::Context &mContext;
};
......
......@@ -37,6 +37,7 @@ class CLDeviceImpl : angle::NonCopyable
std::vector<size_t> mMaxWorkItemSizes;
cl_ulong mMaxMemAllocSize = 0u;
cl_bool mImageSupport = CL_FALSE;
std::string mIL_Version;
NameVersionVector mILsWithVersion;
size_t mImage2D_MaxWidth = 0u;
size_t mImage2D_MaxHeight = 0u;
......@@ -47,6 +48,7 @@ class CLDeviceImpl : angle::NonCopyable
size_t mImageMaxArraySize = 0u;
cl_uint mImagePitchAlignment = 0u;
cl_uint mImageBaseAddressAlignment = 0u;
std::string mBuiltInKernels;
NameVersionVector mBuiltInKernelsWithVersion;
std::string mVersionStr;
cl_version mVersion = 0u;
......
//
// 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.
//
// CLProgramImpl.cpp: Implements the class methods for CLProgramImpl.
#include "libANGLE/renderer/CLProgramImpl.h"
namespace rx
{
CLProgramImpl::CLProgramImpl(const cl::Program &program) : mProgram(program) {}
CLProgramImpl::~CLProgramImpl() = 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.
//
// CLProgramImpl.h: Defines the abstract rx::CLProgramImpl class.
#ifndef LIBANGLE_RENDERER_CLPROGRAMIMPL_H_
#define LIBANGLE_RENDERER_CLPROGRAMIMPL_H_
#include "libANGLE/renderer/CLtypes.h"
namespace rx
{
class CLProgramImpl : angle::NonCopyable
{
public:
using Ptr = std::unique_ptr<CLProgramImpl>;
CLProgramImpl(const cl::Program &program);
virtual ~CLProgramImpl();
virtual std::string getSource() const = 0;
protected:
const cl::Program &mProgram;
};
} // namespace rx
#endif // LIBANGLE_RENDERER_CLPROGRAMIMPL_H_
......@@ -19,6 +19,8 @@ _cl_backend_sources = [
"CLMemoryCL.h",
"CLPlatformCL.cpp",
"CLPlatformCL.h",
"CLProgramCL.cpp",
"CLProgramCL.h",
"CLSamplerCL.cpp",
"CLSamplerCL.h",
"cl_types.h",
......
......@@ -10,6 +10,7 @@
#include "libANGLE/renderer/cl/CLCommandQueueCL.h"
#include "libANGLE/renderer/cl/CLDeviceCL.h"
#include "libANGLE/renderer/cl/CLMemoryCL.h"
#include "libANGLE/renderer/cl/CLProgramCL.h"
#include "libANGLE/renderer/cl/CLSamplerCL.h"
#include "libANGLE/CLBuffer.h"
......@@ -19,6 +20,7 @@
#include "libANGLE/CLImage.h"
#include "libANGLE/CLMemory.h"
#include "libANGLE/CLPlatform.h"
#include "libANGLE/CLProgram.h"
#include "libANGLE/CLSampler.h"
#include "libANGLE/Debug.h"
......@@ -202,4 +204,68 @@ CLSamplerImpl::Ptr CLContextCL::createSampler(const cl::Sampler &sampler, cl_int
: nullptr);
}
CLProgramImpl::Ptr CLContextCL::createProgramWithSource(const cl::Program &program,
const std::string &source,
cl_int *errcodeRet)
{
const char *sourceStr = source.c_str();
const size_t length = source.length();
const cl_program nativeProgram = mNative->getDispatch().clCreateProgramWithSource(
mNative, 1u, &sourceStr, &length, errcodeRet);
return CLProgramImpl::Ptr(nativeProgram != nullptr ? new CLProgramCL(program, nativeProgram)
: nullptr);
}
CLProgramImpl::Ptr CLContextCL::createProgramWithIL(const cl::Program &program,
const void *il,
size_t length,
cl_int *errcodeRet)
{
const cl_program nativeProgram =
mNative->getDispatch().clCreateProgramWithIL(mNative, il, length, errcodeRet);
return CLProgramImpl::Ptr(nativeProgram != nullptr ? new CLProgramCL(program, nativeProgram)
: nullptr);
}
CLProgramImpl::Ptr CLContextCL::createProgramWithBinary(const cl::Program &program,
const cl::Binaries &binaries,
cl_int *binaryStatus,
cl_int *errcodeRet)
{
ASSERT(program.getDevices().size() == binaries.size());
std::vector<cl_device_id> nativeDevices;
for (const cl::DeviceRefPtr &device : program.getDevices())
{
nativeDevices.emplace_back(device->getImpl<CLDeviceCL &>().getNative());
}
std::vector<size_t> lengths;
std::vector<const unsigned char *> nativeBinaries;
for (const cl::Binary &binary : binaries)
{
lengths.emplace_back(binary.size());
nativeBinaries.emplace_back(binary.data());
}
const cl_program nativeProgram = mNative->getDispatch().clCreateProgramWithBinary(
mNative, static_cast<cl_uint>(nativeDevices.size()), nativeDevices.data(), lengths.data(),
nativeBinaries.data(), binaryStatus, errcodeRet);
return CLProgramImpl::Ptr(nativeProgram != nullptr ? new CLProgramCL(program, nativeProgram)
: nullptr);
}
CLProgramImpl::Ptr CLContextCL::createProgramWithBuiltInKernels(const cl::Program &program,
const char *kernel_names,
cl_int *errcodeRet)
{
std::vector<cl_device_id> nativeDevices;
for (const cl::DeviceRefPtr &device : program.getDevices())
{
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,
errcodeRet);
return CLProgramImpl::Ptr(nativeProgram != nullptr ? new CLProgramCL(program, nativeProgram)
: nullptr);
}
} // namespace rx
......@@ -39,6 +39,24 @@ class CLContextCL : public CLContextImpl
CLSamplerImpl::Ptr createSampler(const cl::Sampler &sampler, cl_int *errcodeRet) override;
CLProgramImpl::Ptr createProgramWithSource(const cl::Program &program,
const std::string &source,
cl_int *errcodeRet) override;
CLProgramImpl::Ptr createProgramWithIL(const cl::Program &program,
const void *il,
size_t length,
cl_int *errcodeRet) override;
CLProgramImpl::Ptr createProgramWithBinary(const cl::Program &program,
const cl::Binaries &binaries,
cl_int *binaryStatus,
cl_int *errcodeRet) override;
CLProgramImpl::Ptr createProgramWithBuiltInKernels(const cl::Program &program,
const char *kernel_names,
cl_int *errcodeRet) override;
private:
const cl_context mNative;
};
......
......@@ -114,13 +114,21 @@ CLDeviceImpl::Info CLDeviceCL::createInfo(cl_device_type type) const
info.mExtensions.assign(valString.data());
RemoveUnsupportedCLExtensions(info.mExtensions);
if (info.mVersion >= CL_MAKE_VERSION(1, 2, 0) &&
(!GetDeviceInfo(mNative, cl::DeviceInfo::ImageMaxBufferSize, info.mImageMaxBufferSize) ||
!GetDeviceInfo(mNative, cl::DeviceInfo::ImageMaxArraySize, info.mImageMaxArraySize) ||
!GetDeviceInfo(mNative, cl::DeviceInfo::PartitionProperties, info.mPartitionProperties) ||
!GetDeviceInfo(mNative, cl::DeviceInfo::PartitionType, info.mPartitionType)))
if (info.mVersion >= CL_MAKE_VERSION(1, 2, 0))
{
return Info{};
if (!GetDeviceInfo(mNative, cl::DeviceInfo::ImageMaxBufferSize, info.mImageMaxBufferSize) ||
!GetDeviceInfo(mNative, cl::DeviceInfo::ImageMaxArraySize, info.mImageMaxArraySize) ||
!GetDeviceInfo(mNative, cl::DeviceInfo::BuiltInKernels, valString))
{
return Info{};
}
info.mBuiltInKernels.assign(valString.data());
if (!GetDeviceInfo(mNative, cl::DeviceInfo::PartitionProperties,
info.mPartitionProperties) ||
!GetDeviceInfo(mNative, cl::DeviceInfo::PartitionType, info.mPartitionType))
{
return Info{};
}
}
if (info.mVersion >= CL_MAKE_VERSION(2, 0, 0) &&
......@@ -131,6 +139,15 @@ CLDeviceImpl::Info CLDeviceCL::createInfo(cl_device_type type) const
return Info{};
}
if (info.mVersion >= CL_MAKE_VERSION(2, 1, 0))
{
if (!GetDeviceInfo(mNative, cl::DeviceInfo::IL_Version, valString))
{
return Info{};
}
info.mIL_Version.assign(valString.data());
}
if (info.mVersion >= CL_MAKE_VERSION(3, 0, 0) &&
(!GetDeviceInfo(mNative, cl::DeviceInfo::ILsWithVersion, info.mILsWithVersion) ||
!GetDeviceInfo(mNative, cl::DeviceInfo::BuiltInKernelsWithVersion,
......
//
// 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.
//
// CLProgramCL.cpp: Implements the class methods for CLProgramCL.
#include "libANGLE/renderer/cl/CLProgramCL.h"
#include "libANGLE/Debug.h"
namespace rx
{
CLProgramCL::CLProgramCL(const cl::Program &program, cl_program native)
: CLProgramImpl(program), mNative(native)
{}
CLProgramCL::~CLProgramCL()
{
if (mNative->getDispatch().clReleaseProgram(mNative) != CL_SUCCESS)
{
ERR() << "Error while releasing CL program";
}
}
std::string CLProgramCL::getSource() const
{
size_t size = 0u;
if (mNative->getDispatch().clGetProgramInfo(mNative, CL_PROGRAM_SOURCE, 0u, nullptr, &size) ==
CL_SUCCESS)
{
if (size != 0u)
{
std::vector<char> valString(size, '\0');
if (mNative->getDispatch().clGetProgramInfo(mNative, CL_PROGRAM_SOURCE, size,
valString.data(), nullptr) == CL_SUCCESS)
{
return std::string(valString.data(), valString.size() - 1u);
}
}
else
{
return std::string{};
}
}
ERR() << "Failed to query CL program source";
return std::string{};
}
} // 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.
//
// CLProgramCL.h: Defines the class interface for CLProgramCL, implementing CLProgramImpl.
#ifndef LIBANGLE_RENDERER_CL_CLPROGRAMCL_H_
#define LIBANGLE_RENDERER_CL_CLPROGRAMCL_H_
#include "libANGLE/renderer/cl/cl_types.h"
#include "libANGLE/renderer/CLProgramImpl.h"
namespace rx
{
class CLProgramCL : public CLProgramImpl
{
public:
CLProgramCL(const cl::Program &program, cl_program native);
~CLProgramCL() override;
std::string getSource() const override;
private:
const cl_program mNative;
};
} // namespace rx
#endif // LIBANGLE_RENDERER_CL_CLPROGRAMCL_H_
......@@ -115,6 +115,8 @@ if (angle_enable_cl) {
"CLMemoryVk.h",
"CLPlatformVk.cpp",
"CLPlatformVk.h",
"CLProgramVk.cpp",
"CLProgramVk.h",
"CLSamplerVk.cpp",
"CLSamplerVk.h",
"cl_types.h",
......
//
// Copyright 2021 The ANGLE Project Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//
// CLProgramVk.cpp: Implements the class methods for CLProgramVk.
#include "libANGLE/renderer/vulkan/CLProgramVk.h"
namespace rx
{
CLProgramVk::CLProgramVk(const cl::Program &program) : CLProgramImpl(program) {}
CLProgramVk::~CLProgramVk() = 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.
//
// CLProgramVk.h: Defines the class interface for CLProgramVk, implementing CLProgramImpl.
#ifndef LIBANGLE_RENDERER_VULKAN_CLPROGRAMVK_H_
#define LIBANGLE_RENDERER_VULKAN_CLPROGRAMVK_H_
#include "libANGLE/renderer/vulkan/cl_types.h"
#include "libANGLE/renderer/CLProgramImpl.h"
namespace rx
{
class CLProgramVk : public CLProgramImpl
{
public:
CLProgramVk(const cl::Program &program);
~CLProgramVk() override;
};
} // namespace rx
#endif // LIBANGLE_RENDERER_VULKAN_CLPROGRAMVK_H_
......@@ -635,6 +635,21 @@ bool ValidateCreateProgramWithSource(cl_context context,
const size_t *lengths,
cl_int *errcode_ret)
{
if (!Context::IsValid(context))
{
ANGLE_ERROR_RETURN(CL_INVALID_CONTEXT, false);
}
if (count == 0u || strings == nullptr)
{
ANGLE_ERROR_RETURN(CL_INVALID_VALUE, false);
}
while (count-- != 0u)
{
if (*strings++ == nullptr)
{
ANGLE_ERROR_RETURN(CL_INVALID_VALUE, false);
}
}
return true;
}
......@@ -646,17 +661,37 @@ bool ValidateCreateProgramWithBinary(cl_context context,
const cl_int *binary_status,
cl_int *errcode_ret)
{
if (!Context::IsValid(context))
{
ANGLE_ERROR_RETURN(CL_INVALID_CONTEXT, false);
}
if (num_devices == 0u || device_list == nullptr || lengths == nullptr || binaries == nullptr)
{
ANGLE_ERROR_RETURN(CL_INVALID_VALUE, false);
}
const Context &ctx = *static_cast<Context *>(context);
while (num_devices-- != 0u)
{
if (!ctx.hasDevice(*device_list++))
{
ANGLE_ERROR_RETURN(CL_INVALID_DEVICE, false);
}
if (*lengths++ == 0u || *binaries++ == nullptr)
{
ANGLE_ERROR_RETURN(CL_INVALID_VALUE, false);
}
}
return true;
}
cl_int ValidateRetainProgram(cl_program program)
{
return CL_SUCCESS;
return Program::IsValid(program) ? CL_SUCCESS : CL_INVALID_PROGRAM;
}
cl_int ValidateReleaseProgram(cl_program program)
{
return CL_SUCCESS;
return Program::IsValid(program) ? CL_SUCCESS : CL_INVALID_PROGRAM;
}
cl_int ValidateBuildProgram(cl_program program,
......@@ -675,6 +710,22 @@ cl_int ValidateGetProgramInfo(cl_program program,
const void *param_value,
const size_t *param_value_size_ret)
{
if (!Program::IsValid(program))
{
return CL_INVALID_PROGRAM;
}
const Platform &platform = static_cast<const Program *>(program)->getContext().getPlatform();
if (param_name == ProgramInfo::InvalidEnum ||
((param_name == ProgramInfo::NumKernels || param_name == ProgramInfo::KernelNames) &&
!platform.isVersionOrNewer(1u, 2u)) ||
(param_name == ProgramInfo::IL && !platform.isVersionOrNewer(2u, 1u)) ||
((param_name == ProgramInfo::ScopeGlobalCtorsPresent ||
param_name == ProgramInfo::ScopeGlobalDtorsPresent) &&
!platform.isVersionOrNewer(2u, 2u)) ||
(param_value_size == 0u && param_value != nullptr))
{
return CL_INVALID_VALUE;
}
return CL_SUCCESS;
}
......@@ -1267,6 +1318,7 @@ bool ValidateCreateImage(cl_context context,
: (image_desc->image_row_pitch != 0u
? image_desc->image_row_pitch
: image_desc->image_width * elemSize);
const size_t sliceSize = image_desc == nullptr
? 0u
: rowPitch * (image_desc->image_type == CL_MEM_OBJECT_IMAGE1D_ARRAY
......@@ -1353,6 +1405,42 @@ bool ValidateCreateProgramWithBuiltInKernels(cl_context context,
const char *kernel_names,
cl_int *errcode_ret)
{
if (!Context::IsValid(context))
{
ANGLE_ERROR_RETURN(CL_INVALID_CONTEXT, false);
}
const Context &ctx = *static_cast<Context *>(context);
if (!ctx.getPlatform().isVersionOrNewer(1u, 2u))
{
ANGLE_ERROR_RETURN(CL_INVALID_CONTEXT, false);
}
if (num_devices == 0u || device_list == nullptr || kernel_names == nullptr)
{
ANGLE_ERROR_RETURN(CL_INVALID_VALUE, false);
}
for (size_t index = 0u; index < num_devices; ++index)
{
if (!ctx.hasDevice(device_list[index]))
{
ANGLE_ERROR_RETURN(CL_INVALID_DEVICE, false);
}
}
// Check for support of each kernel name terminated by semi-colon or end of string
const char *start = kernel_names;
do
{
const char *end = start;
while (*end != '\0' && *end != ';')
{
++end;
}
const size_t length = end - start;
if (length != 0u && !ctx.supportsBuiltInKernel(std::string(start, length)))
{
ANGLE_ERROR_RETURN(CL_INVALID_VALUE, false);
}
start = end;
} while (*start++ != '\0');
return true;
}
......@@ -1693,6 +1781,23 @@ bool ValidateCreateProgramWithIL(cl_context context,
size_t length,
cl_int *errcode_ret)
{
if (!Context::IsValid(context))
{
ANGLE_ERROR_RETURN(CL_INVALID_CONTEXT, false);
}
const Context &ctx = *static_cast<Context *>(context);
if (!ctx.getPlatform().isVersionOrNewer(2u, 1u))
{
ANGLE_ERROR_RETURN(CL_INVALID_CONTEXT, false);
}
if (!ctx.supportsIL())
{
ANGLE_ERROR_RETURN(CL_INVALID_OPERATION, false);
}
if (il == nullptr || length == 0u)
{
ANGLE_ERROR_RETURN(CL_INVALID_VALUE, false);
}
return true;
}
......
......@@ -473,6 +473,7 @@ libangle_cl_headers = [
"src/libANGLE/renderer/CLDeviceImpl.h",
"src/libANGLE/renderer/CLMemoryImpl.h",
"src/libANGLE/renderer/CLPlatformImpl.h",
"src/libANGLE/renderer/CLProgramImpl.h",
"src/libANGLE/renderer/CLSamplerImpl.h",
"src/libANGLE/renderer/CLtypes.h",
"src/libANGLE/validationCL.h",
......@@ -498,6 +499,7 @@ libangle_cl_sources = [
"src/libANGLE/renderer/CLDeviceImpl.cpp",
"src/libANGLE/renderer/CLMemoryImpl.cpp",
"src/libANGLE/renderer/CLPlatformImpl.cpp",
"src/libANGLE/renderer/CLProgramImpl.cpp",
"src/libANGLE/renderer/CLSamplerImpl.cpp",
"src/libANGLE/validationCL.cpp",
]
......
......@@ -377,8 +377,8 @@ cl_program CreateProgramWithSource(cl_context context,
const size_t *lengths,
cl_int *errcode_ret)
{
WARN_NOT_SUPPORTED(CreateProgramWithSource);
return 0;
return static_cast<Context *>(context)->createProgramWithSource(count, strings, lengths,
errcode_ret);
}
cl_program CreateProgramWithBinary(cl_context context,
......@@ -389,8 +389,8 @@ cl_program CreateProgramWithBinary(cl_context context,
cl_int *binary_status,
cl_int *errcode_ret)
{
WARN_NOT_SUPPORTED(CreateProgramWithBinary);
return 0;
return static_cast<Context *>(context)->createProgramWithBinary(
num_devices, device_list, lengths, binaries, binary_status, errcode_ret);
}
cl_program CreateProgramWithBuiltInKernels(cl_context context,
......@@ -399,8 +399,8 @@ cl_program CreateProgramWithBuiltInKernels(cl_context context,
const char *kernel_names,
cl_int *errcode_ret)
{
WARN_NOT_SUPPORTED(CreateProgramWithBuiltInKernels);
return 0;
return static_cast<Context *>(context)->createProgramWithBuiltInKernels(
num_devices, device_list, kernel_names, errcode_ret);
}
cl_program CreateProgramWithIL(cl_context context,
......@@ -408,20 +408,19 @@ cl_program CreateProgramWithIL(cl_context context,
size_t length,
cl_int *errcode_ret)
{
WARN_NOT_SUPPORTED(CreateProgramWithIL);
return 0;
return static_cast<Context *>(context)->createProgramWithIL(il, length, errcode_ret);
}
cl_int RetainProgram(cl_program program)
{
WARN_NOT_SUPPORTED(RetainProgram);
return 0;
static_cast<Program *>(program)->retain();
return CL_SUCCESS;
}
cl_int ReleaseProgram(cl_program program)
{
WARN_NOT_SUPPORTED(ReleaseProgram);
return 0;
static_cast<Program *>(program)->release();
return CL_SUCCESS;
}
cl_int BuildProgram(cl_program program,
......@@ -492,8 +491,8 @@ cl_int GetProgramInfo(cl_program program,
void *param_value,
size_t *param_value_size_ret)
{
WARN_NOT_SUPPORTED(GetProgramInfo);
return 0;
return static_cast<Program *>(program)->getInfo(param_name, param_value_size, param_value,
param_value_size_ret);
}
cl_int GetProgramBuildInfo(cl_program program,
......
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