Commit 01f7e545 by Jamie Madill Committed by Commit Bot

Vulkan: Make SharedResourceUse a custom type.

Gives us better performance when using the command graph. Performance regressed significantly in "Vulkan: Track resource usage via counter." Perf test scores: before CL: 1060 after CL: 1245 this CL: 1085 The small remaining regression can be investigated more fully in the future. It's possible there is some small acceptable regression when switching the command graph design for multithreading. Test: angle_perftests (DrawCall*vulkan_null*manyvbos*) Bug: angleproject:2464 Change-Id: I5e625999a8e8b3e1a045908c51e549f472cd4209 Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/1817102Reviewed-by: 's avatarTim Van Patten <timvp@google.com> Reviewed-by: 's avatarGeoff Lang <geofflang@chromium.org> Commit-Queue: Jamie Madill <jmadill@chromium.org>
parent 3c049a34
...@@ -240,21 +240,26 @@ float CalculateSecondaryCommandBufferPoolWaste(const std::vector<CommandGraphNod ...@@ -240,21 +240,26 @@ float CalculateSecondaryCommandBufferPoolWaste(const std::vector<CommandGraphNod
// CommandGraphResource implementation. // CommandGraphResource implementation.
CommandGraphResource::CommandGraphResource(CommandGraphResourceType resourceType) CommandGraphResource::CommandGraphResource(CommandGraphResourceType resourceType)
: mUse(new ResourceUse), mCurrentWritingNode(nullptr), mResourceType(resourceType) : mCurrentWritingNode(nullptr), mResourceType(resourceType)
{} {
mUse.init();
}
CommandGraphResource::~CommandGraphResource() = default; CommandGraphResource::~CommandGraphResource()
{
mUse.release();
}
bool CommandGraphResource::isResourceInUse(ContextVk *contextVk) const bool CommandGraphResource::isResourceInUse(ContextVk *contextVk) const
{ {
return mUse->counter > 0 || contextVk->isSerialInUse(mUse->serial); return mUse.getCounter() > 1 || contextVk->isSerialInUse(mUse.getSerial());
} }
void CommandGraphResource::resetQueueSerial() void CommandGraphResource::resetQueueSerial()
{ {
mCurrentWritingNode = nullptr; mCurrentWritingNode = nullptr;
mCurrentReadingNodes.clear(); mCurrentReadingNodes.clear();
mUse->serial = Serial(); mUse.resetSerial();
} }
angle::Result CommandGraphResource::recordCommands(ContextVk *context, angle::Result CommandGraphResource::recordCommands(ContextVk *context,
...@@ -1230,14 +1235,21 @@ void CommandGraph::addDependenciesToNextBarrier(size_t begin, ...@@ -1230,14 +1235,21 @@ void CommandGraph::addDependenciesToNextBarrier(size_t begin,
} }
} }
void CommandGraph::releaseResourceUses()
{
for (SharedResourceUse &use : mResourceUses)
{
use.release();
}
mResourceUses.clear();
}
void CommandGraph::releaseResourceUsesAndUpdateSerials(Serial serial) void CommandGraph::releaseResourceUsesAndUpdateSerials(Serial serial)
{ {
for (SharedResourceUse &use : mResourceUses) for (SharedResourceUse &use : mResourceUses)
{ {
ASSERT(use->counter > 0); use.releaseAndUpdateSerial(serial);
use->counter--;
ASSERT(use->serial <= serial);
use->serial = serial;
} }
mResourceUses.clear(); mResourceUses.clear();
......
...@@ -283,7 +283,84 @@ struct ResourceUse ...@@ -283,7 +283,84 @@ struct ResourceUse
Serial serial; Serial serial;
}; };
using SharedResourceUse = std::shared_ptr<ResourceUse>; class SharedResourceUse final : angle::NonCopyable
{
public:
SharedResourceUse() : mUse(nullptr) {}
~SharedResourceUse() { ASSERT(!valid()); }
SharedResourceUse(SharedResourceUse &&rhs) : mUse(rhs.mUse) { rhs.mUse = nullptr; }
SharedResourceUse &operator=(SharedResourceUse &&rhs)
{
std::swap(mUse, rhs.mUse);
return *this;
}
ANGLE_INLINE bool valid() const { return mUse != nullptr; }
void init()
{
ASSERT(!mUse);
mUse = new ResourceUse;
mUse->counter++;
}
ANGLE_INLINE void release()
{
ASSERT(valid());
ASSERT(mUse->counter > 0);
if (--mUse->counter == 0)
{
delete mUse;
}
mUse = nullptr;
}
ANGLE_INLINE void releaseAndUpdateSerial(Serial serial)
{
ASSERT(valid());
ASSERT(mUse->counter > 0);
ASSERT(mUse->serial <= serial);
mUse->serial = serial;
release();
}
ANGLE_INLINE void set(const SharedResourceUse &rhs)
{
ASSERT(rhs.valid());
ASSERT(!valid());
ASSERT(rhs.mUse->counter < std::numeric_limits<uint32_t>::max());
mUse = rhs.mUse;
mUse->counter++;
}
ANGLE_INLINE Serial getSerial() const
{
ASSERT(valid());
return mUse->serial;
}
ANGLE_INLINE void updateSerial(Serial serial)
{
ASSERT(valid());
ASSERT(mUse->serial < serial);
mUse->serial = serial;
}
ANGLE_INLINE void resetSerial()
{
ASSERT(valid());
mUse->serial = Serial();
}
ANGLE_INLINE uint32_t getCounter() const
{
ASSERT(valid());
return mUse->counter;
}
private:
ResourceUse *mUse;
};
// This is a helper class for back-end objects used in Vk command buffers. It records a serial // This is a helper class for back-end objects used in Vk command buffers. It records a serial
// at command recording times indicating an order in the queue. We use Fences to detect when // at command recording times indicating an order in the queue. We use Fences to detect when
...@@ -301,7 +378,7 @@ class CommandGraphResource : angle::NonCopyable ...@@ -301,7 +378,7 @@ class CommandGraphResource : angle::NonCopyable
// Get the current queue serial for this resource. Used to release resources, and for // Get the current queue serial for this resource. Used to release resources, and for
// queries, to know if the queue they are submitted on has finished execution. // queries, to know if the queue they are submitted on has finished execution.
Serial getStoredQueueSerial() const { return mUse->serial; } Serial getStoredQueueSerial() const { return mUse.getSerial(); }
// Sets up dependency relations. 'this' resource is the resource being written to. // Sets up dependency relations. 'this' resource is the resource being written to.
void addWriteDependency(ContextVk *contextVk, CommandGraphResource *writingResource); void addWriteDependency(ContextVk *contextVk, CommandGraphResource *writingResource);
...@@ -448,6 +525,7 @@ class CommandGraph final : angle::NonCopyable ...@@ -448,6 +525,7 @@ class CommandGraph final : angle::NonCopyable
void makeHostVisibleBufferWriteAvailable(); void makeHostVisibleBufferWriteAvailable();
void onResourceUse(const SharedResourceUse &resourceUse); void onResourceUse(const SharedResourceUse &resourceUse);
void releaseResourceUses();
private: private:
CommandGraphNode *allocateBarrierNode(CommandGraphNodeFunction function, CommandGraphNode *allocateBarrierNode(CommandGraphNodeFunction function,
...@@ -525,16 +603,14 @@ ANGLE_INLINE bool CommandGraphResource::hasStartedRenderPass() const ...@@ -525,16 +603,14 @@ ANGLE_INLINE bool CommandGraphResource::hasStartedRenderPass() const
ANGLE_INLINE void CommandGraphResource::onGraphAccess(Serial serial, CommandGraph *commandGraph) ANGLE_INLINE void CommandGraphResource::onGraphAccess(Serial serial, CommandGraph *commandGraph)
{ {
ASSERT(serial >= mUse->serial);
// Store reference to usage in graph. // Store reference to usage in graph.
commandGraph->onResourceUse(mUse); commandGraph->onResourceUse(mUse);
if (serial > mUse->serial) if (serial > mUse.getSerial())
{ {
mCurrentWritingNode = nullptr; mCurrentWritingNode = nullptr;
mCurrentReadingNodes.clear(); mCurrentReadingNodes.clear();
mUse->serial = serial; mUse.updateSerial(serial);
} }
} }
...@@ -632,9 +708,9 @@ ANGLE_INLINE bool CommandGraphResource::hasChildlessWritingNode() const ...@@ -632,9 +708,9 @@ ANGLE_INLINE bool CommandGraphResource::hasChildlessWritingNode() const
// CommandGraph inlines. // CommandGraph inlines.
ANGLE_INLINE void CommandGraph::onResourceUse(const SharedResourceUse &resourceUse) ANGLE_INLINE void CommandGraph::onResourceUse(const SharedResourceUse &resourceUse)
{ {
ASSERT(resourceUse->counter < std::numeric_limits<uint32_t>::max()); SharedResourceUse newUse;
resourceUse->counter++; newUse.set(resourceUse);
mResourceUses.push_back(resourceUse); mResourceUses.emplace_back(std::move(newUse));
} }
} // namespace vk } // namespace vk
} // namespace rx } // namespace rx
......
...@@ -336,6 +336,8 @@ void ContextVk::onDestroy(const gl::Context *context) ...@@ -336,6 +336,8 @@ void ContextVk::onDestroy(const gl::Context *context)
(void)finishImpl(); (void)finishImpl();
} }
mCommandGraph.releaseResourceUses();
mUtils.destroy(device); mUtils.destroy(device);
mRenderPassCache.destroy(device); mRenderPassCache.destroy(device);
...@@ -2824,11 +2826,6 @@ vk::Shared<vk::Fence> ContextVk::getLastSubmittedFence() const ...@@ -2824,11 +2826,6 @@ vk::Shared<vk::Fence> ContextVk::getLastSubmittedFence() const
return fence; return fence;
} }
vk::CommandGraph *ContextVk::getCommandGraph()
{
return &mCommandGraph;
}
angle::Result ContextVk::getTimestamp(uint64_t *timestampOut) angle::Result ContextVk::getTimestamp(uint64_t *timestampOut)
{ {
// The intent of this function is to query the timestamp without stalling the GPU. Currently, // The intent of this function is to query the timestamp without stalling the GPU. Currently,
......
...@@ -302,7 +302,7 @@ class ContextVk : public ContextImpl, public vk::Context, public vk::RenderPassO ...@@ -302,7 +302,7 @@ class ContextVk : public ContextImpl, public vk::Context, public vk::RenderPassO
vk::Shared<vk::Fence> getLastSubmittedFence() const; vk::Shared<vk::Fence> getLastSubmittedFence() const;
// This should only be called from ResourceVk. // This should only be called from ResourceVk.
vk::CommandGraph *getCommandGraph(); vk::CommandGraph *getCommandGraph() { return &mCommandGraph; }
vk::ShaderLibrary &getShaderLibrary() { return mShaderLibrary; } vk::ShaderLibrary &getShaderLibrary() { return mShaderLibrary; }
UtilsVk &getUtils() { return mUtils; } UtilsVk &getUtils() { return mUtils; }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment