Vulkan: invalidate translation buffers for SSBOs
Translation buffers weren't being marked dirty after running a compute
shader in which they are bound as SSBOs.
This change invalidates all SSBOs after a draw or compute call.
Bug: angleproject:3739
Change-Id: I66b56df7e619b55afc7e3da6b5613b6d050e06bb
Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/1717144
Reviewed-by: Shahbaz Youssefi <syoussefi@chromium.org>
Reviewed-by: Jamie Madill <jmadill@chromium.org>
Commit-Queue: James Dong <dongja@google.com>
diff --git a/src/libANGLE/Buffer.cpp b/src/libANGLE/Buffer.cpp
index 9ffcddb..7e036b9 100644
--- a/src/libANGLE/Buffer.cpp
+++ b/src/libANGLE/Buffer.cpp
@@ -210,20 +210,14 @@
return angle::Result::Continue;
}
-void Buffer::onTransformFeedback()
+void Buffer::onDataChanged()
{
mIndexRangeCache.clear();
// Notify when data changes.
onStateChange(angle::SubjectMessage::ContentsChanged);
-}
-void Buffer::onPixelPack()
-{
- mIndexRangeCache.clear();
-
- // Notify when data changes.
- onStateChange(angle::SubjectMessage::ContentsChanged);
+ mImpl->onDataChanged();
}
angle::Result Buffer::getIndexRange(const gl::Context *context,
diff --git a/src/libANGLE/Buffer.h b/src/libANGLE/Buffer.h
index ef3eefe..e43ddf6 100644
--- a/src/libANGLE/Buffer.h
+++ b/src/libANGLE/Buffer.h
@@ -100,8 +100,7 @@
angle::Result unmap(const Context *context, GLboolean *result);
// These are called when another operation changes Buffer data.
- void onTransformFeedback();
- void onPixelPack();
+ void onDataChanged();
angle::Result getIndexRange(const gl::Context *context,
DrawElementsType type,
diff --git a/src/libANGLE/Context.cpp b/src/libANGLE/Context.cpp
index d6edd72..d83f863 100644
--- a/src/libANGLE/Context.cpp
+++ b/src/libANGLE/Context.cpp
@@ -2244,6 +2244,7 @@
ANGLE_CONTEXT_TRY(
mImplementation->drawArraysInstanced(this, mode, first, count, instanceCount));
MarkTransformFeedbackBufferUsage(this, count, instanceCount);
+ MarkShaderStorageBufferUsage(this);
}
void Context::drawElementsInstanced(PrimitiveMode mode,
@@ -2261,6 +2262,7 @@
ANGLE_CONTEXT_TRY(prepareForDraw(mode));
ANGLE_CONTEXT_TRY(
mImplementation->drawElementsInstanced(this, mode, count, type, indices, instances));
+ MarkShaderStorageBufferUsage(this);
}
void Context::drawRangeElements(PrimitiveMode mode,
@@ -2279,18 +2281,21 @@
ANGLE_CONTEXT_TRY(prepareForDraw(mode));
ANGLE_CONTEXT_TRY(
mImplementation->drawRangeElements(this, mode, start, end, count, type, indices));
+ MarkShaderStorageBufferUsage(this);
}
void Context::drawArraysIndirect(PrimitiveMode mode, const void *indirect)
{
ANGLE_CONTEXT_TRY(prepareForDraw(mode));
ANGLE_CONTEXT_TRY(mImplementation->drawArraysIndirect(this, mode, indirect));
+ MarkShaderStorageBufferUsage(this);
}
void Context::drawElementsIndirect(PrimitiveMode mode, DrawElementsType type, const void *indirect)
{
ANGLE_CONTEXT_TRY(prepareForDraw(mode));
ANGLE_CONTEXT_TRY(mImplementation->drawElementsIndirect(this, mode, type, indirect));
+ MarkShaderStorageBufferUsage(this);
}
void Context::flush()
@@ -5395,12 +5400,16 @@
ANGLE_CONTEXT_TRY(prepareForDispatch());
ANGLE_CONTEXT_TRY(mImplementation->dispatchCompute(this, numGroupsX, numGroupsY, numGroupsZ));
+
+ MarkShaderStorageBufferUsage(this);
}
void Context::dispatchComputeIndirect(GLintptr indirect)
{
ANGLE_CONTEXT_TRY(prepareForDispatch());
ANGLE_CONTEXT_TRY(mImplementation->dispatchComputeIndirect(this, indirect));
+
+ MarkShaderStorageBufferUsage(this);
}
void Context::texStorage2D(TextureType target,
@@ -5456,6 +5465,7 @@
ANGLE_CONTEXT_TRY(
mImplementation->drawArrays(this, mode, firsts[drawID], counts[drawID]));
MarkTransformFeedbackBufferUsage(this, counts[drawID], 1);
+ MarkShaderStorageBufferUsage(this);
}
}
else
@@ -5469,6 +5479,7 @@
ANGLE_CONTEXT_TRY(
mImplementation->drawArrays(this, mode, firsts[drawID], counts[drawID]));
MarkTransformFeedbackBufferUsage(this, counts[drawID], 1);
+ MarkShaderStorageBufferUsage(this);
}
}
}
@@ -5494,6 +5505,7 @@
ANGLE_CONTEXT_TRY(mImplementation->drawArraysInstanced(
this, mode, firsts[drawID], counts[drawID], instanceCounts[drawID]));
MarkTransformFeedbackBufferUsage(this, counts[drawID], instanceCounts[drawID]);
+ MarkShaderStorageBufferUsage(this);
}
}
else
@@ -5507,6 +5519,7 @@
ANGLE_CONTEXT_TRY(mImplementation->drawArraysInstanced(
this, mode, firsts[drawID], counts[drawID], instanceCounts[drawID]));
MarkTransformFeedbackBufferUsage(this, counts[drawID], instanceCounts[drawID]);
+ MarkShaderStorageBufferUsage(this);
}
}
}
@@ -5531,6 +5544,7 @@
programObject->setDrawIDUniform(drawID);
ANGLE_CONTEXT_TRY(
mImplementation->drawElements(this, mode, counts[drawID], type, indices[drawID]));
+ MarkShaderStorageBufferUsage(this);
}
}
else
@@ -5543,6 +5557,7 @@
}
ANGLE_CONTEXT_TRY(
mImplementation->drawElements(this, mode, counts[drawID], type, indices[drawID]));
+ MarkShaderStorageBufferUsage(this);
}
}
}
@@ -5568,6 +5583,7 @@
programObject->setDrawIDUniform(drawID);
ANGLE_CONTEXT_TRY(mImplementation->drawElementsInstanced(
this, mode, counts[drawID], type, indices[drawID], instanceCounts[drawID]));
+ MarkShaderStorageBufferUsage(this);
}
}
else
@@ -5580,6 +5596,7 @@
}
ANGLE_CONTEXT_TRY(mImplementation->drawElementsInstanced(
this, mode, counts[drawID], type, indices[drawID], instanceCounts[drawID]));
+ MarkShaderStorageBufferUsage(this);
}
}
}
@@ -8705,6 +8722,7 @@
updateVertexElementLimits(context);
updateBasicDrawStatesError();
updateValidDrawModes(context);
+ updateActiveShaderStorageBufferIndices(context);
}
void StateCache::onVertexArrayFormatChange(Context *context)
@@ -8934,4 +8952,17 @@
}};
}
}
+
+void StateCache::updateActiveShaderStorageBufferIndices(Context *context)
+{
+ mCachedActiveShaderStorageBufferIndices.reset();
+ Program *program = context->getState().getProgram();
+ if (program)
+ {
+ for (const InterfaceBlock &block : program->getState().getShaderStorageBlocks())
+ {
+ mCachedActiveShaderStorageBufferIndices.set(block.binding);
+ }
+ }
+}
} // namespace gl
diff --git a/src/libANGLE/Context.h b/src/libANGLE/Context.h
index 4ae7c7e..1a972bc 100644
--- a/src/libANGLE/Context.h
+++ b/src/libANGLE/Context.h
@@ -247,6 +247,13 @@
return mCachedIntegerVertexAttribTypesValidation[type];
}
+ // Places that can trigger updateActiveShaderStorageBufferIndices:
+ // 1. onProgramExecutableChange.
+ StorageBuffersMask getActiveShaderStorageBufferIndices() const
+ {
+ return mCachedActiveShaderStorageBufferIndices;
+ }
+
// State change notifications.
void onVertexArrayBindingChange(Context *context);
void onProgramExecutableChange(Context *context);
@@ -278,6 +285,7 @@
void updateBasicDrawElementsError();
void updateTransformFeedbackActiveUnpaused(Context *context);
void updateVertexAttribTypesValidation(Context *context);
+ void updateActiveShaderStorageBufferIndices(Context *context);
void setValidDrawModes(bool pointsOK, bool linesOK, bool trisOK, bool lineAdjOK, bool triAdjOK);
@@ -295,6 +303,7 @@
mutable intptr_t mCachedBasicDrawStatesError;
mutable intptr_t mCachedBasicDrawElementsError;
bool mCachedTransformFeedbackActiveUnpaused;
+ StorageBuffersMask mCachedActiveShaderStorageBufferIndices;
// Reserve an extra slot at the end of these maps for invalid enum.
angle::PackedEnumMap<PrimitiveMode, bool, angle::EnumSize<PrimitiveMode>() + 1>
diff --git a/src/libANGLE/Context.inl.h b/src/libANGLE/Context.inl.h
index 4738160..af72e72 100644
--- a/src/libANGLE/Context.inl.h
+++ b/src/libANGLE/Context.inl.h
@@ -46,6 +46,18 @@
}
}
+ANGLE_INLINE void MarkShaderStorageBufferUsage(const Context *context)
+{
+ for (size_t index : context->getStateCache().getActiveShaderStorageBufferIndices())
+ {
+ gl::Buffer *buffer = context->getState().getIndexedShaderStorageBuffer(index).get();
+ if (buffer)
+ {
+ buffer->onDataChanged();
+ }
+ }
+}
+
// Return true if the draw is a no-op, else return false.
// A no-op draw occurs if the count of vertices is less than the minimum required to
// have a valid primitive for this mode (0 for points, 0-1 for lines, 0-2 for tris).
diff --git a/src/libANGLE/Framebuffer.cpp b/src/libANGLE/Framebuffer.cpp
index 64acc8a..0346894 100644
--- a/src/libANGLE/Framebuffer.cpp
+++ b/src/libANGLE/Framebuffer.cpp
@@ -1512,7 +1512,7 @@
Buffer *unpackBuffer = context->getState().getTargetBuffer(BufferBinding::PixelUnpack);
if (unpackBuffer)
{
- unpackBuffer->onPixelPack();
+ unpackBuffer->onDataChanged();
}
return angle::Result::Continue;
diff --git a/src/libANGLE/TransformFeedback.cpp b/src/libANGLE/TransformFeedback.cpp
index 3222f14..129f9c0 100644
--- a/src/libANGLE/TransformFeedback.cpp
+++ b/src/libANGLE/TransformFeedback.cpp
@@ -214,7 +214,7 @@
{
if (buffer.get() != nullptr)
{
- buffer->onTransformFeedback();
+ buffer->onDataChanged();
}
}
}
diff --git a/src/libANGLE/angletypes.h b/src/libANGLE/angletypes.h
index d859073..8c36ab1 100644
--- a/src/libANGLE/angletypes.h
+++ b/src/libANGLE/angletypes.h
@@ -387,6 +387,9 @@
// Used in Framebuffer / Program
using DrawBufferMask = angle::BitSet<IMPLEMENTATION_MAX_DRAW_BUFFERS>;
+// Used in StateCache
+using StorageBuffersMask = angle::BitSet<IMPLEMENTATION_MAX_SHADER_STORAGE_BUFFER_BINDINGS>;
+
template <typename T>
using TexLevelArray = std::array<T, IMPLEMENTATION_MAX_TEXTURE_LEVELS>;
diff --git a/src/libANGLE/renderer/BufferImpl.h b/src/libANGLE/renderer/BufferImpl.h
index 77b7737..ae52f7f 100644
--- a/src/libANGLE/renderer/BufferImpl.h
+++ b/src/libANGLE/renderer/BufferImpl.h
@@ -68,6 +68,8 @@
// Override if accurate native memory size information is available
virtual GLint64 getMemorySize() const;
+ virtual void onDataChanged() {}
+
protected:
const gl::BufferState &mState;
};
diff --git a/src/libANGLE/renderer/vulkan/BufferVk.cpp b/src/libANGLE/renderer/vulkan/BufferVk.cpp
index cc555a3..6f84f89 100644
--- a/src/libANGLE/renderer/vulkan/BufferVk.cpp
+++ b/src/libANGLE/renderer/vulkan/BufferVk.cpp
@@ -377,4 +377,9 @@
}
}
+void BufferVk::onDataChanged()
+{
+ markConversionBuffersDirty();
+}
+
} // namespace rx
diff --git a/src/libANGLE/renderer/vulkan/BufferVk.h b/src/libANGLE/renderer/vulkan/BufferVk.h
index cd4a593..fecf5eb 100644
--- a/src/libANGLE/renderer/vulkan/BufferVk.h
+++ b/src/libANGLE/renderer/vulkan/BufferVk.h
@@ -79,6 +79,8 @@
GLint64 getSize() const { return mState.getSize(); }
+ void onDataChanged() override;
+
const vk::BufferHelper &getBuffer() const
{
ASSERT(mBuffer.valid());
diff --git a/src/libANGLE/renderer/vulkan/RendererVk.cpp b/src/libANGLE/renderer/vulkan/RendererVk.cpp
index c1aeca4..11beebe 100644
--- a/src/libANGLE/renderer/vulkan/RendererVk.cpp
+++ b/src/libANGLE/renderer/vulkan/RendererVk.cpp
@@ -1123,6 +1123,13 @@
maxVersion = std::min(maxVersion, gl::Version(3, 0));
}
+ // ES3.1 requires at least a maximum offset of at least 2047.
+ // If the Vulkan implementation can't support that, we cannot support 3.1.
+ if (mPhysicalDeviceProperties.limits.maxVertexInputAttributeOffset < 2047)
+ {
+ maxVersion = std::min(maxVersion, gl::Version(3, 0));
+ }
+
// Limit to ES2.0 if there are any blockers for 3.0.
// If the command buffer doesn't support queries, we can't support ES3.
diff --git a/src/libANGLE/renderer/vulkan/vk_caps_utils.cpp b/src/libANGLE/renderer/vulkan/vk_caps_utils.cpp
index 5dac9f0..4b79129 100644
--- a/src/libANGLE/renderer/vulkan/vk_caps_utils.cpp
+++ b/src/libANGLE/renderer/vulkan/vk_caps_utils.cpp
@@ -142,8 +142,13 @@
mNativeCaps.maxVertexAttributes = limitsVk.maxVertexInputAttributes;
mNativeCaps.maxVertexAttribBindings = limitsVk.maxVertexInputBindings;
- mNativeCaps.maxVertexAttribRelativeOffset = limitsVk.maxVertexInputAttributeOffset;
- mNativeCaps.maxVertexAttribStride = limitsVk.maxVertexInputBindingStride;
+ // Offset and stride are stored as uint16_t in PackedAttribDesc.
+ mNativeCaps.maxVertexAttribRelativeOffset =
+ std::min(static_cast<uint32_t>(std::numeric_limits<uint16_t>::max()),
+ limitsVk.maxVertexInputAttributeOffset);
+ mNativeCaps.maxVertexAttribStride =
+ std::min(static_cast<uint32_t>(std::numeric_limits<uint16_t>::max()),
+ limitsVk.maxVertexInputBindingStride);
mNativeCaps.maxElementsIndices = std::numeric_limits<GLint>::max();
mNativeCaps.maxElementsVertices = std::numeric_limits<GLint>::max();
diff --git a/src/tests/gl_tests/VertexAttributeTest.cpp b/src/tests/gl_tests/VertexAttributeTest.cpp
index 8bc914b..e55cfeb 100644
--- a/src/tests/gl_tests/VertexAttributeTest.cpp
+++ b/src/tests/gl_tests/VertexAttributeTest.cpp
@@ -1358,7 +1358,7 @@
glUseProgram(computeProgram);
glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, testBuffer);
glDispatchCompute(1, 1, 1);
- glMemoryBarrier(GL_SHADER_STORAGE_BARRIER_BIT);
+ glMemoryBarrier(GL_VERTEX_ATTRIB_ARRAY_BARRIER_BIT);
// Draw again to verify that testBuffer has been changed.
glUseProgram(mProgram);
@@ -1449,6 +1449,8 @@
// Verify that only updating a binding without updating the bound format won't mess up this draw.
TEST_P(VertexAttributeTestES31, OnlyUpdateBindingByBindVertexBuffer)
{
+ ANGLE_SKIP_TEST_IF(IsVulkan()); // anglebug.com/3598 - vertex attrib binding
+
// Default binding index for test
constexpr GLint kTestBinding = 10;
initOnlyUpdateBindingTest(kTestBinding);
@@ -1486,6 +1488,8 @@
// Verify that only updating a binding without updating the bound format won't mess up this draw.
TEST_P(VertexAttributeTestES31, OnlyUpdateBindingByVertexAttribPointer)
{
+ ANGLE_SKIP_TEST_IF(IsVulkan()); // anglebug.com/3598 - vertex attrib binding
+
// Default binding index for test
constexpr GLint kTestBinding = 10;
initOnlyUpdateBindingTest(kTestBinding);
@@ -2053,7 +2057,11 @@
ES3_OPENGLES(),
ES3_VULKAN());
-ANGLE_INSTANTIATE_TEST(VertexAttributeTestES31, ES31_D3D11(), ES31_OPENGL(), ES31_OPENGLES());
+ANGLE_INSTANTIATE_TEST(VertexAttributeTestES31,
+ ES31_D3D11(),
+ ES31_OPENGL(),
+ ES31_OPENGLES(),
+ ES31_VULKAN());
ANGLE_INSTANTIATE_TEST(VertexAttributeCachingTest,
ES2_D3D9(),