Edit

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

Branch :

  • Show log

    Commit

  • Author : Jamie Madill
    Date : 2021-09-20 11:29:01
    Hash : 49ac15a5
    Message : Optimize VAO bindings. This CL makes the XFB binding tracking WebGL-only. That will speed up VAO binding changes in non-WebGL considerably. Also has a few inline micro-optimizations that may not have a large effect. Bug: angleproject:6371 Change-Id: Ib0a26a3b956dcd6ff78626e5cd6514b46270d882 Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/3170116 Reviewed-by: Shahbaz Youssefi <syoussefi@chromium.org> Reviewed-by: Tim Van Patten <timvp@google.com> Commit-Queue: Jamie Madill <jmadill@chromium.org>

  • src/libANGLE/RefCountObject.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.
    //
    
    // RefCountObject.h: Defines the gl::RefCountObject base class that provides
    // lifecycle support for GL objects using the traditional BindObject scheme, but
    // that need to be reference counted for correct cross-context deletion.
    // (Concretely, textures, buffers and renderbuffers.)
    
    #ifndef LIBANGLE_REFCOUNTOBJECT_H_
    #define LIBANGLE_REFCOUNTOBJECT_H_
    
    #include "angle_gl.h"
    #include "common/PackedEnums.h"
    #include "common/debug.h"
    #include "libANGLE/Error.h"
    #include "libANGLE/Observer.h"
    #include "libANGLE/renderer/serial_utils.h"
    
    #include <cstddef>
    
    namespace angle
    {
    
    template <typename ContextT, typename ErrorT>
    class RefCountObject : angle::NonCopyable
    {
      public:
        using ContextType = ContextT;
        using ErrorType   = ErrorT;
    
        RefCountObject() : mRefCount(0) {}
    
        virtual void onDestroy(const ContextType *context) {}
    
        void addRef() const { ++mRefCount; }
    
        ANGLE_INLINE void release(const ContextType *context)
        {
            ASSERT(mRefCount > 0);
            if (--mRefCount == 0)
            {
                onDestroy(context);
                delete this;
            }
        }
    
        size_t getRefCount() const { return mRefCount; }
    
      protected:
        virtual ~RefCountObject() { ASSERT(mRefCount == 0); }
    
        mutable size_t mRefCount;
    };
    
    template <class ObjectType, typename ContextT, typename ErrorT = angle::Result>
    class BindingPointer
    {
      public:
        using ContextType = ContextT;
        using ErrorType   = ErrorT;
    
        BindingPointer() : mObject(nullptr) {}
    
        BindingPointer(ObjectType *object) : mObject(object)
        {
            if (mObject)
            {
                mObject->addRef();
            }
        }
    
        BindingPointer(const BindingPointer &other) : mObject(other.mObject)
        {
            if (mObject)
            {
                mObject->addRef();
            }
        }
    
        BindingPointer &operator=(BindingPointer &&other)
        {
            std::swap(mObject, other.mObject);
            return *this;
        }
    
        virtual ~BindingPointer()
        {
            // Objects have to be released before the resource manager is destroyed, so they must be
            // explicitly cleaned up.
            ASSERT(mObject == nullptr);
        }
    
        void set(const ContextType *context, ObjectType *newObject)
        {
            // addRef first in case newObject == mObject and this is the last reference to it.
            if (newObject != nullptr)
            {
                reinterpret_cast<RefCountObject<ContextType, ErrorType> *>(newObject)->addRef();
            }
    
            // Store the old pointer in a temporary so we can set the pointer before calling release.
            // Otherwise the object could still be referenced when its destructor is called.
            ObjectType *oldObject = mObject;
            mObject               = newObject;
            if (oldObject != nullptr)
            {
                reinterpret_cast<RefCountObject<ContextType, ErrorType> *>(oldObject)->release(context);
            }
        }
    
        void assign(ObjectType *object) { mObject = object; }
    
        ObjectType *get() const { return mObject; }
        ObjectType *operator->() const { return mObject; }
    
        bool operator==(const BindingPointer &other) const { return mObject == other.mObject; }
    
        bool operator!=(const BindingPointer &other) const { return !(*this == other); }
    
      protected:
        ANGLE_INLINE void setImpl(ObjectType *obj) { mObject = obj; }
    
      private:
        ObjectType *mObject;
    };
    }  // namespace angle
    
    namespace gl
    {
    class Context;
    
    template <class ObjectType>
    class BindingPointer;
    
    using RefCountObjectNoID = angle::RefCountObject<Context, angle::Result>;
    
    template <typename IDType>
    class RefCountObject : public gl::RefCountObjectNoID
    {
      public:
        explicit RefCountObject(rx::Serial serial, IDType id) : mSerial(serial), mId(id) {}
    
        rx::Serial serial() const { return mSerial; }
        IDType id() const { return mId; }
    
      protected:
        ~RefCountObject() override {}
    
      private:
        // Unique serials are used to identify resources for frame capture.
        rx::Serial mSerial;
        IDType mId;
    };
    
    template <class ObjectType>
    class BindingPointer : public angle::BindingPointer<ObjectType, Context>
    {
      public:
        using ContextType = typename angle::BindingPointer<ObjectType, Context>::ContextType;
        using ErrorType   = typename angle::BindingPointer<ObjectType, Context>::ErrorType;
    
        BindingPointer() {}
    
        BindingPointer(ObjectType *object) : angle::BindingPointer<ObjectType, Context>(object) {}
    
        typename ResourceTypeToID<ObjectType>::IDType id() const
        {
            ObjectType *obj = this->get();
            if (obj)
                return obj->id();
            return {0};
        }
    };
    
    template <class ObjectType>
    class OffsetBindingPointer : public BindingPointer<ObjectType>
    {
      public:
        using ContextType = typename BindingPointer<ObjectType>::ContextType;
        using ErrorType   = typename BindingPointer<ObjectType>::ErrorType;
    
        OffsetBindingPointer() : mOffset(0), mSize(0) {}
    
        void set(const ContextType *context, ObjectType *newObject, GLintptr offset, GLsizeiptr size)
        {
            set(context, newObject);
            updateOffsetAndSize(newObject, offset, size);
        }
    
        GLintptr getOffset() const { return mOffset; }
        GLsizeiptr getSize() const { return mSize; }
    
        bool operator==(const OffsetBindingPointer<ObjectType> &other) const
        {
            return this->get() == other.get() && mOffset == other.mOffset && mSize == other.mSize;
        }
    
        bool operator!=(const OffsetBindingPointer<ObjectType> &other) const
        {
            return !(*this == other);
        }
    
        void assign(ObjectType *newObject, GLintptr offset, GLsizeiptr size)
        {
            assign(newObject);
            updateOffsetAndSize(newObject, offset, size);
        }
    
      private:
        ANGLE_INLINE void updateOffsetAndSize(ObjectType *newObject, GLintptr offset, GLsizeiptr size)
        {
            if (newObject)
            {
                mOffset = offset;
                mSize   = size;
            }
            else
            {
                mOffset = 0;
                mSize   = 0;
            }
        }
    
        // Delete the unparameterized functions. This forces an explicit offset and size.
        using BindingPointer<ObjectType>::set;
        using BindingPointer<ObjectType>::assign;
    
        GLintptr mOffset;
        GLsizeiptr mSize;
    };
    
    template <typename SubjectT>
    class SubjectBindingPointer : protected BindingPointer<SubjectT>, public angle::ObserverBindingBase
    {
      public:
        SubjectBindingPointer(angle::ObserverInterface *observer, angle::SubjectIndex index)
            : ObserverBindingBase(observer, index)
        {}
        ~SubjectBindingPointer() override {}
        SubjectBindingPointer(const SubjectBindingPointer &other) = default;
        SubjectBindingPointer &operator=(const SubjectBindingPointer &other) = default;
    
        void bind(const Context *context, SubjectT *subject)
        {
            // AddRef first in case subject == get()
            if (subject)
            {
                subject->addObserver(this);
                subject->addRef();
            }
    
            if (get())
            {
                get()->removeObserver(this);
                get()->release(context);
            }
    
            this->setImpl(subject);
        }
    
        using BindingPointer<SubjectT>::get;
        using BindingPointer<SubjectT>::operator->;
    
        friend class State;
    };
    }  // namespace gl
    
    namespace egl
    {
    class Display;
    
    using RefCountObject = angle::RefCountObject<Display, Error>;
    
    template <class ObjectType>
    using BindingPointer = angle::BindingPointer<ObjectType, Display, Error>;
    
    }  // namespace egl
    
    #endif  // LIBANGLE_REFCOUNTOBJECT_H_