зеркало из https://github.com/AvaloniaUI/angle.git
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>
This commit is contained in:
Родитель
3e9bc2a72b
Коммит
020abb8b82
|
@ -210,20 +210,14 @@ angle::Result Buffer::unmap(const Context *context, GLboolean *result)
|
|||
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,
|
||||
|
|
|
@ -100,8 +100,7 @@ class Buffer final : public RefCountObject,
|
|||
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,
|
||||
|
|
|
@ -2244,6 +2244,7 @@ void Context::drawArraysInstanced(PrimitiveMode mode,
|
|||
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 @@ void Context::drawElementsInstanced(PrimitiveMode mode,
|
|||
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 @@ void Context::drawRangeElements(PrimitiveMode mode,
|
|||
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 @@ void Context::dispatchCompute(GLuint numGroupsX, GLuint numGroupsY, GLuint numGr
|
|||
|
||||
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 @@ void Context::multiDrawArrays(PrimitiveMode mode,
|
|||
ANGLE_CONTEXT_TRY(
|
||||
mImplementation->drawArrays(this, mode, firsts[drawID], counts[drawID]));
|
||||
MarkTransformFeedbackBufferUsage(this, counts[drawID], 1);
|
||||
MarkShaderStorageBufferUsage(this);
|
||||
}
|
||||
}
|
||||
else
|
||||
|
@ -5469,6 +5479,7 @@ void Context::multiDrawArrays(PrimitiveMode mode,
|
|||
ANGLE_CONTEXT_TRY(
|
||||
mImplementation->drawArrays(this, mode, firsts[drawID], counts[drawID]));
|
||||
MarkTransformFeedbackBufferUsage(this, counts[drawID], 1);
|
||||
MarkShaderStorageBufferUsage(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -5494,6 +5505,7 @@ void Context::multiDrawArraysInstanced(PrimitiveMode mode,
|
|||
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 @@ void Context::multiDrawArraysInstanced(PrimitiveMode mode,
|
|||
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 @@ void Context::multiDrawElements(PrimitiveMode mode,
|
|||
programObject->setDrawIDUniform(drawID);
|
||||
ANGLE_CONTEXT_TRY(
|
||||
mImplementation->drawElements(this, mode, counts[drawID], type, indices[drawID]));
|
||||
MarkShaderStorageBufferUsage(this);
|
||||
}
|
||||
}
|
||||
else
|
||||
|
@ -5543,6 +5557,7 @@ void Context::multiDrawElements(PrimitiveMode mode,
|
|||
}
|
||||
ANGLE_CONTEXT_TRY(
|
||||
mImplementation->drawElements(this, mode, counts[drawID], type, indices[drawID]));
|
||||
MarkShaderStorageBufferUsage(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -5568,6 +5583,7 @@ void Context::multiDrawElementsInstanced(PrimitiveMode mode,
|
|||
programObject->setDrawIDUniform(drawID);
|
||||
ANGLE_CONTEXT_TRY(mImplementation->drawElementsInstanced(
|
||||
this, mode, counts[drawID], type, indices[drawID], instanceCounts[drawID]));
|
||||
MarkShaderStorageBufferUsage(this);
|
||||
}
|
||||
}
|
||||
else
|
||||
|
@ -5580,6 +5596,7 @@ void Context::multiDrawElementsInstanced(PrimitiveMode mode,
|
|||
}
|
||||
ANGLE_CONTEXT_TRY(mImplementation->drawElementsInstanced(
|
||||
this, mode, counts[drawID], type, indices[drawID], instanceCounts[drawID]));
|
||||
MarkShaderStorageBufferUsage(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -8705,6 +8722,7 @@ void StateCache::onProgramExecutableChange(Context *context)
|
|||
updateVertexElementLimits(context);
|
||||
updateBasicDrawStatesError();
|
||||
updateValidDrawModes(context);
|
||||
updateActiveShaderStorageBufferIndices(context);
|
||||
}
|
||||
|
||||
void StateCache::onVertexArrayFormatChange(Context *context)
|
||||
|
@ -8934,4 +8952,17 @@ void StateCache::updateVertexAttribTypesValidation(Context *context)
|
|||
}};
|
||||
}
|
||||
}
|
||||
|
||||
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
|
||||
|
|
|
@ -247,6 +247,13 @@ class StateCache final : angle::NonCopyable
|
|||
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 @@ class StateCache final : angle::NonCopyable
|
|||
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 @@ class StateCache final : angle::NonCopyable
|
|||
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>
|
||||
|
|
|
@ -46,6 +46,18 @@ ANGLE_INLINE void MarkTransformFeedbackBufferUsage(const Context *context,
|
|||
}
|
||||
}
|
||||
|
||||
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).
|
||||
|
|
|
@ -1512,7 +1512,7 @@ angle::Result Framebuffer::readPixels(const Context *context,
|
|||
Buffer *unpackBuffer = context->getState().getTargetBuffer(BufferBinding::PixelUnpack);
|
||||
if (unpackBuffer)
|
||||
{
|
||||
unpackBuffer->onPixelPack();
|
||||
unpackBuffer->onDataChanged();
|
||||
}
|
||||
|
||||
return angle::Result::Continue;
|
||||
|
|
|
@ -214,7 +214,7 @@ void TransformFeedback::onVerticesDrawn(const Context *context, GLsizei count, G
|
|||
{
|
||||
if (buffer.get() != nullptr)
|
||||
{
|
||||
buffer->onTransformFeedback();
|
||||
buffer->onDataChanged();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -387,6 +387,9 @@ using UniformBlockBindingMask = angle::BitSet<IMPLEMENTATION_MAX_COMBINED_SHADER
|
|||
// 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>;
|
||||
|
||||
|
|
|
@ -68,6 +68,8 @@ class BufferImpl : public angle::Subject
|
|||
// Override if accurate native memory size information is available
|
||||
virtual GLint64 getMemorySize() const;
|
||||
|
||||
virtual void onDataChanged() {}
|
||||
|
||||
protected:
|
||||
const gl::BufferState &mState;
|
||||
};
|
||||
|
|
|
@ -377,4 +377,9 @@ void BufferVk::markConversionBuffersDirty()
|
|||
}
|
||||
}
|
||||
|
||||
void BufferVk::onDataChanged()
|
||||
{
|
||||
markConversionBuffersDirty();
|
||||
}
|
||||
|
||||
} // namespace rx
|
||||
|
|
|
@ -79,6 +79,8 @@ class BufferVk : public BufferImpl
|
|||
|
||||
GLint64 getSize() const { return mState.getSize(); }
|
||||
|
||||
void onDataChanged() override;
|
||||
|
||||
const vk::BufferHelper &getBuffer() const
|
||||
{
|
||||
ASSERT(mBuffer.valid());
|
||||
|
|
|
@ -1123,6 +1123,13 @@ gl::Version RendererVk::getMaxSupportedESVersion() const
|
|||
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.
|
||||
|
|
|
@ -142,8 +142,13 @@ void RendererVk::ensureCapsInitialized() const
|
|||
|
||||
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();
|
||||
|
|
|
@ -1358,7 +1358,7 @@ void main()
|
|||
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 @@ TEST_P(VertexAttributeTestES31, ChangeAttribFormatAfterVertexAttribPointer)
|
|||
// 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 @@ TEST_P(VertexAttributeTestES31, OnlyUpdateBindingByBindVertexBuffer)
|
|||
// 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 @@ ANGLE_INSTANTIATE_TEST(VertexAttributeTestES3,
|
|||
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(),
|
||||
|
|
Загрузка…
Ссылка в новой задаче