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