Hash :
2ac49bb6
Author :
Date :
2025-07-01T12:11:12
Reland "Vulkan: Move VertexArray::ElementBuffer away from observer" This reverts commit 79ac1a8cd767a32cce6401203e20c4bd4ca4d539. Reason for revert: the regression bug is fixed in PS6 The regression bug with the original CL is caused by when we bind a vertex array without element buffer rebind, we missed to reset mIndexRangeInlineCache. The other bug is that VertexArray::mDiryBits is 64 bit but VertexArrayBufferBindingMask is 16 bit, in VertexArray::setDependentDirtyBits(), bufferBindingMask.to_ulong() << DIRTY_BIT_BUFFER_DATA_0 is only producing the 32 bit value on windows platform due to unsigned long is 32 bit value. bits() is used and bit shift is operated on to uint64_t here to avoid dropping high bits on windows. Two tests are added that reproduce the regression bug caused by the original CL. Bug: angleproject:400711938 Original change's description: > Revert "Vulkan: Move VertexArray::ElementBuffer away from observer" > > This reverts commit 3f012a43ee2c101543785720eedfeaa80708479d. > > Reason for revert: https://issues.chromium.org/427064102 > > Bug: angleproject:400711938 > Original change's description: > > Vulkan: Move VertexArray::ElementBuffer away from observer > > > > Right now, VertexArray's element buffer is always observing buffer's > > change. In previous CLs, we have moved vertex array away from > > subject/observer usage. This CL moves element buffer away from > > subject/observer as well. Since the gl::Buffer tracks buffer's binding > > to each context's current vertex array's binding point, > > kElementArrayBufferIndex is added to VertexArrayBufferBindingMask bits > > so that the element buffer is tracked exactly the same as other vertex > > array buffer bindings. The VerextArray code has been modified to handle > > this special bit, since element buffer has its own binding point > > VertexArrayState::mElementArrayBuffer as opposed to > > VertexArrayState::mVertexBindings. After this CL, VertexArray object > > should be completely off subject/observer usages. > > > > Bug: angleproject:400711938 > > Change-Id: I662ddfabc95034bdc7734939c944ab033f41801c > > Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/6552160 > > Reviewed-by: Shahbaz Youssefi <syoussefi@chromium.org> > > Reviewed-by: Geoff Lang <geofflang@chromium.org> > > Commit-Queue: Charlie Lao <cclao@google.com> > > Bug: angleproject:400711938 > Change-Id: I9487ba8b108baaeda1c8a27189dba64f77616774 > Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/6663539 > Commit-Queue: Charlie Lao <cclao@google.com> > Reviewed-by: Amirali Abdolrashidi <abdolrashidi@google.com> Bug: angleproject:400711938 Change-Id: I3f47ad1238c41f12b5cbd7a59b84be3fce1e9562 Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/6664004 Reviewed-by: Amirali Abdolrashidi <abdolrashidi@google.com> Commit-Queue: Charlie Lao <cclao@google.com>
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278
//
// Copyright 2002 The ANGLE Project Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//
// Buffer.h: Defines the gl::Buffer class, representing storage of vertex and/or
// index data. Implements GL buffer objects and related functionality.
// [OpenGL ES 2.0.24] section 2.9 page 21.
#ifndef LIBANGLE_BUFFER_H_
#define LIBANGLE_BUFFER_H_
#include "common/PackedEnums.h"
#include "common/angleutils.h"
#include "libANGLE/Debug.h"
#include "libANGLE/Error.h"
#include "libANGLE/IndexRangeCache.h"
#include "libANGLE/Observer.h"
#include "libANGLE/RefCountObject.h"
#include "libANGLE/angletypes.h"
namespace rx
{
class BufferImpl;
struct BufferFeedback;
class GLImplFactory;
} // namespace rx
namespace gl
{
class Buffer;
class Context;
enum class WebGLBufferType
{
Undefined,
ElementArray,
OtherData,
};
// Track vertex array's binding index of all contexts that a buffer is bound to
class VertexArrayBufferBindingMaskAndContext final
{
public:
VertexArrayBufferBindingMaskAndContext();
~VertexArrayBufferBindingMaskAndContext();
void add(const gl::Context *context, size_t bindingIndex);
void remove(const gl::Context *context, size_t bindingIndex);
VertexArrayBufferBindingMask getBufferBindingMask(const gl::Context *context) const;
private:
// The expectation is that one buffer will only used in a very small number of shared contexts,
// the cost of searching in a vector is negligible.
std::vector<std::pair<const gl::Context *, VertexArrayBufferBindingMask>> mBufferBindingMask;
};
class BufferState final : angle::NonCopyable
{
public:
BufferState();
~BufferState();
BufferUsage getUsage() const { return mUsage; }
GLbitfield getAccessFlags() const { return mAccessFlags; }
GLenum getAccess() const { return mAccess; }
GLboolean isMapped() const { return mMapped; }
void *getMapPointer() const { return mMapPointer; }
GLint64 getMapOffset() const { return mMapOffset; }
GLint64 getMapLength() const { return mMapLength; }
GLint64 getSize() const { return mSize; }
bool isBoundForTransformFeedback() const { return mTransformFeedbackIndexedBindingCount != 0; }
std::string getLabel() const { return mLabel; }
WebGLBufferType getWebGLType() const { return mWebGLType; }
private:
friend class Buffer;
std::string mLabel;
BufferUsage mUsage;
GLint64 mSize;
GLbitfield mAccessFlags;
GLenum mAccess;
GLboolean mMapped;
void *mMapPointer;
GLint64 mMapOffset;
GLint64 mMapLength;
int mBindingCount;
int mTransformFeedbackIndexedBindingCount;
int mTransformFeedbackGenericBindingCount;
GLboolean mImmutable;
GLbitfield mStorageExtUsageFlags;
GLboolean mExternal;
WebGLBufferType mWebGLType;
};
// Vertex Array and Texture track buffer data updates.
struct ContentsObserver
{
static constexpr uint32_t kBufferTextureIndex = std::numeric_limits<uint32_t>::max();
uint32_t bufferIndex = 0;
// VertexArray* (bufferIndex != kBufferTextureIndex) or Texture*
void *observer = nullptr;
};
ANGLE_INLINE bool operator==(const ContentsObserver &lhs, const ContentsObserver &rhs)
{
return lhs.bufferIndex == rhs.bufferIndex && lhs.observer == rhs.observer;
}
class Buffer final : public ThreadSafeRefCountObject<BufferID>,
public LabeledObject,
public angle::Subject
{
public:
Buffer(rx::GLImplFactory *factory, BufferID id);
~Buffer() override;
void onDestroy(const Context *context) override;
void onBind(const Context *context, BufferBinding target);
angle::Result setLabel(const Context *context, const std::string &label) override;
const std::string &getLabel() const override;
angle::Result bufferStorageExternal(Context *context,
BufferBinding target,
GLsizeiptr size,
GLeglClientBufferEXT clientBuffer,
GLbitfield flags);
angle::Result bufferStorage(Context *context,
BufferBinding target,
GLsizeiptr size,
const void *data,
GLbitfield flags);
angle::Result bufferData(Context *context,
BufferBinding target,
const void *data,
GLsizeiptr size,
BufferUsage usage);
angle::Result bufferSubData(const Context *context,
BufferBinding target,
const void *data,
GLsizeiptr size,
GLintptr offset);
angle::Result copyBufferSubData(const Context *context,
Buffer *source,
GLintptr sourceOffset,
GLintptr destOffset,
GLsizeiptr size);
angle::Result map(const Context *context, GLenum access);
angle::Result mapRange(const Context *context,
GLintptr offset,
GLsizeiptr length,
GLbitfield access);
angle::Result unmap(const Context *context, GLboolean *result);
// These are called when another operation changes Buffer data.
void onDataChanged(const Context *context);
angle::Result getIndexRange(const gl::Context *context,
DrawElementsType type,
size_t offset,
size_t count,
bool primitiveRestartEnabled,
IndexRange *outRange) const;
const BufferState &getState() const { return mState; }
BufferUsage getUsage() const { return mState.mUsage; }
GLbitfield getAccessFlags() const { return mState.mAccessFlags; }
GLenum getAccess() const { return mState.mAccess; }
GLboolean isMapped() const { return mState.mMapped; }
bool isPersistentlyMapped() const
{
return (mState.mStorageExtUsageFlags & GL_MAP_PERSISTENT_BIT_EXT) != 0;
}
void *getMapPointer() const { return mState.mMapPointer; }
GLint64 getMapOffset() const { return mState.mMapOffset; }
GLint64 getMapLength() const { return mState.mMapLength; }
GLint64 getSize() const { return mState.mSize; }
GLint64 getMemorySize() const;
GLboolean isImmutable() const { return mState.mImmutable; }
GLbitfield getStorageExtUsageFlags() const { return mState.mStorageExtUsageFlags; }
// Buffers are always initialized immediately when allocated
InitState initState() const { return InitState::Initialized; }
rx::BufferImpl *getImplementation() const { return mImpl; }
// Note: we pass "isWebGL" to this function to clarify it's only valid if WebGL is enabled.
// We pass the boolean flag instead of the pointer because this header can't read Context.h.
ANGLE_INLINE bool hasWebGLXFBBindingConflict(bool isWebGL) const
{
if (!isWebGL)
{
return false;
}
// The transform feedback generic binding point is not an indexed binding point but it also
// does not count as a non-transform-feedback use of the buffer, so we subtract it from the
// binding count when checking if the buffer is bound to a non-transform-feedback location.
// See https://crbug.com/853978
return mState.mTransformFeedbackIndexedBindingCount > 0 &&
mState.mTransformFeedbackIndexedBindingCount !=
mState.mBindingCount - mState.mTransformFeedbackGenericBindingCount;
}
bool isDoubleBoundForTransformFeedback() const;
void onTFBindingChanged(const Context *context, bool bound, bool indexed);
void onNonTFBindingChanged(int incr) { mState.mBindingCount += incr; }
angle::Result getSubData(const gl::Context *context,
GLintptr offset,
GLsizeiptr size,
void *outData);
void addVertexArrayBinding(const gl::Context *context, size_t bindingIndex)
{
mVertexArrayBufferBindingMaskAndContext.add(context, bindingIndex);
}
void removeVertexArrayBinding(const gl::Context *context, size_t bindingIndex)
{
mVertexArrayBufferBindingMaskAndContext.remove(context, bindingIndex);
}
VertexArrayBufferBindingMask getVertexArrayBinding(const gl::Context *context) const
{
return mVertexArrayBufferBindingMaskAndContext.getBufferBindingMask(context);
}
void addContentsObserver(VertexArray *vertexArray, uint32_t bufferIndex);
void removeContentsObserver(VertexArray *vertexArray, uint32_t bufferIndex);
void addContentsObserver(Texture *texture);
void removeContentsObserver(Texture *texture);
bool hasContentsObserver(Texture *texture) const;
void applyImplFeedback(const gl::Context *context, const rx::BufferFeedback &feedback);
private:
angle::Result bufferDataImpl(Context *context,
BufferBinding target,
const void *data,
GLsizeiptr size,
BufferUsage usage,
GLbitfield flags,
BufferStorage bufferStorage);
angle::Result bufferExternalDataImpl(Context *context,
BufferBinding target,
GLeglClientBufferEXT clientBuffer,
GLsizeiptr size,
GLbitfield flags);
void onStateChange(const Context *context, angle::SubjectMessage message);
void onContentsChange(const Context *context);
size_t getContentsObserverIndex(void *observer, uint32_t bufferIndex) const;
void removeContentsObserverImpl(void *observer, uint32_t bufferIndex);
angle::Result setDataWithUsageFlags(const gl::Context *context,
gl::BufferBinding target,
GLeglClientBufferEXT clientBuffer,
const void *data,
size_t size,
gl::BufferUsage usage,
GLbitfield flags,
gl::BufferStorage bufferStorage);
BufferState mState;
rx::BufferImpl *mImpl;
// Current VertexArray's binding index bitmask
VertexArrayBufferBindingMaskAndContext mVertexArrayBufferBindingMaskAndContext;
angle::FastVector<ContentsObserver, angle::kMaxFixedObservers> mContentsObservers;
mutable IndexRangeCache mIndexRangeCache;
};
} // namespace gl
#endif // LIBANGLE_BUFFER_H_