|
| 1 | +From 33defc607f50e3f47442c716df697290a5380d4c Mon Sep 17 00:00:00 2001 |
| 2 | +From: Geoff Lang < [email protected]> |
| 3 | +Date: Wed, 25 Jun 2025 13:17:47 -0400 |
| 4 | +Subject: [PATCH] Validate buffers bound for transform feedback are not |
| 5 | + modified. |
| 6 | + |
| 7 | +Upstream Patch Link: https://chromium.googlesource.com/angle/angle/+/2f8193ecfe1ed464374ae56235cfdc112343f9c3 |
| 8 | + |
| 9 | +(Edited/backported by < [email protected]> for clean application) |
| 10 | + |
| 11 | +The ES spec says it is undefined to write to a buffer that is currently |
| 12 | +being used for transform feedback output but recommends generating an |
| 13 | +error. Generate INVALID_OPERATION in this case. |
| 14 | + |
| 15 | +Bug: chromium:427162086 |
| 16 | +Change-Id: I727d18c2035509fe2e5d60680eb5198e40a60e33 |
| 17 | +Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/6673310 |
| 18 | +Commit-Queue: Geoff Lang < [email protected]> |
| 19 | +Reviewed-by: Vasiliy Telezhnikov < [email protected]> |
| 20 | +--- |
| 21 | + .../angle/src/libANGLE/TransformFeedback.cpp | 12 +++++++++++ |
| 22 | + .../angle/src/libANGLE/TransformFeedback.h | 4 ++++ |
| 23 | + .../angle/src/libANGLE/validationES2.cpp | 20 +++++++++++++++++++ |
| 24 | + 3 files changed, 36 insertions(+) |
| 25 | + |
| 26 | +diff --git a/src/3rdparty/angle/src/libANGLE/TransformFeedback.cpp b/src/3rdparty/angle/src/libANGLE/TransformFeedback.cpp |
| 27 | +index 99235deb..4f9b3110 100644 |
| 28 | +--- a/src/3rdparty/angle/src/libANGLE/TransformFeedback.cpp |
| 29 | ++++ b/src/3rdparty/angle/src/libANGLE/TransformFeedback.cpp |
| 30 | +@@ -197,6 +197,18 @@ void TransformFeedback::bindIndexedBuffer(const Context *context, |
| 31 | + mImplementation->bindIndexedBuffer(index, mState.mIndexedBuffers[index]); |
| 32 | + } |
| 33 | + |
| 34 | ++bool TransformFeedback::isBufferBound(BufferID bufferID) const |
| 35 | ++{ |
| 36 | ++ for (const auto &buffer : mState.mIndexedBuffers) |
| 37 | ++ { |
| 38 | ++ if (buffer.id() == bufferID) |
| 39 | ++ { |
| 40 | ++ return true; |
| 41 | ++ } |
| 42 | ++ } |
| 43 | ++ return false; |
| 44 | ++} |
| 45 | ++ |
| 46 | + const OffsetBindingPointer<Buffer> &TransformFeedback::getIndexedBuffer(size_t index) const |
| 47 | + { |
| 48 | + ASSERT(index < mState.mIndexedBuffers.size()); |
| 49 | +diff --git a/src/3rdparty/angle/src/libANGLE/TransformFeedback.h b/src/3rdparty/angle/src/libANGLE/TransformFeedback.h |
| 50 | +index 2b35d43f..e1fd53ce 100644 |
| 51 | +--- a/src/3rdparty/angle/src/libANGLE/TransformFeedback.h |
| 52 | ++++ b/src/3rdparty/angle/src/libANGLE/TransformFeedback.h |
| 53 | +@@ -84,6 +84,10 @@ class TransformFeedback final : public RefCountObject, public LabeledObject |
| 54 | + const OffsetBindingPointer<Buffer> &getIndexedBuffer(size_t index) const; |
| 55 | + size_t getIndexedBufferCount() const; |
| 56 | + |
| 57 | ++ // Returns true if the buffer is bound to any of the indexed binding points in this transform |
| 58 | ++ // feedback. |
| 59 | ++ bool isBufferBound(BufferID bufferID) const; |
| 60 | ++ |
| 61 | + void detachBuffer(const Context *context, GLuint bufferName); |
| 62 | + |
| 63 | + rx::TransformFeedbackImpl *getImplementation(); |
| 64 | +diff --git a/src/3rdparty/angle/src/libANGLE/validationES2.cpp b/src/3rdparty/angle/src/libANGLE/validationES2.cpp |
| 65 | +index 5e505aa6..0469728c 100644 |
| 66 | +--- a/src/3rdparty/angle/src/libANGLE/validationES2.cpp |
| 67 | ++++ b/src/3rdparty/angle/src/libANGLE/validationES2.cpp |
| 68 | +@@ -4220,6 +4220,26 @@ bool ValidateBufferData(ValidationContext *context, |
| 69 | + return false; |
| 70 | + } |
| 71 | + |
| 72 | ++ // Do some additional WebGL-specific validation |
| 73 | ++ if (ANGLE_UNLIKELY(context->isWebGL())) |
| 74 | ++ { |
| 75 | ++ if (buffer->hasWebGLXFBBindingConflict(true)) |
| 76 | ++ { |
| 77 | ++ ANGLE_VALIDATION_ERR(context, InvalidOperation(), BufferBoundForTransformFeedback); |
| 78 | ++ return false; |
| 79 | ++ } |
| 80 | ++ |
| 81 | ++ const TransformFeedback *transformFeedbackObject = |
| 82 | ++ context->getState().getCurrentTransformFeedback(); |
| 83 | ++ if (transformFeedbackObject && transformFeedbackObject->isActive() && |
| 84 | ++ !transformFeedbackObject->isPaused() && |
| 85 | ++ transformFeedbackObject->isBufferBound(buffer->id())) |
| 86 | ++ { |
| 87 | ++ ANGLE_VALIDATION_ERR(context, InvalidOperation(), BufferBoundForTransformFeedback); |
| 88 | ++ return false; |
| 89 | ++ } |
| 90 | ++ } |
| 91 | ++ |
| 92 | + return true; |
| 93 | + } |
| 94 | + |
| 95 | +-- |
| 96 | +2.34.1 |
| 97 | + |
0 commit comments