| 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 "impeller/renderer/backend/vulkan/vk.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_) {
495 InsertBarrierForInputAttachmentRead(
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