// // 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 namespace cl { cl_int Context::getInfo(ContextInfo name, size_t valueSize, void *value, size_t *valueSizeRet) const { std::vector 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(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(*propIt++); break; case CL_QUEUE_SIZE: size = static_cast(*propIt++); break; } } // Include the trailing zero ++propIt; propArray.reserve(propIt - properties); propArray.insert(propArray.cend(), properties, propIt); } return Object::Create(errorCode, *this, device->cast(), std::move(propArray), props, size); } cl_command_queue Context::createCommandQueue(cl_device_id device, CommandQueueProperties properties, cl_int &errorCode) { return Object::Create(errorCode, *this, device->cast(), properties); } cl_mem Context::createBuffer(const cl_mem_properties *properties, MemFlags flags, size_t size, void *hostPtr, cl_int &errorCode) { return Object::Create(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(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(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(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(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(*propIt++); break; case CL_SAMPLER_ADDRESSING_MODE: addressingMode = FromCLenum(static_cast(*propIt++)); break; case CL_SAMPLER_FILTER_MODE: filterMode = FromCLenum(static_cast(*propIt++)); break; } } // Include the trailing zero ++propIt; propArray.reserve(propIt - properties); propArray.insert(propArray.cend(), properties, propIt); } return Object::Create(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(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(errorCode, *this, std::move(source)); } cl_program Context::createProgramWithIL(const void *il, size_t length, cl_int &errorCode) { return Object::Create(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()); } return Object::Create(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()); } return Object::Create(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()); } ProgramPtrs programs; programs.reserve(numInputPrograms); while (numInputPrograms-- != 0u) { programs.emplace_back(&(*inputPrograms++)->cast()); } return Object::Create(errorCode, *this, devices, options, programs, pfnNotify, userData); } cl_event Context::createUserEvent(cl_int &errorCode) { return Object::Create(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(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