Commit 0136ac37 by Jiacheng Lu Committed by Commit Bot

Separate dirty bit for attrib's binding VBO change

Make a separate dirty bit DIRTY_ATTRIB_POINTER_BUFFER for vertex attrib's binding buffer change. So in handling glVertexAttribPointer, ANGLE will only modify a vulkan graphics pipeline when attrib.format, attrib.stride or attrib.divisor change. If only the VBO pointer changes, then Vulkan can update the state via "vkCmdBindVertexBuffers()" without triggering a pipeline update. Bug: angleproject:3256 Change-Id: I01e02adde3708963b496a20050a5723e8eb57ab2 Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/1707614Reviewed-by: 's avatarJamie Madill <jmadill@chromium.org> Commit-Queue: Jiacheng Lu <lujc@google.com>
parent 6aca71d7
...@@ -457,8 +457,6 @@ ANGLE_INLINE void VertexArray::setVertexAttribPointerImpl(const Context *context ...@@ -457,8 +457,6 @@ ANGLE_INLINE void VertexArray::setVertexAttribPointerImpl(const Context *context
{ {
ASSERT(attribIndex < getMaxAttribs()); ASSERT(attribIndex < getMaxAttribs());
GLintptr offset = boundBuffer ? reinterpret_cast<GLintptr>(pointer) : 0;
VertexAttribute &attrib = mState.mVertexAttributes[attribIndex]; VertexAttribute &attrib = mState.mVertexAttributes[attribIndex];
SetComponentTypeMask(componentType, attribIndex, &mState.mVertexAttributesTypeMask); SetComponentTypeMask(componentType, attribIndex, &mState.mVertexAttributesTypeMask);
...@@ -473,28 +471,35 @@ ANGLE_INLINE void VertexArray::setVertexAttribPointerImpl(const Context *context ...@@ -473,28 +471,35 @@ ANGLE_INLINE void VertexArray::setVertexAttribPointerImpl(const Context *context
GLsizei effectiveStride = GLsizei effectiveStride =
stride != 0 ? stride : static_cast<GLsizei>(ComputeVertexAttributeTypeSize(attrib)); stride != 0 ? stride : static_cast<GLsizei>(ComputeVertexAttributeTypeSize(attrib));
if (pointer != attrib.pointer || attrib.vertexAttribArrayStride != static_cast<GLuint>(stride)) if (attrib.vertexAttribArrayStride != static_cast<GLuint>(stride))
{ {
attribDirty = true; attribDirty = true;
} }
attrib.pointer = pointer;
attrib.vertexAttribArrayStride = stride; attrib.vertexAttribArrayStride = stride;
// "Pointer buffer" dirty bit disabled because of a bug. http://anglebug.com/3256 // If we switch from an array buffer to a client pointer(or vice-versa), we set the whole
// attribute dirty. This notifies the Vulkan back-end to update all its caches.
const VertexBinding &binding = mState.mVertexBindings[attribIndex];
if ((boundBuffer == nullptr) != (binding.getBuffer().get() == nullptr))
{
attribDirty = true;
}
// Change of attrib.pointer is not part of attribDirty. Pointer is actually the buffer offset
// which is handled within bindVertexBufferImpl and reflected in bufferDirty.
attrib.pointer = pointer;
GLintptr offset = boundBuffer ? reinterpret_cast<GLintptr>(pointer) : 0;
const bool bufferDirty =
bindVertexBufferImpl(context, attribIndex, boundBuffer, offset, effectiveStride); bindVertexBufferImpl(context, attribIndex, boundBuffer, offset, effectiveStride);
if (attribDirty)
{
setDirtyAttribBit(attribIndex, DIRTY_ATTRIB_POINTER); setDirtyAttribBit(attribIndex, DIRTY_ATTRIB_POINTER);
ANGLE_UNUSED_VARIABLE(attribDirty); }
else if (bufferDirty)
// if (bindVertexBufferImpl(context, attribIndex, boundBuffer, offset, effectiveStride) && {
// !attribDirty) setDirtyAttribBit(attribIndex, DIRTY_ATTRIB_POINTER_BUFFER);
//{ }
// setDirtyAttribBit(attribIndex, DIRTY_ATTRIB_POINTER_BUFFER);
//}
// else if (attribDirty)
//{
// setDirtyAttribBit(attribIndex, DIRTY_ATTRIB_POINTER);
//}
mState.mNullPointerClientMemoryAttribsMask.set(attribIndex, mState.mNullPointerClientMemoryAttribsMask.set(attribIndex,
boundBuffer == nullptr && pointer == nullptr); boundBuffer == nullptr && pointer == nullptr);
......
...@@ -361,18 +361,15 @@ angle::Result VertexArrayVk::syncState(const gl::Context *context, ...@@ -361,18 +361,15 @@ angle::Result VertexArrayVk::syncState(const gl::Context *context,
#define ANGLE_VERTEX_DIRTY_ATTRIB_FUNC(INDEX) \ #define ANGLE_VERTEX_DIRTY_ATTRIB_FUNC(INDEX) \
case gl::VertexArray::DIRTY_BIT_ATTRIB_0 + INDEX: \ case gl::VertexArray::DIRTY_BIT_ATTRIB_0 + INDEX: \
if ((*attribBits)[INDEX].to_ulong() == \
angle::Bit<unsigned long>(gl::VertexArray::DIRTY_ATTRIB_POINTER_BUFFER)) \
{ \
syncDirtyBuffer(contextVk, bindings[INDEX], INDEX); \
} \
else \
{ \ { \
const bool bufferOnly = \
(*attribBits)[INDEX].to_ulong() == \
angle::Bit<unsigned long>(gl::VertexArray::DIRTY_ATTRIB_POINTER_BUFFER); \
ANGLE_TRY(syncDirtyAttrib(contextVk, attribs[INDEX], \ ANGLE_TRY(syncDirtyAttrib(contextVk, attribs[INDEX], \
bindings[attribs[INDEX].bindingIndex], INDEX)); \ bindings[attribs[INDEX].bindingIndex], INDEX, bufferOnly)); \
} \
(*attribBits)[INDEX].reset(); \ (*attribBits)[INDEX].reset(); \
break; break; \
}
ANGLE_VERTEX_INDEX_CASES(ANGLE_VERTEX_DIRTY_ATTRIB_FUNC) ANGLE_VERTEX_INDEX_CASES(ANGLE_VERTEX_DIRTY_ATTRIB_FUNC)
...@@ -380,8 +377,8 @@ angle::Result VertexArrayVk::syncState(const gl::Context *context, ...@@ -380,8 +377,8 @@ angle::Result VertexArrayVk::syncState(const gl::Context *context,
case gl::VertexArray::DIRTY_BIT_BINDING_0 + INDEX: \ case gl::VertexArray::DIRTY_BIT_BINDING_0 + INDEX: \
for (size_t attribIndex : bindings[INDEX].getBoundAttributesMask()) \ for (size_t attribIndex : bindings[INDEX].getBoundAttributesMask()) \
{ \ { \
ANGLE_TRY( \ ANGLE_TRY(syncDirtyAttrib(contextVk, attribs[attribIndex], bindings[INDEX], \
syncDirtyAttrib(contextVk, attribs[attribIndex], bindings[INDEX], attribIndex)); \ attribIndex, false)); \
} \ } \
(*bindingBits)[INDEX].reset(); \ (*bindingBits)[INDEX].reset(); \
break; break;
...@@ -391,7 +388,7 @@ angle::Result VertexArrayVk::syncState(const gl::Context *context, ...@@ -391,7 +388,7 @@ angle::Result VertexArrayVk::syncState(const gl::Context *context,
#define ANGLE_VERTEX_DIRTY_BUFFER_DATA_FUNC(INDEX) \ #define ANGLE_VERTEX_DIRTY_BUFFER_DATA_FUNC(INDEX) \
case gl::VertexArray::DIRTY_BIT_BUFFER_DATA_0 + INDEX: \ case gl::VertexArray::DIRTY_BIT_BUFFER_DATA_0 + INDEX: \
ANGLE_TRY(syncDirtyAttrib(contextVk, attribs[INDEX], \ ANGLE_TRY(syncDirtyAttrib(contextVk, attribs[INDEX], \
bindings[attribs[INDEX].bindingIndex], INDEX)); \ bindings[attribs[INDEX].bindingIndex], INDEX, false)); \
break; break;
ANGLE_VERTEX_INDEX_CASES(ANGLE_VERTEX_DIRTY_BUFFER_DATA_FUNC) ANGLE_VERTEX_INDEX_CASES(ANGLE_VERTEX_DIRTY_BUFFER_DATA_FUNC)
...@@ -423,17 +420,17 @@ ANGLE_INLINE void VertexArrayVk::setDefaultPackedInput(ContextVk *contextVk, siz ...@@ -423,17 +420,17 @@ ANGLE_INLINE void VertexArrayVk::setDefaultPackedInput(ContextVk *contextVk, siz
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,
bool bufferOnly)
{ {
RendererVk *renderer = contextVk->getRenderer();
bool anyVertexBufferConvertedOnGpu = false;
if (attrib.enabled) if (attrib.enabled)
{ {
gl::Buffer *bufferGL = binding.getBuffer().get(); RendererVk *renderer = contextVk->getRenderer();
const vk::Format &vertexFormat = renderer->getFormat(attrib.format->id); const vk::Format &vertexFormat = renderer->getFormat(attrib.format->id);
GLuint stride;
GLuint stride;
bool anyVertexBufferConvertedOnGpu = false;
gl::Buffer *bufferGL = binding.getBuffer().get();
if (bufferGL) if (bufferGL)
{ {
BufferVk *bufferVk = vk::GetImpl(bufferGL); BufferVk *bufferVk = vk::GetImpl(bufferGL);
...@@ -443,8 +440,6 @@ angle::Result VertexArrayVk::syncDirtyAttrib(ContextVk *contextVk, ...@@ -443,8 +440,6 @@ angle::Result VertexArrayVk::syncDirtyAttrib(ContextVk *contextVk,
if (vertexFormat.vertexLoadRequiresConversion || !bindingIsAligned) if (vertexFormat.vertexLoadRequiresConversion || !bindingIsAligned)
{ {
stride = vertexFormat.bufferFormat().pixelBytes;
ConversionBuffer *conversion = bufferVk->getVertexConversionBuffer( ConversionBuffer *conversion = bufferVk->getVertexConversionBuffer(
renderer, angleFormat.id, binding.getStride(), renderer, angleFormat.id, binding.getStride(),
binding.getOffset() + attrib.relativeOffset); binding.getOffset() + attrib.relativeOffset);
...@@ -463,13 +458,21 @@ angle::Result VertexArrayVk::syncDirtyAttrib(ContextVk *contextVk, ...@@ -463,13 +458,21 @@ angle::Result VertexArrayVk::syncDirtyAttrib(ContextVk *contextVk,
vertexFormat, conversion, vertexFormat, conversion,
attrib.relativeOffset)); attrib.relativeOffset));
} }
// If conversion happens, the destination buffer stride may be changed,
// therefore an attribute change needs to be called. Note that it may trigger
// unnecessary vulkan PSO update when the destination buffer stride does not
// change, but for simplity just make it conservative
bufferOnly = false;
} }
mCurrentArrayBuffers[attribIndex] = conversion->data.getCurrentBuffer(); vk::BufferHelper *bufferHelper = conversion->data.getCurrentBuffer();
mCurrentArrayBufferHandles[attribIndex] = mCurrentArrayBuffers[attribIndex] = bufferHelper;
mCurrentArrayBuffers[attribIndex]->getBuffer().getHandle(); mCurrentArrayBufferHandles[attribIndex] = bufferHelper->getBuffer().getHandle();
mCurrentArrayBufferOffsets[attribIndex] = mCurrentArrayBufferOffsets[attribIndex] = conversion->lastAllocationOffset;
conversion->lastAllocationOffset - attrib.relativeOffset;
// Converted buffer is tightly packed
stride = vertexFormat.bufferFormat().pixelBytes;
} }
else else
{ {
...@@ -484,7 +487,6 @@ angle::Result VertexArrayVk::syncDirtyAttrib(ContextVk *contextVk, ...@@ -484,7 +487,6 @@ angle::Result VertexArrayVk::syncDirtyAttrib(ContextVk *contextVk,
else else
{ {
vk::BufferHelper &bufferHelper = bufferVk->getBuffer(); vk::BufferHelper &bufferHelper = bufferVk->getBuffer();
mCurrentArrayBuffers[attribIndex] = &bufferHelper; mCurrentArrayBuffers[attribIndex] = &bufferHelper;
mCurrentArrayBufferHandles[attribIndex] = bufferHelper.getBuffer().getHandle(); mCurrentArrayBufferHandles[attribIndex] = bufferHelper.getBuffer().getHandle();
mCurrentArrayBufferOffsets[attribIndex] = binding.getOffset(); mCurrentArrayBufferOffsets[attribIndex] = binding.getOffset();
...@@ -497,12 +499,26 @@ angle::Result VertexArrayVk::syncDirtyAttrib(ContextVk *contextVk, ...@@ -497,12 +499,26 @@ angle::Result VertexArrayVk::syncDirtyAttrib(ContextVk *contextVk,
mCurrentArrayBuffers[attribIndex] = &mTheNullBuffer; mCurrentArrayBuffers[attribIndex] = &mTheNullBuffer;
mCurrentArrayBufferHandles[attribIndex] = mTheNullBuffer.getBuffer().getHandle(); mCurrentArrayBufferHandles[attribIndex] = mTheNullBuffer.getBuffer().getHandle();
mCurrentArrayBufferOffsets[attribIndex] = 0; mCurrentArrayBufferOffsets[attribIndex] = 0;
// Client side buffer will be transfered to a tightly packed buffer later
stride = vertexFormat.bufferFormat().pixelBytes; stride = vertexFormat.bufferFormat().pixelBytes;
} }
if (bufferOnly)
{
contextVk->invalidateVertexBuffers();
}
else
{
contextVk->onVertexAttributeChange(attribIndex, stride, binding.getDivisor(), contextVk->onVertexAttributeChange(attribIndex, stride, binding.getDivisor(),
attrib.format->id, attrib.relativeOffset); attrib.format->id, attrib.relativeOffset);
} }
if (anyVertexBufferConvertedOnGpu &&
renderer->getFeatures().flushAfterVertexConversion.enabled)
{
ANGLE_TRY(contextVk->flushImpl(nullptr));
}
}
else else
{ {
contextVk->invalidateDefaultAttribute(attribIndex); contextVk->invalidateDefaultAttribute(attribIndex);
...@@ -515,38 +531,9 @@ angle::Result VertexArrayVk::syncDirtyAttrib(ContextVk *contextVk, ...@@ -515,38 +531,9 @@ angle::Result VertexArrayVk::syncDirtyAttrib(ContextVk *contextVk,
setDefaultPackedInput(contextVk, attribIndex); setDefaultPackedInput(contextVk, attribIndex);
} }
if (anyVertexBufferConvertedOnGpu && renderer->getFeatures().flushAfterVertexConversion.enabled)
{
ANGLE_TRY(contextVk->flushImpl(nullptr));
}
return angle::Result::Continue; return angle::Result::Continue;
} }
void VertexArrayVk::syncDirtyBuffer(ContextVk *contextVk,
const gl::VertexBinding &binding,
size_t bindingIndex)
{
gl::Buffer *bufferGL = binding.getBuffer().get();
if (bufferGL)
{
BufferVk *bufferVk = vk::GetImpl(bufferGL);
vk::BufferHelper &bufferHelper = bufferVk->getBuffer();
mCurrentArrayBuffers[bindingIndex] = &bufferHelper;
mCurrentArrayBufferHandles[bindingIndex] = bufferHelper.getBuffer().getHandle();
mCurrentArrayBufferOffsets[bindingIndex] = binding.getOffset();
}
else
{
mCurrentArrayBuffers[bindingIndex] = &mTheNullBuffer;
mCurrentArrayBufferHandles[bindingIndex] = mTheNullBuffer.getBuffer().getHandle();
mCurrentArrayBufferOffsets[bindingIndex] = 0;
}
contextVk->invalidateVertexBuffers();
}
angle::Result VertexArrayVk::updateClientAttribs(const gl::Context *context, angle::Result VertexArrayVk::updateClientAttribs(const gl::Context *context,
GLint firstVertex, GLint firstVertex,
GLsizei vertexOrIndexCount, GLsizei vertexOrIndexCount,
......
...@@ -108,11 +108,8 @@ class VertexArrayVk : public VertexArrayImpl ...@@ -108,11 +108,8 @@ class VertexArrayVk : public VertexArrayImpl
angle::Result syncDirtyAttrib(ContextVk *contextVk, angle::Result 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,
bool bufferOnly);
void syncDirtyBuffer(ContextVk *contextVk,
const gl::VertexBinding &binding,
size_t bindingIndex);
gl::AttribArray<VkBuffer> mCurrentArrayBufferHandles; gl::AttribArray<VkBuffer> mCurrentArrayBufferHandles;
gl::AttribArray<VkDeviceSize> mCurrentArrayBufferOffsets; gl::AttribArray<VkDeviceSize> mCurrentArrayBufferOffsets;
......
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