blob: 87b06f22f12a3c5a647defac59df5f14b7dcb7de [file] [log] [blame]
//
// Copyright 2022 The ANGLE Project Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//
// Suballocation.cpp:
// Implements class methods for BufferBlock and Suballocation and other related classes
//
// #include "libANGLE/renderer/vulkan/vk_utils.h"
#include "libANGLE/renderer/vulkan/Suballocation.h"
#include "libANGLE/Context.h"
#include "libANGLE/renderer/vulkan/RendererVk.h"
#include "libANGLE/renderer/vulkan/vk_mem_alloc_wrapper.h"
namespace rx
{
namespace vk
{
// BufferBlock implementation.
BufferBlock::BufferBlock() : mMemoryPropertyFlags(0), mSize(0), mMappedMemory(nullptr) {}
BufferBlock::BufferBlock(BufferBlock &&other)
: mVirtualBlock(std::move(other.mVirtualBlock)),
mBuffer(std::move(other.mBuffer)),
mDeviceMemory(std::move(other.mDeviceMemory)),
mMemoryPropertyFlags(other.mMemoryPropertyFlags),
mSize(other.mSize),
mMappedMemory(other.mMappedMemory),
mSerial(other.mSerial),
mCountRemainsEmpty(0)
{}
BufferBlock &BufferBlock::operator=(BufferBlock &&other)
{
std::swap(mVirtualBlock, other.mVirtualBlock);
std::swap(mBuffer, other.mBuffer);
std::swap(mDeviceMemory, other.mDeviceMemory);
std::swap(mMemoryPropertyFlags, other.mMemoryPropertyFlags);
std::swap(mSize, other.mSize);
std::swap(mMappedMemory, other.mMappedMemory);
std::swap(mSerial, other.mSerial);
std::swap(mCountRemainsEmpty, other.mCountRemainsEmpty);
return *this;
}
BufferBlock::~BufferBlock()
{
ASSERT(!mVirtualBlock.valid());
ASSERT(!mBuffer.valid());
ASSERT(!mDeviceMemory.valid());
ASSERT(mDescriptorSetCacheManager.empty());
}
void BufferBlock::destroy(RendererVk *renderer)
{
VkDevice device = renderer->getDevice();
mDescriptorSetCacheManager.destroyKeys(renderer);
if (mMappedMemory)
{
unmap(device);
}
mVirtualBlock.destroy(device);
mBuffer.destroy(device);
mDeviceMemory.destroy(device);
}
angle::Result BufferBlock::init(Context *context,
Buffer &buffer,
vma::VirtualBlockCreateFlags flags,
DeviceMemory &deviceMemory,
VkMemoryPropertyFlags memoryPropertyFlags,
VkDeviceSize size)
{
RendererVk *renderer = context->getRenderer();
ASSERT(!mVirtualBlock.valid());
ASSERT(!mBuffer.valid());
ASSERT(!mDeviceMemory.valid());
ANGLE_VK_TRY(context, mVirtualBlock.init(renderer->getDevice(), flags, size));
mBuffer = std::move(buffer);
mDeviceMemory = std::move(deviceMemory);
mMemoryPropertyFlags = memoryPropertyFlags;
mSize = size;
mMappedMemory = nullptr;
mSerial = renderer->getResourceSerialFactory().generateBufferSerial();
return angle::Result::Continue;
}
void BufferBlock::initWithoutVirtualBlock(Context *context,
Buffer &buffer,
DeviceMemory &deviceMemory,
VkMemoryPropertyFlags memoryPropertyFlags,
VkDeviceSize size)
{
RendererVk *renderer = context->getRenderer();
ASSERT(!mVirtualBlock.valid());
ASSERT(!mBuffer.valid());
ASSERT(!mDeviceMemory.valid());
mBuffer = std::move(buffer);
mDeviceMemory = std::move(deviceMemory);
mMemoryPropertyFlags = memoryPropertyFlags;
mSize = size;
mMappedMemory = nullptr;
mSerial = renderer->getResourceSerialFactory().generateBufferSerial();
}
VkResult BufferBlock::map(const VkDevice device)
{
ASSERT(mMappedMemory == nullptr);
return mDeviceMemory.map(device, 0, mSize, 0, &mMappedMemory);
}
void BufferBlock::unmap(const VkDevice device)
{
mDeviceMemory.unmap(device);
mMappedMemory = nullptr;
}
void BufferBlock::free(VmaVirtualAllocation allocation, VkDeviceSize offset)
{
std::unique_lock<std::mutex> lock(mVirtualBlockMutex);
mVirtualBlock.free(allocation, offset);
}
int32_t BufferBlock::getAndIncrementEmptyCounter()
{
return ++mCountRemainsEmpty;
}
void BufferBlock::calculateStats(vma::StatInfo *pStatInfo) const
{
std::unique_lock<std::mutex> lock(mVirtualBlockMutex);
mVirtualBlock.calculateStats(pStatInfo);
}
// BufferSuballocation implementation.
VkResult BufferSuballocation::map(Context *context)
{
return mBufferBlock->map(context->getDevice());
}
// SharedBufferSuballocationGarbage implementation.
bool SharedBufferSuballocationGarbage::destroyIfComplete(RendererVk *renderer,
Serial completedSerial)
{
if (mLifetime.isCurrentlyInUse(completedSerial))
{
return false;
}
mBuffer.destroy(renderer->getDevice());
mSuballocation.destroy(renderer);
mLifetime.release();
return true;
}
} // namespace vk
} // namespace rx