blob: 01c158cca318bbd565f7cde286b3f358e89692dc [file] [log] [blame]
//
// 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.
//
// CLContext.cpp: Implements the cl::Context class.
#include "libANGLE/CLContext.h"
#include "libANGLE/CLBuffer.h"
#include "libANGLE/CLCommandQueue.h"
#include "libANGLE/CLEvent.h"
#include "libANGLE/CLImage.h"
#include "libANGLE/CLMemory.h"
#include "libANGLE/CLProgram.h"
#include "libANGLE/CLSampler.h"
#include <cstring>
namespace cl
{
cl_int Context::getInfo(ContextInfo name, size_t valueSize, void *value, size_t *valueSizeRet) const
{
std::vector<cl_device_id> devices;
cl_uint valUInt = 0u;
const void *copyValue = nullptr;
size_t copySize = 0u;
switch (name)
{
case ContextInfo::ReferenceCount:
valUInt = getRefCount();
copyValue = &valUInt;
copySize = sizeof(valUInt);
break;
case ContextInfo::NumDevices:
valUInt = static_cast<decltype(valUInt)>(mDevices.size());
copyValue = &valUInt;
copySize = sizeof(valUInt);
break;
case ContextInfo::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 ContextInfo::Properties:
copyValue = mProperties.data();
copySize = mProperties.size() * sizeof(decltype(mProperties)::value_type);
break;
default:
ASSERT(false);
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 specified in the Context Attributes table and param_value is not a NULL value.
if (valueSize < copySize)
{
return CL_INVALID_VALUE;
}
if (copyValue != nullptr)
{
std::memcpy(value, copyValue, copySize);
}
}
if (valueSizeRet != nullptr)
{
*valueSizeRet = copySize;
}
return CL_SUCCESS;
}
cl_command_queue Context::createCommandQueueWithProperties(cl_device_id device,
const cl_queue_properties *properties,
cl_int &errorCode)
{
CommandQueue::PropArray propArray;
CommandQueueProperties props;
cl_uint size = CommandQueue::kNoSize;
if (properties != nullptr)
{
const cl_queue_properties *propIt = properties;
while (*propIt != 0)
{
switch (*propIt++)
{
case CL_QUEUE_PROPERTIES:
props = static_cast<cl_command_queue_properties>(*propIt++);
break;
case CL_QUEUE_SIZE:
size = static_cast<decltype(size)>(*propIt++);
break;
}
}
// Include the trailing zero
++propIt;
propArray.reserve(propIt - properties);
propArray.insert(propArray.cend(), properties, propIt);
}
return Object::Create<CommandQueue>(errorCode, *this, device->cast<Device>(),
std::move(propArray), props, size);
}
cl_command_queue Context::createCommandQueue(cl_device_id device,
CommandQueueProperties properties,
cl_int &errorCode)
{
return Object::Create<CommandQueue>(errorCode, *this, device->cast<Device>(), properties);
}
cl_mem Context::createBuffer(const cl_mem_properties *properties,
MemFlags flags,
size_t size,
void *hostPtr,
cl_int &errorCode)
{
return Object::Create<Buffer>(errorCode, *this, Memory::PropArray{}, flags, size, hostPtr);
}
cl_mem Context::createImage(const cl_mem_properties *properties,
MemFlags flags,
const cl_image_format *format,
const cl_image_desc *desc,
void *hostPtr,
cl_int &errorCode)
{
const ImageDescriptor imageDesc = {FromCLenum<MemObjectType>(desc->image_type),
desc->image_width,
desc->image_height,
desc->image_depth,
desc->image_array_size,
desc->image_row_pitch,
desc->image_slice_pitch,
desc->num_mip_levels,
desc->num_samples};
return Object::Create<Image>(errorCode, *this, Memory::PropArray{}, flags, *format, imageDesc,
Memory::Cast(desc->buffer), hostPtr);
}
cl_mem Context::createImage2D(MemFlags flags,
const cl_image_format *format,
size_t width,
size_t height,
size_t rowPitch,
void *hostPtr,
cl_int &errorCode)
{
const ImageDescriptor imageDesc = {
MemObjectType::Image2D, width, height, 0u, 0u, rowPitch, 0u, 0u, 0u};
return Object::Create<Image>(errorCode, *this, Memory::PropArray{}, flags, *format, imageDesc,
nullptr, hostPtr);
}
cl_mem Context::createImage3D(MemFlags flags,
const cl_image_format *format,
size_t width,
size_t height,
size_t depth,
size_t rowPitch,
size_t slicePitch,
void *hostPtr,
cl_int &errorCode)
{
const ImageDescriptor imageDesc = {
MemObjectType::Image3D, width, height, depth, 0u, rowPitch, slicePitch, 0u, 0u};
return Object::Create<Image>(errorCode, *this, Memory::PropArray{}, flags, *format, imageDesc,
nullptr, hostPtr);
}
cl_int Context::getSupportedImageFormats(MemFlags flags,
MemObjectType imageType,
cl_uint numEntries,
cl_image_format *imageFormats,
cl_uint *numImageFormats)
{
return mImpl->getSupportedImageFormats(flags, imageType, numEntries, imageFormats,
numImageFormats);
}
cl_sampler Context::createSamplerWithProperties(const cl_sampler_properties *properties,
cl_int &errorCode)
{
Sampler::PropArray propArray;
cl_bool normalizedCoords = CL_TRUE;
AddressingMode addressingMode = AddressingMode::Clamp;
FilterMode filterMode = FilterMode::Nearest;
if (properties != nullptr)
{
const cl_sampler_properties *propIt = properties;
while (*propIt != 0)
{
switch (*propIt++)
{
case CL_SAMPLER_NORMALIZED_COORDS:
normalizedCoords = static_cast<decltype(normalizedCoords)>(*propIt++);
break;
case CL_SAMPLER_ADDRESSING_MODE:
addressingMode = FromCLenum<AddressingMode>(static_cast<CLenum>(*propIt++));
break;
case CL_SAMPLER_FILTER_MODE:
filterMode = FromCLenum<FilterMode>(static_cast<CLenum>(*propIt++));
break;
}
}
// Include the trailing zero
++propIt;
propArray.reserve(propIt - properties);
propArray.insert(propArray.cend(), properties, propIt);
}
return Object::Create<Sampler>(errorCode, *this, std::move(propArray), normalizedCoords,
addressingMode, filterMode);
}
cl_sampler Context::createSampler(cl_bool normalizedCoords,
AddressingMode addressingMode,
FilterMode filterMode,
cl_int &errorCode)
{
return Object::Create<Sampler>(errorCode, *this, Sampler::PropArray{}, normalizedCoords,
addressingMode, filterMode);
}
cl_program Context::createProgramWithSource(cl_uint count,
const char **strings,
const size_t *lengths,
cl_int &errorCode)
{
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 Object::Create<Program>(errorCode, *this, std::move(source));
}
cl_program Context::createProgramWithIL(const void *il, size_t length, cl_int &errorCode)
{
return Object::Create<Program>(errorCode, *this, il, length);
}
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 &errorCode)
{
DevicePtrs devs;
devs.reserve(numDevices);
while (numDevices-- != 0u)
{
devs.emplace_back(&(*devices++)->cast<Device>());
}
return Object::Create<Program>(errorCode, *this, std::move(devs), lengths, binaries,
binaryStatus);
}
cl_program Context::createProgramWithBuiltInKernels(cl_uint numDevices,
const cl_device_id *devices,
const char *kernelNames,
cl_int &errorCode)
{
DevicePtrs devs;
devs.reserve(numDevices);
while (numDevices-- != 0u)
{
devs.emplace_back(&(*devices++)->cast<Device>());
}
return Object::Create<Program>(errorCode, *this, std::move(devs), kernelNames);
}
cl_program Context::linkProgram(cl_uint numDevices,
const cl_device_id *deviceList,
const char *options,
cl_uint numInputPrograms,
const cl_program *inputPrograms,
ProgramCB pfnNotify,
void *userData,
cl_int &errorCode)
{
DevicePtrs devices;
devices.reserve(numDevices);
while (numDevices-- != 0u)
{
devices.emplace_back(&(*deviceList++)->cast<Device>());
}
ProgramPtrs programs;
programs.reserve(numInputPrograms);
while (numInputPrograms-- != 0u)
{
programs.emplace_back(&(*inputPrograms++)->cast<Program>());
}
return Object::Create<Program>(errorCode, *this, devices, options, programs, pfnNotify,
userData);
}
cl_event Context::createUserEvent(cl_int &errorCode)
{
return Object::Create<Event>(errorCode, *this);
}
cl_int Context::waitForEvents(cl_uint numEvents, const cl_event *eventList)
{
return mImpl->waitForEvents(Event::Cast(numEvents, eventList));
}
Context::~Context() = default;
void Context::ErrorCallback(const char *errinfo, const void *privateInfo, size_t cb, void *userData)
{
Context *const context = static_cast<Context *>(userData);
if (!Context::IsValid(context))
{
WARN() << "Context error for invalid context";
return;
}
if (context->mNotify != nullptr)
{
context->mNotify(errinfo, privateInfo, cb, context->mUserData);
}
}
Context::Context(Platform &platform,
PropArray &&properties,
DevicePtrs &&devices,
ContextErrorCB notify,
void *userData,
bool userSync,
cl_int &errorCode)
: mPlatform(platform),
mProperties(std::move(properties)),
mNotify(notify),
mUserData(userData),
mImpl(platform.getImpl().createContext(*this, devices, userSync, errorCode)),
mDevices(std::move(devices))
{}
Context::Context(Platform &platform,
PropArray &&properties,
DeviceType deviceType,
ContextErrorCB notify,
void *userData,
bool userSync,
cl_int &errorCode)
: mPlatform(platform),
mProperties(std::move(properties)),
mNotify(notify),
mUserData(userData),
mImpl(platform.getImpl().createContextFromType(*this, deviceType, userSync, errorCode)),
mDevices(mImpl ? mImpl->getDevices(errorCode) : DevicePtrs{})
{}
} // namespace cl