| // | |
| // 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 |