tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

VertexArray.h (17381B)


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