| // Copyright 2017 The Fuchsia Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #ifndef LIB_ESCHER_IMPL_COMMAND_BUFFER_SEQUENCER_H_ |
| #define LIB_ESCHER_IMPL_COMMAND_BUFFER_SEQUENCER_H_ |
| |
| #include <cstdint> |
| #include <vector> |
| |
| namespace escher { |
| |
| namespace test { |
| class ReleaseFenceSignallerTest; |
| } |
| |
| namespace impl { |
| |
| // Listener that can be registered with CommandBufferSequencer. |
| class CommandBufferSequencerListener { |
| public: |
| virtual ~CommandBufferSequencerListener() {} |
| |
| // Notify the listener that all command buffers with seq # <= sequence_number |
| // have finished executing on the GPU. |
| virtual void OnCommandBufferFinished(uint64_t sequence_number) = 0; |
| }; |
| |
| // CommandBufferSequencer is responsible for global sequencing of CommandBuffers |
| // within a single Escher instance (across multiple CommandBufferPools and |
| // Vulkan queues). It also tracks the highest sequence number, such that all |
| // CommandBuffers with equal or lower sequence number have finished execution. |
| class CommandBufferSequencer { |
| public: |
| ~CommandBufferSequencer(); |
| |
| // Get the most recent sequence number generated for a CommandBuffer. All |
| // future sequence numbers will be greater since sequence numbers are |
| // monotonically-increasing. |
| uint64_t latest_sequence_number() { return latest_sequence_number_; } |
| |
| void AddListener(CommandBufferSequencerListener* listener); |
| void RemoveListener(CommandBufferSequencerListener* listener); |
| |
| private: |
| // Only CommandBufferPool, and unit tests, are allowed to generate and finish |
| // sequences. |
| friend class CommandBufferPool; |
| friend class ::escher::test::ReleaseFenceSignallerTest; |
| |
| // Obtain a monotonically-increasing sequence number for a CommandBuffer that |
| // is about to be obtained from a CommandBufferPool. |
| uint64_t GenerateNextCommandBufferSequenceNumber(); |
| |
| // Receive a notification that the CommandBuffer with the specified sequence |
| // number has completed execution. |
| // |
| // If |sequence_number| > 1 + |last_finished_sequence_number_|, then there |
| // are CommandBuffers with a lower sequence number that have not completed. |
| // In this case, wait for these to complete by adding |sequence_number| to |
| // |out_of_sequence_numbers_|. |
| // |
| // Otherwise, increment |last_finished_sequence_number_|. Then, check whether |
| // any values in |out_of_sequence_numbers_| are now "in sequence"; if so, |
| // remove them and increment |last_finished_sequence_number_| accordingly. |
| // |
| // If either of these cases causes |last_finished_sequence_number_| to change, |
| // notify all registered listeners. |
| void CommandBufferFinished(uint64_t sequence_number); |
| |
| // The last sequence number returned by GenerateNextSequenceNumber(). |
| uint64_t latest_sequence_number_ = 0; |
| // The highest sequence number where its command-buffer, and all command- |
| // buffers for all previous sequence numbers, have finished. |
| uint64_t last_finished_sequence_number_ = 0; |
| |
| // Sequence numbers of command-buffers that finished out-of-sequence. |
| std::vector<uint64_t> out_of_sequence_numbers_; |
| |
| std::vector<CommandBufferSequencerListener*> listeners_; |
| }; |
| |
| } // namespace impl |
| } // namespace escher |
| |
| #endif // LIB_ESCHER_IMPL_COMMAND_BUFFER_SEQUENCER_H_ |