Revert "Vulkan: Use different strategy for buffer memory allocation"

This reverts commit 0dbe308d91.

Reason for revert: crbug.com/1253325

Original change's description:
> Vulkan: Use different strategy for buffer memory allocation
>
> This CL uses different memory allocation strategy based on the requested
> size. If the requested size exceeds 1M, we use dedicated memory
> allocation to avoid memory waste associated with the sub-allocator.
> Otherwise we uses VMA's sub-allocator pool.  This CL creates two sets of
> customized pool so that we uses different allocation strategy for each
> set of pool: the small pool uses buddy algorithm which favors speed over
> memory and large pool uses default algorithm that favors memory saving
> over speed. This CL also replaces vmaFindMemoryTypeIndexForBufferInfo
> with vmaFindMemoryTypeIndex to avoid create and destroy VkBuffer object
> just try to find memoryTypeIndex.
>
> Bug: b/195588159
> Change-Id: I2bddbfffd77ba2ce6b9389d83a31051c4b748c4d
> Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/2939490
> Commit-Queue: Charlie Lao <cclao@google.com>
> Reviewed-by: Jamie Madill <jmadill@chromium.org>
> Reviewed-by: Shahbaz Youssefi <syoussefi@chromium.org>
> Reviewed-by: Tim Van Patten <timvp@google.com>

Bug: b/195588159
Change-Id: I2c8fe8cb2930d16f5212570d32be68e7c6a6e5f3
No-Presubmit: true
No-Tree-Checks: true
No-Try: true
Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/3244258
Reviewed-by: Charlie Lao <cclao@google.com>
Commit-Queue: Charlie Lao <cclao@google.com>
Bot-Commit: Rubber Stamper <rubber-stamper@appspot.gserviceaccount.com>
This commit is contained in:
Charlie Lao 2021-10-26 19:06:19 +00:00 коммит произвёл Angle LUCI CQ
Родитель 6b315a7845
Коммит 421dbf200d
8 изменённых файлов: 101 добавлений и 419 удалений

Просмотреть файл

@ -1411,7 +1411,7 @@ angle::Result RendererVk::initialize(DisplayVk *displayVk,
preferredLargeHeapBlockSize));
// Create buffer memory allocator
mBufferMemoryAllocator.initialize(this);
ANGLE_VK_TRY(displayVk, mBufferMemoryAllocator.initialize(this, preferredLargeHeapBlockSize));
{
ANGLE_TRACE_EVENT0("gpu.angle,startup", "GlslangWarmup");
@ -3687,170 +3687,32 @@ void MemoryReport::logMemoryReportStats() const
// BufferMemoryAllocator implementation.
BufferMemoryAllocator::BufferMemoryAllocator() {}
BufferMemoryAllocator::~BufferMemoryAllocator()
BufferMemoryAllocator::~BufferMemoryAllocator() {}
VkResult BufferMemoryAllocator::initialize(RendererVk *renderer,
VkDeviceSize preferredLargeHeapBlockSize)
{
std::lock_guard<std::mutex> lock(mVMAPoolMutex);
for (VMAPoolArray &vmaPoolArray : mVMAPools)
{
for (VMAPool &vmaPool : vmaPoolArray)
{
ASSERT(!vmaPool.valid());
}
}
ASSERT(renderer->getAllocator().valid());
return VK_SUCCESS;
}
void BufferMemoryAllocator::destroy(RendererVk *renderer)
{
const Allocator &allocator = renderer->getAllocator();
void BufferMemoryAllocator::destroy(RendererVk *renderer) {}
std::lock_guard<std::mutex> lock(mVMAPoolMutex);
for (VMAPoolArray &vmaPoolArray : mVMAPools)
{
for (VMAPool &vmaPool : vmaPoolArray)
{
vmaPool.destroy(allocator);
}
}
}
angle::Result BufferMemoryAllocator::createBuffer(Context *context,
const VkBufferCreateInfo &bufferCreateInfo,
VkMemoryPropertyFlags requiredFlags,
VkMemoryPropertyFlags preferredFlags,
bool persistentlyMappedBuffers,
uint32_t *memoryTypeIndexOut,
Buffer *bufferOut,
Allocation *allocationOut)
VkResult BufferMemoryAllocator::createBuffer(RendererVk *renderer,
const VkBufferCreateInfo &bufferCreateInfo,
VkMemoryPropertyFlags requiredFlags,
VkMemoryPropertyFlags preferredFlags,
bool persistentlyMappedBuffers,
uint32_t *memoryTypeIndexOut,
Buffer *bufferOut,
Allocation *allocationOut)
{
ASSERT(bufferOut && !bufferOut->valid());
ASSERT(allocationOut && !allocationOut->valid());
RendererVk *renderer = context->getRenderer();
const Allocator &allocator = renderer->getAllocator();
ANGLE_VK_TRY(context,
vma::CreateBuffer(allocator.getHandle(), &bufferCreateInfo, requiredFlags,
preferredFlags, persistentlyMappedBuffers, memoryTypeIndexOut,
&bufferOut->mHandle, &allocationOut->mHandle));
return angle::Result::Continue;
}
VkResult BufferMemoryAllocator::createVMAPool(const Allocator &allocator,
uint32_t memoryTypeIndex,
VMAPoolType poolType,
VMAPool *poolOut)
{
VkDeviceSize blockSize = poolType == VMAPoolType::kSmallPool ? kSmallPoolBlockSize : 0;
vma::PoolCreateFlags poolCreateFlags = vma::POOL_CREATE_IGNORE_BUFFER_IMAGE_GRANULARITY_BIT;
// use buddy algorithm for small pool to favor speed
if (poolType == VMAPoolType::kSmallPool)
{
poolCreateFlags |= vma::POOL_CREATE_BUDDY_ALGORITHM_BIT;
}
// Create a custom pool.
return vma::CreatePool(allocator.getHandle(), memoryTypeIndex, poolCreateFlags, blockSize,
&poolOut->mHandle);
}
VMAPool &BufferMemoryAllocator::getVMAPool(Context *context,
uint32_t memoryTypeIndex,
VkDeviceSize requestedSize,
bool robustResourceInitEnabled,
vma::AllocationCreateFlags &flags)
{
RendererVk *renderer = context->getRenderer();
const Allocator &allocator = renderer->getAllocator();
if (requestedSize > BufferMemoryAllocator::kMaxSizeToUseSubAllocator)
{
// Use VK_NULL_HANDLE VMAPool since VMA requires it been NULL for dedicated memory.
flags |= vma::ALLOCATION_CREATE_DEDICATED_MEMORY_BIT;
return kInvalidVMAPool;
}
// If robust resource init is enabled, we always use the large pool which uses the
// default allocation algorithm to ensure no padding is added at the end of the allocation.
VMAPoolType poolType = (!robustResourceInitEnabled && requestedSize <= kMaxSizeToUseSmallPool)
? VMAPoolType::kSmallPool
: VMAPoolType::kLargePool;
{
std::lock_guard<std::mutex> lock(mVMAPoolMutex);
if (!mVMAPools[poolType][memoryTypeIndex].valid())
{
createVMAPool(allocator, memoryTypeIndex, poolType,
&mVMAPools[poolType][memoryTypeIndex]);
}
}
return mVMAPools[poolType][memoryTypeIndex];
}
angle::Result BufferMemoryAllocator::allocateMemoryForBuffer(Context *context,
Buffer &buffer,
VkMemoryPropertyFlags requiredFlags,
VkMemoryPropertyFlags preferredFlags,
bool persistentlyMapped,
bool robustResourceInitEnabled,
uint32_t *memoryTypeIndexOut,
Allocation *allocationOut,
VkDeviceSize *sizeOut)
{
RendererVk *renderer = context->getRenderer();
const Allocator &allocator = renderer->getAllocator();
const MemoryProperties &memoryProperties = renderer->getMemoryProperties();
vma::AllocationCreateFlags flags = persistentlyMapped ? vma::ALLOCATION_CREATE_MAPPED_BIT : 0;
// Call driver to determine memory requirements.
VkMemoryRequirements vkMemReq;
buffer.getMemoryRequirements(context->getDevice(), &vkMemReq);
uint32_t memoryTypeIndex = kInvalidMemoryTypeIndex;
// We loop through each memory type bit in case of failure.
// This will immediate return if FindMemoryTypeIndex fail, in the case that we have tried
// all memory types that are compatible and still fail to allocate.
while (vkMemReq.memoryTypeBits &&
vma::FindMemoryTypeIndex(allocator.getHandle(), vkMemReq.memoryTypeBits, requiredFlags,
preferredFlags, persistentlyMapped,
&memoryTypeIndex) == VK_SUCCESS)
{
if (vkMemReq.size > memoryProperties.getHeapSizeForMemoryType(memoryTypeIndex))
{
// Remove old memTypeIndex from list of possibilities and loop again
vkMemReq.memoryTypeBits &= ~(1u << memoryTypeIndex);
continue;
}
// Allocate memory using sub-allocator
VMAPool &pool =
getVMAPool(context, memoryTypeIndex, vkMemReq.size, robustResourceInitEnabled, flags);
if (vma::AllocateMemory(allocator.getHandle(), &vkMemReq, requiredFlags, preferredFlags,
flags, pool.getHandle(), memoryTypeIndexOut,
&allocationOut->mHandle, sizeOut) != VK_SUCCESS)
{
// Allocation failed and retry.
vkMemReq.memoryTypeBits &= ~(1u << memoryTypeIndex);
continue;
}
// Bind memory
ASSERT(*memoryTypeIndexOut == memoryTypeIndex);
if (vma::BindBufferMemory(allocator.getHandle(), allocationOut->mHandle, buffer.mHandle) !=
VK_SUCCESS)
{
// Roll back memory allocation and retry
allocationOut->destroy(allocator);
vkMemReq.memoryTypeBits &= ~(1u << memoryTypeIndex);
continue;
}
// Successfully allocate and bind memory
return angle::Result::Continue;
}
// We reach here when we loop through all of memoryTypeBits and still can't allocate
ANGLE_VK_TRY(context, VK_ERROR_OUT_OF_DEVICE_MEMORY);
return angle::Result::Continue;
return vma::CreateBuffer(allocator.getHandle(), &bufferCreateInfo, requiredFlags,
preferredFlags, persistentlyMappedBuffers, memoryTypeIndexOut,
&bufferOut->mHandle, &allocationOut->mHandle);
}
void BufferMemoryAllocator::getMemoryTypeProperties(RendererVk *renderer,
@ -3861,21 +3723,18 @@ void BufferMemoryAllocator::getMemoryTypeProperties(RendererVk *renderer,
vma::GetMemoryTypeProperties(allocator.getHandle(), memoryTypeIndex, flagsOut);
}
angle::Result BufferMemoryAllocator::findMemoryTypeIndexForBufferInfo(
Context *context,
VkResult BufferMemoryAllocator::findMemoryTypeIndexForBufferInfo(
RendererVk *renderer,
const VkBufferCreateInfo &bufferCreateInfo,
VkMemoryPropertyFlags requiredFlags,
VkMemoryPropertyFlags preferredFlags,
bool persistentlyMappedBuffers,
uint32_t *memoryTypeIndexOut) const
{
RendererVk *renderer = context->getRenderer();
const Allocator &allocator = renderer->getAllocator();
ANGLE_VK_TRY(context, vma::FindMemoryTypeIndexForBufferInfo(
allocator.getHandle(), &bufferCreateInfo, requiredFlags,
preferredFlags, persistentlyMappedBuffers, memoryTypeIndexOut));
return angle::Result::Continue;
return vma::FindMemoryTypeIndexForBufferInfo(allocator.getHandle(), &bufferCreateInfo,
requiredFlags, preferredFlags,
persistentlyMappedBuffers, memoryTypeIndexOut);
}
} // namespace vk
} // namespace rx

Просмотреть файл

@ -89,80 +89,30 @@ class BufferMemoryAllocator : angle::NonCopyable
BufferMemoryAllocator();
~BufferMemoryAllocator();
void initialize(RendererVk *renderer) {}
VkResult initialize(RendererVk *renderer, VkDeviceSize preferredLargeHeapBlockSize);
void destroy(RendererVk *renderer);
// Initializes the buffer handle and memory allocation.
angle::Result createBuffer(Context *context,
const VkBufferCreateInfo &bufferCreateInfo,
VkMemoryPropertyFlags requiredFlags,
VkMemoryPropertyFlags preferredFlags,
bool persistentlyMapped,
uint32_t *memoryTypeIndexOut,
Buffer *bufferOut,
Allocation *allocationOut);
angle::Result allocateMemoryForBuffer(Context *context,
Buffer &buffer,
VkMemoryPropertyFlags requiredFlags,
VkMemoryPropertyFlags preferredFlags,
bool persistentlyMapped,
bool robustResourceInitEnabled,
uint32_t *memoryTypeIndexOut,
Allocation *allocationOut,
VkDeviceSize *sizeOut);
VkResult createBuffer(RendererVk *renderer,
const VkBufferCreateInfo &bufferCreateInfo,
VkMemoryPropertyFlags requiredFlags,
VkMemoryPropertyFlags preferredFlags,
bool persistentlyMapped,
uint32_t *memoryTypeIndexOut,
Buffer *bufferOut,
Allocation *allocationOut);
void getMemoryTypeProperties(RendererVk *renderer,
uint32_t memoryTypeIndex,
VkMemoryPropertyFlags *flagsOut) const;
angle::Result findMemoryTypeIndexForBufferInfo(Context *context,
const VkBufferCreateInfo &bufferCreateInfo,
VkMemoryPropertyFlags requiredFlags,
VkMemoryPropertyFlags preferredFlags,
bool persistentlyMappedBuffers,
uint32_t *memoryTypeIndexOut) const;
VkResult findMemoryTypeIndexForBufferInfo(RendererVk *renderer,
const VkBufferCreateInfo &bufferCreateInfo,
VkMemoryPropertyFlags requiredFlags,
VkMemoryPropertyFlags preferredFlags,
bool persistentlyMappedBuffers,
uint32_t *memoryTypeIndexOut) const;
private:
enum class VMAPoolType : uint8_t
{
kSmallPool = 0,
kLargePool = 1,
InvalidEnum = 2,
EnumCount = InvalidEnum,
};
VMAPool kInvalidVMAPool;
static VkResult createVMAPool(const Allocator &allocator,
uint32_t memoryTypeIndex,
VMAPoolType poolType,
VMAPool *poolOut);
VMAPool &getVMAPool(Context *context,
uint32_t memoryTypeIndex,
VkDeviceSize requestedSize,
bool robustResourceInitEnabled,
vma::AllocationCreateFlags &flags);
using VMAPoolArray = std::array<VMAPool, VK_MAX_MEMORY_TYPES>;
using VMAPoolArrays = angle::PackedEnumMap<VMAPoolType, VMAPoolArray>;
VMAPoolArrays mVMAPools;
// The mutex lock protects access to mVMAPools
mutable std::mutex mVMAPoolMutex;
// There are three code paths for buffer memory allocation: If memory is bigger than
// kMaxSizeToUseSubAllocator, we will just use dedicated memory allocation to
// avoid memory waste associated with the sub-allocator. Since the memory size is big, we
// think the overhead of calling into vulkan driver for allocation is small compared to the
// memory access itself. Otherwise we will use VMA sub-allocator to allocate from the memory
// block. We maintain two categories of customized pools: one with smaller block size and
// another with large block size. If size is bigger than kMaxSizeToUseSmallPool, we use the
// large pool, otherwise use the small pool. The large pool uses default allocation algorithm
// that favors memory saving and small pool uses buddy algorithm that favors allocation speed.
// These numbers are experimental and may subject to future tuning based on the platform
// configuration (like the amount of physical memory and GPU family etc).
static constexpr VkDeviceSize kMaxSizeToUseSubAllocator = 1024 * 1024; // 1M
static constexpr VkDeviceSize kMaxSizeToUseSmallPool = 4 * 1024; // 4k
static constexpr VkDeviceSize kSmallPoolBlockSize = 128 * 1024; // 128K
};
} // namespace vk

Просмотреть файл

@ -3547,17 +3547,21 @@ angle::Result BufferHelper::init(ContextVk *contextVk,
BufferMemoryAllocator &bufferMemoryAllocator = renderer->getBufferMemoryAllocator();
bool persistentlyMapped = renderer->getFeatures().persistentlyMappedBuffers.enabled;
DeviceScoped<Buffer> buffer(contextVk->getDevice());
ANGLE_VK_TRY(contextVk, buffer.get().init(contextVk->getDevice(), *createInfo));
ANGLE_TRY(mMemory.init());
// Check that the allocation is not too large.
uint32_t memoryTypeIndex = 0;
ANGLE_VK_TRY(contextVk, bufferMemoryAllocator.findMemoryTypeIndexForBufferInfo(
renderer, *createInfo, requiredFlags, preferredFlags,
persistentlyMapped, &memoryTypeIndex));
bool robustResourceInitEnabled = contextVk->isRobustResourceInitEnabled();
uint32_t memoryTypeIndex = kInvalidMemoryTypeIndex;
VkDeviceSize sizeOut = 0;
ANGLE_TRY(bufferMemoryAllocator.allocateMemoryForBuffer(
contextVk, buffer.get(), requiredFlags, preferredFlags, persistentlyMapped,
robustResourceInitEnabled, &memoryTypeIndex, mMemory.getAllocationObject(), &sizeOut));
VkDeviceSize heapSize =
renderer->getMemoryProperties().getHeapSizeForMemoryType(memoryTypeIndex);
ANGLE_VK_CHECK(contextVk, createInfo->size <= heapSize, VK_ERROR_OUT_OF_DEVICE_MEMORY);
ANGLE_VK_TRY(contextVk, bufferMemoryAllocator.createBuffer(renderer, *createInfo, requiredFlags,
preferredFlags, persistentlyMapped,
&memoryTypeIndex, &mBuffer,
mMemory.getMemoryObject()));
bufferMemoryAllocator.getMemoryTypeProperties(renderer, memoryTypeIndex, &mMemoryPropertyFlags);
mCurrentQueueFamilyIndex = renderer->getQueueFamilyIndex();
@ -3569,29 +3573,21 @@ angle::Result BufferHelper::init(ContextVk *contextVk,
if ((mMemoryPropertyFlags & VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT) == 0 &&
(requestedCreateInfo.usage & VK_BUFFER_USAGE_TRANSFER_DST_BIT) != 0)
{
ANGLE_TRY(initializeNonZeroMemory(contextVk, sizeOut));
ANGLE_TRY(initializeNonZeroMemory(contextVk, createInfo->size));
}
else if ((mMemoryPropertyFlags & VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT) != 0)
{
const Allocator &allocator = renderer->getAllocator();
// Can map the memory.
// Pick an arbitrary value to initialize non-zero memory for sanitization.
constexpr int kNonZeroInitValue = 55;
if (mMemory.getDeviceMemoryObject()->valid())
{
ANGLE_TRY(InitMappableDeviceMemory(contextVk, mMemory.getDeviceMemoryObject(),
sizeOut, kNonZeroInitValue,
mMemoryPropertyFlags));
}
else
{
ANGLE_TRY(InitMappableAllocation(contextVk, renderer->getAllocator(),
mMemory.getAllocationObject(), sizeOut,
kNonZeroInitValue, mMemoryPropertyFlags));
}
ANGLE_TRY(InitMappableAllocation(contextVk, allocator, mMemory.getMemoryObject(), mSize,
kNonZeroInitValue, mMemoryPropertyFlags));
}
}
mBuffer = buffer.release();
ANGLE_TRY(mMemory.init());
return angle::Result::Continue;
}
@ -3617,9 +3613,8 @@ angle::Result BufferHelper::initExternal(ContextVk *contextVk,
ANGLE_VK_TRY(contextVk, mBuffer.init(renderer->getDevice(), modifiedCreateInfo));
ASSERT(!mMemory.getAllocationObject()->valid());
ANGLE_TRY(InitAndroidExternalMemory(contextVk, clientBuffer, memoryProperties, &mBuffer,
&mMemoryPropertyFlags, mMemory.getDeviceMemoryObject()));
&mMemoryPropertyFlags, mMemory.getExternalMemoryObject()));
ANGLE_TRY(mMemory.initExternal(clientBuffer));
@ -3678,8 +3673,8 @@ void BufferHelper::release(RendererVk *renderer)
unmap(renderer);
mSize = 0;
renderer->collectGarbageAndReinit(&mReadOnlyUse, &mBuffer, mMemory.getDeviceMemoryObject(),
mMemory.getAllocationObject());
renderer->collectGarbageAndReinit(&mReadOnlyUse, &mBuffer, mMemory.getExternalMemoryObject(),
mMemory.getMemoryObject());
mReadWriteUse.release();
mReadWriteUse.init();
}

Просмотреть файл

@ -13,17 +13,6 @@
namespace vma
{
#define VALIDATE_POOL_CREATE_FLAG_BITS(x) \
static_assert(static_cast<uint32_t>(x) == static_cast<uint32_t>(VMA_##x), "VMA enum mismatch")
VALIDATE_POOL_CREATE_FLAG_BITS(POOL_CREATE_IGNORE_BUFFER_IMAGE_GRANULARITY_BIT);
VALIDATE_POOL_CREATE_FLAG_BITS(POOL_CREATE_LINEAR_ALGORITHM_BIT);
VALIDATE_POOL_CREATE_FLAG_BITS(POOL_CREATE_BUDDY_ALGORITHM_BIT);
#define VALIDATE_ALLOCATION_CREATE_FLAG_BITS(x) \
static_assert(static_cast<uint32_t>(x) == static_cast<uint32_t>(VMA_##x), "VMA enum mismatch")
VALIDATE_ALLOCATION_CREATE_FLAG_BITS(ALLOCATION_CREATE_DEDICATED_MEMORY_BIT);
VALIDATE_ALLOCATION_CREATE_FLAG_BITS(ALLOCATION_CREATE_MAPPED_BIT);
VkResult InitAllocator(VkPhysicalDevice physicalDevice,
VkDevice device,
VkInstance instance,
@ -85,15 +74,19 @@ void DestroyAllocator(VmaAllocator allocator)
VkResult CreatePool(VmaAllocator allocator,
uint32_t memoryTypeIndex,
PoolCreateFlags flags,
bool buddyAlgorithm,
VkDeviceSize blockSize,
VmaPool *pPool)
{
VmaPoolCreateInfo poolCreateInfo = {};
poolCreateInfo.memoryTypeIndex = memoryTypeIndex;
poolCreateInfo.flags = static_cast<uint32_t>(flags);
poolCreateInfo.blockSize = blockSize;
poolCreateInfo.maxBlockCount = -1; // unlimited
poolCreateInfo.flags = VMA_POOL_CREATE_IGNORE_BUFFER_IMAGE_GRANULARITY_BIT;
if (buddyAlgorithm)
{
poolCreateInfo.flags |= VMA_POOL_CREATE_BUDDY_ALGORITHM_BIT;
}
poolCreateInfo.blockSize = blockSize;
poolCreateInfo.maxBlockCount = -1; // unlimited
return vmaCreatePool(allocator, &poolCreateInfo, pPool);
}
@ -102,41 +95,11 @@ void DestroyPool(VmaAllocator allocator, VmaPool pool)
vmaDestroyPool(allocator, pool);
}
VkResult AllocateMemory(VmaAllocator allocator,
const VkMemoryRequirements *pVkMemoryRequirements,
VkMemoryPropertyFlags requiredFlags,
VkMemoryPropertyFlags preferredFlags,
AllocationCreateFlags flags,
VmaPool customPool,
uint32_t *pMemoryTypeIndexOut,
VmaAllocation *pAllocation,
VkDeviceSize *sizeOut)
{
VkResult result;
VmaAllocationCreateInfo allocationCreateInfo = {};
allocationCreateInfo.requiredFlags = requiredFlags;
allocationCreateInfo.preferredFlags = preferredFlags;
allocationCreateInfo.flags = static_cast<uint32_t>(flags);
allocationCreateInfo.pool = customPool;
VmaAllocationInfo allocationInfo = {};
result = vmaAllocateMemory(allocator, pVkMemoryRequirements, &allocationCreateInfo, pAllocation,
&allocationInfo);
*pMemoryTypeIndexOut = allocationInfo.memoryType;
*sizeOut = allocationInfo.size;
return result;
}
void FreeMemory(VmaAllocator allocator, VmaAllocation allocation)
{
vmaFreeMemory(allocator, allocation);
}
VkResult BindBufferMemory(VmaAllocator allocator, VmaAllocation allocation, VkBuffer buffer)
{
return vmaBindBufferMemory(allocator, allocation, buffer);
}
VkResult CreateBuffer(VmaAllocator allocator,
const VkBufferCreateInfo *pBufferCreateInfo,
VkMemoryPropertyFlags requiredFlags,
@ -150,12 +113,13 @@ VkResult CreateBuffer(VmaAllocator allocator,
VmaAllocationCreateInfo allocationCreateInfo = {};
allocationCreateInfo.requiredFlags = requiredFlags;
allocationCreateInfo.preferredFlags = preferredFlags;
allocationCreateInfo.flags = (persistentlyMapped) ? ALLOCATION_CREATE_MAPPED_BIT : 0;
allocationCreateInfo.flags = (persistentlyMapped) ? VMA_ALLOCATION_CREATE_MAPPED_BIT : 0;
VmaAllocationInfo allocationInfo = {};
result = vmaCreateBuffer(allocator, pBufferCreateInfo, &allocationCreateInfo, pBuffer,
pAllocation, &allocationInfo);
*pMemoryTypeIndexOut = allocationInfo.memoryType;
return result;
}
@ -169,28 +133,12 @@ VkResult FindMemoryTypeIndexForBufferInfo(VmaAllocator allocator,
VmaAllocationCreateInfo allocationCreateInfo = {};
allocationCreateInfo.requiredFlags = requiredFlags;
allocationCreateInfo.preferredFlags = preferredFlags;
allocationCreateInfo.flags = (persistentlyMappedBuffers) ? ALLOCATION_CREATE_MAPPED_BIT : 0;
allocationCreateInfo.flags = (persistentlyMappedBuffers) ? VMA_ALLOCATION_CREATE_MAPPED_BIT : 0;
return vmaFindMemoryTypeIndexForBufferInfo(allocator, pBufferCreateInfo, &allocationCreateInfo,
pMemoryTypeIndexOut);
}
VkResult FindMemoryTypeIndex(VmaAllocator allocator,
uint32_t memoryTypeBits,
VkMemoryPropertyFlags requiredFlags,
VkMemoryPropertyFlags preferredFlags,
bool persistentlyMappedBuffers,
uint32_t *pMemoryTypeIndexOut)
{
VmaAllocationCreateInfo allocationCreateInfo = {};
allocationCreateInfo.requiredFlags = requiredFlags;
allocationCreateInfo.preferredFlags = preferredFlags;
allocationCreateInfo.flags = (persistentlyMappedBuffers) ? ALLOCATION_CREATE_MAPPED_BIT : 0;
return vmaFindMemoryTypeIndex(allocator, memoryTypeBits, &allocationCreateInfo,
pMemoryTypeIndexOut);
}
void GetMemoryTypeProperties(VmaAllocator allocator,
uint32_t memoryTypeIndex,
VkMemoryPropertyFlags *pFlags)

Просмотреть файл

@ -18,24 +18,6 @@ VK_DEFINE_HANDLE(VmaPool)
namespace vma
{
// The following enums for PoolCreateFlagBits and AllocationCreateFlagBits are match to VMA #defines
// so that search in VMA code will be easier. The downside is it does not conform to ANGLE coding
// style because of this.
typedef VkFlags PoolCreateFlags;
typedef enum PoolCreateFlagBits
{
POOL_CREATE_IGNORE_BUFFER_IMAGE_GRANULARITY_BIT = 0x2,
POOL_CREATE_LINEAR_ALGORITHM_BIT = 0x4,
POOL_CREATE_BUDDY_ALGORITHM_BIT = 0x8,
} PoolCreateFlagBits;
typedef VkFlags AllocationCreateFlags;
typedef enum AllocationCreateFlagBits
{
ALLOCATION_CREATE_DEDICATED_MEMORY_BIT = 0x1,
ALLOCATION_CREATE_MAPPED_BIT = 0x4,
} AllocationCreateFlagBits;
VkResult InitAllocator(VkPhysicalDevice physicalDevice,
VkDevice device,
VkInstance instance,
@ -47,24 +29,13 @@ void DestroyAllocator(VmaAllocator allocator);
VkResult CreatePool(VmaAllocator allocator,
uint32_t memoryTypeIndex,
PoolCreateFlags flags,
bool buddyAlgorithm,
VkDeviceSize blockSize,
VmaPool *pPool);
void DestroyPool(VmaAllocator allocator, VmaPool pool);
VkResult AllocateMemory(VmaAllocator allocator,
const VkMemoryRequirements *pVkMemoryRequirements,
VkMemoryPropertyFlags requiredFlags,
VkMemoryPropertyFlags preferredFlags,
AllocationCreateFlags flags,
VmaPool customPool,
uint32_t *pMemoryTypeIndexOut,
VmaAllocation *pAllocation,
VkDeviceSize *sizeOut);
void FreeMemory(VmaAllocator allocator, VmaAllocation allocation);
VkResult BindBufferMemory(VmaAllocator allocator, VmaAllocation allocation, VkBuffer buffer);
VkResult CreateBuffer(VmaAllocator allocator,
const VkBufferCreateInfo *pBufferCreateInfo,
VkMemoryPropertyFlags requiredFlags,
@ -81,13 +52,6 @@ VkResult FindMemoryTypeIndexForBufferInfo(VmaAllocator allocator,
bool persistentlyMappedBuffers,
uint32_t *pMemoryTypeIndexOut);
VkResult FindMemoryTypeIndex(VmaAllocator allocator,
uint32_t memoryTypeBits,
VkMemoryPropertyFlags requiredFlags,
VkMemoryPropertyFlags preferredFlags,
bool persistentlyMappedBuffers,
uint32_t *pMemoryTypeIndexOut);
void GetMemoryTypeProperties(VmaAllocator allocator,
uint32_t memoryTypeIndex,
VkMemoryPropertyFlags *pFlags);

Просмотреть файл

@ -498,9 +498,9 @@ void BufferMemory::unmap(RendererVk *renderer)
{
if (mMappedMemory != nullptr)
{
if (mDeviceMemory.valid())
if (isExternalBuffer())
{
mDeviceMemory.unmap(renderer->getDevice());
mExternalMemory.unmap(renderer->getDevice());
}
else
{
@ -513,13 +513,10 @@ void BufferMemory::unmap(RendererVk *renderer)
void BufferMemory::destroy(RendererVk *renderer)
{
if (mDeviceMemory.valid())
if (isExternalBuffer())
{
mDeviceMemory.destroy(renderer->getDevice());
if (mClientBuffer)
{
ReleaseAndroidExternalMemory(renderer, mClientBuffer);
}
mExternalMemory.destroy(renderer->getDevice());
ReleaseAndroidExternalMemory(renderer, mClientBuffer);
}
else
{
@ -532,17 +529,17 @@ void BufferMemory::flush(RendererVk *renderer,
VkDeviceSize offset,
VkDeviceSize size)
{
if (mDeviceMemory.valid())
if (isExternalBuffer())
{
// if the memory type is not host coherent, we perform an explicit flush
if ((memoryPropertyFlags & VK_MEMORY_PROPERTY_HOST_COHERENT_BIT) == 0)
{
VkMappedMemoryRange mappedRange = {};
mappedRange.sType = VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE;
mappedRange.memory = mDeviceMemory.getHandle();
mappedRange.memory = mExternalMemory.getHandle();
mappedRange.offset = offset;
mappedRange.size = size;
mDeviceMemory.flush(renderer->getDevice(), mappedRange);
mExternalMemory.flush(renderer->getDevice(), mappedRange);
}
}
else
@ -556,17 +553,17 @@ void BufferMemory::invalidate(RendererVk *renderer,
VkDeviceSize offset,
VkDeviceSize size)
{
if (mDeviceMemory.valid())
if (isExternalBuffer())
{
// if the memory type is not device coherent, we perform an explicit invalidate
if ((memoryPropertyFlags & VK_MEMORY_PROPERTY_DEVICE_COHERENT_BIT_AMD) == 0)
{
VkMappedMemoryRange memoryRanges = {};
memoryRanges.sType = VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE;
memoryRanges.memory = mDeviceMemory.getHandle();
memoryRanges.memory = mExternalMemory.getHandle();
memoryRanges.offset = offset;
memoryRanges.size = size;
mDeviceMemory.invalidate(renderer->getDevice(), memoryRanges);
mExternalMemory.invalidate(renderer->getDevice(), memoryRanges);
}
}
else
@ -577,10 +574,10 @@ void BufferMemory::invalidate(RendererVk *renderer,
angle::Result BufferMemory::mapImpl(ContextVk *contextVk, VkDeviceSize size)
{
if (mDeviceMemory.valid())
if (isExternalBuffer())
{
ANGLE_VK_TRY(contextVk, mDeviceMemory.map(contextVk->getRenderer()->getDevice(), 0, size, 0,
&mMappedMemory));
ANGLE_VK_TRY(contextVk, mExternalMemory.map(contextVk->getRenderer()->getDevice(), 0, size,
0, &mMappedMemory));
}
else
{
@ -613,30 +610,27 @@ angle::Result StagingBuffer::init(Context *context, VkDeviceSize size, StagingUs
createInfo.queueFamilyIndexCount = 0;
createInfo.pQueueFamilyIndices = nullptr;
ANGLE_VK_TRY(context, mBuffer.init(context->getDevice(), createInfo));
VkMemoryPropertyFlags preferredFlags = 0;
VkMemoryPropertyFlags requiredFlags =
VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT;
RendererVk *renderer = context->getRenderer();
BufferMemoryAllocator &bufferMemoryAllocator = renderer->getBufferMemoryAllocator();
uint32_t memoryTypeIndex = kInvalidMemoryTypeIndex;
VkDeviceSize sizeOut = 0;
RendererVk *renderer = context->getRenderer();
ANGLE_TRY(bufferMemoryAllocator.allocateMemoryForBuffer(
context, mBuffer, requiredFlags, preferredFlags,
renderer->getFeatures().persistentlyMappedBuffers.enabled, false, &memoryTypeIndex,
&mAllocation, &sizeOut));
mSize = static_cast<size_t>(sizeOut);
uint32_t memoryTypeIndex = 0;
BufferMemoryAllocator &bufferMemoryAllocator = renderer->getBufferMemoryAllocator();
ANGLE_VK_TRY(context, bufferMemoryAllocator.createBuffer(
renderer, createInfo, requiredFlags, preferredFlags,
renderer->getFeatures().persistentlyMappedBuffers.enabled,
&memoryTypeIndex, &mBuffer, &mAllocation));
mSize = static_cast<size_t>(size);
// Wipe memory to an invalid value when the 'allocateNonZeroMemory' feature is enabled. The
// invalid values ensures our testing doesn't assume zero-initialized memory.
if (renderer->getFeatures().allocateNonZeroMemory.enabled)
{
const Allocator &allocator = renderer->getAllocator();
ANGLE_TRY(InitMappableAllocation(context, allocator, &mAllocation, sizeOut,
kNonZeroInitValue, requiredFlags));
ANGLE_TRY(InitMappableAllocation(context, allocator, &mAllocation, size, kNonZeroInitValue,
requiredFlags));
}
return angle::Result::Continue;

Просмотреть файл

@ -111,12 +111,8 @@ enum class TextureDimension
// next highest values to meet native drivers are 16 bits or 32 bits.
constexpr uint32_t kAttributeOffsetMaxBits = 15;
constexpr uint32_t kInvalidMemoryTypeIndex = UINT32_MAX;
namespace vk
{
class BufferMemory;
// A packed attachment index interface with vulkan API
class PackedAttachmentIndex final
{
@ -395,18 +391,14 @@ class BufferMemory : angle::NonCopyable
bool isExternalBuffer() const { return mClientBuffer != nullptr; }
uint8_t *getMappedMemory() const { return mMappedMemory; }
DeviceMemory *getDeviceMemoryObject() { return &mDeviceMemory; }
Allocation *getAllocationObject() { return &mAllocation; }
DeviceMemory *getExternalMemoryObject() { return &mExternalMemory; }
Allocation *getMemoryObject() { return &mAllocation; }
private:
angle::Result mapImpl(ContextVk *contextVk, VkDeviceSize size);
// mAllocation and mDeviceMemory are mutally exclusive. Only one should be used at any time.
// mAllocation is used when it is allocated by BufferMemoryAllocator. mDeviceMemory is used when
// it is allocated by calling directly into Vulkan driver. External allocations is always
// allocated with vulkan call directly.
Allocation mAllocation;
DeviceMemory mDeviceMemory;
Allocation mAllocation; // use mAllocation if isExternalBuffer() is false
DeviceMemory mExternalMemory; // use mExternalMemory if isExternalBuffer() is true
void *mClientBuffer;
uint8_t *mMappedMemory;

Просмотреть файл

@ -471,16 +471,6 @@ class Allocation final : public WrappedObject<Allocation, VmaAllocation>
friend class BufferMemoryAllocator;
};
class VMAPool final : public WrappedObject<VMAPool, VmaPool>
{
public:
VMAPool() = default;
void destroy(const Allocator &allocator);
private:
friend class BufferMemoryAllocator;
};
class RenderPass final : public WrappedObject<RenderPass, VkRenderPass>
{
public:
@ -1389,16 +1379,6 @@ ANGLE_INLINE void Allocation::invalidate(const Allocator &allocator,
vma::InvalidateAllocation(allocator.getHandle(), mHandle, offset, size);
}
// VMAPool implementation.
ANGLE_INLINE void VMAPool::destroy(const Allocator &allocator)
{
if (valid())
{
vma::DestroyPool(allocator.getHandle(), mHandle);
mHandle = VK_NULL_HANDLE;
}
}
// RenderPass implementation.
ANGLE_INLINE void RenderPass::destroy(VkDevice device)
{