Commit ef3b9b46 by Jamie Madill Committed by Commit Bot

Vulkan: Add ContextVk dirty bits.

These dirty bits mostly track state needed for the command buffer. It should speed up ContextVk::setupDraw by skipping unset dirty bits instead of using boolean checks. Improves perf slightly on the Vulkan null draw call test. Bug: angleproject:2786 Change-Id: I071ce558c522732a17ad101d097ee4d10740abf1 Reviewed-on: https://chromium-review.googlesource.com/1194300 Commit-Queue: Jamie Madill <jmadill@chromium.org> Reviewed-by: 's avatarFrank Henigman <fjhenigman@chromium.org>
parent 37386b02
...@@ -113,12 +113,6 @@ ContextVk::ContextVk(const gl::ContextState &state, RendererVk *renderer) ...@@ -113,12 +113,6 @@ ContextVk::ContextVk(const gl::ContextState &state, RendererVk *renderer)
: ContextImpl(state), : ContextImpl(state),
vk::Context(renderer), vk::Context(renderer),
mCurrentDrawMode(gl::PrimitiveMode::InvalidEnum), mCurrentDrawMode(gl::PrimitiveMode::InvalidEnum),
mDirtyDefaultAttribs(false),
mPipelineDirty(false),
mTexturesDirty(false),
mVertexBuffersDirty(false),
mIndexBufferDirty(false),
mDescriptorSetsDirty(false),
mVertexArray(nullptr), mVertexArray(nullptr),
mDrawFramebuffer(nullptr), mDrawFramebuffer(nullptr),
mProgram(nullptr), mProgram(nullptr),
...@@ -133,6 +127,17 @@ ContextVk::ContextVk(const gl::ContextState &state, RendererVk *renderer) ...@@ -133,6 +127,17 @@ ContextVk::ContextVk(const gl::ContextState &state, RendererVk *renderer)
{ {
memset(&mClearColorValue, 0, sizeof(mClearColorValue)); memset(&mClearColorValue, 0, sizeof(mClearColorValue));
memset(&mClearDepthStencilValue, 0, sizeof(mClearDepthStencilValue)); memset(&mClearDepthStencilValue, 0, sizeof(mClearDepthStencilValue));
mNonIndexedDirtyBitsMask.set();
mNonIndexedDirtyBitsMask.reset(DIRTY_BIT_INDEX_BUFFER);
mIndexedDirtyBitsMask.set();
mNewCommandBufferDirtyBits.set(DIRTY_BIT_PIPELINE);
mNewCommandBufferDirtyBits.set(DIRTY_BIT_TEXTURES);
mNewCommandBufferDirtyBits.set(DIRTY_BIT_VERTEX_BUFFERS);
mNewCommandBufferDirtyBits.set(DIRTY_BIT_INDEX_BUFFER);
mNewCommandBufferDirtyBits.set(DIRTY_BIT_DESCRIPTOR_SETS);
} }
ContextVk::~ContextVk() = default; ContextVk::~ContextVk() = default;
...@@ -249,7 +254,7 @@ angle::Result ContextVk::initPipeline(const gl::DrawCallParams &drawCallParams) ...@@ -249,7 +254,7 @@ angle::Result ContextVk::initPipeline(const gl::DrawCallParams &drawCallParams)
angle::Result ContextVk::setupDraw(const gl::Context *context, angle::Result ContextVk::setupDraw(const gl::Context *context,
const gl::DrawCallParams &drawCallParams, const gl::DrawCallParams &drawCallParams,
bool useIndexBuffer, const DirtyBits &dirtyBitsMask,
vk::CommandBuffer **commandBufferOut) vk::CommandBuffer **commandBufferOut)
{ {
if (drawCallParams.mode() != mCurrentDrawMode) if (drawCallParams.mode() != mCurrentDrawMode)
...@@ -267,117 +272,117 @@ angle::Result ContextVk::setupDraw(const gl::Context *context, ...@@ -267,117 +272,117 @@ angle::Result ContextVk::setupDraw(const gl::Context *context,
// Set any dirty bits that depend on draw call parameters or other objects. // Set any dirty bits that depend on draw call parameters or other objects.
if (mode == vk::RecordingMode::Start) if (mode == vk::RecordingMode::Start)
{ {
mPipelineDirty = true; mDirtyBits |= mNewCommandBufferDirtyBits;
mTexturesDirty = true;
mVertexBuffersDirty = true;
mIndexBufferDirty = true;
mDescriptorSetsDirty = true;
} }
if (context->getStateCache().hasAnyActiveClientAttrib()) if (context->getStateCache().hasAnyActiveClientAttrib())
{ {
ANGLE_TRY(mVertexArray->updateClientAttribs(context, drawCallParams)); ANGLE_TRY(mVertexArray->updateClientAttribs(context, drawCallParams));
mVertexBuffersDirty = true; mDirtyBits.set(DIRTY_BIT_VERTEX_BUFFERS);
} }
if (mProgram->dirtyUniforms()) if (mProgram->dirtyUniforms())
{ {
ANGLE_TRY(mProgram->updateUniforms(this)); ANGLE_TRY(mProgram->updateUniforms(this));
mDescriptorSetsDirty = true; mDirtyBits.set(DIRTY_BIT_DESCRIPTOR_SETS);
} }
// Flush any relevant dirty bits. // Flush any relevant dirty bits.
if (mDirtyDefaultAttribs) for (size_t dirtyBit : mDirtyBits &dirtyBitsMask)
{
ANGLE_TRY(updateDefaultAttributes());
mDirtyDefaultAttribs = false;
}
if (mPipelineDirty)
{
if (!mCurrentPipeline)
{
ANGLE_TRY(initPipeline(drawCallParams));
}
(*commandBufferOut)->bindPipeline(VK_PIPELINE_BIND_POINT_GRAPHICS, mCurrentPipeline->get());
// Update the queue serial for the pipeline object.
ASSERT(mCurrentPipeline && mCurrentPipeline->valid());
mCurrentPipeline->updateSerial(mRenderer->getCurrentQueueSerial());
mPipelineDirty = false;
mVertexBuffersDirty = true;
mIndexBufferDirty = true;
}
// Ensure any writes to the textures are flushed before we read from them.
if (mTexturesDirty)
{ {
ANGLE_TRY(updateActiveTextures(context)); mDirtyBits.reset(dirtyBit);
switch (dirtyBit)
// TODO(jmadill): Should probably merge this for loop with programVk's descriptor update.
for (size_t textureIndex : programGL->getActiveSamplersMask())
{
TextureVk *textureVk = mActiveTextures[textureIndex];
ANGLE_TRY(textureVk->ensureImageInitialized(this));
textureVk->addReadDependency(mDrawFramebuffer);
}
if (mProgram->hasTextures())
{ {
ANGLE_TRY(mProgram->updateTexturesDescriptorSet(this)); case DIRTY_BIT_DEFAULT_ATTRIBS:
} ANGLE_TRY(updateDefaultAttributes());
break;
mDescriptorSetsDirty = true; case DIRTY_BIT_PIPELINE:
mTexturesDirty = false; {
} if (!mCurrentPipeline)
{
ANGLE_TRY(initPipeline(drawCallParams));
}
if (mDescriptorSetsDirty) (*commandBufferOut)
{ ->bindPipeline(VK_PIPELINE_BIND_POINT_GRAPHICS, mCurrentPipeline->get());
ANGLE_TRY(mProgram->updateDescriptorSets(this, drawCallParams, *commandBufferOut));
// Bind the graphics descriptor sets.
(*commandBufferOut)
->bindDescriptorSets(VK_PIPELINE_BIND_POINT_GRAPHICS, mProgram->getPipelineLayout(),
kDriverUniformsDescriptorSetIndex, 1,
&mDriverUniformsDescriptorSet, 0, nullptr);
mDescriptorSetsDirty = false;
}
uint32_t maxAttrib = programGL->getState().getMaxActiveAttribLocation(); // Update the queue serial for the pipeline object.
if (mVertexBuffersDirty && maxAttrib > 0) ASSERT(mCurrentPipeline && mCurrentPipeline->valid());
{ mCurrentPipeline->updateSerial(mRenderer->getCurrentQueueSerial());
const gl::AttributesMask &programAttribsMask = programGL->getActiveAttribLocationsMask(); break;
BindNonNullVertexBufferRanges(*commandBufferOut, programAttribsMask, maxAttrib, }
mVertexArray->getCurrentArrayBufferHandles(), case DIRTY_BIT_TEXTURES:
mVertexArray->getCurrentArrayBufferOffsets()); {
ANGLE_TRY(updateActiveTextures(context));
// TODO(jmadill): Should probably merge this for loop with programVk's descriptor
// update.
for (size_t textureIndex : programGL->getActiveSamplersMask())
{
// Ensure any writes to the textures are flushed before we read from them.
TextureVk *textureVk = mActiveTextures[textureIndex];
ANGLE_TRY(textureVk->ensureImageInitialized(this));
textureVk->addReadDependency(mDrawFramebuffer);
}
if (mProgram->hasTextures())
{
ANGLE_TRY(mProgram->updateTexturesDescriptorSet(this));
}
break;
}
const auto &arrayBufferResources = mVertexArray->getCurrentArrayBufferResources(); case DIRTY_BIT_DESCRIPTOR_SETS:
{
ANGLE_TRY(mProgram->updateDescriptorSets(this, drawCallParams, *commandBufferOut));
// Bind the graphics descriptor sets.
(*commandBufferOut)
->bindDescriptorSets(VK_PIPELINE_BIND_POINT_GRAPHICS,
mProgram->getPipelineLayout(),
kDriverUniformsDescriptorSetIndex, 1,
&mDriverUniformsDescriptorSet, 0, nullptr);
break;
}
for (size_t attribIndex : context->getStateCache().getActiveBufferedAttribsMask()) case DIRTY_BIT_VERTEX_BUFFERS:
{ {
if (arrayBufferResources[attribIndex]) BindNonNullVertexBufferRanges(*commandBufferOut,
arrayBufferResources[attribIndex]->addReadDependency(mDrawFramebuffer); programGL->getActiveAttribLocationsMask(),
} mProgram->getState().getMaxActiveAttribLocation(),
mVertexArray->getCurrentArrayBufferHandles(),
mVertexArray->getCurrentArrayBufferOffsets());
const auto &arrayBufferResources = mVertexArray->getCurrentArrayBufferResources();
for (size_t attribIndex : context->getStateCache().getActiveBufferedAttribsMask())
{
if (arrayBufferResources[attribIndex])
arrayBufferResources[attribIndex]->addReadDependency(mDrawFramebuffer);
}
break;
}
mVertexBuffersDirty = false; case DIRTY_BIT_INDEX_BUFFER:
} {
(*commandBufferOut)
->bindIndexBuffer(mVertexArray->getCurrentElementArrayBufferHandle(),
mVertexArray->getCurrentElementArrayBufferOffset(),
gl_vk::GetIndexType(mCurrentDrawElementsType));
vk::CommandGraphResource *elementArrayBufferResource =
mVertexArray->getCurrentElementArrayBufferResource();
if (elementArrayBufferResource)
{
elementArrayBufferResource->addReadDependency(mDrawFramebuffer);
}
break;
}
if (useIndexBuffer && mIndexBufferDirty) default:
{ UNREACHABLE();
(*commandBufferOut) break;
->bindIndexBuffer(mVertexArray->getCurrentElementArrayBufferHandle(),
mVertexArray->getCurrentElementArrayBufferOffset(),
gl_vk::GetIndexType(mCurrentDrawElementsType));
vk::CommandGraphResource *elementArrayBufferResource =
mVertexArray->getCurrentElementArrayBufferResource();
if (elementArrayBufferResource)
{
elementArrayBufferResource->addReadDependency(mDrawFramebuffer);
} }
mIndexBufferDirty = false;
} }
return angle::Result::Continue(); return angle::Result::Continue();
...@@ -389,32 +394,32 @@ angle::Result ContextVk::setupIndexedDraw(const gl::Context *context, ...@@ -389,32 +394,32 @@ angle::Result ContextVk::setupIndexedDraw(const gl::Context *context,
{ {
if (drawCallParams.type() != mCurrentDrawElementsType) if (drawCallParams.type() != mCurrentDrawElementsType)
{ {
mIndexBufferDirty = true; mDirtyBits.set(DIRTY_BIT_INDEX_BUFFER);
mCurrentDrawElementsType = drawCallParams.type(); mCurrentDrawElementsType = drawCallParams.type();
} }
const gl::Buffer *elementArrayBuffer = mVertexArray->getState().getElementArrayBuffer().get(); const gl::Buffer *elementArrayBuffer = mVertexArray->getState().getElementArrayBuffer().get();
if (!elementArrayBuffer) if (!elementArrayBuffer)
{ {
mIndexBufferDirty = true; mDirtyBits.set(DIRTY_BIT_INDEX_BUFFER);
ANGLE_TRY(mVertexArray->updateIndexTranslation(this, drawCallParams)); ANGLE_TRY(mVertexArray->updateIndexTranslation(this, drawCallParams));
} }
else else
{ {
if (drawCallParams.indices() != mLastIndexBufferOffset) if (drawCallParams.indices() != mLastIndexBufferOffset)
{ {
mIndexBufferDirty = true; mDirtyBits.set(DIRTY_BIT_INDEX_BUFFER);
mLastIndexBufferOffset = drawCallParams.indices(); mLastIndexBufferOffset = drawCallParams.indices();
mVertexArray->updateCurrentElementArrayBufferOffset(mLastIndexBufferOffset); mVertexArray->updateCurrentElementArrayBufferOffset(mLastIndexBufferOffset);
} }
if (drawCallParams.type() == GL_UNSIGNED_BYTE && mIndexBufferDirty) if (drawCallParams.type() == GL_UNSIGNED_BYTE && mDirtyBits[DIRTY_BIT_INDEX_BUFFER])
{ {
ANGLE_TRY(mVertexArray->updateIndexTranslation(this, drawCallParams)); ANGLE_TRY(mVertexArray->updateIndexTranslation(this, drawCallParams));
} }
} }
return setupDraw(context, drawCallParams, true, commandBufferOut); return setupDraw(context, drawCallParams, mIndexedDirtyBitsMask, commandBufferOut);
} }
angle::Result ContextVk::setupLineLoopDraw(const gl::Context *context, angle::Result ContextVk::setupLineLoopDraw(const gl::Context *context,
...@@ -422,10 +427,10 @@ angle::Result ContextVk::setupLineLoopDraw(const gl::Context *context, ...@@ -422,10 +427,10 @@ angle::Result ContextVk::setupLineLoopDraw(const gl::Context *context,
vk::CommandBuffer **commandBufferOut) vk::CommandBuffer **commandBufferOut)
{ {
ANGLE_TRY(mVertexArray->handleLineLoop(this, drawCallParams)); ANGLE_TRY(mVertexArray->handleLineLoop(this, drawCallParams));
mIndexBufferDirty = true; mDirtyBits.set(DIRTY_BIT_INDEX_BUFFER);
mCurrentDrawElementsType = mCurrentDrawElementsType =
drawCallParams.isDrawElements() ? drawCallParams.type() : GL_UNSIGNED_INT; drawCallParams.isDrawElements() ? drawCallParams.type() : GL_UNSIGNED_INT;
return setupDraw(context, drawCallParams, true, commandBufferOut); return setupDraw(context, drawCallParams, mIndexedDirtyBitsMask, commandBufferOut);
} }
gl::Error ContextVk::drawArrays(const gl::Context *context, gl::Error ContextVk::drawArrays(const gl::Context *context,
...@@ -445,7 +450,7 @@ gl::Error ContextVk::drawArrays(const gl::Context *context, ...@@ -445,7 +450,7 @@ gl::Error ContextVk::drawArrays(const gl::Context *context,
} }
else else
{ {
ANGLE_TRY(setupDraw(context, drawCallParams, false, &commandBuffer)); ANGLE_TRY(setupDraw(context, drawCallParams, mNonIndexedDirtyBitsMask, &commandBuffer));
commandBuffer->draw(clampedVertexCount, 1, drawCallParams.firstVertex(), 0); commandBuffer->draw(clampedVertexCount, 1, drawCallParams.firstVertex(), 0);
} }
...@@ -801,16 +806,19 @@ gl::Error ContextVk::syncState(const gl::Context *context, const gl::State::Dirt ...@@ -801,16 +806,19 @@ gl::Error ContextVk::syncState(const gl::Context *context, const gl::State::Dirt
break; break;
case gl::State::DIRTY_BIT_PROGRAM_EXECUTABLE: case gl::State::DIRTY_BIT_PROGRAM_EXECUTABLE:
{ {
mTexturesDirty = true; invalidateCurrentTextures();
// No additional work is needed here. We will update the pipeline desc later. // No additional work is needed here. We will update the pipeline desc later.
invalidateDefaultAttributes(context->getStateCache().getActiveDefaultAttribsMask()); invalidateDefaultAttributes(context->getStateCache().getActiveDefaultAttribsMask());
bool useVertexBuffer = (mProgram->getState().getMaxActiveAttribLocation());
mNonIndexedDirtyBitsMask.set(DIRTY_BIT_VERTEX_BUFFERS, useVertexBuffer);
mIndexedDirtyBitsMask.set(DIRTY_BIT_VERTEX_BUFFERS, useVertexBuffer);
break; break;
} }
case gl::State::DIRTY_BIT_TEXTURE_BINDINGS: case gl::State::DIRTY_BIT_TEXTURE_BINDINGS:
mTexturesDirty = true; invalidateCurrentTextures();
break; break;
case gl::State::DIRTY_BIT_SAMPLER_BINDINGS: case gl::State::DIRTY_BIT_SAMPLER_BINDINGS:
mTexturesDirty = true; invalidateCurrentTextures();
break; break;
case gl::State::DIRTY_BIT_TRANSFORM_FEEDBACK_BINDING: case gl::State::DIRTY_BIT_TRANSFORM_FEEDBACK_BINDING:
break; break;
...@@ -986,10 +994,22 @@ std::vector<PathImpl *> ContextVk::createPaths(GLsizei) ...@@ -986,10 +994,22 @@ std::vector<PathImpl *> ContextVk::createPaths(GLsizei)
void ContextVk::invalidateCurrentPipeline() void ContextVk::invalidateCurrentPipeline()
{ {
mPipelineDirty = true; mDirtyBits.set(DIRTY_BIT_PIPELINE);
mDirtyBits.set(DIRTY_BIT_VERTEX_BUFFERS);
mDirtyBits.set(DIRTY_BIT_INDEX_BUFFER);
mCurrentPipeline = nullptr; mCurrentPipeline = nullptr;
} }
void ContextVk::invalidateCurrentTextures()
{
ASSERT(mProgram);
if (mProgram->hasTextures())
{
mDirtyBits.set(DIRTY_BIT_TEXTURES);
mDirtyBits.set(DIRTY_BIT_DESCRIPTOR_SETS);
}
}
gl::Error ContextVk::dispatchCompute(const gl::Context *context, gl::Error ContextVk::dispatchCompute(const gl::Context *context,
GLuint numGroupsX, GLuint numGroupsX,
GLuint numGroupsY, GLuint numGroupsY,
...@@ -1155,7 +1175,7 @@ const gl::ActiveTextureArray<TextureVk *> &ContextVk::getActiveTextures() const ...@@ -1155,7 +1175,7 @@ const gl::ActiveTextureArray<TextureVk *> &ContextVk::getActiveTextures() const
void ContextVk::invalidateDefaultAttribute(size_t attribIndex) void ContextVk::invalidateDefaultAttribute(size_t attribIndex)
{ {
mDirtyDefaultAttribsMask.set(attribIndex); mDirtyDefaultAttribsMask.set(attribIndex);
mDirtyDefaultAttribs = true; mDirtyBits.set(DIRTY_BIT_DEFAULT_ATTRIBS);
} }
void ContextVk::invalidateDefaultAttributes(const gl::AttributesMask &dirtyMask) void ContextVk::invalidateDefaultAttributes(const gl::AttributesMask &dirtyMask)
...@@ -1163,7 +1183,7 @@ void ContextVk::invalidateDefaultAttributes(const gl::AttributesMask &dirtyMask) ...@@ -1163,7 +1183,7 @@ void ContextVk::invalidateDefaultAttributes(const gl::AttributesMask &dirtyMask)
if (dirtyMask.any()) if (dirtyMask.any())
{ {
mDirtyDefaultAttribsMask = dirtyMask; mDirtyDefaultAttribsMask = dirtyMask;
mDirtyDefaultAttribs = true; mDirtyBits.set(DIRTY_BIT_DEFAULT_ATTRIBS);
} }
} }
......
...@@ -174,13 +174,27 @@ class ContextVk : public ContextImpl, public vk::Context ...@@ -174,13 +174,27 @@ class ContextVk : public ContextImpl, public vk::Context
void handleError(VkResult errorCode, const char *file, unsigned int line) override; void handleError(VkResult errorCode, const char *file, unsigned int line) override;
const gl::ActiveTextureArray<TextureVk *> &getActiveTextures() const; const gl::ActiveTextureArray<TextureVk *> &getActiveTextures() const;
void setIndexBufferDirty() { mIndexBufferDirty = true; } void setIndexBufferDirty() { mDirtyBits.set(DIRTY_BIT_INDEX_BUFFER); }
private: private:
// Dirty bits.
enum DirtyBitType : size_t
{
DIRTY_BIT_DEFAULT_ATTRIBS,
DIRTY_BIT_PIPELINE,
DIRTY_BIT_TEXTURES,
DIRTY_BIT_VERTEX_BUFFERS,
DIRTY_BIT_INDEX_BUFFER,
DIRTY_BIT_DESCRIPTOR_SETS,
DIRTY_BIT_MAX,
};
using DirtyBits = angle::BitSet<DIRTY_BIT_MAX>;
angle::Result initPipeline(const gl::DrawCallParams &drawCallParams); angle::Result initPipeline(const gl::DrawCallParams &drawCallParams);
angle::Result setupDraw(const gl::Context *context, angle::Result setupDraw(const gl::Context *context,
const gl::DrawCallParams &drawCallParams, const gl::DrawCallParams &drawCallParams,
bool useIndexBuffer, const DirtyBits &dirtyBitsMask,
vk::CommandBuffer **commandBufferOut); vk::CommandBuffer **commandBufferOut);
angle::Result setupIndexedDraw(const gl::Context *context, angle::Result setupIndexedDraw(const gl::Context *context,
const gl::DrawCallParams &drawCallParams, const gl::DrawCallParams &drawCallParams,
...@@ -198,6 +212,8 @@ class ContextVk : public ContextImpl, public vk::Context ...@@ -198,6 +212,8 @@ class ContextVk : public ContextImpl, public vk::Context
angle::Result updateDefaultAttributes(); angle::Result updateDefaultAttributes();
angle::Result updateDefaultAttribute(size_t attribIndex); angle::Result updateDefaultAttribute(size_t attribIndex);
void invalidateCurrentTextures();
vk::PipelineAndSerial *mCurrentPipeline; vk::PipelineAndSerial *mCurrentPipeline;
gl::PrimitiveMode mCurrentDrawMode; gl::PrimitiveMode mCurrentDrawMode;
...@@ -210,13 +226,10 @@ class ContextVk : public ContextImpl, public vk::Context ...@@ -210,13 +226,10 @@ class ContextVk : public ContextImpl, public vk::Context
vk::DescriptorSetLayoutArray<vk::DynamicDescriptorPool> mDynamicDescriptorPools; vk::DescriptorSetLayoutArray<vk::DynamicDescriptorPool> mDynamicDescriptorPools;
// Dirty bits. // Dirty bits.
// TODO(jmadill): Make this into a dirty bit set. http://anglebug.com/2786 DirtyBits mDirtyBits;
bool mDirtyDefaultAttribs; DirtyBits mNonIndexedDirtyBitsMask;
bool mPipelineDirty; DirtyBits mIndexedDirtyBitsMask;
bool mTexturesDirty; DirtyBits mNewCommandBufferDirtyBits;
bool mVertexBuffersDirty;
bool mIndexBufferDirty;
bool mDescriptorSetsDirty;
// Cached back-end objects. // Cached back-end objects.
VertexArrayVk *mVertexArray; VertexArrayVk *mVertexArray;
......
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