| // 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. |
| |
| #include "src/ui/lib/escher/impl/frame_manager.h" |
| |
| #include "src/ui/lib/escher/renderer/frame.h" |
| #include "src/ui/lib/escher/util/trace_macros.h" |
| |
| namespace escher { |
| namespace impl { |
| |
| FrameManager::FrameManager(EscherWeakPtr escher) |
| : ResourceManager(escher), |
| // TODO(https://fxbug.dev/42151346): the intention here was to use UniformBufferPool's |
| // recently-added ring-based recycling to manage resource reclamation. |
| // However, this would conflict with upcoming GpuUploader changes; see |
| // https://fxbug.dev/42098213. |
| // For now, clients must use an approach like ModelDisplayListBuilder's, |
| // which takes additional steps to retain uniform buffers to prevent them |
| // from being returned to the pool too early, resulting in the current |
| // frame's data being stomped by the next frame's while it is still in |
| // use. |
| uniform_buffer_pool_(std::move(escher), 1), |
| gpu_vthread_literal_("Escher GPU"), |
| gpu_vthread_id_(TRACE_NONCE()) { |
| // Escher apps will at least double-buffer, so avoid expensive allocations in |
| // the initial few frames. |
| constexpr int kInitialBlockAllocatorCount = 2; |
| for (int i = 0; i < kInitialBlockAllocatorCount; ++i) { |
| block_allocators_.push(std::make_unique<BlockAllocator>()); |
| } |
| } |
| |
| FrameManager::~FrameManager() = default; |
| |
| FramePtr FrameManager::NewFrame(const char* trace_literal, uint64_t frame_number, |
| bool enable_gpu_logging, escher::CommandBuffer::Type requested_type, |
| bool use_protected_memory) { |
| TRACE_DURATION("gfx", "escher::FrameManager::NewFrame"); |
| uniform_buffer_pool_.BeginFrame(); |
| FramePtr frame = fxl::AdoptRef<Frame>( |
| new Frame(this, requested_type, std::move(*GetBlockAllocator().get()), |
| uniform_buffer_pool_.GetWeakPtr(), frame_number, trace_literal, |
| gpu_vthread_literal_, gpu_vthread_id_, enable_gpu_logging, use_protected_memory)); |
| frame->BeginFrame(); |
| return frame; |
| } |
| |
| void FrameManager::OnReceiveOwnable(std::unique_ptr<Resource> resource) { |
| FX_DCHECK(resource->IsKindOf<Frame>()); |
| auto frame = static_cast<Frame*>(resource.get()); |
| block_allocators_.push(std::make_unique<BlockAllocator>(frame->TakeBlockAllocator())); |
| } |
| |
| std::unique_ptr<BlockAllocator> FrameManager::GetBlockAllocator() { |
| if (block_allocators_.empty()) { |
| return std::make_unique<BlockAllocator>(); |
| } |
| |
| std::unique_ptr<BlockAllocator> alloc(std::move(block_allocators_.front())); |
| block_allocators_.pop(); |
| return alloc; |
| } |
| |
| } // namespace impl |
| } // namespace escher |