Commit 3d61ac27 by Jamie Madill Committed by Commit Bot

Vulkan: More micro-optimizations.

Inlining more methods into headers. In total the patch series improves performance by about 60-70% in the Vulkan draw call overhead test. Bug: angleproject:2786 Change-Id: I70913ac6b3d5836c17c13e249950987df362f203 Reviewed-on: https://chromium-review.googlesource.com/1194883 Commit-Queue: Jamie Madill <jmadill@chromium.org> Reviewed-by: 's avatarFrank Henigman <fjhenigman@chromium.org>
parent 9137adea
...@@ -85,16 +85,6 @@ DrawCallParams::DrawCallParams(PrimitiveMode mode, GLenum type, const void *indi ...@@ -85,16 +85,6 @@ DrawCallParams::DrawCallParams(PrimitiveMode mode, GLenum type, const void *indi
{ {
} }
GLint DrawCallParams::firstVertex() const
{
// In some cases we can know the first vertex will be fixed at zero, if we're on the "fast
// path". In these cases the index range is not resolved. If the first vertex is not zero,
// however, then it must be because the index range is resolved. This only applies to the
// D3D11 back-end currently.
ASSERT(mFirstVertex == 0 || (!isDrawElements() || mIndexRange.valid()));
return mFirstVertex;
}
GLsizei DrawCallParams::indexCount() const GLsizei DrawCallParams::indexCount() const
{ {
ASSERT(isDrawElements()); ASSERT(isDrawElements());
......
...@@ -97,7 +97,15 @@ class DrawCallParams final : angle::NonCopyable ...@@ -97,7 +97,15 @@ class DrawCallParams final : angle::NonCopyable
PrimitiveMode mode() const { return mMode; } PrimitiveMode mode() const { return mMode; }
// This value is the sum of 'baseVertex' and the first indexed vertex for DrawElements calls. // This value is the sum of 'baseVertex' and the first indexed vertex for DrawElements calls.
GLint firstVertex() const; GLint firstVertex() const
{
// In some cases we can know the first vertex will be fixed at zero, if we're on the "fast
// path". In these cases the index range is not resolved. If the first vertex is not zero,
// however, then it must be because the index range is resolved. This only applies to the
// D3D11 back-end currently.
ASSERT(mFirstVertex == 0 || (!isDrawElements() || mIndexRange.valid()));
return mFirstVertex;
}
size_t vertexCount() const size_t vertexCount() const
{ {
......
...@@ -52,77 +52,6 @@ angle::Result InitAndBeginCommandBuffer(vk::Context *context, ...@@ -52,77 +52,6 @@ angle::Result InitAndBeginCommandBuffer(vk::Context *context,
} // anonymous namespace } // anonymous namespace
class CommandGraphNode final : angle::NonCopyable
{
public:
CommandGraphNode();
~CommandGraphNode();
// Immutable queries for when we're walking the commands tree.
CommandBuffer *getOutsideRenderPassCommands();
CommandBuffer *getInsideRenderPassCommands();
// For outside the render pass (copies, transitions, etc).
angle::Result beginOutsideRenderPassRecording(Context *context,
const CommandPool &commandPool,
CommandBuffer **commandsOut);
// For rendering commands (draws).
angle::Result beginInsideRenderPassRecording(Context *context, CommandBuffer **commandsOut);
// storeRenderPassInfo and append*RenderTarget store info relevant to the RenderPass.
void storeRenderPassInfo(const Framebuffer &framebuffer,
const gl::Rectangle renderArea,
const vk::RenderPassDesc &renderPassDesc,
const std::vector<VkClearValue> &clearValues);
// Dependency commands order node execution in the command graph.
// Once a node has commands that must happen after it, recording is stopped and the node is
// frozen forever.
static void SetHappensBeforeDependency(CommandGraphNode *beforeNode,
CommandGraphNode *afterNode);
static void SetHappensBeforeDependencies(const std::vector<CommandGraphNode *> &beforeNodes,
CommandGraphNode *afterNode);
bool hasParents() const;
bool hasChildren() const;
// Commands for traversing the node on a flush operation.
VisitedState visitedState() const;
void visitParents(std::vector<CommandGraphNode *> *stack);
angle::Result visitAndExecute(Context *context,
Serial serial,
RenderPassCache *renderPassCache,
CommandBuffer *primaryCommandBuffer);
const gl::Rectangle &getRenderPassRenderArea() const;
private:
void setHasChildren();
// Used for testing only.
bool isChildOf(CommandGraphNode *parent);
// Only used if we need a RenderPass for these commands.
RenderPassDesc mRenderPassDesc;
Framebuffer mRenderPassFramebuffer;
gl::Rectangle mRenderPassRenderArea;
gl::AttachmentArray<VkClearValue> mRenderPassClearValues;
// Keep a separate buffers for commands inside and outside a RenderPass.
// TODO(jmadill): We might not need inside and outside RenderPass commands separate.
CommandBuffer mOutsideRenderPassCommands;
CommandBuffer mInsideRenderPassCommands;
// Parents are commands that must be submitted before 'this' CommandNode can be submitted.
std::vector<CommandGraphNode *> mParents;
// If this is true, other commands exist that must be submitted after 'this' command.
bool mHasChildren;
// Used when traversing the dependency graph.
VisitedState mVisitedState;
};
// CommandGraphResource implementation. // CommandGraphResource implementation.
CommandGraphResource::CommandGraphResource() : mCurrentWritingNode(nullptr) CommandGraphResource::CommandGraphResource() : mCurrentWritingNode(nullptr)
{ {
...@@ -152,11 +81,6 @@ Serial CommandGraphResource::getStoredQueueSerial() const ...@@ -152,11 +81,6 @@ Serial CommandGraphResource::getStoredQueueSerial() const
return mStoredQueueSerial; return mStoredQueueSerial;
} }
bool CommandGraphResource::hasChildlessWritingNode() const
{
return (mCurrentWritingNode != nullptr && !mCurrentWritingNode->hasChildren());
}
bool CommandGraphResource::hasStartedWriteResource() const bool CommandGraphResource::hasStartedWriteResource() const
{ {
return hasChildlessWritingNode() && return hasChildlessWritingNode() &&
...@@ -210,11 +134,6 @@ bool CommandGraphResource::appendToStartedRenderPass(RendererVk *renderer, ...@@ -210,11 +134,6 @@ bool CommandGraphResource::appendToStartedRenderPass(RendererVk *renderer,
} }
} }
bool CommandGraphResource::hasStartedRenderPass() const
{
return hasChildlessWritingNode() && mCurrentWritingNode->getInsideRenderPassCommands()->valid();
}
const gl::Rectangle &CommandGraphResource::getRenderPassRenderArea() const const gl::Rectangle &CommandGraphResource::getRenderPassRenderArea() const
{ {
ASSERT(hasStartedRenderPass()); ASSERT(hasStartedRenderPass());
...@@ -306,12 +225,6 @@ CommandBuffer *CommandGraphNode::getOutsideRenderPassCommands() ...@@ -306,12 +225,6 @@ CommandBuffer *CommandGraphNode::getOutsideRenderPassCommands()
return &mOutsideRenderPassCommands; return &mOutsideRenderPassCommands;
} }
CommandBuffer *CommandGraphNode::getInsideRenderPassCommands()
{
ASSERT(!mHasChildren);
return &mInsideRenderPassCommands;
}
angle::Result CommandGraphNode::beginOutsideRenderPassRecording(Context *context, angle::Result CommandGraphNode::beginOutsideRenderPassRecording(Context *context,
const CommandPool &commandPool, const CommandPool &commandPool,
CommandBuffer **commandsOut) CommandBuffer **commandsOut)
...@@ -410,11 +323,6 @@ void CommandGraphNode::setHasChildren() ...@@ -410,11 +323,6 @@ void CommandGraphNode::setHasChildren()
mHasChildren = true; mHasChildren = true;
} }
bool CommandGraphNode::hasChildren() const
{
return mHasChildren;
}
// Do not call this in anything but testing code, since it's slow. // Do not call this in anything but testing code, since it's slow.
bool CommandGraphNode::isChildOf(CommandGraphNode *parent) bool CommandGraphNode::isChildOf(CommandGraphNode *parent)
{ {
......
...@@ -17,7 +17,89 @@ namespace rx ...@@ -17,7 +17,89 @@ namespace rx
namespace vk namespace vk
{ {
class CommandGraphNode; enum class VisitedState
{
Unvisited,
Ready,
Visited,
};
// Only used internally in the command graph. Kept in the header for better inlining performance.
class CommandGraphNode final : angle::NonCopyable
{
public:
CommandGraphNode();
~CommandGraphNode();
// Immutable queries for when we're walking the commands tree.
CommandBuffer *getOutsideRenderPassCommands();
CommandBuffer *getInsideRenderPassCommands()
{
ASSERT(!mHasChildren);
return &mInsideRenderPassCommands;
}
// For outside the render pass (copies, transitions, etc).
angle::Result beginOutsideRenderPassRecording(Context *context,
const CommandPool &commandPool,
CommandBuffer **commandsOut);
// For rendering commands (draws).
angle::Result beginInsideRenderPassRecording(Context *context, CommandBuffer **commandsOut);
// storeRenderPassInfo and append*RenderTarget store info relevant to the RenderPass.
void storeRenderPassInfo(const Framebuffer &framebuffer,
const gl::Rectangle renderArea,
const vk::RenderPassDesc &renderPassDesc,
const std::vector<VkClearValue> &clearValues);
// Dependency commands order node execution in the command graph.
// Once a node has commands that must happen after it, recording is stopped and the node is
// frozen forever.
static void SetHappensBeforeDependency(CommandGraphNode *beforeNode,
CommandGraphNode *afterNode);
static void SetHappensBeforeDependencies(const std::vector<CommandGraphNode *> &beforeNodes,
CommandGraphNode *afterNode);
bool hasParents() const;
bool hasChildren() const { return mHasChildren; }
// Commands for traversing the node on a flush operation.
VisitedState visitedState() const;
void visitParents(std::vector<CommandGraphNode *> *stack);
angle::Result visitAndExecute(Context *context,
Serial serial,
RenderPassCache *renderPassCache,
CommandBuffer *primaryCommandBuffer);
const gl::Rectangle &getRenderPassRenderArea() const;
private:
void setHasChildren();
// Used for testing only.
bool isChildOf(CommandGraphNode *parent);
// Only used if we need a RenderPass for these commands.
RenderPassDesc mRenderPassDesc;
Framebuffer mRenderPassFramebuffer;
gl::Rectangle mRenderPassRenderArea;
gl::AttachmentArray<VkClearValue> mRenderPassClearValues;
// Keep a separate buffers for commands inside and outside a RenderPass.
// TODO(jmadill): We might not need inside and outside RenderPass commands separate.
CommandBuffer mOutsideRenderPassCommands;
CommandBuffer mInsideRenderPassCommands;
// Parents are commands that must be submitted before 'this' CommandNode can be submitted.
std::vector<CommandGraphNode *> mParents;
// If this is true, other commands exist that must be submitted after 'this' command.
bool mHasChildren;
// Used when traversing the dependency graph.
VisitedState mVisitedState;
};
// 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
...@@ -79,10 +161,17 @@ class CommandGraphResource ...@@ -79,10 +161,17 @@ class CommandGraphResource
void onWriteImpl(CommandGraphNode *writingNode, Serial currentSerial); void onWriteImpl(CommandGraphNode *writingNode, Serial currentSerial);
// Returns true if this node has a current writing node with no children. // Returns true if this node has a current writing node with no children.
bool hasChildlessWritingNode() const; bool hasChildlessWritingNode() const
{
return (mCurrentWritingNode != nullptr && !mCurrentWritingNode->hasChildren());
}
// Checks if we're in a RenderPass without children. // Checks if we're in a RenderPass without children.
bool hasStartedRenderPass() const; bool hasStartedRenderPass() const
{
return hasChildlessWritingNode() &&
mCurrentWritingNode->getInsideRenderPassCommands()->valid();
}
// Updates the in-use serial tracked for this resource. Will clear dependencies if the resource // Updates the in-use serial tracked for this resource. Will clear dependencies if the resource
// was not used in this set of command nodes. // was not used in this set of command nodes.
...@@ -93,13 +182,6 @@ class CommandGraphResource ...@@ -93,13 +182,6 @@ class CommandGraphResource
CommandGraphNode *mCurrentWritingNode; CommandGraphNode *mCurrentWritingNode;
}; };
enum class VisitedState
{
Unvisited,
Ready,
Visited,
};
// Translating OpenGL commands into Vulkan and submitting them immediately loses out on some // Translating OpenGL commands into Vulkan and submitting them immediately loses out on some
// of the powerful flexiblity Vulkan offers in RenderPasses. Load/Store ops can automatically // of the powerful flexiblity Vulkan offers in RenderPasses. Load/Store ops can automatically
// clear RenderPass attachments, or preserve the contents. RenderPass automatic layout transitions // clear RenderPass attachments, or preserve the contents. RenderPass automatic layout transitions
......
...@@ -867,11 +867,6 @@ angle::Result RendererVk::submitFrame(vk::Context *context, ...@@ -867,11 +867,6 @@ angle::Result RendererVk::submitFrame(vk::Context *context,
return angle::Result::Continue(); return angle::Result::Continue();
} }
Serial RendererVk::getCurrentQueueSerial() const
{
return mCurrentQueueSerial;
}
bool RendererVk::isSerialInUse(Serial serial) const bool RendererVk::isSerialInUse(Serial serial) const
{ {
return serial > mLastCompletedQueueSerial; return serial > mLastCompletedQueueSerial;
......
...@@ -74,7 +74,7 @@ class RendererVk : angle::NonCopyable ...@@ -74,7 +74,7 @@ class RendererVk : angle::NonCopyable
const gl::Limitations &getNativeLimitations() const; const gl::Limitations &getNativeLimitations() const;
uint32_t getMaxActiveTextures(); uint32_t getMaxActiveTextures();
Serial getCurrentQueueSerial() const; Serial getCurrentQueueSerial() const { return mCurrentQueueSerial; }
bool isSerialInUse(Serial serial) const; bool isSerialInUse(Serial serial) const;
......
...@@ -507,25 +507,6 @@ void CommandBuffer::endRenderPass() ...@@ -507,25 +507,6 @@ void CommandBuffer::endRenderPass()
vkCmdEndRenderPass(mHandle); vkCmdEndRenderPass(mHandle);
} }
void CommandBuffer::draw(uint32_t vertexCount,
uint32_t instanceCount,
uint32_t firstVertex,
uint32_t firstInstance)
{
ASSERT(valid());
vkCmdDraw(mHandle, vertexCount, instanceCount, firstVertex, firstInstance);
}
void CommandBuffer::drawIndexed(uint32_t indexCount,
uint32_t instanceCount,
uint32_t firstIndex,
int32_t vertexOffset,
uint32_t firstInstance)
{
ASSERT(valid());
vkCmdDrawIndexed(mHandle, indexCount, instanceCount, firstIndex, vertexOffset, firstInstance);
}
void CommandBuffer::bindPipeline(VkPipelineBindPoint pipelineBindPoint, void CommandBuffer::bindPipeline(VkPipelineBindPoint pipelineBindPoint,
const vk::Pipeline &pipeline) const vk::Pipeline &pipeline)
{ {
......
...@@ -380,13 +380,22 @@ class CommandBuffer : public WrappedObject<CommandBuffer, VkCommandBuffer> ...@@ -380,13 +380,22 @@ class CommandBuffer : public WrappedObject<CommandBuffer, VkCommandBuffer>
void draw(uint32_t vertexCount, void draw(uint32_t vertexCount,
uint32_t instanceCount, uint32_t instanceCount,
uint32_t firstVertex, uint32_t firstVertex,
uint32_t firstInstance); uint32_t firstInstance)
{
ASSERT(valid());
vkCmdDraw(mHandle, vertexCount, instanceCount, firstVertex, firstInstance);
}
void drawIndexed(uint32_t indexCount, void drawIndexed(uint32_t indexCount,
uint32_t instanceCount, uint32_t instanceCount,
uint32_t firstIndex, uint32_t firstIndex,
int32_t vertexOffset, int32_t vertexOffset,
uint32_t firstInstance); uint32_t firstInstance)
{
ASSERT(valid());
vkCmdDrawIndexed(mHandle, indexCount, instanceCount, firstIndex, vertexOffset,
firstInstance);
}
void bindPipeline(VkPipelineBindPoint pipelineBindPoint, const Pipeline &pipeline); void bindPipeline(VkPipelineBindPoint pipelineBindPoint, const Pipeline &pipeline);
void bindVertexBuffers(uint32_t firstBinding, void bindVertexBuffers(uint32_t firstBinding,
......
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