blob: 6e17ae4ab1f78c68e7833d6fa3a55ca5ee177792 [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.
//
// CLMemory.cpp: Implements the cl::Memory class.
#include "libANGLE/CLMemory.h"
#include "libANGLE/CLBuffer.h"
#include "libANGLE/CLContext.h"
#include "libANGLE/CLImage.h"
#include "libANGLE/cl_utils.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.excludes(access))
{
flags.set(parentFlags.mask(access));
}
if (flags.excludes(hostAccess))
{
flags.set(parentFlags.mask(hostAccess));
}
flags.set(parentFlags.mask(hostPtrFlags));
}
return flags;
}
} // namespace
angle::Result Memory::setDestructorCallback(MemoryCB pfnNotify, void *userData)
{
mDestructorCallbacks->emplace(pfnNotify, userData);
return angle::Result::Continue;
}
angle::Result 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/42264535
copyValue = &valUInt;
copySize = sizeof(valUInt);
break;
case MemInfo::Properties:
copyValue = mProperties.data();
copySize = mProperties.size() * sizeof(decltype(mProperties)::value_type);
break;
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 Memory Object Info 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;
}
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)
: mContext(&context),
mProperties(std::move(properties)),
mFlags(flags.excludes(CL_MEM_READ_WRITE | CL_MEM_READ_ONLY | CL_MEM_WRITE_ONLY)
? cl::MemFlags{flags.get() | CL_MEM_READ_WRITE}
: flags),
mHostPtr(flags.intersects(CL_MEM_USE_HOST_PTR) ? hostPtr : nullptr),
mImpl(nullptr),
mSize(size),
mMapCount(0u)
{
ANGLE_CL_IMPL_TRY(context.getImpl().createBuffer(buffer, hostPtr, &mImpl));
}
Memory::Memory(const Buffer &buffer, Buffer &parent, MemFlags flags, size_t offset, size_t size)
: mContext(parent.mContext),
mFlags(InheritMemFlags(flags, &parent)),
mHostPtr(parent.mHostPtr != nullptr ? static_cast<char *>(parent.mHostPtr) + offset
: nullptr),
mParent(&parent),
mOffset(offset),
mImpl(nullptr),
mSize(size),
mMapCount(0u)
{
ANGLE_CL_IMPL_TRY(parent.mImpl->createSubBuffer(buffer, flags, size, &mImpl));
}
Memory::Memory(Context &context,
PropArray &&properties,
MemFlags flags,
Memory *parent,
void *hostPtr)
: mContext(&context),
mProperties(std::move(properties)),
mFlags(InheritMemFlags(flags, parent)),
mHostPtr(flags.intersects(CL_MEM_USE_HOST_PTR) ? hostPtr : nullptr),
mParent(parent),
mImpl(nullptr),
mSize(0u),
mMapCount(0u)
{}
} // namespace cl