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