Flutter Impeller
command_queue_vk.cc
Go to the documentation of this file.
1 // Copyright 2013 The Flutter Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #include "fml/status.h"
6 
8 
15 
16 namespace impeller {
17 
18 CommandQueueVK::CommandQueueVK(const std::weak_ptr<ContextVK>& context)
19  : context_(context) {}
20 
22 
24  const std::vector<std::shared_ptr<CommandBuffer>>& buffers,
25  const CompletionCallback& completion_callback,
26  bool block_on_schedule) {
27  if (buffers.empty()) {
28  return fml::Status(fml::StatusCode::kInvalidArgument,
29  "No command buffers provided.");
30  }
31  // Success or failure, you only get to submit once.
32  fml::ScopedCleanupClosure reset([&]() {
33  if (completion_callback) {
34  completion_callback(CommandBuffer::Status::kError);
35  }
36  });
37 
38  std::vector<vk::CommandBuffer> vk_buffers;
39  std::vector<std::shared_ptr<TrackedObjectsVK>> tracked_objects;
40  vk_buffers.reserve(buffers.size());
41  tracked_objects.reserve(buffers.size());
42  for (const std::shared_ptr<CommandBuffer>& buffer : buffers) {
44  if (!command_buffer.EndCommandBuffer()) {
45  return fml::Status(fml::StatusCode::kCancelled,
46  "Failed to end command buffer.");
47  }
48  vk_buffers.push_back(command_buffer.GetCommandBuffer());
49  tracked_objects.push_back(std::move(command_buffer.tracked_objects_));
50  }
51 
52  auto context = context_.lock();
53  if (!context) {
54  VALIDATION_LOG << "Device lost.";
55  return fml::Status(fml::StatusCode::kCancelled, "Device lost.");
56  }
57  auto [fence_result, fence] = context->GetDevice().createFenceUnique({});
58  if (fence_result != vk::Result::eSuccess) {
59  VALIDATION_LOG << "Failed to create fence: " << vk::to_string(fence_result);
60  return fml::Status(fml::StatusCode::kCancelled, "Failed to create fence.");
61  }
62 
63  // This will be called immediately by FenceWaiterVK::AddFence.
64  auto submit_callback = [&context, &vk_buffers](vk::Fence submit_fence) {
65  vk::SubmitInfo submit_info;
66  submit_info.setCommandBuffers(vk_buffers);
67  auto status =
68  context->GetGraphicsQueue()->Submit(submit_info, submit_fence);
69  if (status != vk::Result::eSuccess) {
70  std::string submit_error =
71  "Failed to submit command: " + vk::to_string(status);
72  VALIDATION_LOG << submit_error;
73  return fml::Status(fml::StatusCode::kCancelled, submit_error);
74  }
75  return fml::Status();
76  };
77 
78  // This will be called later when the command completes.
79  auto fence_complete_callback = [completion_callback,
80  tracked_objects =
81  std::move(tracked_objects)]() mutable {
82  // Ensure tracked objects are destructed before calling any final
83  // callbacks.
84  tracked_objects.clear();
85  if (completion_callback) {
86  completion_callback(CommandBuffer::Status::kCompleted);
87  }
88  };
89 
90  // Submit will proceed, call callback with true when it is done and do not
91  // call when `reset` is collected.
92  auto fence_status = context->GetFenceWaiter()->AddFence(
93  std::move(fence), submit_callback, std::move(fence_complete_callback));
94  if (!fence_status.ok()) {
95  return fence_status;
96  }
97  reset.Release();
98  return fml::Status();
99 }
100 
101 } // namespace impeller
static CommandBufferVK & Cast(CommandBuffer &base)
Definition: backend_cast.h:13
std::function< void(CommandBuffer::Status)> CompletionCallback
Definition: command_queue.h:19
CommandQueueVK(const std::weak_ptr< ContextVK > &context)
fml::Status Submit(const std::vector< std::shared_ptr< CommandBuffer >> &buffers, const CompletionCallback &completion_callback={}, bool block_on_schedule=false) override
Submit one or more command buffer objects to be encoded and executed on the GPU.
std::shared_ptr< ContextGLES > context
std::shared_ptr< CommandBuffer > command_buffer
#define VALIDATION_LOG
Definition: validation.h:91