• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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