Flutter Impeller
render_pass_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 <array>
8 #include <cstdint>
9 #include <vector>
10 
11 #include "flutter/fml/logging.h"
12 #include "flutter/fml/trace_event.h"
14 #include "impeller/core/formats.h"
15 #include "impeller/core/sampler.h"
27 #include "vulkan/vulkan_to_string.hpp"
28 
29 namespace impeller {
30 
31 static vk::AttachmentDescription CreateAttachmentDescription(
32  const Attachment& attachment,
33  const std::shared_ptr<Texture> Attachment::*texture_ptr) {
34  const auto& texture = attachment.*texture_ptr;
35  if (!texture) {
36  return {};
37  }
38  const auto& texture_vk = TextureVK::Cast(*texture);
39  const auto& desc = texture->GetTextureDescriptor();
40  auto current_layout = texture_vk.GetLayout();
41 
42  auto load_action = attachment.load_action;
43  auto store_action = attachment.store_action;
44 
45  if (current_layout == vk::ImageLayout::eUndefined) {
46  load_action = LoadAction::kClear;
47  }
48 
49  if (desc.storage_mode == StorageMode::kDeviceTransient) {
50  store_action = StoreAction::kDontCare;
51  } else if (texture_ptr == &Attachment::resolve_texture) {
52  store_action = StoreAction::kStore;
53  }
54 
55  if (current_layout != vk::ImageLayout::ePresentSrcKHR &&
56  current_layout != vk::ImageLayout::eUndefined) {
57  // Note: This should incur a barrier.
58  current_layout = vk::ImageLayout::eGeneral;
59  }
60 
61  return CreateAttachmentDescription(desc.format, //
62  desc.sample_count, //
63  load_action, //
64  store_action, //
65  current_layout //
66  );
67 }
68 
69 static void SetTextureLayout(
70  const Attachment& attachment,
71  const vk::AttachmentDescription& attachment_desc,
72  const std::shared_ptr<CommandBufferVK>& command_buffer,
73  const std::shared_ptr<Texture> Attachment::*texture_ptr) {
74  const auto& texture = attachment.*texture_ptr;
75  if (!texture) {
76  return;
77  }
78  const auto& texture_vk = TextureVK::Cast(*texture);
79 
80  if (attachment_desc.initialLayout == vk::ImageLayout::eGeneral) {
81  BarrierVK barrier;
82  barrier.new_layout = vk::ImageLayout::eGeneral;
83  barrier.cmd_buffer = command_buffer->GetEncoder()->GetCommandBuffer();
84  barrier.src_access = vk::AccessFlagBits::eShaderRead;
85  barrier.src_stage = vk::PipelineStageFlagBits::eFragmentShader;
86  barrier.dst_access = vk::AccessFlagBits::eColorAttachmentWrite |
87  vk::AccessFlagBits::eTransferWrite;
88  barrier.dst_stage = vk::PipelineStageFlagBits::eColorAttachmentOutput |
89  vk::PipelineStageFlagBits::eTransfer;
90 
91  texture_vk.SetLayout(barrier);
92  }
93 
94  // Instead of transitioning layouts manually using barriers, we are going to
95  // make the subpass perform our transitions.
96  texture_vk.SetLayoutWithoutEncoding(attachment_desc.finalLayout);
97 }
98 
99 SharedHandleVK<vk::RenderPass> RenderPassVK::CreateVKRenderPass(
100  const ContextVK& context,
101  const std::shared_ptr<CommandBufferVK>& command_buffer) const {
102  std::vector<vk::AttachmentDescription> attachments;
103 
104  std::vector<vk::AttachmentReference> color_refs;
105  std::vector<vk::AttachmentReference> resolve_refs;
106  vk::AttachmentReference depth_stencil_ref = kUnusedAttachmentReference;
107 
108  // Spec says: "Each element of the pColorAttachments array corresponds to an
109  // output location in the shader, i.e. if the shader declares an output
110  // variable decorated with a Location value of X, then it uses the attachment
111  // provided in pColorAttachments[X]. If the attachment member of any element
112  // of pColorAttachments is VK_ATTACHMENT_UNUSED."
113  //
114  // Just initialize all the elements as unused and fill in the valid bind
115  // points in the loop below.
116  color_refs.resize(render_target_.GetMaxColorAttacmentBindIndex() + 1u,
118  resolve_refs.resize(render_target_.GetMaxColorAttacmentBindIndex() + 1u,
120 
121  for (const auto& [bind_point, color] : render_target_.GetColorAttachments()) {
122  color_refs[bind_point] =
123  vk::AttachmentReference{static_cast<uint32_t>(attachments.size()),
124  vk::ImageLayout::eColorAttachmentOptimal};
125  attachments.emplace_back(
127  SetTextureLayout(color, attachments.back(), command_buffer,
129  if (color.resolve_texture) {
130  resolve_refs[bind_point] = vk::AttachmentReference{
131  static_cast<uint32_t>(attachments.size()), vk::ImageLayout::eGeneral};
132  attachments.emplace_back(
134  SetTextureLayout(color, attachments.back(), command_buffer,
136  }
137  }
138 
139  if (auto depth = render_target_.GetDepthAttachment(); depth.has_value()) {
140  depth_stencil_ref = vk::AttachmentReference{
141  static_cast<uint32_t>(attachments.size()),
142  vk::ImageLayout::eDepthStencilAttachmentOptimal};
143  attachments.emplace_back(
145  SetTextureLayout(depth.value(), attachments.back(), command_buffer,
147  }
148 
149  if (auto stencil = render_target_.GetStencilAttachment();
150  stencil.has_value()) {
151  depth_stencil_ref = vk::AttachmentReference{
152  static_cast<uint32_t>(attachments.size()),
153  vk::ImageLayout::eDepthStencilAttachmentOptimal};
154  attachments.emplace_back(
156  SetTextureLayout(stencil.value(), attachments.back(), command_buffer,
158  }
159 
160  vk::SubpassDescription subpass_desc;
161  subpass_desc.pipelineBindPoint = vk::PipelineBindPoint::eGraphics;
162  subpass_desc.setColorAttachments(color_refs);
163  subpass_desc.setResolveAttachments(resolve_refs);
164  subpass_desc.setPDepthStencilAttachment(&depth_stencil_ref);
165 
166  vk::RenderPassCreateInfo render_pass_desc;
167  render_pass_desc.setAttachments(attachments);
168  render_pass_desc.setPSubpasses(&subpass_desc);
169  render_pass_desc.setSubpassCount(1u);
170 
171  auto [result, pass] =
172  context.GetDevice().createRenderPassUnique(render_pass_desc);
173  if (result != vk::Result::eSuccess) {
174  VALIDATION_LOG << "Failed to create render pass: " << vk::to_string(result);
175  return {};
176  }
177  context.SetDebugName(pass.get(), debug_label_.c_str());
178  return MakeSharedVK(std::move(pass));
179 }
180 
181 RenderPassVK::RenderPassVK(const std::shared_ptr<const Context>& context,
182  const RenderTarget& target,
183  std::weak_ptr<CommandBufferVK> command_buffer)
184  : RenderPass(context, target), command_buffer_(std::move(command_buffer)) {
185  is_valid_ = true;
186 }
187 
188 RenderPassVK::~RenderPassVK() = default;
189 
190 bool RenderPassVK::IsValid() const {
191  return is_valid_;
192 }
193 
194 void RenderPassVK::OnSetLabel(std::string label) {
195  debug_label_ = std::move(label);
196 }
197 
198 static vk::ClearColorValue VKClearValueFromColor(Color color) {
199  vk::ClearColorValue value;
200  value.setFloat32(
201  std::array<float, 4>{color.red, color.green, color.blue, color.alpha});
202  return value;
203 }
204 
205 static vk::ClearDepthStencilValue VKClearValueFromDepthStencil(uint32_t stencil,
206  Scalar depth) {
207  vk::ClearDepthStencilValue value;
208  value.depth = depth;
209  value.stencil = stencil;
210  return value;
211 }
212 
213 static std::vector<vk::ClearValue> GetVKClearValues(
214  const RenderTarget& target) {
215  std::vector<vk::ClearValue> clears;
216 
217  for (const auto& [_, color] : target.GetColorAttachments()) {
218  clears.emplace_back(VKClearValueFromColor(color.clear_color));
219  if (color.resolve_texture) {
220  clears.emplace_back(VKClearValueFromColor(color.clear_color));
221  }
222  }
223 
224  const auto& depth = target.GetDepthAttachment();
225  const auto& stencil = target.GetStencilAttachment();
226 
227  if (depth.has_value()) {
228  clears.emplace_back(VKClearValueFromDepthStencil(
229  stencil ? stencil->clear_stencil : 0u, depth->clear_depth));
230  }
231 
232  if (stencil.has_value()) {
233  clears.emplace_back(VKClearValueFromDepthStencil(
234  stencil->clear_stencil, depth ? depth->clear_depth : 0.0f));
235  }
236 
237  return clears;
238 }
239 
240 SharedHandleVK<vk::Framebuffer> RenderPassVK::CreateVKFramebuffer(
241  const ContextVK& context,
242  const vk::RenderPass& pass) const {
243  vk::FramebufferCreateInfo fb_info;
244 
245  fb_info.renderPass = pass;
246 
247  const auto target_size = render_target_.GetRenderTargetSize();
248  fb_info.width = target_size.width;
249  fb_info.height = target_size.height;
250 
251  fb_info.layers = 1u;
252 
253  std::vector<vk::ImageView> attachments;
254 
255  // This bit must be consistent to ensure compatibility with the pass created
256  // earlier. Follow this order: Color attachments, then depth, then stencil.
257  for (const auto& [_, color] : render_target_.GetColorAttachments()) {
258  // The bind point doesn't matter here since that information is present in
259  // the render pass.
260  attachments.emplace_back(TextureVK::Cast(*color.texture).GetImageView());
261  if (color.resolve_texture) {
262  attachments.emplace_back(
263  TextureVK::Cast(*color.resolve_texture).GetImageView());
264  }
265  }
266  if (auto depth = render_target_.GetDepthAttachment(); depth.has_value()) {
267  attachments.emplace_back(TextureVK::Cast(*depth->texture).GetImageView());
268  }
269  if (auto stencil = render_target_.GetStencilAttachment();
270  stencil.has_value()) {
271  attachments.emplace_back(TextureVK::Cast(*stencil->texture).GetImageView());
272  }
273 
274  fb_info.setAttachments(attachments);
275 
276  auto [result, framebuffer] =
277  context.GetDevice().createFramebufferUnique(fb_info);
278 
279  if (result != vk::Result::eSuccess) {
280  VALIDATION_LOG << "Could not create framebuffer: " << vk::to_string(result);
281  return {};
282  }
283 
284  return MakeSharedVK(std::move(framebuffer));
285 }
286 
287 static bool UpdateBindingLayouts(const Bindings& bindings,
288  const vk::CommandBuffer& buffer) {
289  // All previous writes via a render or blit pass must be done before another
290  // shader attempts to read the resource.
291  BarrierVK barrier;
292  barrier.cmd_buffer = buffer;
293  barrier.src_access = vk::AccessFlagBits::eColorAttachmentWrite |
294  vk::AccessFlagBits::eTransferWrite;
295  barrier.src_stage = vk::PipelineStageFlagBits::eColorAttachmentOutput |
296  vk::PipelineStageFlagBits::eTransfer;
297  barrier.dst_access = vk::AccessFlagBits::eShaderRead;
298  barrier.dst_stage = vk::PipelineStageFlagBits::eFragmentShader;
299 
300  barrier.new_layout = vk::ImageLayout::eShaderReadOnlyOptimal;
301 
302  for (const auto& [_, data] : bindings.sampled_images) {
303  if (!TextureVK::Cast(*data.texture.resource).SetLayout(barrier)) {
304  return false;
305  }
306  }
307  return true;
308 }
309 
310 static bool UpdateBindingLayouts(const Command& command,
311  const vk::CommandBuffer& buffer) {
312  return UpdateBindingLayouts(command.vertex_bindings, buffer) &&
313  UpdateBindingLayouts(command.fragment_bindings, buffer);
314 }
315 
316 static bool UpdateBindingLayouts(const std::vector<Command>& commands,
317  const vk::CommandBuffer& buffer) {
318  for (const auto& command : commands) {
319  if (!UpdateBindingLayouts(command, buffer)) {
320  return false;
321  }
322  }
323  return true;
324 }
325 
326 static bool AllocateAndBindDescriptorSets(const ContextVK& context,
327  const Command& command,
328  CommandEncoderVK& encoder,
329  const PipelineVK& pipeline,
330  size_t command_count) {
331  auto desc_set =
332  pipeline.GetDescriptor().GetVertexDescriptor()->GetDescriptorSetLayouts();
333  auto vk_desc_set = encoder.AllocateDescriptorSet(
334  pipeline.GetDescriptorSetLayout(), command_count);
335  if (!vk_desc_set) {
336  return false;
337  }
338 
339  auto& allocator = *context.GetResourceAllocator();
340 
341  std::vector<vk::DescriptorImageInfo> images;
342  std::vector<vk::DescriptorBufferInfo> buffers;
343  std::vector<vk::WriteDescriptorSet> writes;
344  writes.reserve(command.vertex_bindings.buffers.size() +
345  command.fragment_bindings.buffers.size() +
346  command.fragment_bindings.sampled_images.size());
347  images.reserve(command.fragment_bindings.sampled_images.size());
348  buffers.reserve(command.vertex_bindings.buffers.size() +
349  command.fragment_bindings.buffers.size());
350 
351  auto bind_images = [&encoder, //
352  &images, //
353  &writes, //
354  &vk_desc_set //
355  ](const Bindings& bindings) -> bool {
356  for (const auto& [index, data] : bindings.sampled_images) {
357  auto texture = data.texture.resource;
358  const auto& texture_vk = TextureVK::Cast(*texture);
359  const SamplerVK& sampler = SamplerVK::Cast(*data.sampler.resource);
360 
361  if (!encoder.Track(texture) ||
362  !encoder.Track(sampler.GetSharedSampler())) {
363  return false;
364  }
365 
366  const SampledImageSlot& slot = data.slot;
367 
368  vk::DescriptorImageInfo image_info;
369  image_info.imageLayout = vk::ImageLayout::eShaderReadOnlyOptimal;
370  image_info.sampler = sampler.GetSampler();
371  image_info.imageView = texture_vk.GetImageView();
372  images.push_back(image_info);
373 
374  vk::WriteDescriptorSet write_set;
375  write_set.dstSet = vk_desc_set.value();
376  write_set.dstBinding = slot.binding;
377  write_set.descriptorCount = 1u;
378  write_set.descriptorType = vk::DescriptorType::eCombinedImageSampler;
379  write_set.pImageInfo = &images.back();
380 
381  writes.push_back(write_set);
382  }
383 
384  return true;
385  };
386 
387  auto bind_buffers = [&allocator, //
388  &encoder, //
389  &buffers, //
390  &writes, //
391  &desc_set, //
392  &vk_desc_set //
393  ](const Bindings& bindings) -> bool {
394  for (const auto& [buffer_index, data] : bindings.buffers) {
395  const auto& buffer_view = data.view.resource.buffer;
396 
397  auto device_buffer = buffer_view->GetDeviceBuffer(allocator);
398  if (!device_buffer) {
399  VALIDATION_LOG << "Failed to get device buffer for vertex binding";
400  return false;
401  }
402 
403  auto buffer = DeviceBufferVK::Cast(*device_buffer).GetBuffer();
404  if (!buffer) {
405  return false;
406  }
407 
408  if (!encoder.Track(device_buffer)) {
409  return false;
410  }
411 
412  uint32_t offset = data.view.resource.range.offset;
413 
414  vk::DescriptorBufferInfo buffer_info;
415  buffer_info.buffer = buffer;
416  buffer_info.offset = offset;
417  buffer_info.range = data.view.resource.range.length;
418  buffers.push_back(buffer_info);
419 
420  const ShaderUniformSlot& uniform = data.slot;
421  auto layout_it = std::find_if(desc_set.begin(), desc_set.end(),
422  [&uniform](DescriptorSetLayout& layout) {
423  return layout.binding == uniform.binding;
424  });
425  if (layout_it == desc_set.end()) {
426  VALIDATION_LOG << "Failed to get descriptor set layout for binding "
427  << uniform.binding;
428  return false;
429  }
430  auto layout = *layout_it;
431 
432  vk::WriteDescriptorSet write_set;
433  write_set.dstSet = vk_desc_set.value();
434  write_set.dstBinding = uniform.binding;
435  write_set.descriptorCount = 1u;
436  write_set.descriptorType = ToVKDescriptorType(layout.descriptor_type);
437  write_set.pBufferInfo = &buffers.back();
438 
439  writes.push_back(write_set);
440  }
441  return true;
442  };
443 
444  if (!bind_buffers(command.vertex_bindings) ||
445  !bind_buffers(command.fragment_bindings) ||
446  !bind_images(command.fragment_bindings)) {
447  return false;
448  }
449 
450  context.GetDevice().updateDescriptorSets(writes, {});
451 
452  encoder.GetCommandBuffer().bindDescriptorSets(
453  vk::PipelineBindPoint::eGraphics, // bind point
454  pipeline.GetPipelineLayout(), // layout
455  0, // first set
456  {vk::DescriptorSet{*vk_desc_set}}, // sets
457  nullptr // offsets
458  );
459  return true;
460 }
461 
462 static void SetViewportAndScissor(const Command& command,
463  const vk::CommandBuffer& cmd_buffer,
464  PassBindingsCache& cmd_buffer_cache,
465  const ISize& target_size) {
466  // Set the viewport.
467  const auto& vp = command.viewport.value_or<Viewport>(
468  {.rect = Rect::MakeSize(target_size)});
469  vk::Viewport viewport = vk::Viewport()
470  .setWidth(vp.rect.size.width)
471  .setHeight(-vp.rect.size.height)
472  .setY(vp.rect.size.height)
473  .setMinDepth(0.0f)
474  .setMaxDepth(1.0f);
475  cmd_buffer_cache.SetViewport(cmd_buffer, 0, 1, &viewport);
476 
477  // Set the scissor rect.
478  const auto& sc = command.scissor.value_or(IRect::MakeSize(target_size));
479  vk::Rect2D scissor =
480  vk::Rect2D()
481  .setOffset(vk::Offset2D(sc.origin.x, sc.origin.y))
482  .setExtent(vk::Extent2D(sc.size.width, sc.size.height));
483  cmd_buffer_cache.SetScissor(cmd_buffer, 0, 1, &scissor);
484 }
485 
486 static bool EncodeCommand(const Context& context,
487  const Command& command,
488  CommandEncoderVK& encoder,
489  PassBindingsCache& command_buffer_cache,
490  const ISize& target_size,
491  size_t command_count) {
492  if (command.vertex_count == 0u || command.instance_count == 0u) {
493  return true;
494  }
495 
496 #ifdef IMPELLER_DEBUG
497  fml::ScopedCleanupClosure pop_marker(
498  [&encoder]() { encoder.PopDebugGroup(); });
499  if (!command.label.empty()) {
500  encoder.PushDebugGroup(command.label.c_str());
501  } else {
502  pop_marker.Release();
503  }
504 #endif // IMPELLER_DEBUG
505 
506  const auto& cmd_buffer = encoder.GetCommandBuffer();
507 
508  const auto& pipeline_vk = PipelineVK::Cast(*command.pipeline);
509 
510  if (!AllocateAndBindDescriptorSets(ContextVK::Cast(context), //
511  command, //
512  encoder, //
513  pipeline_vk, //
514  command_count //
515  )) {
516  return false;
517  }
518 
519  command_buffer_cache.BindPipeline(
520  cmd_buffer, vk::PipelineBindPoint::eGraphics, pipeline_vk.GetPipeline());
521 
522  // Set the viewport and scissors.
523  SetViewportAndScissor(command, cmd_buffer, command_buffer_cache, target_size);
524 
525  // Set the stencil reference.
526  command_buffer_cache.SetStencilReference(
527  cmd_buffer, vk::StencilFaceFlagBits::eVkStencilFrontAndBack,
528  command.stencil_reference);
529 
530  // Configure vertex and index and buffers for binding.
531  auto vertex_buffer_view = command.GetVertexBuffer();
532 
533  if (!vertex_buffer_view) {
534  return false;
535  }
536 
537  auto& allocator = *context.GetResourceAllocator();
538 
539  auto vertex_buffer = vertex_buffer_view.buffer->GetDeviceBuffer(allocator);
540 
541  if (!vertex_buffer) {
542  VALIDATION_LOG << "Failed to acquire device buffer"
543  << " for vertex buffer view";
544  return false;
545  }
546 
547  if (!encoder.Track(vertex_buffer)) {
548  return false;
549  }
550 
551  // Bind the vertex buffer.
552  auto vertex_buffer_handle = DeviceBufferVK::Cast(*vertex_buffer).GetBuffer();
553  vk::Buffer vertex_buffers[] = {vertex_buffer_handle};
554  vk::DeviceSize vertex_buffer_offsets[] = {vertex_buffer_view.range.offset};
555  cmd_buffer.bindVertexBuffers(0u, 1u, vertex_buffers, vertex_buffer_offsets);
556 
557  if (command.index_type != IndexType::kNone) {
558  // Bind the index buffer.
559  auto index_buffer_view = command.index_buffer;
560  if (!index_buffer_view) {
561  return false;
562  }
563 
564  auto index_buffer = index_buffer_view.buffer->GetDeviceBuffer(allocator);
565  if (!index_buffer) {
566  VALIDATION_LOG << "Failed to acquire device buffer"
567  << " for index buffer view";
568  return false;
569  }
570 
571  if (!encoder.Track(index_buffer)) {
572  return false;
573  }
574 
575  auto index_buffer_handle = DeviceBufferVK::Cast(*index_buffer).GetBuffer();
576  cmd_buffer.bindIndexBuffer(index_buffer_handle,
577  index_buffer_view.range.offset,
578  ToVKIndexType(command.index_type));
579 
580  // Engage!
581  cmd_buffer.drawIndexed(command.vertex_count, // index count
582  command.instance_count, // instance count
583  0u, // first index
584  command.base_vertex, // vertex offset
585  0u // first instance
586  );
587  } else {
588  cmd_buffer.draw(command.vertex_count, // vertex count
589  command.instance_count, // instance count
590  command.base_vertex, // vertex offset
591  0u // first instance
592  );
593  }
594  return true;
595 }
596 
597 bool RenderPassVK::OnEncodeCommands(const Context& context) const {
598  TRACE_EVENT0("impeller", "RenderPassVK::OnEncodeCommands");
599  if (!IsValid()) {
600  return false;
601  }
602 
603  const auto& vk_context = ContextVK::Cast(context);
604 
605  auto command_buffer = command_buffer_.lock();
606  if (!command_buffer) {
607  VALIDATION_LOG << "Command buffer died before commands could be encoded.";
608  return false;
609  }
610  auto encoder = command_buffer->GetEncoder();
611  if (!encoder) {
612  return false;
613  }
614 
615  fml::ScopedCleanupClosure pop_marker(
616  [&encoder]() { encoder->PopDebugGroup(); });
617  if (!debug_label_.empty()) {
618  encoder->PushDebugGroup(debug_label_.c_str());
619  } else {
620  pop_marker.Release();
621  }
622 
623  auto cmd_buffer = encoder->GetCommandBuffer();
624 
625  if (!UpdateBindingLayouts(commands_, cmd_buffer)) {
626  return false;
627  }
628 
629  render_target_.IterateAllAttachments(
630  [&encoder](const auto& attachment) -> bool {
631  encoder->Track(attachment.texture);
632  encoder->Track(attachment.resolve_texture);
633  return true;
634  });
635 
636  const auto& target_size = render_target_.GetRenderTargetSize();
637 
638  auto render_pass = CreateVKRenderPass(vk_context, command_buffer);
639  if (!render_pass) {
640  VALIDATION_LOG << "Could not create renderpass.";
641  return false;
642  }
643 
644  auto framebuffer = CreateVKFramebuffer(vk_context, *render_pass);
645  if (!framebuffer) {
646  VALIDATION_LOG << "Could not create framebuffer.";
647  return false;
648  }
649 
650  if (!encoder->Track(framebuffer) || !encoder->Track(render_pass)) {
651  return false;
652  }
653 
654  auto clear_values = GetVKClearValues(render_target_);
655 
656  vk::RenderPassBeginInfo pass_info;
657  pass_info.renderPass = *render_pass;
658  pass_info.framebuffer = *framebuffer;
659  pass_info.renderArea.extent.width = static_cast<uint32_t>(target_size.width);
660  pass_info.renderArea.extent.height =
661  static_cast<uint32_t>(target_size.height);
662  pass_info.setClearValues(clear_values);
663 
664  {
665  TRACE_EVENT0("impeller", "EncodeRenderPassCommands");
666  cmd_buffer.beginRenderPass(pass_info, vk::SubpassContents::eInline);
667 
668  fml::ScopedCleanupClosure end_render_pass(
669  [cmd_buffer]() { cmd_buffer.endRenderPass(); });
670 
671  for (const auto& command : commands_) {
672  if (!command.pipeline) {
673  continue;
674  }
675 
676  if (!EncodeCommand(context, command, *encoder, pass_bindings_cache_,
677  target_size, commands_.size())) {
678  return false;
679  }
680  }
681  }
682 
683  return true;
684 }
685 
686 } // namespace impeller
impeller::Command::vertex_count
size_t vertex_count
Definition: command.h:131
impeller::BarrierVK::dst_access
vk::AccessFlags dst_access
Definition: barrier_vk.h:42
impeller::Command
An object used to specify work to the GPU along with references to resources the GPU will used when d...
Definition: command.h:99
impeller::SetViewportAndScissor
static void SetViewportAndScissor(const Command &command, const vk::CommandBuffer &cmd_buffer, PassBindingsCache &cmd_buffer_cache, const ISize &target_size)
Definition: render_pass_vk.cc:462
impeller::Command::scissor
std::optional< IRect > scissor
Definition: command.h:169
impeller::VKClearValueFromDepthStencil
static vk::ClearDepthStencilValue VKClearValueFromDepthStencil(uint32_t stencil, Scalar depth)
Definition: render_pass_vk.cc:205
impeller::DescriptorSetLayout
Definition: shader_types.h:149
impeller::ShaderUniformSlot
Definition: shader_types.h:81
impeller::Attachment::store_action
StoreAction store_action
Definition: formats.h:594
impeller::Scalar
float Scalar
Definition: scalar.h:15
impeller::Command::index_type
IndexType index_type
Definition: command.h:136
barrier_vk.h
impeller::PassBindingsCache::SetStencilReference
void SetStencilReference(vk::CommandBuffer command_buffer, vk::StencilFaceFlags face_mask, uint32_t reference)
Definition: pass_bindings_cache.cc:32
shared_object_vk.h
impeller::CommandEncoderVK::PushDebugGroup
void PushDebugGroup(const char *label) const
Definition: command_encoder_vk.cc:295
impeller::Color
Definition: color.h:122
impeller::PipelineVK::GetPipelineLayout
const vk::PipelineLayout & GetPipelineLayout() const
Definition: pipeline_vk.cc:52
command_encoder_vk.h
impeller::ToVKDescriptorType
constexpr vk::DescriptorType ToVKDescriptorType(DescriptorType type)
Definition: formats_vk.h:273
impeller::BarrierVK::new_layout
vk::ImageLayout new_layout
Definition: barrier_vk.h:22
impeller::ContextVK::GetResourceAllocator
std::shared_ptr< Allocator > GetResourceAllocator() const override
Returns the allocator used to create textures and buffers on the device.
Definition: context_vk.cc:453
impeller::BarrierVK::cmd_buffer
vk::CommandBuffer cmd_buffer
Definition: barrier_vk.h:21
impeller::EncodeCommand
static bool EncodeCommand(const Context &context, const Command &command, CommandEncoderVK &encoder, PassBindingsCache &command_buffer_cache, const ISize &target_size, size_t command_count)
Definition: render_pass_vk.cc:486
formats.h
impeller::Command::viewport
std::optional< Viewport > viewport
Definition: command.h:163
impeller::PipelineVK
Definition: pipeline_vk.h:17
impeller::Color::alpha
Scalar alpha
Definition: color.h:141
impeller::StoreAction::kDontCare
@ kDontCare
impeller::PipelineDescriptor::GetVertexDescriptor
const std::shared_ptr< VertexDescriptor > & GetVertexDescriptor() const
Definition: pipeline_descriptor.cc:213
impeller::Bindings::buffers
std::map< size_t, BufferAndUniformSlot > buffers
Definition: command.h:79
formats_vk.h
impeller::RenderTarget::GetColorAttachments
const std::map< size_t, ColorAttachment > & GetColorAttachments() const
Definition: render_target.cc:209
pipeline_vk.h
render_pass_vk.h
impeller::Command::instance_count
size_t instance_count
Definition: command.h:177
validation.h
impeller::Color::green
Scalar green
Definition: color.h:131
sampler.h
impeller::Command::base_vertex
uint64_t base_vertex
Definition: command.h:156
impeller::SamplerVK
Definition: sampler_vk.h:17
impeller::Command::GetVertexBuffer
BufferView GetVertexBuffer() const
Definition: command.cc:29
impeller::PassBindingsCache::SetScissor
void SetScissor(const IRect &scissor)
Definition: render_pass_mtl.mm:323
impeller::SetTextureLayout
static void SetTextureLayout(const Attachment &attachment, const vk::AttachmentDescription &attachment_desc, const std::shared_ptr< CommandBufferVK > &command_buffer, const std::shared_ptr< Texture > Attachment::*texture_ptr)
Definition: render_pass_vk.cc:69
impeller::CommandEncoderVK::AllocateDescriptorSet
std::optional< vk::DescriptorSet > AllocateDescriptorSet(const vk::DescriptorSetLayout &layout, size_t command_count)
Definition: command_encoder_vk.cc:284
impeller::ShaderUniformSlot::binding
size_t binding
Definition: shader_types.h:85
command_buffer_vk.h
impeller::TSize
Definition: size.h:18
impeller::LoadAction::kClear
@ kClear
impeller::RenderTarget::GetDepthAttachment
const std::optional< DepthAttachment > & GetDepthAttachment() const
Definition: render_target.cc:214
impeller::StorageMode::kDeviceTransient
@ kDeviceTransient
impeller::Command::vertex_bindings
Bindings vertex_bindings
Definition: command.h:108
impeller::BarrierVK
Defines an operations and memory access barrier on a resource.
Definition: barrier_vk.h:20
impeller::GetVKClearValues
static std::vector< vk::ClearValue > GetVKClearValues(const RenderTarget &target)
Definition: render_pass_vk.cc:213
impeller::ToVKIndexType
constexpr vk::IndexType ToVKIndexType(IndexType index_type)
Definition: formats_vk.h:333
impeller::UpdateBindingLayouts
static bool UpdateBindingLayouts(const std::vector< Command > &commands, const vk::CommandBuffer &buffer)
Definition: render_pass_vk.cc:316
impeller::Attachment::texture
std::shared_ptr< Texture > texture
Definition: formats.h:591
impeller::PassBindingsCache
Ensures that bindings on the pass are not redundantly set or updated. Avoids making the driver do add...
Definition: render_pass_mtl.mm:194
impeller::CommandEncoderVK::Track
bool Track(std::shared_ptr< SharedObjectVK > object)
Definition: command_encoder_vk.cc:232
impeller::BufferView::buffer
std::shared_ptr< const Buffer > buffer
Definition: buffer_view.h:14
impeller::SampledImageSlot
Definition: shader_types.h:129
impeller::Color::red
Scalar red
Definition: color.h:126
impeller::Bindings::sampled_images
std::map< size_t, TextureAndSampler > sampled_images
Definition: command.h:78
impeller::BarrierVK::src_access
vk::AccessFlags src_access
Definition: barrier_vk.h:32
impeller::Attachment
Definition: formats.h:590
impeller::RenderTarget
Definition: render_target.h:48
impeller::SamplerVK::GetSampler
vk::Sampler GetSampler() const
Definition: sampler_vk.cc:17
impeller::StoreAction::kStore
@ kStore
impeller::RenderPass::render_target_
const RenderTarget render_target_
Definition: render_pass.h:69
impeller::Pipeline::GetDescriptor
const T & GetDescriptor() const
Get the descriptor that was responsible for creating this pipeline. It may be copied and modified to ...
Definition: pipeline.cc:49
impeller::CommandEncoderVK::PopDebugGroup
void PopDebugGroup() const
Definition: command_encoder_vk.cc:306
texture_vk.h
impeller::ContextVK
Definition: context_vk.h:36
impeller::BarrierVK::dst_stage
vk::PipelineStageFlags dst_stage
Definition: barrier_vk.h:37
impeller::Viewport
Definition: formats.h:352
VALIDATION_LOG
#define VALIDATION_LOG
Definition: validation.h:60
impeller::Command::stencil_reference
uint32_t stencil_reference
Definition: command.h:152
impeller::Attachment::resolve_texture
std::shared_ptr< Texture > resolve_texture
Definition: formats.h:592
impeller::MakeSharedVK
auto MakeSharedVK(vk::UniqueHandle< T, VULKAN_HPP_DEFAULT_DISPATCHER_TYPE > handle)
Definition: shared_object_vk.h:39
impeller::PassBindingsCache::SetViewport
void SetViewport(const Viewport &viewport)
Definition: render_pass_mtl.mm:308
impeller::Context
To do anything rendering related with Impeller, you need a context.
Definition: context.h:47
std
Definition: comparable.h:98
impeller::ContextVK::GetDevice
const vk::Device & GetDevice() const
Definition: context_vk.cc:480
impeller::AllocateAndBindDescriptorSets
static bool AllocateAndBindDescriptorSets(const ContextVK &context, const Command &command, CommandEncoderVK &encoder, const PipelineVK &pipeline, size_t command_count)
Definition: render_pass_vk.cc:326
impeller::Command::fragment_bindings
Bindings fragment_bindings
Definition: command.h:113
impeller::BackendCast< TextureVK, Texture >::Cast
static TextureVK & Cast(Texture &base)
Definition: backend_cast.h:14
impeller::Attachment::load_action
LoadAction load_action
Definition: formats.h:593
device_buffer_vk.h
impeller::kUnusedAttachmentReference
static constexpr vk::AttachmentReference kUnusedAttachmentReference
Definition: formats_vk.h:490
sampler_vk.h
impeller::RenderTarget::GetMaxColorAttacmentBindIndex
size_t GetMaxColorAttacmentBindIndex() const
Definition: render_target.cc:172
impeller::Command::pipeline
std::shared_ptr< Pipeline< PipelineDescriptor > > pipeline
Definition: command.h:103
impeller::SampledImageSlot::binding
size_t binding
Definition: shader_types.h:133
impeller::RenderTarget::GetStencilAttachment
const std::optional< StencilAttachment > & GetStencilAttachment() const
Definition: render_target.cc:218
context_vk.h
impeller::CreateAttachmentDescription
constexpr vk::AttachmentDescription CreateAttachmentDescription(PixelFormat format, SampleCount sample_count, LoadAction load_action, StoreAction store_action, vk::ImageLayout current_layout)
Definition: formats_vk.h:431
impeller::Color::blue
Scalar blue
Definition: color.h:136
impeller::DescriptorSetLayout::descriptor_type
DescriptorType descriptor_type
Definition: shader_types.h:151
impeller::PipelineVK::GetDescriptorSetLayout
const vk::DescriptorSetLayout & GetDescriptorSetLayout() const
Definition: pipeline_vk.cc:56
shader_types.h
impeller::CommandEncoderVK
Definition: command_encoder_vk.h:45
impeller
Definition: aiks_context.cc:10
impeller::PassBindingsCache::BindPipeline
void BindPipeline(vk::CommandBuffer command_buffer, vk::PipelineBindPoint pipeline_bind_point, vk::Pipeline pipeline)
Definition: pass_bindings_cache.cc:8
impeller::CommandEncoderVK::GetCommandBuffer
vk::CommandBuffer GetCommandBuffer() const
Definition: command_encoder_vk.cc:218
impeller::SamplerVK::GetSharedSampler
const std::shared_ptr< SharedObjectVKT< vk::Sampler > > & GetSharedSampler() const
Definition: sampler_vk.cc:22
impeller::Context::GetResourceAllocator
virtual std::shared_ptr< Allocator > GetResourceAllocator() const =0
Returns the allocator used to create textures and buffers on the device.
impeller::BarrierVK::src_stage
vk::PipelineStageFlags src_stage
Definition: barrier_vk.h:27
impeller::Bindings
Definition: command.h:77
impeller::VKClearValueFromColor
static vk::ClearColorValue VKClearValueFromColor(Color color)
Definition: render_pass_vk.cc:198
impeller::Command::index_buffer
BufferView index_buffer
Definition: command.h:121