Edit

kc3-lang/angle/src/libANGLE/Buffer.h

Branch :

  • Show log

    Commit

  • Author : Jamie Madill
    Date : 2021-09-17 13:16:36
    Hash : cf8c5678
    Message : Vulkan: Don't sync VAOs after BufferSubData calls. We still need to syncState after buffers that contain converted attributes are updated. Includes a perf regression test. Bug: angleproject:6371 Change-Id: I54227fc43e7b3fe79072da7783dab0177ccb0486 Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/3182706 Commit-Queue: Jamie Madill <jmadill@chromium.org> Reviewed-by: Tim Van Patten <timvp@google.com> Reviewed-by: Shahbaz Youssefi <syoussefi@chromium.org>

  • src/libANGLE/Buffer.h
  • //
    // Copyright 2002 The ANGLE Project Authors. All rights reserved.
    // Use of this source code is governed by a BSD-style license that can be
    // found in the LICENSE file.
    //
    
    // Buffer.h: Defines the gl::Buffer class, representing storage of vertex and/or
    // index data. Implements GL buffer objects and related functionality.
    // [OpenGL ES 2.0.24] section 2.9 page 21.
    
    #ifndef LIBANGLE_BUFFER_H_
    #define LIBANGLE_BUFFER_H_
    
    #include "common/PackedEnums.h"
    #include "common/angleutils.h"
    #include "libANGLE/Debug.h"
    #include "libANGLE/Error.h"
    #include "libANGLE/IndexRangeCache.h"
    #include "libANGLE/Observer.h"
    #include "libANGLE/RefCountObject.h"
    #include "libANGLE/angletypes.h"
    
    namespace rx
    {
    class BufferImpl;
    class GLImplFactory;
    }  // namespace rx
    
    namespace gl
    {
    class Buffer;
    class Context;
    
    class BufferState final : angle::NonCopyable
    {
      public:
        BufferState();
        ~BufferState();
    
        BufferUsage getUsage() const { return mUsage; }
        GLbitfield getAccessFlags() const { return mAccessFlags; }
        GLenum getAccess() const { return mAccess; }
        GLboolean isMapped() const { return mMapped; }
        void *getMapPointer() const { return mMapPointer; }
        GLint64 getMapOffset() const { return mMapOffset; }
        GLint64 getMapLength() const { return mMapLength; }
        GLint64 getSize() const { return mSize; }
        bool isBoundForTransformFeedback() const { return mTransformFeedbackIndexedBindingCount != 0; }
        std::string getLabel() const { return mLabel; }
    
      private:
        friend class Buffer;
    
        std::string mLabel;
    
        BufferUsage mUsage;
        GLint64 mSize;
        GLbitfield mAccessFlags;
        GLenum mAccess;
        GLboolean mMapped;
        void *mMapPointer;
        GLint64 mMapOffset;
        GLint64 mMapLength;
        int mBindingCount;
        int mTransformFeedbackIndexedBindingCount;
        int mTransformFeedbackGenericBindingCount;
        GLboolean mImmutable;
        GLbitfield mStorageExtUsageFlags;
        GLboolean mExternal;
    };
    
    // Some Vertex Array Objects track buffer data updates.
    struct ContentsObserver
    {
        VertexArray *vertexArray = nullptr;
        uint32_t bufferIndex     = 0;
    };
    
    ANGLE_INLINE bool operator==(const ContentsObserver &lhs, const ContentsObserver &rhs)
    {
        return lhs.vertexArray == rhs.vertexArray && lhs.bufferIndex == rhs.bufferIndex;
    }
    
    class Buffer final : public RefCountObject<BufferID>,
                         public LabeledObject,
                         public angle::ObserverInterface,
                         public angle::Subject
    {
      public:
        Buffer(rx::GLImplFactory *factory, BufferID id);
        ~Buffer() override;
        void onDestroy(const Context *context) override;
    
        void setLabel(const Context *context, const std::string &label) override;
        const std::string &getLabel() const override;
    
        angle::Result bufferStorageExternal(Context *context,
                                            BufferBinding target,
                                            GLsizeiptr size,
                                            GLeglClientBufferEXT clientBuffer,
                                            GLbitfield flags);
        angle::Result bufferStorage(Context *context,
                                    BufferBinding target,
                                    GLsizeiptr size,
                                    const void *data,
                                    GLbitfield flags);
        angle::Result bufferData(Context *context,
                                 BufferBinding target,
                                 const void *data,
                                 GLsizeiptr size,
                                 BufferUsage usage);
        angle::Result bufferSubData(const Context *context,
                                    BufferBinding target,
                                    const void *data,
                                    GLsizeiptr size,
                                    GLintptr offset);
        angle::Result copyBufferSubData(const Context *context,
                                        Buffer *source,
                                        GLintptr sourceOffset,
                                        GLintptr destOffset,
                                        GLsizeiptr size);
        angle::Result map(const Context *context, GLenum access);
        angle::Result mapRange(const Context *context,
                               GLintptr offset,
                               GLsizeiptr length,
                               GLbitfield access);
        angle::Result unmap(const Context *context, GLboolean *result);
    
        // These are called when another operation changes Buffer data.
        void onDataChanged();
    
        angle::Result getIndexRange(const gl::Context *context,
                                    DrawElementsType type,
                                    size_t offset,
                                    size_t count,
                                    bool primitiveRestartEnabled,
                                    IndexRange *outRange) const;
        const BufferState &getState() const { return mState; }
        BufferUsage getUsage() const { return mState.mUsage; }
        GLbitfield getAccessFlags() const { return mState.mAccessFlags; }
        GLenum getAccess() const { return mState.mAccess; }
        GLboolean isMapped() const { return mState.mMapped; }
        void *getMapPointer() const { return mState.mMapPointer; }
        GLint64 getMapOffset() const { return mState.mMapOffset; }
        GLint64 getMapLength() const { return mState.mMapLength; }
        GLint64 getSize() const { return mState.mSize; }
        GLint64 getMemorySize() const;
        GLboolean isImmutable() const { return mState.mImmutable; }
        GLbitfield getStorageExtUsageFlags() const { return mState.mStorageExtUsageFlags; }
    
        // Buffers are always initialized immediately when allocated
        InitState initState() const { return InitState::Initialized; }
    
        rx::BufferImpl *getImplementation() const { return mImpl; }
    
        // Note: we pass "isWebGL" to this function to clarify it's only valid if WebGL is enabled.
        // We pass the boolean flag instead of the pointer because this header can't read Context.h.
        ANGLE_INLINE bool hasWebGLXFBBindingConflict(bool isWebGL) const
        {
            if (!isWebGL)
            {
                return false;
            }
    
            // The transform feedback generic binding point is not an indexed binding point but it also
            // does not count as a non-transform-feedback use of the buffer, so we subtract it from the
            // binding count when checking if the buffer is bound to a non-transform-feedback location.
            // See https://crbug.com/853978
            return mState.mTransformFeedbackIndexedBindingCount > 0 &&
                   mState.mTransformFeedbackIndexedBindingCount !=
                       mState.mBindingCount - mState.mTransformFeedbackGenericBindingCount;
        }
    
        bool isDoubleBoundForTransformFeedback() const;
        void onTFBindingChanged(const Context *context, bool bound, bool indexed);
        void onNonTFBindingChanged(int incr) { mState.mBindingCount += incr; }
        angle::Result getSubData(const gl::Context *context,
                                 GLintptr offset,
                                 GLsizeiptr size,
                                 void *outData);
    
        // angle::ObserverInterface implementation.
        void onSubjectStateChange(angle::SubjectIndex index, angle::SubjectMessage message) override;
    
        void addContentsObserver(VertexArray *vertexArray, uint32_t bufferIndex);
        void removeContentsObserver(VertexArray *vertexArray, uint32_t bufferIndex);
    
      private:
        angle::Result bufferDataImpl(Context *context,
                                     BufferBinding target,
                                     const void *data,
                                     GLsizeiptr size,
                                     BufferUsage usage,
                                     GLbitfield flags);
        angle::Result bufferExternalDataImpl(Context *context,
                                             BufferBinding target,
                                             GLeglClientBufferEXT clientBuffer,
                                             GLsizeiptr size,
                                             GLbitfield flags);
    
        void onContentsChange();
        size_t getContentsObserverIndex(VertexArray *vertexArray, uint32_t bufferIndex) const;
    
        BufferState mState;
        rx::BufferImpl *mImpl;
        angle::ObserverBinding mImplObserver;
    
        angle::FastVector<ContentsObserver, angle::kMaxFixedObservers> mContentsObservers;
        mutable IndexRangeCache mIndexRangeCache;
    };
    
    }  // namespace gl
    
    #endif  // LIBANGLE_BUFFER_H_