| // Copyright 2018 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 SRC_UI_LIB_ESCHER_RENDERER_RENDER_QUEUE_H_ |
| #define SRC_UI_LIB_ESCHER_RENDERER_RENDER_QUEUE_H_ |
| |
| #include "src/ui/lib/escher/renderer/render_queue_item.h" |
| #include "src/ui/lib/escher/vk/command_buffer.h" |
| |
| namespace escher { |
| |
| // RenderQueue provides an abstraction to allow renderable objects of different |
| // types to be sorted according to a uniform criterion before emitting commands |
| // into a Vulkan command buffer. Client use of RenderQueue typically follows |
| // these steps: |
| // - call Push() repeatedly to add all renderable objects to the queue. |
| // - call Sort() once to sort the items according to their integer sort key. |
| // - call GenerateCommands() once to add Vulkan commands to a command buffer. |
| // - call clear() to clear all items, preparing the queue to be used next frame. |
| // |
| // See the method documentation for additional details. |
| class RenderQueue final { |
| public: |
| RenderQueue(); |
| RenderQueue(const RenderQueue& other) = delete; |
| RenderQueue(RenderQueue&& other); |
| ~RenderQueue(); |
| |
| // The method arguments are encapsulated in a RenderQueueItem. Since |
| // |object_data| and |instance_data| are void*, it is clearly up to the caller |
| // to manage their lifecycle (including any data that they point to). For |
| // example, any CPU memory must be valid until Clear() is called, and any GPU |
| // resources must be kept alive until all Vulkan command buffers that |
| // reference them are finished. |
| void Push(uint64_t sort_key, const void* object_data, const void* instance_data, |
| RenderQueueItem::Func func); |
| void Push(const RenderQueueItem& item); |
| |
| // Performs a stable sort of all items, according to the |sort_key| provided |
| // to Push(). Using a simple integer as the sort key allows clients a large |
| // degree of flexibility in defining sort criteria. For example, translucent |
| // objects must be sorted back-to-front after all opaque objects, whereas |
| // opaque objects are more efficiently rendered front-to-back. |
| void Sort(); |
| |
| // Generate Vulkan commands for items in the queue, by iterating over the |
| // items and invoking each item's RenderFunc on it. If multiple consecutive |
| // items have the same |object_data|, they are batched into a single call to |
| // RenderFunc; in this case the number of consecutive items is encoded in the |
| // |instance_count|. Otherwise, |instance_count| == 1. |
| // |
| // This is typically called after Sort(), but this is not necessary. For |
| // example, clients may choose to not call Sort() in order to profile the |
| // performance difference of sorting vs. not sorting. |
| void GenerateCommands(CommandBuffer* cmd_buf, const CommandBuffer::SavedState* state, |
| const RenderQueueContext* context = nullptr) const; |
| |
| // This variant of GenerateCommands() behaves similarly to the one above, |
| // except that it only generates commands for a sub-range of the items in the |
| // queue. This is typically used for debugging. |
| void GenerateCommands(CommandBuffer* cmd_buf, const CommandBuffer::SavedState* state, |
| const RenderQueueContext* context, size_t start_index, size_t count) const; |
| |
| void clear() { items_.clear(); } |
| size_t size() const { return items_.size(); } |
| bool empty() const { return size() == 0; } |
| |
| protected: |
| std::vector<RenderQueueItem> items_; |
| }; |
| |
| // Inline function definitions. |
| |
| inline void RenderQueue::Push(uint64_t sort_key, const void* object_data, const void* instance_data, |
| RenderQueueItem::Func func) { |
| items_.push_back({sort_key, object_data, instance_data, func}); |
| } |
| |
| inline void RenderQueue::Push(const RenderQueueItem& item) { items_.push_back(item); } |
| |
| } // namespace escher |
| |
| #endif // SRC_UI_LIB_ESCHER_RENDERER_RENDER_QUEUE_H_ |