Flutter Impeller
command_encoder_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 
6 
7 #include "flutter/fml/closure.h"
11 
12 namespace impeller {
13 
15  public:
16  explicit TrackedObjectsVK(
17  const std::weak_ptr<const DeviceHolder>& device_holder,
18  const std::shared_ptr<CommandPoolVK>& pool)
19  : desc_pool_(device_holder) {
20  if (!pool) {
21  return;
22  }
23  auto buffer = pool->CreateCommandBuffer();
24  if (!buffer) {
25  return;
26  }
27  pool_ = pool;
28  buffer_ = std::move(buffer);
29  is_valid_ = true;
30  }
31 
33  if (!buffer_) {
34  return;
35  }
36  pool_->CollectCommandBuffer(std::move(buffer_));
37  }
38 
39  bool IsValid() const { return is_valid_; }
40 
41  void Track(std::shared_ptr<SharedObjectVK> object) {
42  if (!object) {
43  return;
44  }
45  tracked_objects_.insert(std::move(object));
46  }
47 
48  void Track(std::shared_ptr<const Buffer> buffer) {
49  if (!buffer) {
50  return;
51  }
52  tracked_buffers_.insert(std::move(buffer));
53  }
54 
55  bool IsTracking(const std::shared_ptr<const Buffer>& buffer) const {
56  if (!buffer) {
57  return false;
58  }
59  return tracked_buffers_.find(buffer) != tracked_buffers_.end();
60  }
61 
62  void Track(std::shared_ptr<const TextureSourceVK> texture) {
63  if (!texture) {
64  return;
65  }
66  tracked_textures_.insert(std::move(texture));
67  }
68 
69  bool IsTracking(const std::shared_ptr<const TextureSourceVK>& texture) const {
70  if (!texture) {
71  return false;
72  }
73  return tracked_textures_.find(texture) != tracked_textures_.end();
74  }
75 
76  vk::CommandBuffer GetCommandBuffer() const { return *buffer_; }
77 
78  DescriptorPoolVK& GetDescriptorPool() { return desc_pool_; }
79 
80  private:
81  DescriptorPoolVK desc_pool_;
82  // `shared_ptr` since command buffers have a link to the command pool.
83  std::shared_ptr<CommandPoolVK> pool_;
84  vk::UniqueCommandBuffer buffer_;
85  std::set<std::shared_ptr<SharedObjectVK>> tracked_objects_;
86  std::set<std::shared_ptr<const Buffer>> tracked_buffers_;
87  std::set<std::shared_ptr<const TextureSourceVK>> tracked_textures_;
88  bool is_valid_ = false;
89 
90  FML_DISALLOW_COPY_AND_ASSIGN(TrackedObjectsVK);
91 };
92 
94  const std::weak_ptr<const ContextVK>& context)
95  : context_(context) {}
96 
97 void CommandEncoderFactoryVK::SetLabel(const std::string& label) {
98  label_ = label;
99 }
100 
101 std::shared_ptr<CommandEncoderVK> CommandEncoderFactoryVK::Create() {
102  auto context = context_.lock();
103  if (!context) {
104  return nullptr;
105  }
106  auto& context_vk = ContextVK::Cast(*context);
107  auto recycler = context_vk.GetCommandPoolRecycler();
108  if (!recycler) {
109  return nullptr;
110  }
111  auto tls_pool = recycler->Get();
112  if (!tls_pool) {
113  return nullptr;
114  }
115 
116  auto tracked_objects = std::make_shared<TrackedObjectsVK>(
117  context_vk.GetDeviceHolder(), tls_pool);
118  auto queue = context_vk.GetGraphicsQueue();
119 
120  if (!tracked_objects || !tracked_objects->IsValid() || !queue) {
121  return nullptr;
122  }
123 
124  vk::CommandBufferBeginInfo begin_info;
125  begin_info.flags = vk::CommandBufferUsageFlagBits::eOneTimeSubmit;
126  if (tracked_objects->GetCommandBuffer().begin(begin_info) !=
127  vk::Result::eSuccess) {
128  VALIDATION_LOG << "Could not begin command buffer.";
129  return nullptr;
130  }
131 
132  if (label_.has_value()) {
133  context_vk.SetDebugName(tracked_objects->GetCommandBuffer(),
134  label_.value());
135  }
136 
137  return std::make_shared<CommandEncoderVK>(context_vk.GetDeviceHolder(),
138  tracked_objects, queue,
139  context_vk.GetFenceWaiter());
140 }
141 
143  std::weak_ptr<const DeviceHolder> device_holder,
144  std::shared_ptr<TrackedObjectsVK> tracked_objects,
145  const std::shared_ptr<QueueVK>& queue,
146  std::shared_ptr<FenceWaiterVK> fence_waiter)
147  : device_holder_(std::move(device_holder)),
148  tracked_objects_(std::move(tracked_objects)),
149  queue_(queue),
150  fence_waiter_(std::move(fence_waiter)) {}
151 
153 
155  return is_valid_;
156 }
157 
159  // Make sure to call callback with `false` if anything returns early.
160  bool fail_callback = !!callback;
161  if (!IsValid()) {
162  VALIDATION_LOG << "Cannot submit invalid CommandEncoderVK.";
163  if (fail_callback) {
164  callback(false);
165  }
166  return false;
167  }
168 
169  // Success or failure, you only get to submit once.
170  fml::ScopedCleanupClosure reset([&]() {
171  if (fail_callback) {
172  callback(false);
173  }
174  Reset();
175  });
176 
177  InsertDebugMarker("QueueSubmit");
178 
179  auto command_buffer = GetCommandBuffer();
180 
181  auto status = command_buffer.end();
182  if (status != vk::Result::eSuccess) {
183  VALIDATION_LOG << "Failed to end command buffer: " << vk::to_string(status);
184  return false;
185  }
186  std::shared_ptr<const DeviceHolder> strong_device = device_holder_.lock();
187  if (!strong_device) {
188  VALIDATION_LOG << "Device lost.";
189  return false;
190  }
191  auto [fence_result, fence] = strong_device->GetDevice().createFenceUnique({});
192  if (fence_result != vk::Result::eSuccess) {
193  VALIDATION_LOG << "Failed to create fence: " << vk::to_string(fence_result);
194  return false;
195  }
196 
197  vk::SubmitInfo submit_info;
198  std::vector<vk::CommandBuffer> buffers = {command_buffer};
199  submit_info.setCommandBuffers(buffers);
200  status = queue_->Submit(submit_info, *fence);
201  if (status != vk::Result::eSuccess) {
202  VALIDATION_LOG << "Failed to submit queue: " << vk::to_string(status);
203  return false;
204  }
205 
206  // Submit will proceed, call callback with true when it is done and do not
207  // call when `reset` is collected.
208  fail_callback = false;
209  return fence_waiter_->AddFence(
210  std::move(fence),
211  [callback, tracked_objects = std::move(tracked_objects_)] {
212  if (callback) {
213  callback(true);
214  }
215  });
216 }
217 
218 vk::CommandBuffer CommandEncoderVK::GetCommandBuffer() const {
219  if (tracked_objects_) {
220  return tracked_objects_->GetCommandBuffer();
221  }
222  return {};
223 }
224 
225 void CommandEncoderVK::Reset() {
226  tracked_objects_.reset();
227 
228  queue_ = nullptr;
229  is_valid_ = false;
230 }
231 
232 bool CommandEncoderVK::Track(std::shared_ptr<SharedObjectVK> object) {
233  if (!IsValid()) {
234  return false;
235  }
236  tracked_objects_->Track(std::move(object));
237  return true;
238 }
239 
240 bool CommandEncoderVK::Track(std::shared_ptr<const Buffer> buffer) {
241  if (!IsValid()) {
242  return false;
243  }
244  tracked_objects_->Track(std::move(buffer));
245  return true;
246 }
247 
249  const std::shared_ptr<const Buffer>& buffer) const {
250  if (!IsValid()) {
251  return false;
252  }
253  return tracked_objects_->IsTracking(buffer);
254 }
255 
256 bool CommandEncoderVK::Track(std::shared_ptr<const TextureSourceVK> texture) {
257  if (!IsValid()) {
258  return false;
259  }
260  tracked_objects_->Track(std::move(texture));
261  return true;
262 }
263 
264 bool CommandEncoderVK::Track(const std::shared_ptr<const Texture>& texture) {
265  if (!IsValid()) {
266  return false;
267  }
268  if (!texture) {
269  return true;
270  }
271  return Track(TextureVK::Cast(*texture).GetTextureSource());
272 }
273 
275  const std::shared_ptr<const Texture>& texture) const {
276  if (!IsValid()) {
277  return false;
278  }
279  std::shared_ptr<const TextureSourceVK> source =
280  TextureVK::Cast(*texture).GetTextureSource();
281  return tracked_objects_->IsTracking(source);
282 }
283 
284 std::optional<vk::DescriptorSet> CommandEncoderVK::AllocateDescriptorSet(
285  const vk::DescriptorSetLayout& layout,
286  size_t command_count) {
287  if (!IsValid()) {
288  return std::nullopt;
289  }
290 
291  return tracked_objects_->GetDescriptorPool().AllocateDescriptorSet(
292  layout, command_count);
293 }
294 
295 void CommandEncoderVK::PushDebugGroup(const char* label) const {
296  if (!HasValidationLayers()) {
297  return;
298  }
299  vk::DebugUtilsLabelEXT label_info;
300  label_info.pLabelName = label;
301  if (auto command_buffer = GetCommandBuffer()) {
302  command_buffer.beginDebugUtilsLabelEXT(label_info);
303  }
304 }
305 
307  if (!HasValidationLayers()) {
308  return;
309  }
310  if (auto command_buffer = GetCommandBuffer()) {
311  command_buffer.endDebugUtilsLabelEXT();
312  }
313 }
314 
315 void CommandEncoderVK::InsertDebugMarker(const char* label) const {
316  if (!HasValidationLayers()) {
317  return;
318  }
319  vk::DebugUtilsLabelEXT label_info;
320  label_info.pLabelName = label;
321  if (auto command_buffer = GetCommandBuffer()) {
322  command_buffer.insertDebugUtilsLabelEXT(label_info);
323  }
324  if (queue_) {
325  queue_->InsertDebugMarker(label);
326  }
327 }
328 
329 } // namespace impeller
impeller::CommandEncoderVK::Submit
bool Submit(SubmitCallback callback={})
Definition: command_encoder_vk.cc:158
fence_waiter_vk.h
impeller::CommandEncoderVK::PushDebugGroup
void PushDebugGroup(const char *label) const
Definition: command_encoder_vk.cc:295
impeller::TrackedObjectsVK
Definition: command_encoder_vk.cc:14
command_encoder_vk.h
impeller::TrackedObjectsVK::TrackedObjectsVK
TrackedObjectsVK(const std::weak_ptr< const DeviceHolder > &device_holder, const std::shared_ptr< CommandPoolVK > &pool)
Definition: command_encoder_vk.cc:16
impeller::TrackedObjectsVK::IsTracking
bool IsTracking(const std::shared_ptr< const Buffer > &buffer) const
Definition: command_encoder_vk.cc:55
impeller::TrackedObjectsVK::~TrackedObjectsVK
~TrackedObjectsVK()
Definition: command_encoder_vk.cc:32
impeller::TrackedObjectsVK::IsTracking
bool IsTracking(const std::shared_ptr< const TextureSourceVK > &texture) const
Definition: command_encoder_vk.cc:69
impeller::TextureVK::GetTextureSource
std::shared_ptr< const TextureSourceVK > GetTextureSource() const
Definition: texture_vk.cc:136
impeller::CommandEncoderVK::CommandEncoderVK
CommandEncoderVK(std::weak_ptr< const DeviceHolder > device_holder, std::shared_ptr< TrackedObjectsVK > tracked_objects, const std::shared_ptr< QueueVK > &queue, std::shared_ptr< FenceWaiterVK > fence_waiter)
Definition: command_encoder_vk.cc:142
impeller::CommandEncoderVK::AllocateDescriptorSet
std::optional< vk::DescriptorSet > AllocateDescriptorSet(const vk::DescriptorSetLayout &layout, size_t command_count)
Definition: command_encoder_vk.cc:284
impeller::CommandEncoderFactoryVK::SetLabel
void SetLabel(const std::string &label)
Definition: command_encoder_vk.cc:97
impeller::TrackedObjectsVK::GetDescriptorPool
DescriptorPoolVK & GetDescriptorPool()
Definition: command_encoder_vk.cc:78
impeller::TrackedObjectsVK::IsValid
bool IsValid() const
Definition: command_encoder_vk.cc:39
impeller::CommandEncoderVK::SubmitCallback
std::function< void(bool)> SubmitCallback
Definition: command_encoder_vk.h:47
impeller::CommandEncoderVK::Track
bool Track(std::shared_ptr< SharedObjectVK > object)
Definition: command_encoder_vk.cc:232
impeller::DescriptorPoolVK
A short-lived dynamically-sized descriptor pool. Descriptors from this pool don't need to be freed in...
Definition: descriptor_pool_vk.h:28
impeller::TrackedObjectsVK::GetCommandBuffer
vk::CommandBuffer GetCommandBuffer() const
Definition: command_encoder_vk.cc:76
impeller::CommandEncoderFactoryVK::CommandEncoderFactoryVK
CommandEncoderFactoryVK(const std::weak_ptr< const ContextVK > &context)
Definition: command_encoder_vk.cc:93
impeller::TrackedObjectsVK::Track
void Track(std::shared_ptr< const TextureSourceVK > texture)
Definition: command_encoder_vk.cc:62
impeller::CommandEncoderVK::InsertDebugMarker
void InsertDebugMarker(const char *label) const
Definition: command_encoder_vk.cc:315
impeller::CommandEncoderVK::PopDebugGroup
void PopDebugGroup() const
Definition: command_encoder_vk.cc:306
texture_vk.h
VALIDATION_LOG
#define VALIDATION_LOG
Definition: validation.h:60
impeller::CommandEncoderVK::~CommandEncoderVK
~CommandEncoderVK()
std
Definition: comparable.h:98
impeller::BackendCast< ContextVK, Context >::Cast
static ContextVK & Cast(Context &base)
Definition: backend_cast.h:14
impeller::CommandEncoderVK::IsTracking
bool IsTracking(const std::shared_ptr< const Buffer > &texture) const
Definition: command_encoder_vk.cc:248
context_vk.h
impeller::TrackedObjectsVK::Track
void Track(std::shared_ptr< SharedObjectVK > object)
Definition: command_encoder_vk.cc:41
impeller::HasValidationLayers
bool HasValidationLayers()
Definition: context_vk.cc:40
impeller::CommandEncoderVK::IsValid
bool IsValid() const
Definition: command_encoder_vk.cc:154
impeller
Definition: aiks_context.cc:10
impeller::CommandEncoderVK::GetCommandBuffer
vk::CommandBuffer GetCommandBuffer() const
Definition: command_encoder_vk.cc:218
impeller::TrackedObjectsVK::Track
void Track(std::shared_ptr< const Buffer > buffer)
Definition: command_encoder_vk.cc:48
impeller::CommandEncoderFactoryVK::Create
std::shared_ptr< CommandEncoderVK > Create()
Definition: command_encoder_vk.cc:101