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