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 // CLMemoryVk.cpp: Implements the class methods for CLMemoryVk.
7
8 #include "libANGLE/renderer/vulkan/CLMemoryVk.h"
9 #include "libANGLE/renderer/vulkan/CLContextVk.h"
10 #include "libANGLE/renderer/vulkan/vk_renderer.h"
11
12 #include "libANGLE/CLBuffer.h"
13 #include "libANGLE/CLContext.h"
14 #include "libANGLE/CLMemory.h"
15 #include "libANGLE/cl_utils.h"
16
17 namespace rx
18 {
19
CLMemoryVk(const cl::Memory & memory)20 CLMemoryVk::CLMemoryVk(const cl::Memory &memory)
21 : CLMemoryImpl(memory),
22 mContext(&memory.getContext().getImpl<CLContextVk>()),
23 mRenderer(mContext->getRenderer()),
24 mMapPtr(nullptr),
25 mMapCount(0),
26 mParent(nullptr)
27 {}
28
~CLMemoryVk()29 CLMemoryVk::~CLMemoryVk()
30 {
31 mContext->mAssociatedObjects->mMemories.erase(mMemory.getNative());
32 }
33
createSubBuffer(const cl::Buffer & buffer,cl::MemFlags flags,size_t size,CLMemoryImpl::Ptr * subBufferOut)34 angle::Result CLMemoryVk::createSubBuffer(const cl::Buffer &buffer,
35 cl::MemFlags flags,
36 size_t size,
37 CLMemoryImpl::Ptr *subBufferOut)
38 {
39 UNIMPLEMENTED();
40 ANGLE_CL_RETURN_ERROR(CL_OUT_OF_RESOURCES);
41 }
42
getMapPtr(uint8_t ** mapPtrOut)43 angle::Result CLMemoryVk::getMapPtr(uint8_t **mapPtrOut)
44 {
45 if (mMapPtr == nullptr && mapPtrOut != nullptr)
46 {
47 ANGLE_TRY(map());
48 *mapPtrOut = mMapPtr;
49 }
50 return angle::Result::Continue;
51 }
52
getVkUsageFlags()53 VkBufferUsageFlags CLMemoryVk::getVkUsageFlags()
54 {
55 VkBufferUsageFlags usageFlags =
56 VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT;
57
58 if (mMemory.getFlags().isSet(CL_MEM_WRITE_ONLY))
59 {
60 usageFlags |= VK_BUFFER_USAGE_STORAGE_BUFFER_BIT;
61 }
62 else if (mMemory.getFlags().isSet(CL_MEM_READ_ONLY))
63 {
64 usageFlags |= VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT;
65 }
66 else
67 {
68 usageFlags |= VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT | VK_BUFFER_USAGE_STORAGE_BUFFER_BIT;
69 }
70
71 return usageFlags;
72 }
73
getVkMemPropertyFlags()74 VkMemoryPropertyFlags CLMemoryVk::getVkMemPropertyFlags()
75 {
76 // TODO: http://anglebug.com/8588
77 VkMemoryPropertyFlags propFlags = VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT;
78
79 if (mMemory.getFlags().isSet(CL_MEM_USE_HOST_PTR | CL_MEM_ALLOC_HOST_PTR |
80 CL_MEM_COPY_HOST_PTR))
81 {
82 propFlags |= VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT;
83 }
84
85 return propFlags;
86 }
87
copyTo(void * dst,size_t srcOffset,size_t size)88 angle::Result CLMemoryVk::copyTo(void *dst, size_t srcOffset, size_t size)
89 {
90 ANGLE_TRY(map());
91 void *src = reinterpret_cast<void *>(mMapPtr + srcOffset);
92 std::memcpy(dst, src, size);
93 ANGLE_TRY(unmap());
94 return angle::Result::Continue;
95 }
96
copyTo(CLMemoryVk * dst,size_t srcOffset,size_t dstOffset,size_t size)97 angle::Result CLMemoryVk::copyTo(CLMemoryVk *dst, size_t srcOffset, size_t dstOffset, size_t size)
98 {
99 ANGLE_TRY(map());
100 ANGLE_TRY(dst->map());
101 uint8_t *ptr = nullptr;
102 ANGLE_TRY(dst->getMapPtr(&ptr));
103 ANGLE_TRY(copyTo(reinterpret_cast<void *>(ptr + dstOffset), srcOffset, size));
104 ANGLE_TRY(unmap());
105 ANGLE_TRY(dst->unmap());
106 return angle::Result::Continue;
107 }
108
copyFrom(const void * src,size_t srcOffset,size_t size)109 angle::Result CLMemoryVk::copyFrom(const void *src, size_t srcOffset, size_t size)
110 {
111 ANGLE_TRY(map());
112 void *dst = reinterpret_cast<void *>(reinterpret_cast<uintptr_t>(mMapPtr) + srcOffset);
113 std::memcpy(dst, src, size);
114 ANGLE_TRY(unmap());
115 return angle::Result::Continue;
116 }
117
CLBufferVk(const cl::Buffer & buffer)118 CLBufferVk::CLBufferVk(const cl::Buffer &buffer) : CLMemoryVk(buffer)
119 {
120 if (buffer.isSubBuffer())
121 {
122 mParent = &buffer.getParent()->getImpl<CLBufferVk>();
123 }
124 mDefaultBufferCreateInfo = {};
125 mDefaultBufferCreateInfo.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO;
126 mDefaultBufferCreateInfo.size = buffer.getSize();
127 mDefaultBufferCreateInfo.usage = getVkUsageFlags();
128 mDefaultBufferCreateInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
129 }
130
~CLBufferVk()131 CLBufferVk::~CLBufferVk()
132 {
133 ANGLE_CL_IMPL_TRY(unmap());
134 mBuffer.destroy(mRenderer);
135 }
136
createSubBuffer(const cl::Buffer & buffer,cl::MemFlags flags,size_t size,CLMemoryImpl::Ptr * subBufferOut)137 angle::Result CLBufferVk::createSubBuffer(const cl::Buffer &buffer,
138 cl::MemFlags flags,
139 size_t size,
140 CLMemoryImpl::Ptr *subBufferOut)
141 {
142 UNIMPLEMENTED();
143 ANGLE_CL_RETURN_ERROR(CL_OUT_OF_RESOURCES);
144 }
145
create(void * hostPtr)146 angle::Result CLBufferVk::create(void *hostPtr)
147 {
148 if (!isSubBuffer())
149 {
150 VkBufferCreateInfo createInfo = mDefaultBufferCreateInfo;
151 createInfo.size = getSize();
152 VkMemoryPropertyFlags memFlags = getVkMemPropertyFlags();
153 if (IsError(mBuffer.init(mContext, createInfo, memFlags)))
154 {
155 ANGLE_CL_RETURN_ERROR(CL_OUT_OF_RESOURCES);
156 }
157 if (mMemory.getFlags().isSet(CL_MEM_USE_HOST_PTR | CL_MEM_COPY_HOST_PTR))
158 {
159 ASSERT(hostPtr);
160 ANGLE_CL_IMPL_TRY_ERROR(setDataImpl(static_cast<uint8_t *>(hostPtr), getSize(), 0),
161 CL_OUT_OF_RESOURCES);
162 }
163 }
164 return angle::Result::Continue;
165 }
166
map()167 angle::Result CLBufferVk::map()
168 {
169 if (mParent != nullptr)
170 {
171 ANGLE_TRY(mParent->getMapPtr(&mMapPtr));
172 if (mMapPtr != nullptr)
173 {
174 mMapPtr += mBuffer.getOffset();
175 return angle::Result::Continue;
176 }
177 ANGLE_CL_RETURN_ERROR(CL_OUT_OF_RESOURCES);
178 }
179
180 if (!IsError(mBuffer.map(mContext, &mMapPtr)))
181 {
182 return angle::Result::Continue;
183 }
184
185 ANGLE_CL_RETURN_ERROR(CL_OUT_OF_RESOURCES);
186 }
187
unmap()188 angle::Result CLBufferVk::unmap()
189 {
190 if (mParent != nullptr)
191 {
192 ANGLE_CL_IMPL_TRY_ERROR(mParent->unmap(), CL_OUT_OF_RESOURCES);
193 return angle::Result::Continue;
194 }
195 mBuffer.unmap(mRenderer);
196 mMapPtr = nullptr;
197 return angle::Result::Continue;
198 }
199
setDataImpl(const uint8_t * data,size_t size,size_t offset)200 angle::Result CLBufferVk::setDataImpl(const uint8_t *data, size_t size, size_t offset)
201 {
202 // buffer cannot be in use state
203 ASSERT(mBuffer.valid());
204 ASSERT(!isCurrentlyInUse());
205 ASSERT(size + offset <= getSize());
206 ASSERT(data != nullptr);
207
208 // Assuming host visible buffers for now
209 // TODO: http://anglebug.com/8589
210 if (!mBuffer.isHostVisible())
211 {
212 UNIMPLEMENTED();
213 ANGLE_CL_RETURN_ERROR(CL_OUT_OF_RESOURCES);
214 }
215
216 uint8_t *mapPointer = nullptr;
217 ANGLE_TRY(mBuffer.mapWithOffset(mContext, &mapPointer, offset));
218 ASSERT(mapPointer != nullptr);
219
220 std::memcpy(mapPointer, data, size);
221 mBuffer.unmap(mRenderer);
222
223 return angle::Result::Continue;
224 }
225
isCurrentlyInUse() const226 bool CLBufferVk::isCurrentlyInUse() const
227 {
228 return !mRenderer->hasResourceUseFinished(mBuffer.getResourceUse());
229 }
230
231 } // namespace rx
232