1 //
2 // Copyright 2021 The ANGLE Project Authors. All rights reserved.
3 // Use of this source code is governed by a BSD-style license that can be
4 // found in the LICENSE file.
5 //
6 // CLMemory.cpp: Implements the cl::Memory class.
7 
8 #include "libANGLE/CLMemory.h"
9 
10 #include "libANGLE/CLBuffer.h"
11 #include "libANGLE/CLContext.h"
12 
13 #include <cstring>
14 
15 namespace cl
16 {
17 
18 namespace
19 {
20 
InheritMemFlags(MemFlags flags,Memory * parent)21 MemFlags InheritMemFlags(MemFlags flags, Memory *parent)
22 {
23     if (parent != nullptr)
24     {
25         const MemFlags parentFlags = parent->getFlags();
26         const MemFlags access(CL_MEM_READ_WRITE | CL_MEM_READ_ONLY | CL_MEM_WRITE_ONLY);
27         const MemFlags hostAccess(CL_MEM_HOST_WRITE_ONLY | CL_MEM_HOST_READ_ONLY |
28                                   CL_MEM_HOST_NO_ACCESS);
29         const MemFlags hostPtrFlags(CL_MEM_USE_HOST_PTR | CL_MEM_ALLOC_HOST_PTR |
30                                     CL_MEM_COPY_HOST_PTR);
31         if (flags.isNotSet(access))
32         {
33             flags.set(parentFlags.mask(access));
34         }
35         if (flags.isNotSet(hostAccess))
36         {
37             flags.set(parentFlags.mask(hostAccess));
38         }
39         flags.set(parentFlags.mask(hostPtrFlags));
40     }
41     return flags;
42 }
43 
44 }  // namespace
45 
setDestructorCallback(MemoryCB pfnNotify,void * userData)46 cl_int Memory::setDestructorCallback(MemoryCB pfnNotify, void *userData)
47 {
48     mDestructorCallbacks->emplace(pfnNotify, userData);
49     return CL_SUCCESS;
50 }
51 
getInfo(MemInfo name,size_t valueSize,void * value,size_t * valueSizeRet) const52 cl_int Memory::getInfo(MemInfo name, size_t valueSize, void *value, size_t *valueSizeRet) const
53 {
54     static_assert(
55         std::is_same<cl_uint, cl_bool>::value && std::is_same<cl_uint, cl_mem_object_type>::value,
56         "OpenCL type mismatch");
57 
58     cl_uint valUInt       = 0u;
59     void *valPointer      = nullptr;
60     const void *copyValue = nullptr;
61     size_t copySize       = 0u;
62 
63     switch (name)
64     {
65         case MemInfo::Type:
66             valUInt   = ToCLenum(getType());
67             copyValue = &valUInt;
68             copySize  = sizeof(valUInt);
69             break;
70         case MemInfo::Flags:
71             copyValue = &mFlags;
72             copySize  = sizeof(mFlags);
73             break;
74         case MemInfo::Size:
75             copyValue = &mSize;
76             copySize  = sizeof(mSize);
77             break;
78         case MemInfo::HostPtr:
79             copyValue = &mHostPtr;
80             copySize  = sizeof(mHostPtr);
81             break;
82         case MemInfo::MapCount:
83             valUInt   = mMapCount;
84             copyValue = &valUInt;
85             copySize  = sizeof(valUInt);
86             break;
87         case MemInfo::ReferenceCount:
88             valUInt   = getRefCount();
89             copyValue = &valUInt;
90             copySize  = sizeof(valUInt);
91             break;
92         case MemInfo::Context:
93             valPointer = mContext->getNative();
94             copyValue  = &valPointer;
95             copySize   = sizeof(valPointer);
96             break;
97         case MemInfo::AssociatedMemObject:
98             valPointer = Memory::CastNative(mParent.get());
99             copyValue  = &valPointer;
100             copySize   = sizeof(valPointer);
101             break;
102         case MemInfo::Offset:
103             copyValue = &mOffset;
104             copySize  = sizeof(mOffset);
105             break;
106         case MemInfo::UsesSVM_Pointer:
107             valUInt   = CL_FALSE;  // TODO(jplate) Check for SVM pointer anglebug.com/6002
108             copyValue = &valUInt;
109             copySize  = sizeof(valUInt);
110             break;
111         case MemInfo::Properties:
112             copyValue = mProperties.data();
113             copySize  = mProperties.size() * sizeof(decltype(mProperties)::value_type);
114             break;
115         default:
116             return CL_INVALID_VALUE;
117     }
118 
119     if (value != nullptr)
120     {
121         // CL_INVALID_VALUE if size in bytes specified by param_value_size is < size of return type
122         // as described in the Memory Object Info table and param_value is not NULL.
123         if (valueSize < copySize)
124         {
125             return CL_INVALID_VALUE;
126         }
127         if (copyValue != nullptr)
128         {
129             std::memcpy(value, copyValue, copySize);
130         }
131     }
132     if (valueSizeRet != nullptr)
133     {
134         *valueSizeRet = copySize;
135     }
136     return CL_SUCCESS;
137 }
138 
~Memory()139 Memory::~Memory()
140 {
141     std::stack<CallbackData> callbacks;
142     mDestructorCallbacks->swap(callbacks);
143     while (!callbacks.empty())
144     {
145         const MemoryCB callback = callbacks.top().first;
146         void *const userData    = callbacks.top().second;
147         callbacks.pop();
148         callback(this, userData);
149     }
150 }
151 
Memory(const Buffer & buffer,Context & context,PropArray && properties,MemFlags flags,size_t size,void * hostPtr,cl_int & errorCode)152 Memory::Memory(const Buffer &buffer,
153                Context &context,
154                PropArray &&properties,
155                MemFlags flags,
156                size_t size,
157                void *hostPtr,
158                cl_int &errorCode)
159     : mContext(&context),
160       mProperties(std::move(properties)),
161       mFlags(flags),
162       mHostPtr(flags.isSet(CL_MEM_USE_HOST_PTR) ? hostPtr : nullptr),
163       mImpl(context.getImpl().createBuffer(buffer, size, hostPtr, errorCode)),
164       mSize(size),
165       mMapCount(0u)
166 {}
167 
Memory(const Buffer & buffer,Buffer & parent,MemFlags flags,size_t offset,size_t size,cl_int & errorCode)168 Memory::Memory(const Buffer &buffer,
169                Buffer &parent,
170                MemFlags flags,
171                size_t offset,
172                size_t size,
173                cl_int &errorCode)
174     : mContext(parent.mContext),
175       mFlags(InheritMemFlags(flags, &parent)),
176       mHostPtr(parent.mHostPtr != nullptr ? static_cast<char *>(parent.mHostPtr) + offset
177                                           : nullptr),
178       mParent(&parent),
179       mOffset(offset),
180       mImpl(parent.mImpl->createSubBuffer(buffer, flags, size, errorCode)),
181       mSize(size),
182       mMapCount(0u)
183 {}
184 
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)185 Memory::Memory(const Image &image,
186                Context &context,
187                PropArray &&properties,
188                MemFlags flags,
189                const cl_image_format &format,
190                const ImageDescriptor &desc,
191                Memory *parent,
192                void *hostPtr,
193                cl_int &errorCode)
194     : mContext(&context),
195       mProperties(std::move(properties)),
196       mFlags(InheritMemFlags(flags, parent)),
197       mHostPtr(flags.isSet(CL_MEM_USE_HOST_PTR) ? hostPtr : nullptr),
198       mParent(parent),
199       mImpl(context.getImpl().createImage(image, flags, format, desc, hostPtr, errorCode)),
200       mSize(mImpl ? mImpl->getSize(errorCode) : 0u),
201       mMapCount(0u)
202 {}
203 
204 }  // namespace cl
205