| // |
| // 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. |
| // |
| // CLMemory.cpp: Implements the cl::Memory class. |
| |
| #include "libANGLE/CLMemory.h" |
| |
| #include "libANGLE/CLBuffer.h" |
| #include "libANGLE/CLContext.h" |
| |
| #include <cstring> |
| |
| namespace cl |
| { |
| |
| namespace |
| { |
| |
| MemFlags InheritMemFlags(MemFlags flags, Memory *parent) |
| { |
| if (parent != nullptr) |
| { |
| const MemFlags parentFlags = parent->getFlags(); |
| const MemFlags access(CL_MEM_READ_WRITE | CL_MEM_READ_ONLY | CL_MEM_WRITE_ONLY); |
| const MemFlags hostAccess(CL_MEM_HOST_WRITE_ONLY | CL_MEM_HOST_READ_ONLY | |
| CL_MEM_HOST_NO_ACCESS); |
| const MemFlags hostPtrFlags(CL_MEM_USE_HOST_PTR | CL_MEM_ALLOC_HOST_PTR | |
| CL_MEM_COPY_HOST_PTR); |
| if (flags.isNotSet(access)) |
| { |
| flags.set(parentFlags.mask(access)); |
| } |
| if (flags.isNotSet(hostAccess)) |
| { |
| flags.set(parentFlags.mask(hostAccess)); |
| } |
| flags.set(parentFlags.mask(hostPtrFlags)); |
| } |
| return flags; |
| } |
| |
| } // namespace |
| |
| cl_int Memory::setDestructorCallback(MemoryCB pfnNotify, void *userData) |
| { |
| mDestructorCallbacks->emplace(pfnNotify, userData); |
| return CL_SUCCESS; |
| } |
| |
| cl_int Memory::getInfo(MemInfo name, size_t valueSize, void *value, size_t *valueSizeRet) const |
| { |
| static_assert( |
| std::is_same<cl_uint, cl_bool>::value && std::is_same<cl_uint, cl_mem_object_type>::value, |
| "OpenCL type mismatch"); |
| |
| cl_uint valUInt = 0u; |
| void *valPointer = nullptr; |
| const void *copyValue = nullptr; |
| size_t copySize = 0u; |
| |
| switch (name) |
| { |
| case MemInfo::Type: |
| valUInt = ToCLenum(getType()); |
| copyValue = &valUInt; |
| copySize = sizeof(valUInt); |
| break; |
| case MemInfo::Flags: |
| copyValue = &mFlags; |
| copySize = sizeof(mFlags); |
| break; |
| case MemInfo::Size: |
| copyValue = &mSize; |
| copySize = sizeof(mSize); |
| break; |
| case MemInfo::HostPtr: |
| copyValue = &mHostPtr; |
| copySize = sizeof(mHostPtr); |
| break; |
| case MemInfo::MapCount: |
| valUInt = mMapCount; |
| copyValue = &valUInt; |
| copySize = sizeof(valUInt); |
| break; |
| case MemInfo::ReferenceCount: |
| valUInt = getRefCount(); |
| copyValue = &valUInt; |
| copySize = sizeof(valUInt); |
| break; |
| case MemInfo::Context: |
| valPointer = mContext->getNative(); |
| copyValue = &valPointer; |
| copySize = sizeof(valPointer); |
| break; |
| case MemInfo::AssociatedMemObject: |
| valPointer = Memory::CastNative(mParent.get()); |
| copyValue = &valPointer; |
| copySize = sizeof(valPointer); |
| break; |
| case MemInfo::Offset: |
| copyValue = &mOffset; |
| copySize = sizeof(mOffset); |
| break; |
| case MemInfo::UsesSVM_Pointer: |
| valUInt = CL_FALSE; // TODO(jplate) Check for SVM pointer anglebug.com/6002 |
| copyValue = &valUInt; |
| copySize = sizeof(valUInt); |
| break; |
| case MemInfo::Properties: |
| copyValue = mProperties.data(); |
| copySize = mProperties.size() * sizeof(decltype(mProperties)::value_type); |
| break; |
| default: |
| 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 described in the Memory Object Info table and param_value is not NULL. |
| if (valueSize < copySize) |
| { |
| return CL_INVALID_VALUE; |
| } |
| if (copyValue != nullptr) |
| { |
| std::memcpy(value, copyValue, copySize); |
| } |
| } |
| if (valueSizeRet != nullptr) |
| { |
| *valueSizeRet = copySize; |
| } |
| return CL_SUCCESS; |
| } |
| |
| Memory::~Memory() |
| { |
| std::stack<CallbackData> callbacks; |
| mDestructorCallbacks->swap(callbacks); |
| while (!callbacks.empty()) |
| { |
| const MemoryCB callback = callbacks.top().first; |
| void *const userData = callbacks.top().second; |
| callbacks.pop(); |
| callback(this, userData); |
| } |
| } |
| |
| Memory::Memory(const Buffer &buffer, |
| Context &context, |
| PropArray &&properties, |
| MemFlags flags, |
| size_t size, |
| void *hostPtr, |
| cl_int &errorCode) |
| : mContext(&context), |
| mProperties(std::move(properties)), |
| mFlags(flags), |
| mHostPtr(flags.isSet(CL_MEM_USE_HOST_PTR) ? hostPtr : nullptr), |
| mImpl(context.getImpl().createBuffer(buffer, size, hostPtr, errorCode)), |
| mSize(size), |
| mMapCount(0u) |
| {} |
| |
| Memory::Memory(const Buffer &buffer, |
| Buffer &parent, |
| MemFlags flags, |
| size_t offset, |
| size_t size, |
| cl_int &errorCode) |
| : mContext(parent.mContext), |
| mFlags(InheritMemFlags(flags, &parent)), |
| mHostPtr(parent.mHostPtr != nullptr ? static_cast<char *>(parent.mHostPtr) + offset |
| : nullptr), |
| mParent(&parent), |
| mOffset(offset), |
| mImpl(parent.mImpl->createSubBuffer(buffer, flags, size, errorCode)), |
| mSize(size), |
| mMapCount(0u) |
| {} |
| |
| Memory::Memory(const Image &image, |
| Context &context, |
| PropArray &&properties, |
| MemFlags flags, |
| const cl_image_format &format, |
| const ImageDescriptor &desc, |
| Memory *parent, |
| void *hostPtr, |
| cl_int &errorCode) |
| : mContext(&context), |
| mProperties(std::move(properties)), |
| mFlags(InheritMemFlags(flags, parent)), |
| mHostPtr(flags.isSet(CL_MEM_USE_HOST_PTR) ? hostPtr : nullptr), |
| mParent(parent), |
| mImpl(context.getImpl().createImage(image, flags, format, desc, hostPtr, errorCode)), |
| mSize(mImpl ? mImpl->getSize(errorCode) : 0u), |
| mMapCount(0u) |
| {} |
| |
| } // namespace cl |