• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //
2 // Copyright 2022 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 // Suballocation.cpp:
7 //    Implements class methods for BufferBlock and Suballocation and other related classes
8 //
9 
10 // #include "libANGLE/renderer/vulkan/vk_utils.h"
11 
12 #include "libANGLE/renderer/vulkan/Suballocation.h"
13 #include "libANGLE/Context.h"
14 #include "libANGLE/renderer/vulkan/RendererVk.h"
15 #include "libANGLE/renderer/vulkan/vk_mem_alloc_wrapper.h"
16 
17 namespace rx
18 {
19 namespace vk
20 {
21 // BufferBlock implementation.
BufferBlock()22 BufferBlock::BufferBlock()
23     : mMemoryPropertyFlags(0),
24       mSize(0),
25       mAllocatedBufferSize(0),
26       mMemoryAllocationType(MemoryAllocationType::InvalidEnum),
27       mMemoryTypeIndex(kInvalidMemoryTypeIndex),
28       mMappedMemory(nullptr)
29 {}
30 
BufferBlock(BufferBlock && other)31 BufferBlock::BufferBlock(BufferBlock &&other)
32     : mVirtualBlock(std::move(other.mVirtualBlock)),
33       mBuffer(std::move(other.mBuffer)),
34       mDeviceMemory(std::move(other.mDeviceMemory)),
35       mMemoryPropertyFlags(other.mMemoryPropertyFlags),
36       mSize(other.mSize),
37       mAllocatedBufferSize(other.mAllocatedBufferSize),
38       mMemoryAllocationType(other.mMemoryAllocationType),
39       mMemoryTypeIndex(other.mMemoryTypeIndex),
40       mMappedMemory(other.mMappedMemory),
41       mSerial(other.mSerial),
42       mCountRemainsEmpty(0)
43 {}
44 
operator =(BufferBlock && other)45 BufferBlock &BufferBlock::operator=(BufferBlock &&other)
46 {
47     std::swap(mVirtualBlock, other.mVirtualBlock);
48     std::swap(mBuffer, other.mBuffer);
49     std::swap(mDeviceMemory, other.mDeviceMemory);
50     std::swap(mMemoryPropertyFlags, other.mMemoryPropertyFlags);
51     std::swap(mSize, other.mSize);
52     std::swap(mAllocatedBufferSize, other.mAllocatedBufferSize);
53     std::swap(mMemoryAllocationType, other.mMemoryAllocationType);
54     std::swap(mMemoryTypeIndex, other.mMemoryTypeIndex);
55     std::swap(mMappedMemory, other.mMappedMemory);
56     std::swap(mSerial, other.mSerial);
57     std::swap(mCountRemainsEmpty, other.mCountRemainsEmpty);
58     return *this;
59 }
60 
~BufferBlock()61 BufferBlock::~BufferBlock()
62 {
63     ASSERT(!mVirtualBlock.valid());
64     ASSERT(!mBuffer.valid());
65     ASSERT(!mDeviceMemory.valid());
66     ASSERT(mDescriptorSetCacheManager.empty());
67 }
68 
destroy(RendererVk * renderer)69 void BufferBlock::destroy(RendererVk *renderer)
70 {
71     VkDevice device = renderer->getDevice();
72 
73     mDescriptorSetCacheManager.destroyKeys(renderer);
74     if (mMappedMemory)
75     {
76         unmap(device);
77     }
78 
79     renderer->onMemoryDealloc(mMemoryAllocationType, mAllocatedBufferSize, mMemoryTypeIndex,
80                               mDeviceMemory.getHandle());
81 
82     mVirtualBlock.destroy(device);
83     mBuffer.destroy(device);
84     mDeviceMemory.destroy(device);
85 }
86 
init(Context * context,Buffer & buffer,uint32_t memoryTypeIndex,vma::VirtualBlockCreateFlags flags,DeviceMemory & deviceMemory,VkMemoryPropertyFlags memoryPropertyFlags,VkDeviceSize size)87 angle::Result BufferBlock::init(Context *context,
88                                 Buffer &buffer,
89                                 uint32_t memoryTypeIndex,
90                                 vma::VirtualBlockCreateFlags flags,
91                                 DeviceMemory &deviceMemory,
92                                 VkMemoryPropertyFlags memoryPropertyFlags,
93                                 VkDeviceSize size)
94 {
95     RendererVk *renderer = context->getRenderer();
96     ASSERT(!mVirtualBlock.valid());
97     ASSERT(!mBuffer.valid());
98     ASSERT(!mDeviceMemory.valid());
99 
100     ANGLE_VK_TRY(context, mVirtualBlock.init(renderer->getDevice(), flags, size));
101 
102     mBuffer               = std::move(buffer);
103     mDeviceMemory         = std::move(deviceMemory);
104     mMemoryPropertyFlags  = memoryPropertyFlags;
105     mSize                 = size;
106     mAllocatedBufferSize  = size;
107     mMemoryAllocationType = MemoryAllocationType::Buffer;
108     mMemoryTypeIndex      = memoryTypeIndex;
109     mMappedMemory         = nullptr;
110     mSerial               = renderer->getResourceSerialFactory().generateBufferSerial();
111 
112     return angle::Result::Continue;
113 }
114 
initWithoutVirtualBlock(Context * context,Buffer & buffer,MemoryAllocationType memoryAllocationType,uint32_t memoryTypeIndex,DeviceMemory & deviceMemory,VkMemoryPropertyFlags memoryPropertyFlags,VkDeviceSize size,VkDeviceSize allocatedBufferSize)115 void BufferBlock::initWithoutVirtualBlock(Context *context,
116                                           Buffer &buffer,
117                                           MemoryAllocationType memoryAllocationType,
118                                           uint32_t memoryTypeIndex,
119                                           DeviceMemory &deviceMemory,
120                                           VkMemoryPropertyFlags memoryPropertyFlags,
121                                           VkDeviceSize size,
122                                           VkDeviceSize allocatedBufferSize)
123 {
124     RendererVk *renderer = context->getRenderer();
125     ASSERT(!mVirtualBlock.valid());
126     ASSERT(!mBuffer.valid());
127     ASSERT(!mDeviceMemory.valid());
128 
129     mBuffer               = std::move(buffer);
130     mDeviceMemory         = std::move(deviceMemory);
131     mMemoryPropertyFlags  = memoryPropertyFlags;
132     mSize                 = size;
133     mAllocatedBufferSize  = allocatedBufferSize;
134     mMemoryAllocationType = memoryAllocationType;
135     mMemoryTypeIndex      = memoryTypeIndex;
136     mMappedMemory         = nullptr;
137     mSerial               = renderer->getResourceSerialFactory().generateBufferSerial();
138 }
139 
map(const VkDevice device)140 VkResult BufferBlock::map(const VkDevice device)
141 {
142     ASSERT(mMappedMemory == nullptr);
143     return mDeviceMemory.map(device, 0, mSize, 0, &mMappedMemory);
144 }
145 
unmap(const VkDevice device)146 void BufferBlock::unmap(const VkDevice device)
147 {
148     mDeviceMemory.unmap(device);
149     mMappedMemory = nullptr;
150 }
151 
allocate(VkDeviceSize size,VkDeviceSize alignment,VmaVirtualAllocation * allocationOut,VkDeviceSize * offsetOut)152 VkResult BufferBlock::allocate(VkDeviceSize size,
153                                VkDeviceSize alignment,
154                                VmaVirtualAllocation *allocationOut,
155                                VkDeviceSize *offsetOut)
156 {
157     std::unique_lock<std::mutex> lock(mVirtualBlockMutex);
158     mCountRemainsEmpty = 0;
159     return mVirtualBlock.allocate(size, alignment, allocationOut, offsetOut);
160 }
161 
free(VmaVirtualAllocation allocation,VkDeviceSize offset)162 void BufferBlock::free(VmaVirtualAllocation allocation, VkDeviceSize offset)
163 {
164     std::unique_lock<std::mutex> lock(mVirtualBlockMutex);
165     mVirtualBlock.free(allocation, offset);
166 }
167 
getAndIncrementEmptyCounter()168 int32_t BufferBlock::getAndIncrementEmptyCounter()
169 {
170     return ++mCountRemainsEmpty;
171 }
172 
calculateStats(vma::StatInfo * pStatInfo) const173 void BufferBlock::calculateStats(vma::StatInfo *pStatInfo) const
174 {
175     std::unique_lock<std::mutex> lock(mVirtualBlockMutex);
176     mVirtualBlock.calculateStats(pStatInfo);
177 }
178 
179 // BufferSuballocation implementation.
map(Context * context)180 VkResult BufferSuballocation::map(Context *context)
181 {
182     return mBufferBlock->map(context->getDevice());
183 }
184 
185 // SharedBufferSuballocationGarbage implementation.
destroyIfComplete(RendererVk * renderer)186 bool SharedBufferSuballocationGarbage::destroyIfComplete(RendererVk *renderer)
187 {
188     if (renderer->hasResourceUseFinished(mLifetime))
189     {
190         mBuffer.destroy(renderer->getDevice());
191         mSuballocation.destroy(renderer);
192         return true;
193     }
194     return false;
195 }
196 
hasResourceUseSubmitted(RendererVk * renderer) const197 bool SharedBufferSuballocationGarbage::hasResourceUseSubmitted(RendererVk *renderer) const
198 {
199     return renderer->hasResourceUseSubmitted(mLifetime);
200 }
201 }  // namespace vk
202 }  // namespace rx
203