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