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 "fml/status.h"
14 #include "impeller/core/formats.h"
15 #include "impeller/core/texture.h"
28 #include "vulkan/vulkan_handles.hpp"
29 
30 namespace impeller {
31 
32 // Warning: if any of the constant values or layouts are changed in the
33 // framebuffer fetch shader, then this input binding may need to be
34 // manually changed.
35 //
36 // See: impeller/entity/shaders/blending/framebuffer_blend.frag
37 static constexpr size_t kMagicSubpassInputBinding = 64u;
38 
39 static vk::ClearColorValue VKClearValueFromColor(Color color) {
40  vk::ClearColorValue value;
41  value.setFloat32(
42  std::array<float, 4>{color.red, color.green, color.blue, color.alpha});
43  return value;
44 }
45 
46 static vk::ClearDepthStencilValue VKClearValueFromDepthStencil(uint32_t stencil,
47  Scalar depth) {
48  vk::ClearDepthStencilValue value;
49  value.depth = depth;
50  value.stencil = stencil;
51  return value;
52 }
53 
54 static std::vector<vk::ClearValue> GetVKClearValues(
55  const RenderTarget& target) {
56  std::vector<vk::ClearValue> clears;
57 
58  for (const auto& [_, color] : target.GetColorAttachments()) {
59  clears.emplace_back(VKClearValueFromColor(color.clear_color));
60  if (color.resolve_texture) {
61  clears.emplace_back(VKClearValueFromColor(color.clear_color));
62  }
63  }
64 
65  const auto& depth = target.GetDepthAttachment();
66  const auto& stencil = target.GetStencilAttachment();
67 
68  if (depth.has_value()) {
69  clears.emplace_back(VKClearValueFromDepthStencil(
70  stencil ? stencil->clear_stencil : 0u, depth->clear_depth));
71  } else if (stencil.has_value()) {
72  clears.emplace_back(VKClearValueFromDepthStencil(
73  stencil->clear_stencil, depth ? depth->clear_depth : 0.0f));
74  }
75 
76  return clears;
77 }
78 
79 SharedHandleVK<vk::RenderPass> RenderPassVK::CreateVKRenderPass(
80  const ContextVK& context,
81  const SharedHandleVK<vk::RenderPass>& recycled_renderpass,
82  const std::shared_ptr<CommandBufferVK>& command_buffer) const {
83  BarrierVK barrier;
84  barrier.new_layout = vk::ImageLayout::eGeneral;
85  barrier.cmd_buffer = command_buffer->GetEncoder()->GetCommandBuffer();
86  barrier.src_access = vk::AccessFlagBits::eShaderRead;
87  barrier.src_stage = vk::PipelineStageFlagBits::eFragmentShader;
88  barrier.dst_access = vk::AccessFlagBits::eColorAttachmentWrite |
89  vk::AccessFlagBits::eTransferWrite;
90  barrier.dst_stage = vk::PipelineStageFlagBits::eColorAttachmentOutput |
91  vk::PipelineStageFlagBits::eTransfer;
92 
93  RenderPassBuilderVK builder;
94 
95  for (const auto& [bind_point, color] : render_target_.GetColorAttachments()) {
96  builder.SetColorAttachment(
97  bind_point, //
98  color.texture->GetTextureDescriptor().format, //
99  color.texture->GetTextureDescriptor().sample_count, //
100  color.load_action, //
101  color.store_action //
102  );
103  TextureVK::Cast(*color.texture).SetLayout(barrier);
104  if (color.resolve_texture) {
105  TextureVK::Cast(*color.resolve_texture).SetLayout(barrier);
106  }
107  }
108 
109  if (auto depth = render_target_.GetDepthAttachment(); depth.has_value()) {
110  builder.SetDepthStencilAttachment(
111  depth->texture->GetTextureDescriptor().format, //
112  depth->texture->GetTextureDescriptor().sample_count, //
113  depth->load_action, //
114  depth->store_action //
115  );
116  } else if (auto stencil = render_target_.GetStencilAttachment();
117  stencil.has_value()) {
118  builder.SetStencilAttachment(
119  stencil->texture->GetTextureDescriptor().format, //
120  stencil->texture->GetTextureDescriptor().sample_count, //
121  stencil->load_action, //
122  stencil->store_action //
123  );
124  }
125 
126  if (recycled_renderpass != nullptr) {
127  return recycled_renderpass;
128  }
129 
130  auto pass = builder.Build(context.GetDevice());
131 
132  if (!pass) {
133  VALIDATION_LOG << "Failed to create render pass for framebuffer.";
134  return {};
135  }
136 
137  context.SetDebugName(pass.get(), debug_label_.c_str());
138 
139  return MakeSharedVK(std::move(pass));
140 }
141 
142 RenderPassVK::RenderPassVK(const std::shared_ptr<const Context>& context,
143  const RenderTarget& target,
144  std::shared_ptr<CommandBufferVK> command_buffer)
145  : RenderPass(context, target), command_buffer_(std::move(command_buffer)) {
146  color_image_vk_ =
147  render_target_.GetColorAttachments().find(0u)->second.texture;
148  resolve_image_vk_ =
149  render_target_.GetColorAttachments().find(0u)->second.resolve_texture;
150 
151  const auto& vk_context = ContextVK::Cast(*context);
152  const std::shared_ptr<CommandEncoderVK>& encoder =
153  command_buffer_->GetEncoder();
154  command_buffer_vk_ = encoder->GetCommandBuffer();
155  render_target_.IterateAllAttachments(
156  [&encoder](const auto& attachment) -> bool {
157  encoder->Track(attachment.texture);
158  encoder->Track(attachment.resolve_texture);
159  return true;
160  });
161 
162  SharedHandleVK<vk::RenderPass> recycled_render_pass;
163  SharedHandleVK<vk::Framebuffer> recycled_framebuffer;
164  if (resolve_image_vk_) {
165  recycled_render_pass =
166  TextureVK::Cast(*resolve_image_vk_).GetCachedRenderPass();
167  recycled_framebuffer =
168  TextureVK::Cast(*resolve_image_vk_).GetCachedFramebuffer();
169  }
170 
171  const auto& target_size = render_target_.GetRenderTargetSize();
172 
173  render_pass_ =
174  CreateVKRenderPass(vk_context, recycled_render_pass, command_buffer_);
175  if (!render_pass_) {
176  VALIDATION_LOG << "Could not create renderpass.";
177  is_valid_ = false;
178  return;
179  }
180 
181  auto framebuffer = (recycled_framebuffer == nullptr)
182  ? CreateVKFramebuffer(vk_context, *render_pass_)
183  : recycled_framebuffer;
184  if (!framebuffer) {
185  VALIDATION_LOG << "Could not create framebuffer.";
186  is_valid_ = false;
187  return;
188  }
189 
190  if (!encoder->Track(framebuffer) || !encoder->Track(render_pass_)) {
191  is_valid_ = false;
192  return;
193  }
194  if (resolve_image_vk_) {
195  TextureVK::Cast(*resolve_image_vk_).SetCachedFramebuffer(framebuffer);
196  TextureVK::Cast(*resolve_image_vk_).SetCachedRenderPass(render_pass_);
197  }
198 
199  auto clear_values = GetVKClearValues(render_target_);
200 
201  vk::RenderPassBeginInfo pass_info;
202  pass_info.renderPass = *render_pass_;
203  pass_info.framebuffer = *framebuffer;
204  pass_info.renderArea.extent.width = static_cast<uint32_t>(target_size.width);
205  pass_info.renderArea.extent.height =
206  static_cast<uint32_t>(target_size.height);
207  pass_info.setClearValues(clear_values);
208 
209  command_buffer_vk_.beginRenderPass(pass_info, vk::SubpassContents::eInline);
210 
211  // Set the initial viewport.
212  const auto vp = Viewport{.rect = Rect::MakeSize(target_size)};
213  vk::Viewport viewport = vk::Viewport()
214  .setWidth(vp.rect.GetWidth())
215  .setHeight(-vp.rect.GetHeight())
216  .setY(vp.rect.GetHeight())
217  .setMinDepth(0.0f)
218  .setMaxDepth(1.0f);
219  command_buffer_vk_.setViewport(0, 1, &viewport);
220 
221  // Set the initial scissor.
222  const auto sc = IRect::MakeSize(target_size);
223  vk::Rect2D scissor =
224  vk::Rect2D()
225  .setOffset(vk::Offset2D(sc.GetX(), sc.GetY()))
226  .setExtent(vk::Extent2D(sc.GetWidth(), sc.GetHeight()));
227  command_buffer_vk_.setScissor(0, 1, &scissor);
228 
229  // Set the initial stencil reference.
230  command_buffer_vk_.setStencilReference(
231  vk::StencilFaceFlagBits::eVkStencilFrontAndBack, 0u);
232 
233  is_valid_ = true;
234 }
235 
236 RenderPassVK::~RenderPassVK() = default;
237 
238 bool RenderPassVK::IsValid() const {
239  return is_valid_;
240 }
241 
242 void RenderPassVK::OnSetLabel(std::string label) {
243 #ifdef IMPELLER_DEBUG
244  ContextVK::Cast(*context_).SetDebugName(render_pass_->Get(),
245  std::string(label).c_str());
246 #endif // IMPELLER_DEBUG
247 }
248 
249 SharedHandleVK<vk::Framebuffer> RenderPassVK::CreateVKFramebuffer(
250  const ContextVK& context,
251  const vk::RenderPass& pass) const {
252  vk::FramebufferCreateInfo fb_info;
253 
254  fb_info.renderPass = pass;
255 
256  const auto target_size = render_target_.GetRenderTargetSize();
257  fb_info.width = target_size.width;
258  fb_info.height = target_size.height;
259  fb_info.layers = 1u;
260 
261  std::vector<vk::ImageView> attachments;
262 
263  // This bit must be consistent to ensure compatibility with the pass created
264  // earlier. Follow this order: Color attachments, then depth-stencil, then
265  // stencil.
266  for (const auto& [_, color] : render_target_.GetColorAttachments()) {
267  // The bind point doesn't matter here since that information is present in
268  // the render pass.
269  attachments.emplace_back(
270  TextureVK::Cast(*color.texture).GetRenderTargetView());
271  if (color.resolve_texture) {
272  attachments.emplace_back(
273  TextureVK::Cast(*color.resolve_texture).GetRenderTargetView());
274  }
275  }
276  if (auto depth = render_target_.GetDepthAttachment(); depth.has_value()) {
277  attachments.emplace_back(
278  TextureVK::Cast(*depth->texture).GetRenderTargetView());
279  } else if (auto stencil = render_target_.GetStencilAttachment();
280  stencil.has_value()) {
281  attachments.emplace_back(
282  TextureVK::Cast(*stencil->texture).GetRenderTargetView());
283  }
284 
285  fb_info.setAttachments(attachments);
286 
287  auto [result, framebuffer] =
288  context.GetDevice().createFramebufferUnique(fb_info);
289 
290  if (result != vk::Result::eSuccess) {
291  VALIDATION_LOG << "Could not create framebuffer: " << vk::to_string(result);
292  return {};
293  }
294 
295  return MakeSharedVK(std::move(framebuffer));
296 }
297 
298 // |RenderPass|
299 void RenderPassVK::SetPipeline(
300  const std::shared_ptr<Pipeline<PipelineDescriptor>>& pipeline) {
301  pipeline_ = pipeline;
302 
303  if (!pipeline_) {
304  return;
305  }
306 
307  pipeline_uses_input_attachments_ =
308  pipeline_->GetDescriptor().GetVertexDescriptor()->UsesInputAttacments();
309 
310  if (pipeline_uses_input_attachments_) {
311  if (bound_image_offset_ >= kMaxBindings) {
312  pipeline_ = nullptr;
313  return;
314  }
315  vk::DescriptorImageInfo image_info;
316  image_info.imageLayout = vk::ImageLayout::eGeneral;
317  image_info.sampler = VK_NULL_HANDLE;
318  image_info.imageView = TextureVK::Cast(*color_image_vk_).GetImageView();
319  image_workspace_[bound_image_offset_++] = image_info;
320 
321  vk::WriteDescriptorSet write_set;
322  write_set.dstBinding = kMagicSubpassInputBinding;
323  write_set.descriptorCount = 1u;
324  write_set.descriptorType = vk::DescriptorType::eInputAttachment;
325  write_set.pImageInfo = &image_workspace_[bound_image_offset_ - 1];
326 
327  write_workspace_[descriptor_write_offset_++] = write_set;
328  }
329 }
330 
331 // |RenderPass|
332 void RenderPassVK::SetCommandLabel(std::string_view label) {
333 #ifdef IMPELLER_DEBUG
334  command_buffer_->GetEncoder()->PushDebugGroup(label);
335  has_label_ = true;
336 #endif // IMPELLER_DEBUG
337 }
338 
339 // |RenderPass|
340 void RenderPassVK::SetStencilReference(uint32_t value) {
341  command_buffer_vk_.setStencilReference(
342  vk::StencilFaceFlagBits::eVkStencilFrontAndBack, value);
343 }
344 
345 // |RenderPass|
346 void RenderPassVK::SetBaseVertex(uint64_t value) {
347  base_vertex_ = value;
348 }
349 
350 // |RenderPass|
351 void RenderPassVK::SetViewport(Viewport viewport) {
352  vk::Viewport viewport_vk = vk::Viewport()
353  .setWidth(viewport.rect.GetWidth())
354  .setHeight(-viewport.rect.GetHeight())
355  .setY(viewport.rect.GetHeight())
356  .setMinDepth(0.0f)
357  .setMaxDepth(1.0f);
358  command_buffer_vk_.setViewport(0, 1, &viewport_vk);
359 }
360 
361 // |RenderPass|
362 void RenderPassVK::SetScissor(IRect scissor) {
363  vk::Rect2D scissor_vk =
364  vk::Rect2D()
365  .setOffset(vk::Offset2D(scissor.GetX(), scissor.GetY()))
366  .setExtent(vk::Extent2D(scissor.GetWidth(), scissor.GetHeight()));
367  command_buffer_vk_.setScissor(0, 1, &scissor_vk);
368 }
369 
370 // |RenderPass|
371 void RenderPassVK::SetInstanceCount(size_t count) {
372  instance_count_ = count;
373 }
374 
375 // |RenderPass|
376 bool RenderPassVK::SetVertexBuffer(VertexBuffer buffer) {
377  vertex_count_ = buffer.vertex_count;
378  if (buffer.index_type == IndexType::kUnknown || !buffer.vertex_buffer) {
379  return false;
380  }
381 
382  if (!command_buffer_->GetEncoder()->Track(buffer.vertex_buffer.buffer)) {
383  return false;
384  }
385 
386  // Bind the vertex buffer.
387  vk::Buffer vertex_buffer_handle =
388  DeviceBufferVK::Cast(*buffer.vertex_buffer.buffer).GetBuffer();
389  vk::Buffer vertex_buffers[] = {vertex_buffer_handle};
390  vk::DeviceSize vertex_buffer_offsets[] = {buffer.vertex_buffer.range.offset};
391 
392  command_buffer_vk_.bindVertexBuffers(0u, 1u, vertex_buffers,
393  vertex_buffer_offsets);
394 
395  // Bind the index buffer.
396  if (buffer.index_type != IndexType::kNone) {
397  has_index_buffer_ = true;
398  const BufferView& index_buffer_view = buffer.index_buffer;
399  if (!index_buffer_view) {
400  return false;
401  }
402 
403  const std::shared_ptr<const DeviceBuffer>& index_buffer =
404  index_buffer_view.buffer;
405  if (!index_buffer) {
406  VALIDATION_LOG << "Failed to acquire device buffer"
407  << " for index buffer view";
408  return false;
409  }
410 
411  if (!command_buffer_->GetEncoder()->Track(index_buffer)) {
412  return false;
413  }
414 
415  vk::Buffer index_buffer_handle =
416  DeviceBufferVK::Cast(*index_buffer).GetBuffer();
417  command_buffer_vk_.bindIndexBuffer(index_buffer_handle,
418  index_buffer_view.range.offset,
419  ToVKIndexType(buffer.index_type));
420  } else {
421  has_index_buffer_ = false;
422  }
423  return true;
424 }
425 
426 // |RenderPass|
427 fml::Status RenderPassVK::Draw() {
428  if (!pipeline_) {
429  return fml::Status(fml::StatusCode::kCancelled,
430  "No valid pipeline is bound to the RenderPass.");
431  }
432 
433  //----------------------------------------------------------------------------
434  /// If there are immutable samplers referenced in the render pass, the base
435  /// pipeline variant is no longer valid and needs to be re-constructed to
436  /// reference the samplers.
437  ///
438  /// This is an instance of JIT creation of PSOs that can cause jank. It is
439  /// unavoidable because it isn't possible to know all possible combinations of
440  /// target YUV conversions. Fortunately, this will only ever happen when
441  /// rendering to external textures. Like Android Hardware Buffers on Android.
442  ///
443  /// Even when JIT creation is unavoidable, pipelines will cache their variants
444  /// when able and all pipeline creation will happen via a base pipeline cache
445  /// anyway. So the jank can be mostly entirely ameliorated and it should only
446  /// ever happen when the first unknown YUV conversion is encountered.
447  ///
448  /// Jank can be completely eliminated by pre-populating known YUV conversion
449  /// pipelines.
450  if (immutable_sampler_) {
451  std::shared_ptr<PipelineVK> pipeline_variant =
452  PipelineVK::Cast(*pipeline_)
453  .CreateVariantForImmutableSamplers(immutable_sampler_);
454  if (!pipeline_variant) {
455  return fml::Status(
456  fml::StatusCode::kAborted,
457  "Could not create pipeline variant with immutable sampler.");
458  }
459  pipeline_ = std::move(pipeline_variant);
460  }
461 
462  const auto& context_vk = ContextVK::Cast(*context_);
463  const auto& pipeline_vk = PipelineVK::Cast(*pipeline_);
464 
465  auto descriptor_result =
466  command_buffer_->GetEncoder()->AllocateDescriptorSets(
467  pipeline_vk.GetDescriptorSetLayout(), context_vk);
468  if (!descriptor_result.ok()) {
469  return fml::Status(fml::StatusCode::kAborted,
470  "Could not allocate descriptor sets.");
471  }
472  const auto descriptor_set = descriptor_result.value();
473  const auto pipeline_layout = pipeline_vk.GetPipelineLayout();
474  command_buffer_vk_.bindPipeline(vk::PipelineBindPoint::eGraphics,
475  pipeline_vk.GetPipeline());
476 
477  for (auto i = 0u; i < descriptor_write_offset_; i++) {
478  write_workspace_[i].dstSet = descriptor_set;
479  }
480 
481  context_vk.GetDevice().updateDescriptorSets(descriptor_write_offset_,
482  write_workspace_.data(), 0u, {});
483 
484  command_buffer_vk_.bindDescriptorSets(
485  vk::PipelineBindPoint::eGraphics, // bind point
486  pipeline_layout, // layout
487  0, // first set
488  1, // set count
489  &descriptor_set, // sets
490  0, // offset count
491  nullptr // offsets
492  );
493 
494  if (pipeline_uses_input_attachments_) {
496  command_buffer_vk_, TextureVK::Cast(*color_image_vk_).GetImage());
497  }
498 
499  if (has_index_buffer_) {
500  command_buffer_vk_.drawIndexed(vertex_count_, // index count
501  instance_count_, // instance count
502  0u, // first index
503  base_vertex_, // vertex offset
504  0u // first instance
505  );
506  } else {
507  command_buffer_vk_.draw(vertex_count_, // vertex count
508  instance_count_, // instance count
509  base_vertex_, // vertex offset
510  0u // first instance
511  );
512  }
513 
514 #ifdef IMPELLER_DEBUG
515  if (has_label_) {
516  command_buffer_->GetEncoder()->PopDebugGroup();
517  }
518 #endif // IMPELLER_DEBUG
519  has_label_ = false;
520  has_index_buffer_ = false;
521  bound_image_offset_ = 0u;
522  bound_buffer_offset_ = 0u;
523  descriptor_write_offset_ = 0u;
524  instance_count_ = 1u;
525  base_vertex_ = 0u;
526  vertex_count_ = 0u;
527  pipeline_ = nullptr;
528  pipeline_uses_input_attachments_ = false;
529  immutable_sampler_ = nullptr;
530  return fml::Status();
531 }
532 
533 // The RenderPassVK binding methods only need the binding, set, and buffer type
534 // information.
535 bool RenderPassVK::BindResource(ShaderStage stage,
536  DescriptorType type,
537  const ShaderUniformSlot& slot,
538  const ShaderMetadata& metadata,
539  BufferView view) {
540  return BindResource(slot.binding, type, view);
541 }
542 
543 bool RenderPassVK::BindResource(
544  ShaderStage stage,
545  DescriptorType type,
546  const ShaderUniformSlot& slot,
547  const std::shared_ptr<const ShaderMetadata>& metadata,
548  BufferView view) {
549  return BindResource(slot.binding, type, view);
550 }
551 
552 bool RenderPassVK::BindResource(size_t binding,
553  DescriptorType type,
554  const BufferView& view) {
555  if (bound_buffer_offset_ >= kMaxBindings) {
556  return false;
557  }
558 
559  const std::shared_ptr<const DeviceBuffer>& device_buffer = view.buffer;
560  auto buffer = DeviceBufferVK::Cast(*device_buffer).GetBuffer();
561  if (!buffer) {
562  return false;
563  }
564 
565  if (!command_buffer_->GetEncoder()->Track(device_buffer)) {
566  return false;
567  }
568 
569  uint32_t offset = view.range.offset;
570 
571  vk::DescriptorBufferInfo buffer_info;
572  buffer_info.buffer = buffer;
573  buffer_info.offset = offset;
574  buffer_info.range = view.range.length;
575  buffer_workspace_[bound_buffer_offset_++] = buffer_info;
576 
577  vk::WriteDescriptorSet write_set;
578  write_set.dstBinding = binding;
579  write_set.descriptorCount = 1u;
580  write_set.descriptorType = ToVKDescriptorType(type);
581  write_set.pBufferInfo = &buffer_workspace_[bound_buffer_offset_ - 1];
582 
583  write_workspace_[descriptor_write_offset_++] = write_set;
584  return true;
585 }
586 
587 bool RenderPassVK::BindResource(ShaderStage stage,
588  DescriptorType type,
589  const SampledImageSlot& slot,
590  const ShaderMetadata& metadata,
591  std::shared_ptr<const Texture> texture,
592  const std::unique_ptr<const Sampler>& sampler) {
593  if (bound_buffer_offset_ >= kMaxBindings) {
594  return false;
595  }
596  if (!texture->IsValid() || !sampler) {
597  return false;
598  }
599  const TextureVK& texture_vk = TextureVK::Cast(*texture);
600  const SamplerVK& sampler_vk = SamplerVK::Cast(*sampler);
601 
602  if (!command_buffer_->GetEncoder()->Track(texture)) {
603  return false;
604  }
605 
606  if (!immutable_sampler_) {
607  immutable_sampler_ = texture_vk.GetImmutableSamplerVariant(sampler_vk);
608  }
609 
610  vk::DescriptorImageInfo image_info;
611  image_info.imageLayout = vk::ImageLayout::eShaderReadOnlyOptimal;
612  image_info.sampler = sampler_vk.GetSampler();
613  image_info.imageView = texture_vk.GetImageView();
614  image_workspace_[bound_image_offset_++] = image_info;
615 
616  vk::WriteDescriptorSet write_set;
617  write_set.dstBinding = slot.binding;
618  write_set.descriptorCount = 1u;
619  write_set.descriptorType = vk::DescriptorType::eCombinedImageSampler;
620  write_set.pImageInfo = &image_workspace_[bound_image_offset_ - 1];
621 
622  write_workspace_[descriptor_write_offset_++] = write_set;
623  return true;
624 }
625 
626 bool RenderPassVK::OnEncodeCommands(const Context& context) const {
627  command_buffer_->GetEncoder()->GetCommandBuffer().endRenderPass();
628 
629  // If this render target will be consumed by a subsequent render pass,
630  // perform a layout transition to a shader read state.
631  const std::shared_ptr<Texture>& result_texture =
632  resolve_image_vk_ ? resolve_image_vk_ : color_image_vk_;
633  if (result_texture->GetTextureDescriptor().usage &
634  TextureUsage::kShaderRead) {
635  BarrierVK barrier;
636  barrier.cmd_buffer = command_buffer_vk_;
637  barrier.src_access = vk::AccessFlagBits::eColorAttachmentWrite |
638  vk::AccessFlagBits::eTransferWrite;
639  barrier.src_stage = vk::PipelineStageFlagBits::eColorAttachmentOutput |
640  vk::PipelineStageFlagBits::eTransfer;
641  barrier.dst_access = vk::AccessFlagBits::eShaderRead;
642  barrier.dst_stage = vk::PipelineStageFlagBits::eFragmentShader;
643 
644  barrier.new_layout = vk::ImageLayout::eShaderReadOnlyOptimal;
645 
646  if (!TextureVK::Cast(*result_texture).SetLayout(barrier)) {
647  return false;
648  }
649  }
650 
651  return true;
652 }
653 
654 } // namespace impeller
impeller::VKClearValueFromDepthStencil
static vk::ClearDepthStencilValue VKClearValueFromDepthStencil(uint32_t stencil, Scalar depth)
Definition: render_pass_vk.cc:46
impeller::Scalar
float Scalar
Definition: scalar.h:18
barrier_vk.h
impeller::TextureVK::GetCachedFramebuffer
SharedHandleVK< vk::Framebuffer > GetCachedFramebuffer() const
Definition: texture_vk.cc:187
shared_object_vk.h
impeller::Color
Definition: color.h:124
command_encoder_vk.h
device_buffer.h
impeller::ToVKDescriptorType
constexpr vk::DescriptorType ToVKDescriptorType(DescriptorType type)
Definition: formats_vk.h:267
formats.h
impeller::Color::alpha
Scalar alpha
Definition: color.h:143
impeller::ShaderStage
ShaderStage
Definition: shader_types.h:22
formats_vk.h
impeller::RenderTarget::GetColorAttachments
const std::map< size_t, ColorAttachment > & GetColorAttachments() const
Definition: render_target.cc:198
pipeline_vk.h
render_pass_vk.h
validation.h
impeller::Color::green
Scalar green
Definition: color.h:133
vk.h
impeller::TextureVK::SetLayout
bool SetLayout(const BarrierVK &barrier) const
Definition: texture_vk.cc:159
command_buffer_vk.h
impeller::kMaxBindings
static constexpr size_t kMaxBindings
Definition: pipeline_vk.h:26
impeller::RenderTarget::GetDepthAttachment
const std::optional< DepthAttachment > & GetDepthAttachment() const
Definition: render_target.cc:203
impeller::GetVKClearValues
static std::vector< vk::ClearValue > GetVKClearValues(const RenderTarget &target)
Definition: render_pass_vk.cc:54
impeller::ToVKIndexType
constexpr vk::IndexType ToVKIndexType(IndexType index_type)
Definition: formats_vk.h:350
impeller::InsertBarrierForInputAttachmentRead
void InsertBarrierForInputAttachmentRead(const vk::CommandBuffer &buffer, const vk::Image &image)
Inserts the appropriate barriers to ensure that subsequent commands can read from the specified image...
Definition: render_pass_builder_vk.cc:158
impeller::TextureVK::SetCachedFramebuffer
void SetCachedFramebuffer(const SharedHandleVK< vk::Framebuffer > &framebuffer)
Definition: texture_vk.cc:177
impeller::Color::red
Scalar red
Definition: color.h:128
render_pass_builder_vk.h
impeller::RenderTarget
Definition: render_target.h:38
impeller::RenderPass::render_target_
const RenderTarget render_target_
Definition: render_pass.h:179
texture_vk.h
impeller::IRect
TRect< int64_t > IRect
Definition: rect.h:662
impeller::kMagicSubpassInputBinding
static constexpr size_t kMagicSubpassInputBinding
Definition: render_pass_vk.cc:37
VALIDATION_LOG
#define VALIDATION_LOG
Definition: validation.h:73
impeller::MakeSharedVK
auto MakeSharedVK(vk::UniqueHandle< T, VULKAN_HPP_DEFAULT_DISPATCHER_TYPE > handle)
Definition: shared_object_vk.h:43
impeller::TRect< Scalar >::MakeSize
constexpr static TRect MakeSize(const TSize< U > &size)
Definition: rect.h:146
std
Definition: comparable.h:95
impeller::BackendCast< TextureVK, Texture >::Cast
static TextureVK & Cast(Texture &base)
Definition: backend_cast.h:13
device_buffer_vk.h
impeller::TextureVK::GetCachedRenderPass
SharedHandleVK< vk::RenderPass > GetCachedRenderPass() const
Definition: texture_vk.cc:191
texture.h
sampler_vk.h
offset
Point offset
Definition: stroke_path_geometry.cc:300
impeller::RenderTarget::GetStencilAttachment
const std::optional< StencilAttachment > & GetStencilAttachment() const
Definition: render_target.cc:207
context_vk.h
impeller::Color::blue
Scalar blue
Definition: color.h:138
impeller
Definition: aiks_blur_unittests.cc:20
impeller::VKClearValueFromColor
static vk::ClearColorValue VKClearValueFromColor(Color color)
Definition: render_pass_vk.cc:39
impeller::DescriptorType
DescriptorType
Definition: shader_types.h:153
impeller::TextureVK::SetCachedRenderPass
void SetCachedRenderPass(const SharedHandleVK< vk::RenderPass > &render_pass)
Definition: texture_vk.cc:182