зеркало из https://github.com/AvaloniaUI/angle.git
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:
Родитель
6b315a7845
Коммит
421dbf200d
|
@ -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)
|
||||
{
|
||||
|
|
Загрузка…
Ссылка в новой задаче