// // 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. // // AllocatorHelperRing: // Implements the ring buffer allocator helpers used in the command buffers. // #include "libANGLE/renderer/vulkan/AllocatorHelperRing.h" #include "libANGLE/renderer/vulkan/SecondaryCommandBuffer.h" namespace rx { namespace vk { void SharedCommandBlockAllocator::resetAllocator() { ASSERT(!mAllocator || !mAllocator->isShared()); if (mAllocSharedCP) { mAllocSharedCP->releaseAndUpdate(&mAllocReleaseCP); mAllocSharedCP = nullptr; } ASSERT(!mAllocSharedCP && !mAllocReleaseCP.valid()); } void SharedCommandBlockAllocator::attachAllocator(SharedCommandMemoryAllocator *allocator) { ASSERT(allocator); ASSERT(!mAllocator); mAllocator = allocator; if (mAllocator->isShared()) { mAllocator->releaseToSharedCP(); } } SharedCommandMemoryAllocator *SharedCommandBlockAllocator::detachAllocator( bool isCommandBufferEmpty) { ASSERT(mAllocator); if (!isCommandBufferEmpty) { // Must call reset() after detach from non-empty command buffer (OK to have an empty RP) ASSERT(!mAllocSharedCP && !mAllocReleaseCP.valid()); mAllocSharedCP = mAllocator->acquireSharedCP(); mAllocReleaseCP = mAllocator->get().getReleaseCheckPoint(); } SharedCommandMemoryAllocator *result = mAllocator; mAllocator = nullptr; return result; } void SharedCommandBlockPool::attachAllocator(SharedCommandMemoryAllocator *source) { ASSERT(source); RingBufferAllocator &sourceIn = source->get(); ASSERT(sourceIn.valid()); ASSERT(mCommandBuffer->hasEmptyCommands()); ASSERT(mLastCommandBlock == nullptr); ASSERT(mFinishedCommandSize == 0); ASSERT(!mAllocator.valid()); mAllocator = std::move(sourceIn); mAllocator.setFragmentReserve(kCommandHeaderSize); pushNewCommandBlock(mAllocator.allocate(0)); mAllocator.setListener(this); } void SharedCommandBlockPool::detachAllocator(SharedCommandMemoryAllocator *destination) { ASSERT(destination); RingBufferAllocator &destinationOut = destination->get(); ASSERT(!destinationOut.valid()); ASSERT(mAllocator.valid()); mAllocator.setListener(nullptr); finishLastCommandBlock(); if (mFinishedCommandSize == 0) { mCommandBuffer->clearCommands(); } else { mAllocator.setFragmentReserve(0); (void)mAllocator.allocate(sizeof(kCommandHeaderSize)); } destinationOut = std::move(mAllocator); } void SharedCommandBlockPool::pushNewCommandBlock(uint8_t *block) { mLastCommandBlock = block; mCommandBuffer->pushToCommands(block); } void SharedCommandBlockPool::finishLastCommandBlock() { mFinishedCommandSize = getCommandSize(); terminateLastCommandBlock(); mLastCommandBlock = nullptr; } void SharedCommandBlockPool::onRingBufferNewFragment() { pushNewCommandBlock(mAllocator.getPointer()); } void SharedCommandBlockPool::onRingBufferFragmentEnd() { finishLastCommandBlock(); } void SharedCommandBlockPool::getMemoryUsageStats(size_t *usedMemoryOut, size_t *allocatedMemoryOut) const { *usedMemoryOut = getCommandSize(); *allocatedMemoryOut = getCommandSize(); } } // namespace vk } // namespace rx