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