Edit

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

Branch :

  • Show log

    Commit

  • Author : Jamie Madill
    Date : 2022-01-21 11:35:45
    Hash : 7c1346bd
    Message : Vulkan: Consolidate uniforms code in ProgramExecutableVk. De-duplicates several methods. Refactoring change only. Bug: angleproject:3570 Change-Id: Ib68bc30b3e9b1087871bb268ea292677e0c9fe2e Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/3408061 Reviewed-by: Shahbaz Youssefi <syoussefi@chromium.org> Reviewed-by: Tim Van Patten <timvp@google.com> Commit-Queue: Jamie Madill <jmadill@chromium.org>

  • src/libANGLE/Observer.h
  • //
    // Copyright 2016 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.
    //
    // Observer:
    //   Implements the Observer pattern for sending state change notifications
    //   from Subject objects to dependent Observer objects.
    //
    //   See design document:
    //   https://docs.google.com/document/d/15Edfotqg6_l1skTEL8ADQudF_oIdNa7i8Po43k6jMd4/
    
    #ifndef LIBANGLE_OBSERVER_H_
    #define LIBANGLE_OBSERVER_H_
    
    #include "common/FastVector.h"
    #include "common/angleutils.h"
    
    namespace angle
    {
    template <typename HaystackT, typename NeedleT>
    bool IsInContainer(const HaystackT &haystack, const NeedleT &needle)
    {
        return std::find(haystack.begin(), haystack.end(), needle) != haystack.end();
    }
    
    using SubjectIndex = size_t;
    
    // Messages are used to distinguish different Subject events that get sent to a single Observer.
    // It could be possible to improve the handling by using different callback functions instead
    // of a single handler function. But in some cases we want to share a single binding between
    // Observer and Subject and handle different types of events.
    enum class SubjectMessage
    {
        // Used by gl::VertexArray to notify gl::Context of a gl::Buffer binding count change. Triggers
        // a validation cache update. Also used by gl::Texture to notify gl::Framebuffer of loops.
        BindingChanged,
    
        // Only the contents (pixels, bytes, etc) changed in this Subject. Distinct from the object
        // storage.
        ContentsChanged,
    
        // Sent by gl::Sampler, gl::Texture, gl::Framebuffer and others to notifiy gl::Context. This
        // flag indicates to call syncState before next use.
        DirtyBitsFlagged,
    
        // Generic state change message. Used in multiple places for different purposes.
        SubjectChanged,
    
        // Indicates a bound gl::Buffer is now mapped or unmapped. Passed from gl::Buffer, through
        // gl::VertexArray, into gl::Context. Used to track validation.
        SubjectMapped,
        SubjectUnmapped,
        // Indicates a bound buffer was reallocated when it was mapped, to prevent having to flush
        // pending commands and waiting for the GPU to become idle.
        InternalMemoryAllocationChanged,
    
        // Indicates that a buffer's storage has changed. Used to prevent use-after-free error. (Vulkan)
        BufferVkStorageChanged,
    
        // Indicates an external change to the default framebuffer.
        SurfaceChanged,
    
        // Indicates a separable program's textures or images changed in the ProgramExecutable.
        ProgramTextureOrImageBindingChanged,
        // Indicates a separable program was successfully re-linked.
        ProgramRelinked,
        // Indicates a separable program's sampler uniforms were updated.
        SamplerUniformsUpdated,
        // Other types of uniform change.
        ProgramUniformUpdated,
    
        // Indicates a Storage of back-end in gl::Texture has been released.
        StorageReleased,
    
        // Indicates that all pending updates are complete in the subject.
        InitializationComplete,
    };
    
    // The observing class inherits from this interface class.
    class ObserverInterface
    {
      public:
        virtual ~ObserverInterface();
        virtual void onSubjectStateChange(SubjectIndex index, SubjectMessage message) = 0;
    };
    
    class ObserverBindingBase
    {
      public:
        ObserverBindingBase(ObserverInterface *observer, SubjectIndex subjectIndex)
            : mObserver(observer), mIndex(subjectIndex)
        {}
        virtual ~ObserverBindingBase() {}
    
        ObserverInterface *getObserver() const { return mObserver; }
        SubjectIndex getSubjectIndex() const { return mIndex; }
    
        virtual void onSubjectReset() {}
    
      private:
        ObserverInterface *mObserver;
        SubjectIndex mIndex;
    };
    
    constexpr size_t kMaxFixedObservers = 8;
    
    // Maintains a list of observer bindings. Sends update messages to the observer.
    class Subject : NonCopyable
    {
      public:
        Subject();
        virtual ~Subject();
    
        void onStateChange(SubjectMessage message) const;
        bool hasObservers() const;
        void resetObservers();
    
        ANGLE_INLINE void addObserver(ObserverBindingBase *observer)
        {
            ASSERT(!IsInContainer(mObservers, observer));
            mObservers.push_back(observer);
        }
    
        ANGLE_INLINE void removeObserver(ObserverBindingBase *observer)
        {
            ASSERT(IsInContainer(mObservers, observer));
            mObservers.remove_and_permute(observer);
        }
    
      private:
        // Keep a short list of observers so we can allocate/free them quickly. But since we support
        // unlimited bindings, have a spill-over list of that uses dynamic allocation.
        angle::FastVector<ObserverBindingBase *, kMaxFixedObservers> mObservers;
    };
    
    // Keeps a binding between a Subject and Observer, with a specific subject index.
    class ObserverBinding final : public ObserverBindingBase
    {
      public:
        ObserverBinding(ObserverInterface *observer, SubjectIndex index);
        ~ObserverBinding() override;
        ObserverBinding(const ObserverBinding &other);
        ObserverBinding &operator=(const ObserverBinding &other);
    
        void bind(Subject *subject);
    
        ANGLE_INLINE void reset() { bind(nullptr); }
    
        void onStateChange(SubjectMessage message) const;
        void onSubjectReset() override;
    
        ANGLE_INLINE const Subject *getSubject() const { return mSubject; }
    
        ANGLE_INLINE void assignSubject(Subject *subject) { mSubject = subject; }
    
      private:
        Subject *mSubject;
    };
    
    }  // namespace angle
    
    #endif  // LIBANGLE_OBSERVER_H_