зеркало из https://github.com/AvaloniaUI/angle.git
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:
Родитель
5da062baf1
Коммит
191c236a6b
|
@ -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, ¤tPool, &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, ¤tPool, ¤tEntry));
|
||||
|
||||
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;
|
||||
|
|
Загрузка…
Ссылка в новой задаче