xref: /aosp_15_r20/external/angle/src/libANGLE/VertexArray.h (revision 8975f5c5ed3d1c378011245431ada316dfb6f244)
1*8975f5c5SAndroid Build Coastguard Worker //
2*8975f5c5SAndroid Build Coastguard Worker // Copyright 2013 The ANGLE Project Authors. All rights reserved.
3*8975f5c5SAndroid Build Coastguard Worker // Use of this source code is governed by a BSD-style license that can be
4*8975f5c5SAndroid Build Coastguard Worker // found in the LICENSE file.
5*8975f5c5SAndroid Build Coastguard Worker //
6*8975f5c5SAndroid Build Coastguard Worker // This class contains prototypes for representing GLES 3 Vertex Array Objects:
7*8975f5c5SAndroid Build Coastguard Worker //
8*8975f5c5SAndroid Build Coastguard Worker //   The buffer objects that are to be used by the vertex stage of the GL are collected
9*8975f5c5SAndroid Build Coastguard Worker //   together to form a vertex array object. All state related to the definition of data used
10*8975f5c5SAndroid Build Coastguard Worker //   by the vertex processor is encapsulated in a vertex array object.
11*8975f5c5SAndroid Build Coastguard Worker //
12*8975f5c5SAndroid Build Coastguard Worker 
13*8975f5c5SAndroid Build Coastguard Worker #ifndef LIBANGLE_VERTEXARRAY_H_
14*8975f5c5SAndroid Build Coastguard Worker #define LIBANGLE_VERTEXARRAY_H_
15*8975f5c5SAndroid Build Coastguard Worker 
16*8975f5c5SAndroid Build Coastguard Worker #include "common/Optional.h"
17*8975f5c5SAndroid Build Coastguard Worker #include "libANGLE/Constants.h"
18*8975f5c5SAndroid Build Coastguard Worker #include "libANGLE/Debug.h"
19*8975f5c5SAndroid Build Coastguard Worker #include "libANGLE/Observer.h"
20*8975f5c5SAndroid Build Coastguard Worker #include "libANGLE/RefCountObject.h"
21*8975f5c5SAndroid Build Coastguard Worker #include "libANGLE/VertexAttribute.h"
22*8975f5c5SAndroid Build Coastguard Worker 
23*8975f5c5SAndroid Build Coastguard Worker #include <vector>
24*8975f5c5SAndroid Build Coastguard Worker 
25*8975f5c5SAndroid Build Coastguard Worker namespace rx
26*8975f5c5SAndroid Build Coastguard Worker {
27*8975f5c5SAndroid Build Coastguard Worker class GLImplFactory;
28*8975f5c5SAndroid Build Coastguard Worker class VertexArrayImpl;
29*8975f5c5SAndroid Build Coastguard Worker }  // namespace rx
30*8975f5c5SAndroid Build Coastguard Worker 
31*8975f5c5SAndroid Build Coastguard Worker namespace gl
32*8975f5c5SAndroid Build Coastguard Worker {
33*8975f5c5SAndroid Build Coastguard Worker class Buffer;
34*8975f5c5SAndroid Build Coastguard Worker 
35*8975f5c5SAndroid Build Coastguard Worker constexpr uint32_t kElementArrayBufferIndex = MAX_VERTEX_ATTRIBS;
36*8975f5c5SAndroid Build Coastguard Worker 
37*8975f5c5SAndroid Build Coastguard Worker class VertexArrayState final : angle::NonCopyable
38*8975f5c5SAndroid Build Coastguard Worker {
39*8975f5c5SAndroid Build Coastguard Worker   public:
40*8975f5c5SAndroid Build Coastguard Worker     VertexArrayState(VertexArray *vertexArray, size_t maxAttribs, size_t maxBindings);
41*8975f5c5SAndroid Build Coastguard Worker     ~VertexArrayState();
42*8975f5c5SAndroid Build Coastguard Worker 
getLabel()43*8975f5c5SAndroid Build Coastguard Worker     const std::string &getLabel() const { return mLabel; }
44*8975f5c5SAndroid Build Coastguard Worker 
getElementArrayBuffer()45*8975f5c5SAndroid Build Coastguard Worker     Buffer *getElementArrayBuffer() const { return mElementArrayBuffer.get(); }
getMaxAttribs()46*8975f5c5SAndroid Build Coastguard Worker     size_t getMaxAttribs() const { return mVertexAttributes.size(); }
getMaxBindings()47*8975f5c5SAndroid Build Coastguard Worker     size_t getMaxBindings() const { return mVertexBindings.size(); }
getEnabledAttributesMask()48*8975f5c5SAndroid Build Coastguard Worker     const AttributesMask &getEnabledAttributesMask() const { return mEnabledAttributesMask; }
getVertexAttributes()49*8975f5c5SAndroid Build Coastguard Worker     const std::vector<VertexAttribute> &getVertexAttributes() const { return mVertexAttributes; }
getVertexAttribute(size_t attribIndex)50*8975f5c5SAndroid Build Coastguard Worker     const VertexAttribute &getVertexAttribute(size_t attribIndex) const
51*8975f5c5SAndroid Build Coastguard Worker     {
52*8975f5c5SAndroid Build Coastguard Worker         return mVertexAttributes[attribIndex];
53*8975f5c5SAndroid Build Coastguard Worker     }
getVertexBindings()54*8975f5c5SAndroid Build Coastguard Worker     const std::vector<VertexBinding> &getVertexBindings() const { return mVertexBindings; }
getVertexBinding(size_t bindingIndex)55*8975f5c5SAndroid Build Coastguard Worker     const VertexBinding &getVertexBinding(size_t bindingIndex) const
56*8975f5c5SAndroid Build Coastguard Worker     {
57*8975f5c5SAndroid Build Coastguard Worker         return mVertexBindings[bindingIndex];
58*8975f5c5SAndroid Build Coastguard Worker     }
getBindingFromAttribIndex(size_t attribIndex)59*8975f5c5SAndroid Build Coastguard Worker     const VertexBinding &getBindingFromAttribIndex(size_t attribIndex) const
60*8975f5c5SAndroid Build Coastguard Worker     {
61*8975f5c5SAndroid Build Coastguard Worker         return mVertexBindings[mVertexAttributes[attribIndex].bindingIndex];
62*8975f5c5SAndroid Build Coastguard Worker     }
getBindingIndexFromAttribIndex(size_t attribIndex)63*8975f5c5SAndroid Build Coastguard Worker     size_t getBindingIndexFromAttribIndex(size_t attribIndex) const
64*8975f5c5SAndroid Build Coastguard Worker     {
65*8975f5c5SAndroid Build Coastguard Worker         return mVertexAttributes[attribIndex].bindingIndex;
66*8975f5c5SAndroid Build Coastguard Worker     }
67*8975f5c5SAndroid Build Coastguard Worker 
68*8975f5c5SAndroid Build Coastguard Worker     void setAttribBinding(const Context *context, size_t attribIndex, GLuint newBindingIndex);
69*8975f5c5SAndroid Build Coastguard Worker 
70*8975f5c5SAndroid Build Coastguard Worker     // Extra validation performed on the Vertex Array.
71*8975f5c5SAndroid Build Coastguard Worker     bool hasEnabledNullPointerClientArray() const;
72*8975f5c5SAndroid Build Coastguard Worker 
73*8975f5c5SAndroid Build Coastguard Worker     // Get all the attributes in an AttributesMask that are using the given binding.
74*8975f5c5SAndroid Build Coastguard Worker     AttributesMask getBindingToAttributesMask(GLuint bindingIndex) const;
75*8975f5c5SAndroid Build Coastguard Worker 
getVertexAttributesTypeMask()76*8975f5c5SAndroid Build Coastguard Worker     ComponentTypeMask getVertexAttributesTypeMask() const { return mVertexAttributesTypeMask; }
77*8975f5c5SAndroid Build Coastguard Worker 
getClientMemoryAttribsMask()78*8975f5c5SAndroid Build Coastguard Worker     AttributesMask getClientMemoryAttribsMask() const { return mClientMemoryAttribsMask; }
79*8975f5c5SAndroid Build Coastguard Worker 
getNullPointerClientMemoryAttribsMask()80*8975f5c5SAndroid Build Coastguard Worker     AttributesMask getNullPointerClientMemoryAttribsMask() const
81*8975f5c5SAndroid Build Coastguard Worker     {
82*8975f5c5SAndroid Build Coastguard Worker         return mNullPointerClientMemoryAttribsMask;
83*8975f5c5SAndroid Build Coastguard Worker     }
84*8975f5c5SAndroid Build Coastguard Worker 
getBufferBindingMask()85*8975f5c5SAndroid Build Coastguard Worker     VertexArrayBufferBindingMask getBufferBindingMask() const { return mBufferBindingMask; }
86*8975f5c5SAndroid Build Coastguard Worker 
id()87*8975f5c5SAndroid Build Coastguard Worker     VertexArrayID id() const { return mId; }
88*8975f5c5SAndroid Build Coastguard Worker 
89*8975f5c5SAndroid Build Coastguard Worker     bool isDefault() const;
90*8975f5c5SAndroid Build Coastguard Worker 
91*8975f5c5SAndroid Build Coastguard Worker   private:
92*8975f5c5SAndroid Build Coastguard Worker     void updateCachedMutableOrNonPersistentArrayBuffers(size_t index);
93*8975f5c5SAndroid Build Coastguard Worker 
94*8975f5c5SAndroid Build Coastguard Worker     friend class VertexArray;
95*8975f5c5SAndroid Build Coastguard Worker     VertexArrayID mId;
96*8975f5c5SAndroid Build Coastguard Worker     std::string mLabel;
97*8975f5c5SAndroid Build Coastguard Worker     std::vector<VertexAttribute> mVertexAttributes;
98*8975f5c5SAndroid Build Coastguard Worker     SubjectBindingPointer<Buffer> mElementArrayBuffer;
99*8975f5c5SAndroid Build Coastguard Worker     std::vector<VertexBinding> mVertexBindings;
100*8975f5c5SAndroid Build Coastguard Worker     AttributesMask mEnabledAttributesMask;
101*8975f5c5SAndroid Build Coastguard Worker     ComponentTypeMask mVertexAttributesTypeMask;
102*8975f5c5SAndroid Build Coastguard Worker     AttributesMask mLastSyncedEnabledAttributesMask;
103*8975f5c5SAndroid Build Coastguard Worker 
104*8975f5c5SAndroid Build Coastguard Worker     // Track which binding index has a buffer bound
105*8975f5c5SAndroid Build Coastguard Worker     VertexArrayBufferBindingMask mBufferBindingMask;
106*8975f5c5SAndroid Build Coastguard Worker 
107*8975f5c5SAndroid Build Coastguard Worker     // This is a performance optimization for buffer binding. Allows element array buffer updates.
108*8975f5c5SAndroid Build Coastguard Worker     friend class State;
109*8975f5c5SAndroid Build Coastguard Worker 
110*8975f5c5SAndroid Build Coastguard Worker     // From the GLES 3.1 spec:
111*8975f5c5SAndroid Build Coastguard Worker     // When a generic attribute array is sourced from client memory, the vertex attribute binding
112*8975f5c5SAndroid Build Coastguard Worker     // state is ignored. Thus we don't have to worry about binding state when using client memory
113*8975f5c5SAndroid Build Coastguard Worker     // attribs.
114*8975f5c5SAndroid Build Coastguard Worker     AttributesMask mClientMemoryAttribsMask;
115*8975f5c5SAndroid Build Coastguard Worker     AttributesMask mNullPointerClientMemoryAttribsMask;
116*8975f5c5SAndroid Build Coastguard Worker 
117*8975f5c5SAndroid Build Coastguard Worker     // Used for validation cache. Indexed by attribute.
118*8975f5c5SAndroid Build Coastguard Worker     AttributesMask mCachedMappedArrayBuffers;
119*8975f5c5SAndroid Build Coastguard Worker     AttributesMask mCachedMutableOrImpersistentArrayBuffers;
120*8975f5c5SAndroid Build Coastguard Worker     AttributesMask mCachedInvalidMappedArrayBuffer;
121*8975f5c5SAndroid Build Coastguard Worker };
122*8975f5c5SAndroid Build Coastguard Worker 
123*8975f5c5SAndroid Build Coastguard Worker class VertexArrayBufferContentsObservers final : angle::NonCopyable
124*8975f5c5SAndroid Build Coastguard Worker {
125*8975f5c5SAndroid Build Coastguard Worker   public:
126*8975f5c5SAndroid Build Coastguard Worker     VertexArrayBufferContentsObservers(VertexArray *vertexArray);
127*8975f5c5SAndroid Build Coastguard Worker     void enableForBuffer(Buffer *buffer, uint32_t bufferIndex);
128*8975f5c5SAndroid Build Coastguard Worker     void disableForBuffer(Buffer *buffer, uint32_t bufferIndex);
any()129*8975f5c5SAndroid Build Coastguard Worker     bool any() const { return mBufferObserversBitMask.any(); }
130*8975f5c5SAndroid Build Coastguard Worker 
131*8975f5c5SAndroid Build Coastguard Worker   private:
132*8975f5c5SAndroid Build Coastguard Worker     VertexArray *mVertexArray;
133*8975f5c5SAndroid Build Coastguard Worker     // Bit is set when it is observing the buffer content change
134*8975f5c5SAndroid Build Coastguard Worker     gl::AttributesMask mBufferObserversBitMask;
135*8975f5c5SAndroid Build Coastguard Worker };
136*8975f5c5SAndroid Build Coastguard Worker 
137*8975f5c5SAndroid Build Coastguard Worker class VertexArray final : public angle::ObserverInterface,
138*8975f5c5SAndroid Build Coastguard Worker                           public LabeledObject,
139*8975f5c5SAndroid Build Coastguard Worker                           public angle::Subject
140*8975f5c5SAndroid Build Coastguard Worker {
141*8975f5c5SAndroid Build Coastguard Worker   public:
142*8975f5c5SAndroid Build Coastguard Worker     // Dirty bits for VertexArrays use a hierarchical design. At the top level, each attribute
143*8975f5c5SAndroid Build Coastguard Worker     // has a single dirty bit. Then an array of MAX_ATTRIBS dirty bits each has a dirty bit for
144*8975f5c5SAndroid Build Coastguard Worker     // enabled/pointer/format/binding. Bindings are handled similarly. Note that because the
145*8975f5c5SAndroid Build Coastguard Worker     // total number of dirty bits is 33, it will not be as fast on a 32-bit machine, which
146*8975f5c5SAndroid Build Coastguard Worker     // can't support the advanced 64-bit scanning intrinsics. We could consider packing the
147*8975f5c5SAndroid Build Coastguard Worker     // binding and attribute bits together if this becomes a problem.
148*8975f5c5SAndroid Build Coastguard Worker     //
149*8975f5c5SAndroid Build Coastguard Worker     // Special note on "DIRTY_ATTRIB_POINTER_BUFFER": this is a special case when the app
150*8975f5c5SAndroid Build Coastguard Worker     // calls glVertexAttribPointer but only changes a VBO and/or offset binding. This allows
151*8975f5c5SAndroid Build Coastguard Worker     // the Vulkan back-end to skip performing a pipeline change for performance.
152*8975f5c5SAndroid Build Coastguard Worker     enum DirtyBitType
153*8975f5c5SAndroid Build Coastguard Worker     {
154*8975f5c5SAndroid Build Coastguard Worker         // This vertex array has lost buffer observation. Check against actual buffer storage is
155*8975f5c5SAndroid Build Coastguard Worker         // required.
156*8975f5c5SAndroid Build Coastguard Worker         DIRTY_BIT_LOST_OBSERVATION,
157*8975f5c5SAndroid Build Coastguard Worker 
158*8975f5c5SAndroid Build Coastguard Worker         DIRTY_BIT_ELEMENT_ARRAY_BUFFER,
159*8975f5c5SAndroid Build Coastguard Worker         DIRTY_BIT_ELEMENT_ARRAY_BUFFER_DATA,
160*8975f5c5SAndroid Build Coastguard Worker 
161*8975f5c5SAndroid Build Coastguard Worker         // Dirty bits for bindings.
162*8975f5c5SAndroid Build Coastguard Worker         DIRTY_BIT_BINDING_0,
163*8975f5c5SAndroid Build Coastguard Worker         DIRTY_BIT_BINDING_MAX = DIRTY_BIT_BINDING_0 + MAX_VERTEX_ATTRIB_BINDINGS,
164*8975f5c5SAndroid Build Coastguard Worker 
165*8975f5c5SAndroid Build Coastguard Worker         // We keep separate dirty bits for bound buffers whose data changed since last update.
166*8975f5c5SAndroid Build Coastguard Worker         DIRTY_BIT_BUFFER_DATA_0   = DIRTY_BIT_BINDING_MAX,
167*8975f5c5SAndroid Build Coastguard Worker         DIRTY_BIT_BUFFER_DATA_MAX = DIRTY_BIT_BUFFER_DATA_0 + MAX_VERTEX_ATTRIB_BINDINGS,
168*8975f5c5SAndroid Build Coastguard Worker 
169*8975f5c5SAndroid Build Coastguard Worker         // Dirty bits for attributes.
170*8975f5c5SAndroid Build Coastguard Worker         DIRTY_BIT_ATTRIB_0   = DIRTY_BIT_BUFFER_DATA_MAX,
171*8975f5c5SAndroid Build Coastguard Worker         DIRTY_BIT_ATTRIB_MAX = DIRTY_BIT_ATTRIB_0 + MAX_VERTEX_ATTRIBS,
172*8975f5c5SAndroid Build Coastguard Worker 
173*8975f5c5SAndroid Build Coastguard Worker         DIRTY_BIT_UNKNOWN = DIRTY_BIT_ATTRIB_MAX,
174*8975f5c5SAndroid Build Coastguard Worker         DIRTY_BIT_MAX     = DIRTY_BIT_UNKNOWN,
175*8975f5c5SAndroid Build Coastguard Worker     };
176*8975f5c5SAndroid Build Coastguard Worker 
177*8975f5c5SAndroid Build Coastguard Worker     // We want to keep the number of dirty bits within 64 to keep iteration times fast.
178*8975f5c5SAndroid Build Coastguard Worker     static_assert(DIRTY_BIT_MAX <= 64, "Too many vertex array dirty bits.");
179*8975f5c5SAndroid Build Coastguard Worker     // The dirty bit processing has the logic to avoid redundant processing by removing other dirty
180*8975f5c5SAndroid Build Coastguard Worker     // bits when it processes dirtyBits. This assertion ensures these dirty bit order matches what
181*8975f5c5SAndroid Build Coastguard Worker     // VertexArrayVk::syncState expects.
182*8975f5c5SAndroid Build Coastguard Worker     static_assert(DIRTY_BIT_BINDING_0 < DIRTY_BIT_BUFFER_DATA_0,
183*8975f5c5SAndroid Build Coastguard Worker                   "BINDING dirty bits should come before DATA.");
184*8975f5c5SAndroid Build Coastguard Worker     static_assert(DIRTY_BIT_BUFFER_DATA_0 < DIRTY_BIT_ATTRIB_0,
185*8975f5c5SAndroid Build Coastguard Worker                   "DATA dirty bits should come before ATTRIB.");
186*8975f5c5SAndroid Build Coastguard Worker     static_assert(DIRTY_BIT_LOST_OBSERVATION < DIRTY_BIT_BINDING_0,
187*8975f5c5SAndroid Build Coastguard Worker                   "LOST_OBSERVATION dirty bits should come before BINDING.");
188*8975f5c5SAndroid Build Coastguard Worker 
189*8975f5c5SAndroid Build Coastguard Worker     enum DirtyAttribBitType
190*8975f5c5SAndroid Build Coastguard Worker     {
191*8975f5c5SAndroid Build Coastguard Worker         DIRTY_ATTRIB_ENABLED,
192*8975f5c5SAndroid Build Coastguard Worker         DIRTY_ATTRIB_POINTER,
193*8975f5c5SAndroid Build Coastguard Worker         DIRTY_ATTRIB_FORMAT,
194*8975f5c5SAndroid Build Coastguard Worker         DIRTY_ATTRIB_BINDING,
195*8975f5c5SAndroid Build Coastguard Worker         DIRTY_ATTRIB_POINTER_BUFFER,
196*8975f5c5SAndroid Build Coastguard Worker         DIRTY_ATTRIB_MAX,
197*8975f5c5SAndroid Build Coastguard Worker     };
198*8975f5c5SAndroid Build Coastguard Worker 
199*8975f5c5SAndroid Build Coastguard Worker     enum DirtyBindingBitType
200*8975f5c5SAndroid Build Coastguard Worker     {
201*8975f5c5SAndroid Build Coastguard Worker         DIRTY_BINDING_BUFFER,
202*8975f5c5SAndroid Build Coastguard Worker         DIRTY_BINDING_DIVISOR,
203*8975f5c5SAndroid Build Coastguard Worker         DIRTY_BINDING_STRIDE,
204*8975f5c5SAndroid Build Coastguard Worker         DIRTY_BINDING_OFFSET,
205*8975f5c5SAndroid Build Coastguard Worker         DIRTY_BINDING_MAX,
206*8975f5c5SAndroid Build Coastguard Worker     };
207*8975f5c5SAndroid Build Coastguard Worker 
208*8975f5c5SAndroid Build Coastguard Worker     using DirtyBits                = angle::BitSet<DIRTY_BIT_MAX>;
209*8975f5c5SAndroid Build Coastguard Worker     using DirtyAttribBits          = angle::BitSet<DIRTY_ATTRIB_MAX>;
210*8975f5c5SAndroid Build Coastguard Worker     using DirtyBindingBits         = angle::BitSet<DIRTY_BINDING_MAX>;
211*8975f5c5SAndroid Build Coastguard Worker     using DirtyAttribBitsArray     = std::array<DirtyAttribBits, MAX_VERTEX_ATTRIBS>;
212*8975f5c5SAndroid Build Coastguard Worker     using DirtyBindingBitsArray    = std::array<DirtyBindingBits, MAX_VERTEX_ATTRIB_BINDINGS>;
213*8975f5c5SAndroid Build Coastguard Worker     using DirtyObserverBindingBits = angle::BitSet<MAX_VERTEX_ATTRIB_BINDINGS>;
214*8975f5c5SAndroid Build Coastguard Worker 
215*8975f5c5SAndroid Build Coastguard Worker     VertexArray(rx::GLImplFactory *factory,
216*8975f5c5SAndroid Build Coastguard Worker                 VertexArrayID id,
217*8975f5c5SAndroid Build Coastguard Worker                 size_t maxAttribs,
218*8975f5c5SAndroid Build Coastguard Worker                 size_t maxAttribBindings);
219*8975f5c5SAndroid Build Coastguard Worker 
220*8975f5c5SAndroid Build Coastguard Worker     void onDestroy(const Context *context);
221*8975f5c5SAndroid Build Coastguard Worker 
id()222*8975f5c5SAndroid Build Coastguard Worker     VertexArrayID id() const { return mId; }
223*8975f5c5SAndroid Build Coastguard Worker 
224*8975f5c5SAndroid Build Coastguard Worker     angle::Result setLabel(const Context *context, const std::string &label) override;
225*8975f5c5SAndroid Build Coastguard Worker     const std::string &getLabel() const override;
226*8975f5c5SAndroid Build Coastguard Worker 
227*8975f5c5SAndroid Build Coastguard Worker     const VertexBinding &getVertexBinding(size_t bindingIndex) const;
228*8975f5c5SAndroid Build Coastguard Worker     const VertexAttribute &getVertexAttribute(size_t attribIndex) const;
getBindingFromAttribIndex(size_t attribIndex)229*8975f5c5SAndroid Build Coastguard Worker     const VertexBinding &getBindingFromAttribIndex(size_t attribIndex) const
230*8975f5c5SAndroid Build Coastguard Worker     {
231*8975f5c5SAndroid Build Coastguard Worker         return mState.getBindingFromAttribIndex(attribIndex);
232*8975f5c5SAndroid Build Coastguard Worker     }
233*8975f5c5SAndroid Build Coastguard Worker 
234*8975f5c5SAndroid Build Coastguard Worker     // Returns true if the function finds and detaches a bound buffer.
235*8975f5c5SAndroid Build Coastguard Worker     bool detachBuffer(const Context *context, BufferID bufferID);
236*8975f5c5SAndroid Build Coastguard Worker 
237*8975f5c5SAndroid Build Coastguard Worker     void setVertexAttribDivisor(const Context *context, size_t index, GLuint divisor);
238*8975f5c5SAndroid Build Coastguard Worker     void enableAttribute(size_t attribIndex, bool enabledState);
239*8975f5c5SAndroid Build Coastguard Worker 
240*8975f5c5SAndroid Build Coastguard Worker     void setVertexAttribPointer(const Context *context,
241*8975f5c5SAndroid Build Coastguard Worker                                 size_t attribIndex,
242*8975f5c5SAndroid Build Coastguard Worker                                 Buffer *boundBuffer,
243*8975f5c5SAndroid Build Coastguard Worker                                 GLint size,
244*8975f5c5SAndroid Build Coastguard Worker                                 VertexAttribType type,
245*8975f5c5SAndroid Build Coastguard Worker                                 bool normalized,
246*8975f5c5SAndroid Build Coastguard Worker                                 GLsizei stride,
247*8975f5c5SAndroid Build Coastguard Worker                                 const void *pointer);
248*8975f5c5SAndroid Build Coastguard Worker 
249*8975f5c5SAndroid Build Coastguard Worker     void setVertexAttribIPointer(const Context *context,
250*8975f5c5SAndroid Build Coastguard Worker                                  size_t attribIndex,
251*8975f5c5SAndroid Build Coastguard Worker                                  Buffer *boundBuffer,
252*8975f5c5SAndroid Build Coastguard Worker                                  GLint size,
253*8975f5c5SAndroid Build Coastguard Worker                                  VertexAttribType type,
254*8975f5c5SAndroid Build Coastguard Worker                                  GLsizei stride,
255*8975f5c5SAndroid Build Coastguard Worker                                  const void *pointer);
256*8975f5c5SAndroid Build Coastguard Worker 
257*8975f5c5SAndroid Build Coastguard Worker     void setVertexAttribFormat(size_t attribIndex,
258*8975f5c5SAndroid Build Coastguard Worker                                GLint size,
259*8975f5c5SAndroid Build Coastguard Worker                                VertexAttribType type,
260*8975f5c5SAndroid Build Coastguard Worker                                bool normalized,
261*8975f5c5SAndroid Build Coastguard Worker                                bool pureInteger,
262*8975f5c5SAndroid Build Coastguard Worker                                GLuint relativeOffset);
263*8975f5c5SAndroid Build Coastguard Worker     void bindVertexBuffer(const Context *context,
264*8975f5c5SAndroid Build Coastguard Worker                           size_t bindingIndex,
265*8975f5c5SAndroid Build Coastguard Worker                           Buffer *boundBuffer,
266*8975f5c5SAndroid Build Coastguard Worker                           GLintptr offset,
267*8975f5c5SAndroid Build Coastguard Worker                           GLsizei stride);
268*8975f5c5SAndroid Build Coastguard Worker     void setVertexAttribBinding(const Context *context, size_t attribIndex, GLuint bindingIndex);
269*8975f5c5SAndroid Build Coastguard Worker     void setVertexBindingDivisor(const Context *context, size_t bindingIndex, GLuint divisor);
270*8975f5c5SAndroid Build Coastguard Worker 
getElementArrayBuffer()271*8975f5c5SAndroid Build Coastguard Worker     Buffer *getElementArrayBuffer() const { return mState.getElementArrayBuffer(); }
getMaxAttribs()272*8975f5c5SAndroid Build Coastguard Worker     size_t getMaxAttribs() const { return mState.getMaxAttribs(); }
getMaxBindings()273*8975f5c5SAndroid Build Coastguard Worker     size_t getMaxBindings() const { return mState.getMaxBindings(); }
274*8975f5c5SAndroid Build Coastguard Worker 
getVertexAttributes()275*8975f5c5SAndroid Build Coastguard Worker     const std::vector<VertexAttribute> &getVertexAttributes() const
276*8975f5c5SAndroid Build Coastguard Worker     {
277*8975f5c5SAndroid Build Coastguard Worker         return mState.getVertexAttributes();
278*8975f5c5SAndroid Build Coastguard Worker     }
getVertexBindings()279*8975f5c5SAndroid Build Coastguard Worker     const std::vector<VertexBinding> &getVertexBindings() const
280*8975f5c5SAndroid Build Coastguard Worker     {
281*8975f5c5SAndroid Build Coastguard Worker         return mState.getVertexBindings();
282*8975f5c5SAndroid Build Coastguard Worker     }
283*8975f5c5SAndroid Build Coastguard Worker 
getImplementation()284*8975f5c5SAndroid Build Coastguard Worker     rx::VertexArrayImpl *getImplementation() const { return mVertexArray; }
285*8975f5c5SAndroid Build Coastguard Worker 
getEnabledAttributesMask()286*8975f5c5SAndroid Build Coastguard Worker     const AttributesMask &getEnabledAttributesMask() const
287*8975f5c5SAndroid Build Coastguard Worker     {
288*8975f5c5SAndroid Build Coastguard Worker         return mState.getEnabledAttributesMask();
289*8975f5c5SAndroid Build Coastguard Worker     }
290*8975f5c5SAndroid Build Coastguard Worker 
getClientAttribsMask()291*8975f5c5SAndroid Build Coastguard Worker     AttributesMask getClientAttribsMask() const { return mState.mClientMemoryAttribsMask; }
292*8975f5c5SAndroid Build Coastguard Worker 
hasEnabledNullPointerClientArray()293*8975f5c5SAndroid Build Coastguard Worker     bool hasEnabledNullPointerClientArray() const
294*8975f5c5SAndroid Build Coastguard Worker     {
295*8975f5c5SAndroid Build Coastguard Worker         return mState.hasEnabledNullPointerClientArray();
296*8975f5c5SAndroid Build Coastguard Worker     }
297*8975f5c5SAndroid Build Coastguard Worker 
hasInvalidMappedArrayBuffer()298*8975f5c5SAndroid Build Coastguard Worker     bool hasInvalidMappedArrayBuffer() const
299*8975f5c5SAndroid Build Coastguard Worker     {
300*8975f5c5SAndroid Build Coastguard Worker         return mState.mCachedInvalidMappedArrayBuffer.any();
301*8975f5c5SAndroid Build Coastguard Worker     }
302*8975f5c5SAndroid Build Coastguard Worker 
getState()303*8975f5c5SAndroid Build Coastguard Worker     const VertexArrayState &getState() const { return mState; }
304*8975f5c5SAndroid Build Coastguard Worker 
isBufferAccessValidationEnabled()305*8975f5c5SAndroid Build Coastguard Worker     bool isBufferAccessValidationEnabled() const { return mBufferAccessValidationEnabled; }
306*8975f5c5SAndroid Build Coastguard Worker 
307*8975f5c5SAndroid Build Coastguard Worker     // Observer implementation
308*8975f5c5SAndroid Build Coastguard Worker     void onSubjectStateChange(angle::SubjectIndex index, angle::SubjectMessage message) override;
309*8975f5c5SAndroid Build Coastguard Worker     void onBufferContentsChange(uint32_t bufferIndex);
310*8975f5c5SAndroid Build Coastguard Worker 
311*8975f5c5SAndroid Build Coastguard Worker     static size_t GetVertexIndexFromDirtyBit(size_t dirtyBit);
312*8975f5c5SAndroid Build Coastguard Worker 
313*8975f5c5SAndroid Build Coastguard Worker     angle::Result syncState(const Context *context);
hasAnyDirtyBit()314*8975f5c5SAndroid Build Coastguard Worker     bool hasAnyDirtyBit() const { return mDirtyBits.any(); }
315*8975f5c5SAndroid Build Coastguard Worker 
getAttributesTypeMask()316*8975f5c5SAndroid Build Coastguard Worker     ComponentTypeMask getAttributesTypeMask() const { return mState.mVertexAttributesTypeMask; }
getAttributesMask()317*8975f5c5SAndroid Build Coastguard Worker     AttributesMask getAttributesMask() const { return mState.mEnabledAttributesMask; }
318*8975f5c5SAndroid Build Coastguard Worker 
319*8975f5c5SAndroid Build Coastguard Worker     void onBindingChanged(const Context *context, int incr);
320*8975f5c5SAndroid Build Coastguard Worker     bool hasTransformFeedbackBindingConflict(const Context *context) const;
321*8975f5c5SAndroid Build Coastguard Worker 
getIndexRange(const Context * context,DrawElementsType type,GLsizei indexCount,const void * indices,IndexRange * indexRangeOut)322*8975f5c5SAndroid Build Coastguard Worker     ANGLE_INLINE angle::Result getIndexRange(const Context *context,
323*8975f5c5SAndroid Build Coastguard Worker                                              DrawElementsType type,
324*8975f5c5SAndroid Build Coastguard Worker                                              GLsizei indexCount,
325*8975f5c5SAndroid Build Coastguard Worker                                              const void *indices,
326*8975f5c5SAndroid Build Coastguard Worker                                              IndexRange *indexRangeOut) const
327*8975f5c5SAndroid Build Coastguard Worker     {
328*8975f5c5SAndroid Build Coastguard Worker         Buffer *elementArrayBuffer = mState.mElementArrayBuffer.get();
329*8975f5c5SAndroid Build Coastguard Worker         if (elementArrayBuffer && mIndexRangeCache.get(type, indexCount, indices, indexRangeOut))
330*8975f5c5SAndroid Build Coastguard Worker         {
331*8975f5c5SAndroid Build Coastguard Worker             return angle::Result::Continue;
332*8975f5c5SAndroid Build Coastguard Worker         }
333*8975f5c5SAndroid Build Coastguard Worker 
334*8975f5c5SAndroid Build Coastguard Worker         return getIndexRangeImpl(context, type, indexCount, indices, indexRangeOut);
335*8975f5c5SAndroid Build Coastguard Worker     }
336*8975f5c5SAndroid Build Coastguard Worker 
setBufferAccessValidationEnabled(bool enabled)337*8975f5c5SAndroid Build Coastguard Worker     void setBufferAccessValidationEnabled(bool enabled)
338*8975f5c5SAndroid Build Coastguard Worker     {
339*8975f5c5SAndroid Build Coastguard Worker         mBufferAccessValidationEnabled = enabled;
340*8975f5c5SAndroid Build Coastguard Worker     }
341*8975f5c5SAndroid Build Coastguard Worker 
342*8975f5c5SAndroid Build Coastguard Worker   private:
343*8975f5c5SAndroid Build Coastguard Worker     ~VertexArray() override;
344*8975f5c5SAndroid Build Coastguard Worker 
345*8975f5c5SAndroid Build Coastguard Worker     // This is a performance optimization for buffer binding. Allows element array buffer updates.
346*8975f5c5SAndroid Build Coastguard Worker     friend class State;
347*8975f5c5SAndroid Build Coastguard Worker 
348*8975f5c5SAndroid Build Coastguard Worker     void setDirtyAttribBit(size_t attribIndex, DirtyAttribBitType dirtyAttribBit);
349*8975f5c5SAndroid Build Coastguard Worker     void setDirtyBindingBit(size_t bindingIndex, DirtyBindingBitType dirtyBindingBit);
350*8975f5c5SAndroid Build Coastguard Worker     void clearDirtyAttribBit(size_t attribIndex, DirtyAttribBitType dirtyAttribBit);
351*8975f5c5SAndroid Build Coastguard Worker 
352*8975f5c5SAndroid Build Coastguard Worker     DirtyBitType getDirtyBitFromIndex(bool contentsChanged, angle::SubjectIndex index) const;
353*8975f5c5SAndroid Build Coastguard Worker     void setDependentDirtyBit(bool contentsChanged, angle::SubjectIndex index);
354*8975f5c5SAndroid Build Coastguard Worker 
355*8975f5c5SAndroid Build Coastguard Worker     // These are used to optimize draw call validation.
356*8975f5c5SAndroid Build Coastguard Worker     void updateCachedBufferBindingSize(VertexBinding *binding);
357*8975f5c5SAndroid Build Coastguard Worker     void updateCachedTransformFeedbackBindingValidation(size_t bindingIndex, const Buffer *buffer);
358*8975f5c5SAndroid Build Coastguard Worker     void updateCachedArrayBuffersMasks(bool isMapped,
359*8975f5c5SAndroid Build Coastguard Worker                                        bool isImmutable,
360*8975f5c5SAndroid Build Coastguard Worker                                        bool isPersistent,
361*8975f5c5SAndroid Build Coastguard Worker                                        const AttributesMask &boundAttributesMask);
362*8975f5c5SAndroid Build Coastguard Worker     void updateCachedMappedArrayBuffersBinding(const VertexBinding &binding);
363*8975f5c5SAndroid Build Coastguard Worker 
364*8975f5c5SAndroid Build Coastguard Worker     angle::Result getIndexRangeImpl(const Context *context,
365*8975f5c5SAndroid Build Coastguard Worker                                     DrawElementsType type,
366*8975f5c5SAndroid Build Coastguard Worker                                     GLsizei indexCount,
367*8975f5c5SAndroid Build Coastguard Worker                                     const void *indices,
368*8975f5c5SAndroid Build Coastguard Worker                                     IndexRange *indexRangeOut) const;
369*8975f5c5SAndroid Build Coastguard Worker 
370*8975f5c5SAndroid Build Coastguard Worker     void setVertexAttribPointerImpl(const Context *context,
371*8975f5c5SAndroid Build Coastguard Worker                                     ComponentType componentType,
372*8975f5c5SAndroid Build Coastguard Worker                                     bool pureInteger,
373*8975f5c5SAndroid Build Coastguard Worker                                     size_t attribIndex,
374*8975f5c5SAndroid Build Coastguard Worker                                     Buffer *boundBuffer,
375*8975f5c5SAndroid Build Coastguard Worker                                     GLint size,
376*8975f5c5SAndroid Build Coastguard Worker                                     VertexAttribType type,
377*8975f5c5SAndroid Build Coastguard Worker                                     bool normalized,
378*8975f5c5SAndroid Build Coastguard Worker                                     GLsizei stride,
379*8975f5c5SAndroid Build Coastguard Worker                                     const void *pointer);
380*8975f5c5SAndroid Build Coastguard Worker 
381*8975f5c5SAndroid Build Coastguard Worker     // These two functions return true if the state was dirty.
382*8975f5c5SAndroid Build Coastguard Worker     bool setVertexAttribFormatImpl(VertexAttribute *attrib,
383*8975f5c5SAndroid Build Coastguard Worker                                    GLint size,
384*8975f5c5SAndroid Build Coastguard Worker                                    VertexAttribType type,
385*8975f5c5SAndroid Build Coastguard Worker                                    bool normalized,
386*8975f5c5SAndroid Build Coastguard Worker                                    bool pureInteger,
387*8975f5c5SAndroid Build Coastguard Worker                                    GLuint relativeOffset);
388*8975f5c5SAndroid Build Coastguard Worker 
389*8975f5c5SAndroid Build Coastguard Worker     DirtyBindingBits bindVertexBufferImpl(const Context *context,
390*8975f5c5SAndroid Build Coastguard Worker                                           size_t bindingIndex,
391*8975f5c5SAndroid Build Coastguard Worker                                           Buffer *boundBuffer,
392*8975f5c5SAndroid Build Coastguard Worker                                           GLintptr offset,
393*8975f5c5SAndroid Build Coastguard Worker                                           GLsizei stride);
394*8975f5c5SAndroid Build Coastguard Worker 
395*8975f5c5SAndroid Build Coastguard Worker     void onBind(const Context *context);
396*8975f5c5SAndroid Build Coastguard Worker     void onUnbind(const Context *context);
397*8975f5c5SAndroid Build Coastguard Worker 
398*8975f5c5SAndroid Build Coastguard Worker     VertexArrayID mId;
399*8975f5c5SAndroid Build Coastguard Worker 
400*8975f5c5SAndroid Build Coastguard Worker     VertexArrayState mState;
401*8975f5c5SAndroid Build Coastguard Worker     DirtyBits mDirtyBits;
402*8975f5c5SAndroid Build Coastguard Worker     DirtyAttribBitsArray mDirtyAttribBits;
403*8975f5c5SAndroid Build Coastguard Worker     DirtyBindingBitsArray mDirtyBindingBits;
404*8975f5c5SAndroid Build Coastguard Worker     Optional<DirtyBits> mDirtyBitsGuard;
405*8975f5c5SAndroid Build Coastguard Worker 
406*8975f5c5SAndroid Build Coastguard Worker     rx::VertexArrayImpl *mVertexArray;
407*8975f5c5SAndroid Build Coastguard Worker 
408*8975f5c5SAndroid Build Coastguard Worker     std::vector<angle::ObserverBinding> mArrayBufferObserverBindings;
409*8975f5c5SAndroid Build Coastguard Worker 
410*8975f5c5SAndroid Build Coastguard Worker     AttributesMask mCachedTransformFeedbackConflictedBindingsMask;
411*8975f5c5SAndroid Build Coastguard Worker 
412*8975f5c5SAndroid Build Coastguard Worker     class IndexRangeCache final : angle::NonCopyable
413*8975f5c5SAndroid Build Coastguard Worker     {
414*8975f5c5SAndroid Build Coastguard Worker       public:
415*8975f5c5SAndroid Build Coastguard Worker         IndexRangeCache();
416*8975f5c5SAndroid Build Coastguard Worker 
invalidate()417*8975f5c5SAndroid Build Coastguard Worker         void invalidate() { mTypeKey = DrawElementsType::InvalidEnum; }
418*8975f5c5SAndroid Build Coastguard Worker 
get(DrawElementsType type,GLsizei indexCount,const void * indices,IndexRange * indexRangeOut)419*8975f5c5SAndroid Build Coastguard Worker         bool get(DrawElementsType type,
420*8975f5c5SAndroid Build Coastguard Worker                  GLsizei indexCount,
421*8975f5c5SAndroid Build Coastguard Worker                  const void *indices,
422*8975f5c5SAndroid Build Coastguard Worker                  IndexRange *indexRangeOut)
423*8975f5c5SAndroid Build Coastguard Worker         {
424*8975f5c5SAndroid Build Coastguard Worker             size_t offset = reinterpret_cast<uintptr_t>(indices);
425*8975f5c5SAndroid Build Coastguard Worker             if (mTypeKey == type && mIndexCountKey == indexCount && mOffsetKey == offset)
426*8975f5c5SAndroid Build Coastguard Worker             {
427*8975f5c5SAndroid Build Coastguard Worker                 *indexRangeOut = mPayload;
428*8975f5c5SAndroid Build Coastguard Worker                 return true;
429*8975f5c5SAndroid Build Coastguard Worker             }
430*8975f5c5SAndroid Build Coastguard Worker 
431*8975f5c5SAndroid Build Coastguard Worker             return false;
432*8975f5c5SAndroid Build Coastguard Worker         }
433*8975f5c5SAndroid Build Coastguard Worker 
434*8975f5c5SAndroid Build Coastguard Worker         void put(DrawElementsType type,
435*8975f5c5SAndroid Build Coastguard Worker                  GLsizei indexCount,
436*8975f5c5SAndroid Build Coastguard Worker                  size_t offset,
437*8975f5c5SAndroid Build Coastguard Worker                  const IndexRange &indexRange);
438*8975f5c5SAndroid Build Coastguard Worker 
439*8975f5c5SAndroid Build Coastguard Worker       private:
440*8975f5c5SAndroid Build Coastguard Worker         DrawElementsType mTypeKey;
441*8975f5c5SAndroid Build Coastguard Worker         GLsizei mIndexCountKey;
442*8975f5c5SAndroid Build Coastguard Worker         size_t mOffsetKey;
443*8975f5c5SAndroid Build Coastguard Worker         IndexRange mPayload;
444*8975f5c5SAndroid Build Coastguard Worker     };
445*8975f5c5SAndroid Build Coastguard Worker 
446*8975f5c5SAndroid Build Coastguard Worker     mutable IndexRangeCache mIndexRangeCache;
447*8975f5c5SAndroid Build Coastguard Worker     bool mBufferAccessValidationEnabled;
448*8975f5c5SAndroid Build Coastguard Worker     VertexArrayBufferContentsObservers mContentsObservers;
449*8975f5c5SAndroid Build Coastguard Worker };
450*8975f5c5SAndroid Build Coastguard Worker 
451*8975f5c5SAndroid Build Coastguard Worker }  // namespace gl
452*8975f5c5SAndroid Build Coastguard Worker 
453*8975f5c5SAndroid Build Coastguard Worker #endif  // LIBANGLE_VERTEXARRAY_H_
454