Vulkan: Remove "current queue serial".

Queries, semaphores, and pipelines instead use the normal
vk::Resource design to track their lifetimes. Removes the current
serial APIs from all classes. Current serials are still tracked
internally in the command queue classes.

Bug: b/169788986
Change-Id: Idcd2c2a93bc8225c6f3f7c247eb8fcfb76be1030
Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/3223644
Reviewed-by: Shahbaz Youssefi <syoussefi@chromium.org>
Reviewed-by: Tim Van Patten <timvp@google.com>
Commit-Queue: Jamie Madill <jmadill@chromium.org>
This commit is contained in:
Jamie Madill 2021-10-14 17:01:45 -04:00 коммит произвёл Angle LUCI CQ
Родитель 5da062baf1
Коммит 191c236a6b
11 изменённых файлов: 164 добавлений и 170 удалений

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

@ -590,12 +590,6 @@ Serial CommandProcessor::getLastCompletedQueueSerial() const
return mCommandQueue.getLastCompletedQueueSerial();
}
Serial CommandProcessor::getCurrentQueueSerial() const
{
std::lock_guard<std::mutex> lock(mQueueSerialMutex);
return mCommandQueue.getCurrentQueueSerial();
}
bool CommandProcessor::isBusy() const
{
std::lock_guard<std::mutex> serialLock(mQueueSerialMutex);
@ -1247,11 +1241,6 @@ Serial CommandQueue::getLastCompletedQueueSerial() const
return mLastCompletedQueueSerial;
}
Serial CommandQueue::getCurrentQueueSerial() const
{
return mCurrentQueueSerial;
}
bool CommandQueue::isBusy() const
{
return mLastSubmittedQueueSerial > mLastCompletedQueueSerial;

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

@ -320,7 +320,6 @@ class CommandQueueInterface : angle::NonCopyable
virtual angle::Result ensureNoPendingWork(Context *context) = 0;
virtual Serial getLastCompletedQueueSerial() const = 0;
virtual Serial getCurrentQueueSerial() const = 0;
virtual bool isBusy() const = 0;
};
@ -381,7 +380,6 @@ class CommandQueue final : public CommandQueueInterface
angle::Result ensureNoPendingWork(Context *context) override { return angle::Result::Continue; }
Serial getLastCompletedQueueSerial() const override;
Serial getCurrentQueueSerial() const override;
bool isBusy() const override;
angle::Result queueSubmit(Context *context,
@ -528,7 +526,6 @@ class CommandProcessor : public Context, public CommandQueueInterface
angle::Result ensureNoPendingWork(Context *context) override;
Serial getLastCompletedQueueSerial() const override;
Serial getCurrentQueueSerial() const override;
bool isBusy() const override;
egl::ContextPriority getDriverPriority(egl::ContextPriority priority)

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

@ -1387,9 +1387,8 @@ angle::Result ContextVk::handleDirtyGraphicsPipelineDesc(DirtyBits::Iterator *di
}
// Update the queue serial for the pipeline object.
ASSERT(mCurrentGraphicsPipeline && mCurrentGraphicsPipeline->valid());
// TODO: https://issuetracker.google.com/issues/169788986: Need to change this so that we get
// the actual serial used when this work is submitted.
mCurrentGraphicsPipeline->updateSerial(getCurrentQueueSerial());
mCurrentGraphicsPipeline->retain(&mResourceUseList);
const VkPipeline newPipeline = mCurrentGraphicsPipeline->getPipeline().getHandle();
@ -1472,10 +1471,8 @@ angle::Result ContextVk::handleDirtyComputePipelineBinding()
ASSERT(mCurrentComputePipeline);
mOutsideRenderPassCommands->getCommandBuffer().bindComputePipeline(
mCurrentComputePipeline->get());
// TODO: https://issuetracker.google.com/issues/169788986: Need to change this so that we get
// the actual serial used when this work is submitted.
mCurrentComputePipeline->updateSerial(getCurrentQueueSerial());
mCurrentComputePipeline->getPipeline());
mCurrentComputePipeline->retain(&mResourceUseList);
return angle::Result::Continue;
}

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

@ -407,7 +407,6 @@ class ContextVk : public ContextImpl, public vk::Context, public MultisampleText
const vk::CommandPool &getCommandPool() const;
Serial getCurrentQueueSerial() const { return mRenderer->getCurrentQueueSerial(); }
Serial getLastCompletedQueueSerial() const { return mRenderer->getLastCompletedQueueSerial(); }
bool isSerialInUse(Serial serial) const;
@ -977,7 +976,7 @@ class ContextVk : public ContextImpl, public vk::Context, public MultisampleText
vk::CommandBuffer *mRenderPassCommandBuffer;
vk::PipelineHelper *mCurrentGraphicsPipeline;
vk::PipelineAndSerial *mCurrentComputePipeline;
vk::PipelineHelper *mCurrentComputePipeline;
gl::PrimitiveMode mCurrentDrawMode;
WindowSurfaceVk *mCurrentWindowSurface;
@ -991,7 +990,7 @@ class ContextVk : public ContextImpl, public vk::Context, public MultisampleText
std::unique_ptr<vk::GraphicsPipelineDesc> mGraphicsPipelineDesc;
vk::GraphicsPipelineTransitionBits mGraphicsPipelineTransition;
// These pools are externally sychronized, so cannot be accessed from different
// These pools are externally synchronized, so cannot be accessed from different
// threads simultaneously. Hence, we keep them in the ContextVk instead of the RendererVk.
// Note that this implementation would need to change in shared resource scenarios. Likely
// we'd instead share a single set of pools between the share groups.

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

@ -890,7 +890,7 @@ angle::Result ProgramExecutableVk::getGraphicsPipeline(
}
angle::Result ProgramExecutableVk::getComputePipeline(ContextVk *contextVk,
vk::PipelineAndSerial **pipelineOut)
vk::PipelineHelper **pipelineOut)
{
const gl::State &glState = contextVk->getState();
const gl::ProgramExecutable *glExecutable = glState.getProgramExecutable();

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

@ -150,7 +150,7 @@ class ProgramExecutableVk
const vk::GraphicsPipelineDesc **descPtrOut,
vk::PipelineHelper **pipelineOut);
angle::Result getComputePipeline(ContextVk *contextVk, vk::PipelineAndSerial **pipelineOut);
angle::Result getComputePipeline(ContextVk *contextVk, vk::PipelineHelper **pipelineOut);
const vk::PipelineLayout &getPipelineLayout() const { return mPipelineLayout.get(); }
angle::Result createPipelineLayout(ContextVk *contextVk,

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

@ -339,19 +339,6 @@ class RendererVk : angle::NonCopyable
uint64_t getMaxFenceWaitTimeNs() const;
ANGLE_INLINE Serial getCurrentQueueSerial()
{
if (mFeatures.asyncCommandQueue.enabled)
{
return mCommandProcessor.getCurrentQueueSerial();
}
else
{
std::lock_guard<std::mutex> lock(mCommandQueueMutex);
return mCommandQueue.getCurrentQueueSerial();
}
}
ANGLE_INLINE Serial getLastCompletedQueueSerial()
{
if (mFeatures.asyncCommandQueue.enabled)

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

@ -1453,16 +1453,13 @@ angle::Result UtilsVk::setupProgram(ContextVk *contextVk,
const vk::BindingPointer<vk::PipelineLayout> &pipelineLayout = mPipelineLayouts[function];
Serial serial = contextVk->getCurrentQueueSerial();
if (isCompute)
{
vk::PipelineAndSerial *pipelineAndSerial;
vk::PipelineHelper *pipeline;
program->setShader(gl::ShaderType::Compute, fsCsShader);
ANGLE_TRY(program->getComputePipeline(contextVk, pipelineLayout.get(), &pipelineAndSerial));
// TODO: https://issuetracker.google.com/issues/169788986: Update serial handling.
pipelineAndSerial->updateSerial(serial);
commandBuffer->bindComputePipeline(pipelineAndSerial->get());
ANGLE_TRY(program->getComputePipeline(contextVk, pipelineLayout.get(), &pipeline));
pipeline->retain(&contextVk->getResourceUseList());
commandBuffer->bindComputePipeline(pipeline->getPipeline());
contextVk->invalidateComputePipelineBinding();
}
@ -1482,7 +1479,7 @@ angle::Result UtilsVk::setupProgram(ContextVk *contextVk,
ANGLE_TRY(program->getGraphicsPipeline(
contextVk, &contextVk->getRenderPassCache(), *pipelineCache, pipelineLayout.get(),
*pipelineDesc, gl::AttributesMask(), gl::ComponentTypeMask(), &descPtr, &helper));
helper->updateSerial(serial);
helper->retain(&contextVk->getResourceUseList());
commandBuffer->bindGraphicsPipeline(helper->getPipeline());
contextVk->invalidateGraphicsPipelineBinding();

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

@ -13,6 +13,7 @@
#include "common/Color.h"
#include "common/FixedVector.h"
#include "libANGLE/renderer/vulkan/ResourceVk.h"
#include "libANGLE/renderer/vulkan/vk_utils.h"
namespace rx
@ -52,8 +53,6 @@ class DynamicDescriptorPool;
class ImageHelper;
enum class ImageLayout;
using PipelineAndSerial = ObjectAndSerial<Pipeline>;
using RefCountedDescriptorSetLayout = RefCounted<DescriptorSetLayout>;
using RefCountedPipelineLayout = RefCounted<PipelineLayout>;
using RefCountedSamplerYcbcrConversion = RefCounted<SamplerYcbcrConversion>;
@ -964,18 +963,16 @@ ANGLE_INLINE bool GraphicsPipelineTransitionMatch(GraphicsPipelineTransitionBits
return true;
}
class PipelineHelper final : angle::NonCopyable
class PipelineHelper final : public Resource
{
public:
PipelineHelper();
~PipelineHelper();
~PipelineHelper() override;
inline explicit PipelineHelper(Pipeline &&pipeline);
void destroy(VkDevice device);
void updateSerial(Serial serial) { mSerial = serial; }
bool valid() const { return mPipeline.valid(); }
Serial getSerial() const { return mSerial; }
Pipeline &getPipeline() { return mPipeline; }
ANGLE_INLINE bool findTransition(GraphicsPipelineTransitionBits bits,
@ -1001,7 +998,6 @@ class PipelineHelper final : angle::NonCopyable
private:
std::vector<GraphicsPipelineTransition> mTransitions;
Serial mSerial;
Pipeline mPipeline;
};

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

@ -4,7 +4,7 @@
// found in the LICENSE file.
//
// vk_helpers:
// Helper utilitiy classes that manage Vulkan resources.
// Helper utility classes that manage Vulkan resources.
#include "libANGLE/renderer/vulkan/vk_helpers.h"
#include "libANGLE/renderer/driver_utils.h"
@ -2721,31 +2721,35 @@ DynamicallyGrowingPool<Pool>::~DynamicallyGrowingPool() = default;
template <typename Pool>
angle::Result DynamicallyGrowingPool<Pool>::initEntryPool(Context *contextVk, uint32_t poolSize)
{
ASSERT(mPools.empty() && mPoolStats.empty());
mPoolSize = poolSize;
ASSERT(mPools.empty());
mPoolSize = poolSize;
mCurrentFreeEntry = poolSize;
return angle::Result::Continue;
}
template <typename Pool>
void DynamicallyGrowingPool<Pool>::destroyEntryPool()
void DynamicallyGrowingPool<Pool>::destroyEntryPool(VkDevice device)
{
for (PoolResource &resource : mPools)
{
destroyPoolImpl(device, resource.pool);
}
mPools.clear();
mPoolStats.clear();
}
template <typename Pool>
bool DynamicallyGrowingPool<Pool>::findFreeEntryPool(ContextVk *contextVk)
{
Serial lastCompletedQueueSerial = contextVk->getLastCompletedQueueSerial();
for (size_t i = 0; i < mPools.size(); ++i)
for (size_t poolIndex = 0; poolIndex < mPools.size(); ++poolIndex)
{
if (mPoolStats[i].freedCount == mPoolSize &&
mPoolStats[i].serial <= lastCompletedQueueSerial)
PoolResource &pool = mPools[poolIndex];
if (pool.freedCount == mPoolSize && !pool.isCurrentlyInUse(lastCompletedQueueSerial))
{
mCurrentPool = i;
mCurrentPool = poolIndex;
mCurrentFreeEntry = 0;
mPoolStats[i].freedCount = 0;
pool.freedCount = 0;
return true;
}
@ -2757,10 +2761,7 @@ bool DynamicallyGrowingPool<Pool>::findFreeEntryPool(ContextVk *contextVk)
template <typename Pool>
angle::Result DynamicallyGrowingPool<Pool>::allocateNewEntryPool(ContextVk *contextVk, Pool &&pool)
{
mPools.push_back(std::move(pool));
PoolStats poolStats = {0, Serial()};
mPoolStats.push_back(poolStats);
mPools.emplace_back(std::move(pool), 0);
mCurrentPool = mPools.size() - 1;
mCurrentFreeEntry = 0;
@ -2771,13 +2772,45 @@ angle::Result DynamicallyGrowingPool<Pool>::allocateNewEntryPool(ContextVk *cont
template <typename Pool>
void DynamicallyGrowingPool<Pool>::onEntryFreed(ContextVk *contextVk, size_t poolIndex)
{
ASSERT(poolIndex < mPoolStats.size() && mPoolStats[poolIndex].freedCount < mPoolSize);
// Take note of the current serial to avoid reallocating a query in the same pool
mPoolStats[poolIndex].serial = contextVk->getCurrentQueueSerial();
++mPoolStats[poolIndex].freedCount;
ASSERT(poolIndex < mPools.size() && mPools[poolIndex].freedCount < mPoolSize);
mPools[poolIndex].retain(&contextVk->getResourceUseList());
++mPools[poolIndex].freedCount;
}
template <typename Pool>
angle::Result DynamicallyGrowingPool<Pool>::allocatePoolEntries(ContextVk *contextVk,
uint32_t entryCount,
uint32_t *poolIndex,
uint32_t *currentEntryOut)
{
if (mCurrentFreeEntry + entryCount > mPoolSize)
{
if (!findFreeEntryPool(contextVk))
{
Pool newPool;
ANGLE_TRY(allocatePoolImpl(contextVk, newPool, mPoolSize));
ANGLE_TRY(allocateNewEntryPool(contextVk, std::move(newPool)));
}
}
*poolIndex = static_cast<uint32_t>(mCurrentPool);
*currentEntryOut = mCurrentFreeEntry;
mCurrentFreeEntry += entryCount;
return angle::Result::Continue;
}
template <typename Pool>
DynamicallyGrowingPool<Pool>::PoolResource::PoolResource(Pool &&poolIn, uint32_t freedCountIn)
: pool(std::move(poolIn)), freedCount(freedCountIn)
{}
template <typename Pool>
DynamicallyGrowingPool<Pool>::PoolResource::PoolResource(PoolResource &&other)
: pool(std::move(other.pool)), freedCount(other.freedCount)
{}
// DynamicQueryPool implementation
DynamicQueryPool::DynamicQueryPool() = default;
@ -2786,21 +2819,18 @@ DynamicQueryPool::~DynamicQueryPool() = default;
angle::Result DynamicQueryPool::init(ContextVk *contextVk, VkQueryType type, uint32_t poolSize)
{
ANGLE_TRY(initEntryPool(contextVk, poolSize));
mQueryType = type;
ANGLE_TRY(allocateNewPool(contextVk));
return angle::Result::Continue;
}
void DynamicQueryPool::destroy(VkDevice device)
{
for (QueryPool &queryPool : mPools)
{
queryPool.destroy(device);
}
destroyEntryPool(device);
}
destroyEntryPool();
void DynamicQueryPool::destroyPoolImpl(VkDevice device, QueryPool &poolToDestroy)
{
poolToDestroy.destroy(device);
}
angle::Result DynamicQueryPool::allocateQuery(ContextVk *contextVk,
@ -2809,17 +2839,32 @@ angle::Result DynamicQueryPool::allocateQuery(ContextVk *contextVk,
{
ASSERT(!queryOut->valid());
if (mCurrentFreeEntry + queryCount > mPoolSize)
uint32_t currentPool = 0;
uint32_t queryIndex = 0;
ANGLE_TRY(allocatePoolEntries(contextVk, queryCount, &currentPool, &queryIndex));
queryOut->init(this, currentPool, queryIndex, queryCount);
return angle::Result::Continue;
}
angle::Result DynamicQueryPool::allocatePoolImpl(ContextVk *contextVk,
QueryPool &poolToAllocate,
uint32_t entriesToAllocate)
{
VkQueryPoolCreateInfo queryPoolInfo = {};
queryPoolInfo.sType = VK_STRUCTURE_TYPE_QUERY_POOL_CREATE_INFO;
queryPoolInfo.flags = 0;
queryPoolInfo.queryType = this->mQueryType;
queryPoolInfo.queryCount = entriesToAllocate;
queryPoolInfo.pipelineStatistics = 0;
if (this->mQueryType == VK_QUERY_TYPE_PIPELINE_STATISTICS)
{
// No more queries left in this pool, create another one.
ANGLE_TRY(allocateNewPool(contextVk));
queryPoolInfo.pipelineStatistics = VK_QUERY_PIPELINE_STATISTIC_CLIPPING_INVOCATIONS_BIT;
}
uint32_t queryIndex = mCurrentFreeEntry;
mCurrentFreeEntry += queryCount;
queryOut->init(this, mCurrentPool, queryIndex, queryCount);
ANGLE_VK_TRY(contextVk, poolToAllocate.init(contextVk->getDevice(), queryPoolInfo));
return angle::Result::Continue;
}
@ -2836,32 +2881,6 @@ void DynamicQueryPool::freeQuery(ContextVk *contextVk, QueryHelper *query)
}
}
angle::Result DynamicQueryPool::allocateNewPool(ContextVk *contextVk)
{
if (findFreeEntryPool(contextVk))
{
return angle::Result::Continue;
}
VkQueryPoolCreateInfo queryPoolInfo = {};
queryPoolInfo.sType = VK_STRUCTURE_TYPE_QUERY_POOL_CREATE_INFO;
queryPoolInfo.flags = 0;
queryPoolInfo.queryType = mQueryType;
queryPoolInfo.queryCount = mPoolSize;
queryPoolInfo.pipelineStatistics = 0;
if (mQueryType == VK_QUERY_TYPE_PIPELINE_STATISTICS)
{
queryPoolInfo.pipelineStatistics = VK_QUERY_PIPELINE_STATISTIC_CLIPPING_INVOCATIONS_BIT;
}
QueryPool queryPool;
ANGLE_VK_TRY(contextVk, queryPool.init(contextVk->getDevice(), queryPoolInfo));
return allocateNewEntryPool(contextVk, std::move(queryPool));
}
// QueryResult implementation
void QueryResult::setResults(uint64_t *results, uint32_t queryCount)
{
@ -3113,21 +3132,12 @@ DynamicSemaphorePool::~DynamicSemaphorePool() = default;
angle::Result DynamicSemaphorePool::init(ContextVk *contextVk, uint32_t poolSize)
{
ANGLE_TRY(initEntryPool(contextVk, poolSize));
ANGLE_TRY(allocateNewPool(contextVk));
return angle::Result::Continue;
}
void DynamicSemaphorePool::destroy(VkDevice device)
{
for (auto &semaphorePool : mPools)
{
for (Semaphore &semaphore : semaphorePool)
{
semaphore.destroy(device);
}
}
destroyEntryPool();
destroyEntryPool(device);
}
angle::Result DynamicSemaphorePool::allocateSemaphore(ContextVk *contextVk,
@ -3135,13 +3145,11 @@ angle::Result DynamicSemaphorePool::allocateSemaphore(ContextVk *contextVk,
{
ASSERT(!semaphoreOut->getSemaphore());
if (mCurrentFreeEntry >= mPoolSize)
{
// No more queries left in this pool, create another one.
ANGLE_TRY(allocateNewPool(contextVk));
}
uint32_t currentPool = 0;
uint32_t currentEntry = 0;
ANGLE_TRY(allocatePoolEntries(contextVk, 1, &currentPool, &currentEntry));
semaphoreOut->init(mCurrentPool, &mPools[mCurrentPool][mCurrentFreeEntry++]);
semaphoreOut->init(currentPool, &getPool(currentPool)[currentEntry]);
return angle::Result::Continue;
}
@ -3155,31 +3163,26 @@ void DynamicSemaphorePool::freeSemaphore(ContextVk *contextVk, SemaphoreHelper *
}
}
angle::Result DynamicSemaphorePool::allocateNewPool(ContextVk *contextVk)
angle::Result DynamicSemaphorePool::allocatePoolImpl(ContextVk *contextVk,
std::vector<Semaphore> &poolToAllocate,
uint32_t entriesToAllocate)
{
if (findFreeEntryPool(contextVk))
{
return angle::Result::Continue;
}
std::vector<Semaphore> newPool(mPoolSize);
for (Semaphore &semaphore : newPool)
poolToAllocate.resize(entriesToAllocate);
for (Semaphore &semaphore : poolToAllocate)
{
ANGLE_VK_TRY(contextVk, semaphore.init(contextVk->getDevice()));
}
// This code is safe as long as the growth of the outer vector in vector<vector<T>> is done by
// moving the inner vectors, making sure references to the inner vector remain intact.
Semaphore *assertMove = mPools.size() > 0 ? mPools[0].data() : nullptr;
ANGLE_TRY(allocateNewEntryPool(contextVk, std::move(newPool)));
ASSERT(assertMove == nullptr || assertMove == mPools[0].data());
return angle::Result::Continue;
}
void DynamicSemaphorePool::destroyPoolImpl(VkDevice device, std::vector<Semaphore> &poolToDestroy)
{
for (Semaphore &semaphore : poolToDestroy)
{
semaphore.destroy(device);
}
}
// SemaphoreHelper implementation
SemaphoreHelper::SemaphoreHelper() : mSemaphorePoolIndex(0), mSemaphore(0) {}
@ -8336,7 +8339,7 @@ void ShaderProgramHelper::destroy(RendererVk *rendererVk)
void ShaderProgramHelper::release(ContextVk *contextVk)
{
mGraphicsPipelines.release(contextVk);
contextVk->addGarbage(&mComputePipeline.get());
contextVk->addGarbage(&mComputePipeline.getPipeline());
for (BindingPointer<ShaderAndSerial> &shader : mShaders)
{
shader.reset();
@ -8374,7 +8377,7 @@ void ShaderProgramHelper::setSpecializationConstant(sh::vk::SpecializationConsta
angle::Result ShaderProgramHelper::getComputePipeline(Context *context,
const PipelineLayout &pipelineLayout,
PipelineAndSerial **pipelineOut)
PipelineHelper **pipelineOut)
{
if (mComputePipeline.valid())
{
@ -8403,8 +8406,8 @@ angle::Result ShaderProgramHelper::getComputePipeline(Context *context,
PipelineCache *pipelineCache = nullptr;
ANGLE_TRY(renderer->getPipelineCache(&pipelineCache));
ANGLE_VK_TRY(context, mComputePipeline.get().initCompute(context->getDevice(), createInfo,
*pipelineCache));
ANGLE_VK_TRY(context, mComputePipeline.getPipeline().initCompute(context->getDevice(),
createInfo, *pipelineCache));
*pipelineOut = &mComputePipeline;
return angle::Result::Continue;

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

@ -4,16 +4,17 @@
// found in the LICENSE file.
//
// vk_helpers:
// Helper utilitiy classes that manage Vulkan resources.
// Helper utility classes that manage Vulkan resources.
#ifndef LIBANGLE_RENDERER_VULKAN_VK_HELPERS_H_
#define LIBANGLE_RENDERER_VULKAN_VK_HELPERS_H_
#include "common/MemoryBuffer.h"
#include "libANGLE/renderer/vulkan/ResourceVk.h"
#include "libANGLE/renderer/vulkan/vk_cache_utils.h"
#include "libANGLE/renderer/vulkan/vk_format_utils.h"
#include <functional>
namespace gl
{
class ImageIndex;
@ -358,7 +359,9 @@ class DynamicallyGrowingPool : angle::NonCopyable
protected:
angle::Result initEntryPool(Context *contextVk, uint32_t poolSize);
void destroyEntryPool();
virtual void destroyPoolImpl(VkDevice device, Pool &poolToDestroy) = 0;
void destroyEntryPool(VkDevice device);
// Checks to see if any pool is already free, in which case it sets it as current pool and
// returns true.
@ -370,24 +373,46 @@ class DynamicallyGrowingPool : angle::NonCopyable
// Called by the implementation whenever an entry is freed.
void onEntryFreed(ContextVk *contextVk, size_t poolIndex);
const Pool &getPool(size_t index) const
{
return const_cast<DynamicallyGrowingPool *>(this)->getPool(index);
}
Pool &getPool(size_t index)
{
ASSERT(index < mPools.size());
return mPools[index].pool;
}
uint32_t getPoolSize() const { return mPoolSize; }
virtual angle::Result allocatePoolImpl(ContextVk *contextVk,
Pool &poolToAllocate,
uint32_t entriesToAllocate) = 0;
angle::Result allocatePoolEntries(ContextVk *contextVk,
uint32_t entryCount,
uint32_t *poolIndexOut,
uint32_t *currentEntryOut);
private:
// The pool size, to know when a pool is completely freed.
uint32_t mPoolSize;
std::vector<Pool> mPools;
struct PoolStats
struct PoolResource : public Resource
{
PoolResource(Pool &&poolIn, uint32_t freedCountIn);
PoolResource(PoolResource &&other);
Pool pool;
// A count corresponding to each pool indicating how many of its allocated entries
// have been freed. Once that value reaches mPoolSize for each pool, that pool is considered
// free and reusable. While keeping a bitset would allow allocation of each index, the
// slight runtime overhead of finding free indices is not worth the slight memory overhead
// of creating new pools when unnecessary.
uint32_t freedCount;
// The serial of the renderer is stored on each object free to make sure no
// new allocations are made from the pool until it's not in use.
Serial serial;
};
std::vector<PoolStats> mPoolStats;
std::vector<PoolResource> mPools;
// Index into mPools indicating pool we are currently allocating from.
size_t mCurrentPool;
@ -418,10 +443,13 @@ class DynamicQueryPool final : public DynamicallyGrowingPool<QueryPool>
angle::Result allocateQuery(ContextVk *contextVk, QueryHelper *queryOut, uint32_t queryCount);
void freeQuery(ContextVk *contextVk, QueryHelper *query);
const QueryPool &getQueryPool(size_t index) const { return mPools[index]; }
const QueryPool &getQueryPool(size_t index) const { return getPool(index); }
private:
angle::Result allocateNewPool(ContextVk *contextVk);
angle::Result allocatePoolImpl(ContextVk *contextVk,
QueryPool &poolToAllocate,
uint32_t entriesToAllocate) override;
void destroyPoolImpl(VkDevice device, QueryPool &poolToDestroy) override;
// Information required to create new query pools
VkQueryType mQueryType;
@ -545,15 +573,16 @@ class DynamicSemaphorePool final : public DynamicallyGrowingPool<std::vector<Sem
angle::Result init(ContextVk *contextVk, uint32_t poolSize);
void destroy(VkDevice device);
bool isValid() { return mPoolSize > 0; }
// autoFree can be used to allocate a semaphore that's expected to be freed at the end of the
// frame. This renders freeSemaphore unnecessary and saves an eventual search.
angle::Result allocateSemaphore(ContextVk *contextVk, SemaphoreHelper *semaphoreOut);
void freeSemaphore(ContextVk *contextVk, SemaphoreHelper *semaphore);
private:
angle::Result allocateNewPool(ContextVk *contextVk);
angle::Result allocatePoolImpl(ContextVk *contextVk,
std::vector<Semaphore> &poolToAllocate,
uint32_t entriesToAllocate) override;
void destroyPoolImpl(VkDevice device, std::vector<Semaphore> &poolToDestroy) override;
};
// Semaphores that are allocated from the semaphore pool are encapsulated in a helper object,
@ -2605,14 +2634,14 @@ class ShaderProgramHelper : angle::NonCopyable
angle::Result getComputePipeline(Context *context,
const PipelineLayout &pipelineLayout,
PipelineAndSerial **pipelineOut);
PipelineHelper **pipelineOut);
private:
ShaderAndSerialMap mShaders;
GraphicsPipelineCache mGraphicsPipelines;
// We should probably use PipelineHelper here so we can remove PipelineAndSerial.
PipelineAndSerial mComputePipeline;
PipelineHelper mComputePipeline;
// Specialization constants, currently only used by the graphics queue.
SpecializationConstants mSpecializationConstants;