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