// // 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. // // CLProgram.cpp: Implements the cl::Program class. #include "libANGLE/CLProgram.h" #include "libANGLE/CLContext.h" #include "libANGLE/CLPlatform.h" #include "libANGLE/cl_utils.h" #include namespace cl { angle::Result Program::build(cl_uint numDevices, const cl_device_id *deviceList, const char *options, ProgramCB pfnNotify, void *userData) { DevicePtrs devices; devices.reserve(numDevices); while (numDevices-- != 0u) { devices.emplace_back(&(*deviceList++)->cast()); } Program *notify = nullptr; if (pfnNotify != nullptr) { // This program has to be retained until the notify callback is called. retain(); *mCallback = CallbackData(pfnNotify, userData); notify = this; } return mImpl->build(devices, options, notify); } angle::Result Program::compile(cl_uint numDevices, const cl_device_id *deviceList, const char *options, cl_uint numInputHeaders, const cl_program *inputHeaders, const char **headerIncludeNames, ProgramCB pfnNotify, void *userData) { DevicePtrs devices; devices.reserve(numDevices); while (numDevices-- != 0u) { devices.emplace_back(&(*deviceList++)->cast()); } ProgramPtrs programs; programs.reserve(numInputHeaders); while (numInputHeaders-- != 0u) { programs.emplace_back(&(*inputHeaders++)->cast()); } Program *notify = nullptr; if (pfnNotify != nullptr) { // This program has to be retained until the notify callback is called. retain(); *mCallback = CallbackData(pfnNotify, userData); notify = this; } return mImpl->compile(devices, options, programs, headerIncludeNames, notify); } angle::Result Program::getInfo(ProgramInfo name, size_t valueSize, void *value, size_t *valueSizeRet) const { std::vector devices; cl_uint valUInt = 0u; void *valPointer = nullptr; const void *copyValue = nullptr; size_t copySize = 0u; switch (name) { case ProgramInfo::ReferenceCount: valUInt = getRefCount(); copyValue = &valUInt; copySize = sizeof(valUInt); break; case ProgramInfo::Context: valPointer = mContext->getNative(); copyValue = &valPointer; copySize = sizeof(valPointer); break; case ProgramInfo::NumDevices: valUInt = static_cast(mDevices.size()); copyValue = &valUInt; copySize = sizeof(valUInt); break; case ProgramInfo::Devices: devices.reserve(mDevices.size()); for (const DevicePtr &device : mDevices) { devices.emplace_back(device->getNative()); } copyValue = devices.data(); copySize = devices.size() * sizeof(decltype(devices)::value_type); break; case ProgramInfo::Source: if (!mSource.empty()) { copyValue = mSource.c_str(); copySize = mSource.length() + 1u; } break; case ProgramInfo::IL: if (!mIL.empty()) { copyValue = mIL.c_str(); copySize = mIL.length() + 1u; } break; case ProgramInfo::BinarySizes: case ProgramInfo::Binaries: case ProgramInfo::NumKernels: case ProgramInfo::KernelNames: case ProgramInfo::ScopeGlobalCtorsPresent: case ProgramInfo::ScopeGlobalDtorsPresent: return mImpl->getInfo(name, valueSize, value, valueSizeRet); default: ANGLE_CL_RETURN_ERROR(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 Program Object Queries table and param_value is not NULL. if (valueSize < copySize) { ANGLE_CL_RETURN_ERROR(CL_INVALID_VALUE); } if (copyValue != nullptr) { std::memcpy(value, copyValue, copySize); } } if (valueSizeRet != nullptr) { *valueSizeRet = copySize; } return angle::Result::Continue; } angle::Result Program::getBuildInfo(cl_device_id device, ProgramBuildInfo name, size_t valueSize, void *value, size_t *valueSizeRet) const { return mImpl->getBuildInfo(device->cast(), name, valueSize, value, valueSizeRet); } cl_kernel Program::createKernel(const char *kernel_name) { return Object::Create(*this, kernel_name); } angle::Result Program::createKernels(cl_uint numKernels, cl_kernel *kernels, cl_uint *numKernelsRet) { if (kernels == nullptr) { numKernels = 0u; } rx::CLKernelImpl::CreateFuncs createFuncs; ANGLE_TRY(mImpl->createKernels(numKernels, createFuncs, numKernelsRet)); KernelPtrs krnls; krnls.reserve(createFuncs.size()); while (!createFuncs.empty()) { krnls.emplace_back(new Kernel(*this, createFuncs.front())); if (krnls.back()->mImpl == nullptr) { return angle::Result::Stop; } createFuncs.pop_front(); } for (KernelPtr &kernel : krnls) { *kernels++ = kernel.release(); } return angle::Result::Continue; } Program::~Program() = default; void Program::callback() { CallbackData callbackData; mCallback->swap(callbackData); const ProgramCB callback = callbackData.first; void *const userData = callbackData.second; ASSERT(callback != nullptr); callback(this, userData); // This program can be released after the callback was called. if (release()) { delete this; } } Program::Program(Context &context, std::string &&source) : mContext(&context), mDevices(context.getDevices()), mNumAttachedKernels(0u), mImpl(nullptr), mSource(std::move(source)) { ANGLE_CL_IMPL_TRY(context.getImpl().createProgramWithSource(*this, mSource, &mImpl)); } Program::Program(Context &context, const void *il, size_t length) : mContext(&context), mDevices(context.getDevices()), mIL(static_cast(il), length), mNumAttachedKernels(0u), mImpl(nullptr) { ANGLE_CL_IMPL_TRY(context.getImpl().createProgramWithIL(*this, il, length, &mImpl)); } Program::Program(Context &context, DevicePtrs &&devices, const size_t *lengths, const unsigned char **binaries, cl_int *binaryStatus) : mContext(&context), mDevices(std::move(devices)), mNumAttachedKernels(0u), mImpl(nullptr) { ANGLE_CL_IMPL_TRY( context.getImpl().createProgramWithBinary(*this, lengths, binaries, binaryStatus, &mImpl)); } Program::Program(Context &context, DevicePtrs &&devices, const char *kernelNames) : mContext(&context), mDevices(std::move(devices)), mNumAttachedKernels(0u), mImpl(nullptr) { ANGLE_CL_IMPL_TRY( context.getImpl().createProgramWithBuiltInKernels(*this, kernelNames, &mImpl)); } Program::Program(Context &context, const DevicePtrs &devices, const char *options, const cl::ProgramPtrs &inputPrograms, ProgramCB pfnNotify, void *userData) : mContext(&context), mDevices(!devices.empty() ? devices : context.getDevices()), mNumAttachedKernels(0u), mImpl(nullptr) { if (pfnNotify != nullptr) { // This program has to be retained until the notify callback is called. retain(); *mCallback = CallbackData(pfnNotify, userData); } else { *mCallback = CallbackData(); } ANGLE_CL_IMPL_TRY(context.getImpl().linkProgram(*this, mDevices, options, inputPrograms, pfnNotify != nullptr ? this : nullptr, &mImpl)); } } // namespace cl