| // Copyright 2013 The Flutter 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 "impeller/renderer/backend/vulkan/fenced_command_buffer_vk.h" |
| |
| #include <memory> |
| |
| #include "impeller/base/validation.h" |
| #include "impeller/renderer/backend/vulkan/deletion_queue_vk.h" |
| |
| namespace impeller { |
| |
| static vk::CommandBuffer CreateCommandBuffer(vk::Device device, |
| vk::CommandPool pool) { |
| vk::CommandBufferAllocateInfo allocate_info; |
| allocate_info.setLevel(vk::CommandBufferLevel::ePrimary); |
| allocate_info.setCommandBufferCount(1); |
| allocate_info.setCommandPool(pool); |
| |
| auto res = device.allocateCommandBuffers(allocate_info); |
| if (res.result != vk::Result::eSuccess) { |
| VALIDATION_LOG << "Failed to allocate command buffer: " |
| << vk::to_string(res.result); |
| return nullptr; |
| } |
| |
| return res.value[0]; |
| } |
| |
| FencedCommandBufferVK::FencedCommandBufferVK(vk::Device device, |
| vk::Queue queue, |
| vk::CommandPool command_pool) |
| : device_(device), |
| queue_(queue), |
| command_pool_(command_pool), |
| deletion_queue_(std::make_unique<DeletionQueueVK>()) { |
| command_buffer_ = CreateCommandBuffer(device_, command_pool_); |
| } |
| |
| vk::CommandBuffer FencedCommandBufferVK::Get() const { |
| return command_buffer_; |
| } |
| |
| vk::CommandBuffer FencedCommandBufferVK::GetSingleUseChild() { |
| auto child = CreateCommandBuffer(device_, command_pool_); |
| children_.push_back(child); |
| return child; |
| } |
| |
| FencedCommandBufferVK::~FencedCommandBufferVK() { |
| if (!submitted_) { |
| FML_LOG(WARNING) |
| << "FencedCommandBufferVK is being destroyed without being submitted."; |
| children_.push_back(command_buffer_); |
| } |
| device_.freeCommandBuffers(command_pool_, children_); |
| } |
| |
| bool FencedCommandBufferVK::Submit() { |
| if (submitted_) { |
| VALIDATION_LOG << "Command buffer already submitted."; |
| return false; |
| } |
| |
| children_.push_back(command_buffer_); |
| |
| auto fence_res = device_.createFenceUnique(vk::FenceCreateInfo()); |
| if (fence_res.result != vk::Result::eSuccess) { |
| VALIDATION_LOG << "Failed to create fence: " |
| << vk::to_string(fence_res.result); |
| return false; |
| } |
| vk::UniqueFence fence = std::move(fence_res.value); |
| |
| vk::SubmitInfo submit_info; |
| submit_info.setCommandBuffers(children_); |
| auto res = queue_.submit(submit_info, *fence); |
| if (res != vk::Result::eSuccess) { |
| VALIDATION_LOG << "Failed to submit command buffer: " << vk::to_string(res); |
| return false; |
| } |
| |
| auto wait = device_.waitForFences(fence.get(), true, UINT64_MAX); |
| if (wait != vk::Result::eSuccess) { |
| VALIDATION_LOG << "Failed to wait for fence: " << vk::to_string(wait); |
| return false; |
| } |
| |
| // cleanup all the resources held by the command buffer and its children. |
| deletion_queue_->Flush(); |
| |
| submitted_ = true; |
| return true; |
| } |
| |
| DeletionQueueVK* FencedCommandBufferVK::GetDeletionQueue() const { |
| return deletion_queue_.get(); |
| } |
| |
| } // namespace impeller |