Commit 80766cfa by Jamie Madill Committed by Commit Bot

Vulkan: Update individual VAO attribs when dirty.

This simplifies the dirty state updates in VertexArrayVk. It also lets us use a smaller dirty bit mask when a single attribute is marked dirty in a vertex array. Improves performance by about 1-2% in the VBO state change test. Will allow for better performance using a pipeline transition table. Bug: angleproject:3013 Change-Id: I25c5172b3f41b7abac6b8273c8f9cd42eb46cc9f Reviewed-on: https://chromium-review.googlesource.com/c/1403958Reviewed-by: 's avatarYuly Novikov <ynovikov@chromium.org> Commit-Queue: Jamie Madill <jmadill@chromium.org>
parent b827f490
...@@ -365,9 +365,6 @@ angle::Result ContextVk::handleDirtyPipeline(const gl::Context *context, ...@@ -365,9 +365,6 @@ angle::Result ContextVk::handleDirtyPipeline(const gl::Context *context,
{ {
if (!mCurrentPipeline) if (!mCurrentPipeline)
{ {
// Copy over the latest attrib and binding descriptions. This should be done more lazily.
mVertexArray->getPackedInputDescriptions(mGraphicsPipelineDesc.get());
// Draw call shader patching, shader compilation, and pipeline cache query. // Draw call shader patching, shader compilation, and pipeline cache query.
ANGLE_TRY(mProgram->getGraphicsPipeline(this, mCurrentDrawMode, *mGraphicsPipelineDesc, ANGLE_TRY(mProgram->getGraphicsPipeline(this, mCurrentDrawMode, *mGraphicsPipelineDesc,
mProgram->getState().getActiveAttribLocationsMask(), mProgram->getState().getActiveAttribLocationsMask(),
...@@ -1278,7 +1275,7 @@ angle::Result ContextVk::updateDefaultAttribute(size_t attribIndex) ...@@ -1278,7 +1275,7 @@ angle::Result ContextVk::updateDefaultAttribute(size_t attribIndex)
ANGLE_TRY(defaultBuffer.flush(this)); ANGLE_TRY(defaultBuffer.flush(this));
mVertexArray->updateDefaultAttrib(mRenderer, attribIndex, bufferHandle, mVertexArray->updateDefaultAttrib(this, attribIndex, bufferHandle,
static_cast<uint32_t>(offset)); static_cast<uint32_t>(offset));
return angle::Result::Continue; return angle::Result::Continue;
} }
......
...@@ -172,6 +172,17 @@ class ContextVk : public ContextImpl, public vk::Context ...@@ -172,6 +172,17 @@ class ContextVk : public ContextImpl, public vk::Context
mDirtyBits.set(DIRTY_BIT_INDEX_BUFFER); mDirtyBits.set(DIRTY_BIT_INDEX_BUFFER);
} }
ANGLE_INLINE void onVertexAttributeChange(size_t attribIndex,
GLuint stride,
GLuint divisor,
VkFormat format,
GLuint relativeOffset)
{
invalidateVertexAndIndexBuffers();
mGraphicsPipelineDesc->updateVertexInput(static_cast<uint32_t>(attribIndex), stride,
divisor, format, relativeOffset);
}
void invalidateDefaultAttribute(size_t attribIndex); void invalidateDefaultAttribute(size_t attribIndex);
void invalidateDefaultAttributes(const gl::AttributesMask &dirtyMask); void invalidateDefaultAttributes(const gl::AttributesMask &dirtyMask);
void onFramebufferChange(const vk::RenderPassDesc &renderPassDesc); void onFramebufferChange(const vk::RenderPassDesc &renderPassDesc);
......
...@@ -123,8 +123,6 @@ VertexArrayVk::VertexArrayVk(const gl::VertexArrayState &state, RendererVk *rend ...@@ -123,8 +123,6 @@ VertexArrayVk::VertexArrayVk(const gl::VertexArrayState &state, RendererVk *rend
mCurrentArrayBufferConversionCanRelease{}, mCurrentArrayBufferConversionCanRelease{},
mCurrentElementArrayBufferOffset(0), mCurrentElementArrayBufferOffset(0),
mCurrentElementArrayBuffer(nullptr), mCurrentElementArrayBuffer(nullptr),
mPackedInputBindings{},
mPackedInputAttributes{},
mDynamicVertexData(kVertexBufferUsageFlags, kDynamicVertexDataSize, true), mDynamicVertexData(kVertexBufferUsageFlags, kDynamicVertexDataSize, true),
mDynamicIndexData(kIndexBufferUsageFlags, kDynamicIndexDataSize, true), mDynamicIndexData(kIndexBufferUsageFlags, kDynamicIndexDataSize, true),
mTranslatedByteIndexData(kIndexBufferUsageFlags, kDynamicIndexDataSize, true), mTranslatedByteIndexData(kIndexBufferUsageFlags, kDynamicIndexDataSize, true),
...@@ -142,9 +140,6 @@ VertexArrayVk::VertexArrayVk(const gl::VertexArrayState &state, RendererVk *rend ...@@ -142,9 +140,6 @@ VertexArrayVk::VertexArrayVk(const gl::VertexArrayState &state, RendererVk *rend
mDynamicVertexData.init(kMaxVertexFormatAlignment, renderer); mDynamicVertexData.init(kMaxVertexFormatAlignment, renderer);
mDynamicIndexData.init(1, renderer); mDynamicIndexData.init(1, renderer);
mTranslatedByteIndexData.init(1, renderer); mTranslatedByteIndexData.init(1, renderer);
// Initially consider all inputs dirty.
mDirtyPackedInputs.set();
} }
VertexArrayVk::~VertexArrayVk() {} VertexArrayVk::~VertexArrayVk() {}
...@@ -300,26 +295,6 @@ void VertexArrayVk::ensureConversionReleased(RendererVk *renderer, size_t attrib ...@@ -300,26 +295,6 @@ void VertexArrayVk::ensureConversionReleased(RendererVk *renderer, size_t attrib
} }
} }
#define ANGLE_VERTEX_DIRTY_ATTRIB_FUNC(INDEX) \
case gl::VertexArray::DIRTY_BIT_ATTRIB_0 + INDEX: \
ANGLE_TRY(syncDirtyAttrib(contextVk, attribs[INDEX], \
bindings[attribs[INDEX].bindingIndex], INDEX)); \
invalidateContext = true; \
break;
#define ANGLE_VERTEX_DIRTY_BINDING_FUNC(INDEX) \
case gl::VertexArray::DIRTY_BIT_BINDING_0 + INDEX: \
ANGLE_TRY(syncDirtyAttrib(contextVk, attribs[INDEX], \
bindings[attribs[INDEX].bindingIndex], INDEX)); \
invalidateContext = true; \
break;
#define ANGLE_VERTEX_DIRTY_BUFFER_DATA_FUNC(INDEX) \
case gl::VertexArray::DIRTY_BIT_BUFFER_DATA_0 + INDEX: \
ANGLE_TRY(syncDirtyAttrib(contextVk, attribs[INDEX], \
bindings[attribs[INDEX].bindingIndex], INDEX)); \
break;
angle::Result VertexArrayVk::syncState(const gl::Context *context, angle::Result VertexArrayVk::syncState(const gl::Context *context,
const gl::VertexArray::DirtyBits &dirtyBits, const gl::VertexArray::DirtyBits &dirtyBits,
const gl::VertexArray::DirtyAttribBitsArray &attribBits, const gl::VertexArray::DirtyAttribBitsArray &attribBits,
...@@ -367,8 +342,30 @@ angle::Result VertexArrayVk::syncState(const gl::Context *context, ...@@ -367,8 +342,30 @@ angle::Result VertexArrayVk::syncState(const gl::Context *context,
mDirtyLineLoopTranslation = true; mDirtyLineLoopTranslation = true;
break; break;
#define ANGLE_VERTEX_DIRTY_ATTRIB_FUNC(INDEX) \
case gl::VertexArray::DIRTY_BIT_ATTRIB_0 + INDEX: \
ANGLE_TRY(syncDirtyAttrib(contextVk, attribs[INDEX], \
bindings[attribs[INDEX].bindingIndex], INDEX)); \
invalidateContext = true; \
break;
ANGLE_VERTEX_INDEX_CASES(ANGLE_VERTEX_DIRTY_ATTRIB_FUNC); ANGLE_VERTEX_INDEX_CASES(ANGLE_VERTEX_DIRTY_ATTRIB_FUNC);
#define ANGLE_VERTEX_DIRTY_BINDING_FUNC(INDEX) \
case gl::VertexArray::DIRTY_BIT_BINDING_0 + INDEX: \
ANGLE_TRY(syncDirtyAttrib(contextVk, attribs[INDEX], \
bindings[attribs[INDEX].bindingIndex], INDEX)); \
invalidateContext = true; \
break;
ANGLE_VERTEX_INDEX_CASES(ANGLE_VERTEX_DIRTY_BINDING_FUNC); ANGLE_VERTEX_INDEX_CASES(ANGLE_VERTEX_DIRTY_BINDING_FUNC);
#define ANGLE_VERTEX_DIRTY_BUFFER_DATA_FUNC(INDEX) \
case gl::VertexArray::DIRTY_BIT_BUFFER_DATA_0 + INDEX: \
ANGLE_TRY(syncDirtyAttrib(contextVk, attribs[INDEX], \
bindings[attribs[INDEX].bindingIndex], INDEX)); \
break;
ANGLE_VERTEX_INDEX_CASES(ANGLE_VERTEX_DIRTY_BUFFER_DATA_FUNC); ANGLE_VERTEX_INDEX_CASES(ANGLE_VERTEX_DIRTY_BUFFER_DATA_FUNC);
default: default:
...@@ -385,14 +382,27 @@ angle::Result VertexArrayVk::syncState(const gl::Context *context, ...@@ -385,14 +382,27 @@ angle::Result VertexArrayVk::syncState(const gl::Context *context,
return angle::Result::Continue; return angle::Result::Continue;
} }
ANGLE_INLINE void VertexArrayVk::setPackedInputInfo(ContextVk *contextVk,
size_t attribIndex,
const gl::VertexAttribute &attrib,
const gl::VertexBinding &binding)
{
ASSERT(attrib.enabled);
contextVk->onVertexAttributeChange(
attribIndex, mCurrentArrayBufferStrides[attribIndex], binding.getDivisor(),
mCurrentArrayBufferFormats[attribIndex]->vkBufferFormat, attrib.relativeOffset);
}
ANGLE_INLINE void VertexArrayVk::setDefaultPackedInput(ContextVk *contextVk, size_t attribIndex)
{
contextVk->onVertexAttributeChange(attribIndex, 0, 0, VK_FORMAT_R32G32B32A32_SFLOAT, 0);
}
angle::Result VertexArrayVk::syncDirtyAttrib(ContextVk *contextVk, angle::Result VertexArrayVk::syncDirtyAttrib(ContextVk *contextVk,
const gl::VertexAttribute &attrib, const gl::VertexAttribute &attrib,
const gl::VertexBinding &binding, const gl::VertexBinding &binding,
size_t attribIndex) size_t attribIndex)
{ {
// Invalidate the input description for pipelines.
mDirtyPackedInputs.set(attribIndex);
RendererVk *renderer = contextVk->getRenderer(); RendererVk *renderer = contextVk->getRenderer();
bool releaseConversion = true; bool releaseConversion = true;
bool anyVertexBufferConvertedOnGpu = false; bool anyVertexBufferConvertedOnGpu = false;
...@@ -446,6 +456,8 @@ angle::Result VertexArrayVk::syncDirtyAttrib(ContextVk *contextVk, ...@@ -446,6 +456,8 @@ angle::Result VertexArrayVk::syncDirtyAttrib(ContextVk *contextVk,
mCurrentArrayBufferStrides[attribIndex] = mCurrentArrayBufferStrides[attribIndex] =
mCurrentArrayBufferFormats[attribIndex]->bufferFormat().pixelBytes; mCurrentArrayBufferFormats[attribIndex]->bufferFormat().pixelBytes;
} }
setPackedInputInfo(contextVk, attribIndex, attrib, binding);
} }
else else
{ {
...@@ -458,6 +470,8 @@ angle::Result VertexArrayVk::syncDirtyAttrib(ContextVk *contextVk, ...@@ -458,6 +470,8 @@ angle::Result VertexArrayVk::syncDirtyAttrib(ContextVk *contextVk,
mCurrentArrayBufferStrides[attribIndex] = 0; mCurrentArrayBufferStrides[attribIndex] = 0;
mCurrentArrayBufferFormats[attribIndex] = mCurrentArrayBufferFormats[attribIndex] =
&renderer->getFormat(angle::FormatID::R32G32B32A32_FLOAT); &renderer->getFormat(angle::FormatID::R32G32B32A32_FLOAT);
setDefaultPackedInput(contextVk, attribIndex);
} }
if (anyVertexBufferConvertedOnGpu && renderer->getFeatures().flushAfterVertexConversion) if (anyVertexBufferConvertedOnGpu && renderer->getFeatures().flushAfterVertexConversion)
...@@ -471,57 +485,6 @@ angle::Result VertexArrayVk::syncDirtyAttrib(ContextVk *contextVk, ...@@ -471,57 +485,6 @@ angle::Result VertexArrayVk::syncDirtyAttrib(ContextVk *contextVk,
return angle::Result::Continue; return angle::Result::Continue;
} }
void VertexArrayVk::updatePackedInputDescriptions()
{
ASSERT(mDirtyPackedInputs.any());
const auto &attribs = mState.getVertexAttributes();
const auto &bindings = mState.getVertexBindings();
for (auto attribIndex : mDirtyPackedInputs)
{
const auto &attrib = attribs[attribIndex];
const auto &binding = bindings[attrib.bindingIndex];
if (attrib.enabled)
{
updatePackedInputInfo(static_cast<uint32_t>(attribIndex), binding, attrib);
}
else
{
vk::PackedVertexInputBindingDesc &bindingDesc = mPackedInputBindings[attribIndex];
bindingDesc.stride = 0;
bindingDesc.inputRate = VK_VERTEX_INPUT_RATE_VERTEX;
mPackedInputAttributes.formats[attribIndex] =
static_cast<uint16_t>(VK_FORMAT_R32G32B32A32_SFLOAT);
mPackedInputAttributes.offsets[attribIndex] = 0;
}
}
mDirtyPackedInputs.reset();
}
void VertexArrayVk::updatePackedInputInfo(uint32_t attribIndex,
const gl::VertexBinding &binding,
const gl::VertexAttribute &attrib)
{
vk::PackedVertexInputBindingDesc &bindingDesc = mPackedInputBindings[attribIndex];
bindingDesc.stride = static_cast<uint16_t>(mCurrentArrayBufferStrides[attribIndex]);
bindingDesc.inputRate = static_cast<uint16_t>(
binding.getDivisor() > 0 ? VK_VERTEX_INPUT_RATE_INSTANCE : VK_VERTEX_INPUT_RATE_VERTEX);
VkFormat vkFormat = mCurrentArrayBufferFormats[attribIndex]->vkBufferFormat;
ASSERT(vkFormat <= std::numeric_limits<uint16_t>::max());
if (vkFormat == VK_FORMAT_UNDEFINED)
{
UNIMPLEMENTED();
}
mPackedInputAttributes.formats[attribIndex] = static_cast<uint8_t>(vkFormat);
mPackedInputAttributes.offsets[attribIndex] = static_cast<uint16_t>(attrib.relativeOffset);
}
angle::Result VertexArrayVk::updateClientAttribs(const gl::Context *context, angle::Result VertexArrayVk::updateClientAttribs(const gl::Context *context,
GLint firstVertex, GLint firstVertex,
GLsizei vertexOrIndexCount, GLsizei vertexOrIndexCount,
...@@ -717,7 +680,7 @@ angle::Result VertexArrayVk::updateIndexTranslation(ContextVk *contextVk, ...@@ -717,7 +680,7 @@ angle::Result VertexArrayVk::updateIndexTranslation(ContextVk *contextVk,
return angle::Result::Continue; return angle::Result::Continue;
} }
void VertexArrayVk::updateDefaultAttrib(RendererVk *renderer, void VertexArrayVk::updateDefaultAttrib(ContextVk *contextVk,
size_t attribIndex, size_t attribIndex,
VkBuffer bufferHandle, VkBuffer bufferHandle,
uint32_t offset) uint32_t offset)
...@@ -729,8 +692,9 @@ void VertexArrayVk::updateDefaultAttrib(RendererVk *renderer, ...@@ -729,8 +692,9 @@ void VertexArrayVk::updateDefaultAttrib(RendererVk *renderer,
mCurrentArrayBuffers[attribIndex] = nullptr; mCurrentArrayBuffers[attribIndex] = nullptr;
mCurrentArrayBufferStrides[attribIndex] = 0; mCurrentArrayBufferStrides[attribIndex] = 0;
mCurrentArrayBufferFormats[attribIndex] = mCurrentArrayBufferFormats[attribIndex] =
&renderer->getFormat(angle::FormatID::R32G32B32A32_FIXED); &contextVk->getRenderer()->getFormat(angle::FormatID::R32G32B32A32_FIXED);
mDirtyPackedInputs.set(attribIndex);
setDefaultPackedInput(contextVk, attribIndex);
} }
} }
} // namespace rx } // namespace rx
...@@ -36,16 +36,7 @@ class VertexArrayVk : public VertexArrayImpl ...@@ -36,16 +36,7 @@ class VertexArrayVk : public VertexArrayImpl
const gl::VertexArray::DirtyAttribBitsArray &attribBits, const gl::VertexArray::DirtyAttribBitsArray &attribBits,
const gl::VertexArray::DirtyBindingBitsArray &bindingBits) override; const gl::VertexArray::DirtyBindingBitsArray &bindingBits) override;
ANGLE_INLINE void getPackedInputDescriptions(vk::GraphicsPipelineDesc *pipelineDesc) void updateDefaultAttrib(ContextVk *contextVk,
{
if (mDirtyPackedInputs.any())
{
updatePackedInputDescriptions();
}
pipelineDesc->updateVertexInputInfo(mPackedInputBindings, mPackedInputAttributes);
}
void updateDefaultAttrib(RendererVk *renderer,
size_t attribIndex, size_t attribIndex,
VkBuffer bufferHandle, VkBuffer bufferHandle,
uint32_t offset); uint32_t offset);
...@@ -95,15 +86,11 @@ class VertexArrayVk : public VertexArrayImpl ...@@ -95,15 +86,11 @@ class VertexArrayVk : public VertexArrayImpl
const void *indices); const void *indices);
private: private:
// This will update any dirty packed input descriptions, regardless if they're used by the void setPackedInputInfo(ContextVk *contextVk,
// active program. This could lead to slight inefficiencies when the app would repeatedly size_t attribIndex,
// update vertex info for attributes the program doesn't use, (very silly edge case). The const gl::VertexAttribute &attrib,
// advantage is the cached state then doesn't depend on the Program, so doesn't have to be const gl::VertexBinding &binding);
// updated when the active Program changes. void setDefaultPackedInput(ContextVk *contextVk, size_t attribIndex);
void updatePackedInputDescriptions();
void updatePackedInputInfo(uint32_t attribIndex,
const gl::VertexBinding &binding,
const gl::VertexAttribute &attrib);
angle::Result streamIndexData(ContextVk *contextVk, angle::Result streamIndexData(ContextVk *contextVk,
gl::DrawElementsType indexType, gl::DrawElementsType indexType,
...@@ -135,12 +122,6 @@ class VertexArrayVk : public VertexArrayImpl ...@@ -135,12 +122,6 @@ class VertexArrayVk : public VertexArrayImpl
VkDeviceSize mCurrentElementArrayBufferOffset; VkDeviceSize mCurrentElementArrayBufferOffset;
vk::BufferHelper *mCurrentElementArrayBuffer; vk::BufferHelper *mCurrentElementArrayBuffer;
// Keep a cache of binding and attribute descriptions for easy pipeline updates.
// This is copied out of here into the pipeline description on a Context state change.
gl::AttributesMask mDirtyPackedInputs;
vk::VertexInputBindings mPackedInputBindings;
vk::VertexInputAttributes mPackedInputAttributes;
vk::DynamicBuffer mDynamicVertexData; vk::DynamicBuffer mDynamicVertexData;
vk::DynamicBuffer mDynamicIndexData; vk::DynamicBuffer mDynamicIndexData;
vk::DynamicBuffer mTranslatedByteIndexData; vk::DynamicBuffer mTranslatedByteIndexData;
......
...@@ -672,6 +672,27 @@ angle::Result GraphicsPipelineDesc::initializePipeline( ...@@ -672,6 +672,27 @@ angle::Result GraphicsPipelineDesc::initializePipeline(
return angle::Result::Continue; return angle::Result::Continue;
} }
void GraphicsPipelineDesc::updateVertexInput(uint32_t attribIndex,
GLuint stride,
GLuint divisor,
VkFormat format,
GLuint relativeOffset)
{
vk::PackedVertexInputBindingDesc &bindingDesc = mVertexInputBindings[attribIndex];
bindingDesc.stride = static_cast<uint16_t>(stride);
bindingDesc.inputRate = static_cast<uint16_t>(divisor > 0 ? VK_VERTEX_INPUT_RATE_INSTANCE
: VK_VERTEX_INPUT_RATE_VERTEX);
ASSERT(format <= std::numeric_limits<uint16_t>::max());
if (format == VK_FORMAT_UNDEFINED)
{
UNIMPLEMENTED();
}
mVertexInputAttribs.formats[attribIndex] = static_cast<uint8_t>(format);
mVertexInputAttribs.offsets[attribIndex] = static_cast<uint16_t>(relativeOffset);
}
void GraphicsPipelineDesc::updateTopology(gl::PrimitiveMode drawMode) void GraphicsPipelineDesc::updateTopology(gl::PrimitiveMode drawMode)
{ {
mInputAssembltyAndColorBlendStateInfo.topology = mInputAssembltyAndColorBlendStateInfo.topology =
......
...@@ -268,12 +268,11 @@ class GraphicsPipelineDesc final ...@@ -268,12 +268,11 @@ class GraphicsPipelineDesc final
Pipeline *pipelineOut) const; Pipeline *pipelineOut) const;
// Vertex input state // Vertex input state
ANGLE_INLINE void updateVertexInputInfo(const VertexInputBindings &bindings, void updateVertexInput(uint32_t attribIndex,
const VertexInputAttributes &attribs) GLuint stride,
{ GLuint divisor,
mVertexInputBindings = bindings; VkFormat format,
mVertexInputAttribs = attribs; GLuint relativeOffset);
}
// Input assembly info // Input assembly info
void updateTopology(gl::PrimitiveMode drawMode); void updateTopology(gl::PrimitiveMode drawMode);
......
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