| 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 "flutter/fml/logging.h"
12 #include "flutter/fml/trace_event.h"
13 #include "impeller/base/validation.h"
14 #include "impeller/core/formats.h"
15 #include "impeller/core/sampler.h"
16 #include "impeller/core/shader_types.h"
17 #include "impeller/renderer/backend/vulkan/barrier_vk.h"
18 #include "impeller/renderer/backend/vulkan/command_buffer_vk.h"
19 #include "impeller/renderer/backend/vulkan/command_encoder_vk.h"
20 #include "impeller/renderer/backend/vulkan/context_vk.h"
21 #include "impeller/renderer/backend/vulkan/device_buffer_vk.h"
22 #include "impeller/renderer/backend/vulkan/formats_vk.h"
23 #include "impeller/renderer/backend/vulkan/pipeline_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_to_string.hpp"
28
29 namespace impeller {
30
31 static vk::AttachmentDescription CreateAttachmentDescription(
32 const Attachment& attachment,
33 const std::shared_ptr<Texture> Attachment::*texture_ptr) {
34 const auto& texture = attachment.*texture_ptr;
35 if (!texture) {
36 return {};
37 }
38 const auto& texture_vk = TextureVK::Cast(*texture);
39 const auto& desc = texture->GetTextureDescriptor();
40 auto current_layout = texture_vk.GetLayout();
41
42 auto load_action = attachment.load_action;
43 auto store_action = attachment.store_action;
44
45 if (current_layout == vk::ImageLayout::eUndefined) {
46 load_action = LoadAction::kClear;
47 }
48
49 if (desc.storage_mode == StorageMode::kDeviceTransient) {
50 store_action = StoreAction::kDontCare;
51 } else if (texture_ptr == &Attachment::resolve_texture) {
52 store_action = StoreAction::kStore;
53 }
54
55 if (current_layout != vk::ImageLayout::ePresentSrcKHR &&
56 current_layout != vk::ImageLayout::eUndefined) {
57 // Note: This should incur a barrier.
58 current_layout = vk::ImageLayout::eGeneral;
59 }
60
61 return CreateAttachmentDescription(desc.format, //
62 desc.sample_count, //
63 load_action, //
64 store_action, //
65 current_layout //
66 );
67 }
68
69 static void SetTextureLayout(
70 const Attachment& attachment,
71 const vk::AttachmentDescription& attachment_desc,
72 const std::shared_ptr<CommandBufferVK>& command_buffer,
73 const std::shared_ptr<Texture> Attachment::*texture_ptr) {
74 const auto& texture = attachment.*texture_ptr;
75 if (!texture) {
76 return;
77 }
78 const auto& texture_vk = TextureVK::Cast(*texture);
79
80 if (attachment_desc.initialLayout == vk::ImageLayout::eGeneral) {
81 BarrierVK barrier;
82 barrier.new_layout = vk::ImageLayout::eGeneral;
83 barrier.cmd_buffer = command_buffer->GetEncoder()->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 texture_vk.SetLayout(barrier);
92 }
93
94 // Instead of transitioning layouts manually using barriers, we are going to
95 // make the subpass perform our transitions.
96 texture_vk.SetLayoutWithoutEncoding(attachment_desc.finalLayout);
97 }
98
99 SharedHandleVK<vk::RenderPass> RenderPassVK::CreateVKRenderPass(
100 const ContextVK& context,
101 const std::shared_ptr<CommandBufferVK>& command_buffer) const {
102 std::vector<vk::AttachmentDescription> attachments;
103
104 std::vector<vk::AttachmentReference> color_refs;
105 std::vector<vk::AttachmentReference> resolve_refs;
106 vk::AttachmentReference depth_stencil_ref = kUnusedAttachmentReference;
107
108 // Spec says: "Each element of the pColorAttachments array corresponds to an
109 // output location in the shader, i.e. if the shader declares an output
110 // variable decorated with a Location value of X, then it uses the attachment
111 // provided in pColorAttachments[X]. If the attachment member of any element
112 // of pColorAttachments is VK_ATTACHMENT_UNUSED."
113 //
114 // Just initialize all the elements as unused and fill in the valid bind
115 // points in the loop below.
116 color_refs.resize(render_target_.GetMaxColorAttacmentBindIndex() + 1u,
117 kUnusedAttachmentReference);
118 resolve_refs.resize(render_target_.GetMaxColorAttacmentBindIndex() + 1u,
119 kUnusedAttachmentReference);
120
121 for (const auto& [bind_point, color] : render_target_.GetColorAttachments()) {
122 color_refs[bind_point] =
123 vk::AttachmentReference{static_cast<uint32_t>(attachments.size()),
124 vk::ImageLayout::eColorAttachmentOptimal};
125 attachments.emplace_back(
126 CreateAttachmentDescription(color, &Attachment::texture));
127 SetTextureLayout(color, attachments.back(), command_buffer,
128 &Attachment::texture);
129 if (color.resolve_texture) {
130 resolve_refs[bind_point] = vk::AttachmentReference{
131 static_cast<uint32_t>(attachments.size()), vk::ImageLayout::eGeneral};
132 attachments.emplace_back(
133 CreateAttachmentDescription(color, &Attachment::resolve_texture));
134 SetTextureLayout(color, attachments.back(), command_buffer,
135 &Attachment::resolve_texture);
136 }
137 }
138
139 if (auto depth = render_target_.GetDepthAttachment(); depth.has_value()) {
140 depth_stencil_ref = vk::AttachmentReference{
141 static_cast<uint32_t>(attachments.size()),
142 vk::ImageLayout::eDepthStencilAttachmentOptimal};
143 attachments.emplace_back(
144 CreateAttachmentDescription(depth.value(), &Attachment::texture));
145 SetTextureLayout(depth.value(), attachments.back(), command_buffer,
146 &Attachment::texture);
147 }
148
149 if (auto stencil = render_target_.GetStencilAttachment();
150 stencil.has_value()) {
151 depth_stencil_ref = vk::AttachmentReference{
152 static_cast<uint32_t>(attachments.size()),
153 vk::ImageLayout::eDepthStencilAttachmentOptimal};
154 attachments.emplace_back(
155 CreateAttachmentDescription(stencil.value(), &Attachment::texture));
156 SetTextureLayout(stencil.value(), attachments.back(), command_buffer,
157 &Attachment::texture);
158 }
159
160 vk::SubpassDescription subpass_desc;
161 subpass_desc.pipelineBindPoint = vk::PipelineBindPoint::eGraphics;
162 subpass_desc.setColorAttachments(color_refs);
163 subpass_desc.setResolveAttachments(resolve_refs);
164 subpass_desc.setPDepthStencilAttachment(&depth_stencil_ref);
165
166 vk::RenderPassCreateInfo render_pass_desc;
167 render_pass_desc.setAttachments(attachments);
168 render_pass_desc.setPSubpasses(&subpass_desc);
169 render_pass_desc.setSubpassCount(1u);
170
171 auto [result, pass] =
172 context.GetDevice().createRenderPassUnique(render_pass_desc);
173 if (result != vk::Result::eSuccess) {
174 VALIDATION_LOG << "Failed to create render pass: " << vk::to_string(result);
175 return {};
176 }
177 context.SetDebugName(pass.get(), debug_label_.c_str());
178 return MakeSharedVK(std::move(pass));
179 }
180
181 RenderPassVK::RenderPassVK(const std::shared_ptr<const Context>& context,
182 const RenderTarget& target,
183 std::weak_ptr<CommandBufferVK> command_buffer)
184 : RenderPass(context, target), command_buffer_(std::move(command_buffer)) {
185 is_valid_ = true;
186 }
187
188 RenderPassVK::~RenderPassVK() = default;
189
190 bool RenderPassVK::IsValid() const {
191 return is_valid_;
192 }
193
194 void RenderPassVK::OnSetLabel(std::string label) {
195 debug_label_ = std::move(label);
196 }
197
198 static vk::ClearColorValue VKClearValueFromColor(Color color) {
199 vk::ClearColorValue value;
200 value.setFloat32(
201 std::array<float, 4>{color.red, color.green, color.blue, color.alpha});
202 return value;
203 }
204
205 static vk::ClearDepthStencilValue VKClearValueFromDepthStencil(uint32_t stencil,
206 Scalar depth) {
207 vk::ClearDepthStencilValue value;
208 value.depth = depth;
209 value.stencil = stencil;
210 return value;
211 }
212
213 static std::vector<vk::ClearValue> GetVKClearValues(
214 const RenderTarget& target) {
215 std::vector<vk::ClearValue> clears;
216
217 for (const auto& [_, color] : target.GetColorAttachments()) {
218 clears.emplace_back(VKClearValueFromColor(color.clear_color));
219 if (color.resolve_texture) {
220 clears.emplace_back(VKClearValueFromColor(color.clear_color));
221 }
222 }
223
224 const auto& depth = target.GetDepthAttachment();
225 const auto& stencil = target.GetStencilAttachment();
226
227 if (depth.has_value()) {
228 clears.emplace_back(VKClearValueFromDepthStencil(
229 stencil ? stencil->clear_stencil : 0u, depth->clear_depth));
230 }
231
232 if (stencil.has_value()) {
233 clears.emplace_back(VKClearValueFromDepthStencil(
234 stencil->clear_stencil, depth ? depth->clear_depth : 0.0f));
235 }
236
237 return clears;
238 }
239
240 SharedHandleVK<vk::Framebuffer> RenderPassVK::CreateVKFramebuffer(
241 const ContextVK& context,
242 const vk::RenderPass& pass) const {
243 vk::FramebufferCreateInfo fb_info;
244
245 fb_info.renderPass = pass;
246
247 const auto target_size = render_target_.GetRenderTargetSize();
248 fb_info.width = target_size.width;
249 fb_info.height = target_size.height;
250
251 fb_info.layers = 1u;
252
253 std::vector<vk::ImageView> attachments;
254
255 // This bit must be consistent to ensure compatibility with the pass created
256 // earlier. Follow this order: Color attachments, then depth, then stencil.
257 for (const auto& [_, color] : render_target_.GetColorAttachments()) {
258 // The bind point doesn't matter here since that information is present in
259 // the render pass.
260 attachments.emplace_back(TextureVK::Cast(*color.texture).GetImageView());
261 if (color.resolve_texture) {
262 attachments.emplace_back(
263 TextureVK::Cast(*color.resolve_texture).GetImageView());
264 }
265 }
266 if (auto depth = render_target_.GetDepthAttachment(); depth.has_value()) {
267 attachments.emplace_back(TextureVK::Cast(*depth->texture).GetImageView());
268 }
269 if (auto stencil = render_target_.GetStencilAttachment();
270 stencil.has_value()) {
271 attachments.emplace_back(TextureVK::Cast(*stencil->texture).GetImageView());
272 }
273
274 fb_info.setAttachments(attachments);
275
276 auto [result, framebuffer] =
277 context.GetDevice().createFramebufferUnique(fb_info);
278
279 if (result != vk::Result::eSuccess) {
280 VALIDATION_LOG << "Could not create framebuffer: " << vk::to_string(result);
281 return {};
282 }
283
284 return MakeSharedVK(std::move(framebuffer));
285 }
286
287 static bool UpdateBindingLayouts(const Bindings& bindings,
288 const vk::CommandBuffer& buffer) {
289 // All previous writes via a render or blit pass must be done before another
290 // shader attempts to read the resource.
291 BarrierVK barrier;
292 barrier.cmd_buffer = buffer;
293 barrier.src_access = vk::AccessFlagBits::eColorAttachmentWrite |
294 vk::AccessFlagBits::eTransferWrite;
295 barrier.src_stage = vk::PipelineStageFlagBits::eColorAttachmentOutput |
296 vk::PipelineStageFlagBits::eTransfer;
297 barrier.dst_access = vk::AccessFlagBits::eShaderRead;
298 barrier.dst_stage = vk::PipelineStageFlagBits::eFragmentShader;
299
300 barrier.new_layout = vk::ImageLayout::eShaderReadOnlyOptimal;
301
302 for (const auto& [_, data] : bindings.sampled_images) {
303 if (!TextureVK::Cast(*data.texture.resource).SetLayout(barrier)) {
304 return false;
305 }
306 }
307 return true;
308 }
309
310 static bool UpdateBindingLayouts(const Command& command,
311 const vk::CommandBuffer& buffer) {
312 return UpdateBindingLayouts(command.vertex_bindings, buffer) &&
313 UpdateBindingLayouts(command.fragment_bindings, buffer);
314 }
315
316 static bool UpdateBindingLayouts(const std::vector<Command>& commands,
317 const vk::CommandBuffer& buffer) {
318 for (const auto& command : commands) {
319 if (!UpdateBindingLayouts(command, buffer)) {
320 return false;
321 }
322 }
323 return true;
324 }
325
326 static bool AllocateAndBindDescriptorSets(const ContextVK& context,
327 const Command& command,
328 CommandEncoderVK& encoder,
329 const PipelineVK& pipeline,
330 size_t command_count) {
331 auto desc_set =
332 pipeline.GetDescriptor().GetVertexDescriptor()->GetDescriptorSetLayouts();
333 auto vk_desc_set = encoder.AllocateDescriptorSet(
334 pipeline.GetDescriptorSetLayout(), command_count);
335 if (!vk_desc_set) {
336 return false;
337 }
338
339 auto& allocator = *context.GetResourceAllocator();
340
341 std::vector<vk::DescriptorImageInfo> images;
342 std::vector<vk::DescriptorBufferInfo> buffers;
343 std::vector<vk::WriteDescriptorSet> writes;
344 writes.reserve(command.vertex_bindings.buffers.size() +
345 command.fragment_bindings.buffers.size() +
346 command.fragment_bindings.sampled_images.size());
347 images.reserve(command.fragment_bindings.sampled_images.size());
348 buffers.reserve(command.vertex_bindings.buffers.size() +
349 command.fragment_bindings.buffers.size());
350
351 auto bind_images = [&encoder, //
352 &images, //
353 &writes, //
354 &vk_desc_set //
355 ](const Bindings& bindings) -> bool {
356 for (const auto& [index, data] : bindings.sampled_images) {
357 auto texture = data.texture.resource;
358 const auto& texture_vk = TextureVK::Cast(*texture);
359 const SamplerVK& sampler = SamplerVK::Cast(*data.sampler.resource);
360
361 if (!encoder.Track(texture) ||
362 !encoder.Track(sampler.GetSharedSampler())) {
363 return false;
364 }
365
366 const SampledImageSlot& slot = data.slot;
367
368 vk::DescriptorImageInfo image_info;
369 image_info.imageLayout = vk::ImageLayout::eShaderReadOnlyOptimal;
370 image_info.sampler = sampler.GetSampler();
371 image_info.imageView = texture_vk.GetImageView();
372 images.push_back(image_info);
373
374 vk::WriteDescriptorSet write_set;
375 write_set.dstSet = vk_desc_set.value();
376 write_set.dstBinding = slot.binding;
377 write_set.descriptorCount = 1u;
378 write_set.descriptorType = vk::DescriptorType::eCombinedImageSampler;
379 write_set.pImageInfo = &images.back();
380
381 writes.push_back(write_set);
382 }
383
384 return true;
385 };
386
387 auto bind_buffers = [&allocator, //
388 &encoder, //
389 &buffers, //
390 &writes, //
391 &desc_set, //
392 &vk_desc_set //
393 ](const Bindings& bindings) -> bool {
394 for (const auto& [buffer_index, data] : bindings.buffers) {
395 const auto& buffer_view = data.view.resource.buffer;
396
397 auto device_buffer = buffer_view->GetDeviceBuffer(allocator);
398 if (!device_buffer) {
399 VALIDATION_LOG << "Failed to get device buffer for vertex binding";
400 return false;
401 }
402
403 auto buffer = DeviceBufferVK::Cast(*device_buffer).GetBuffer();
404 if (!buffer) {
405 return false;
406 }
407
408 if (!encoder.Track(device_buffer)) {
409 return false;
410 }
411
412 uint32_t offset = data.view.resource.range.offset;
413
414 vk::DescriptorBufferInfo buffer_info;
415 buffer_info.buffer = buffer;
416 buffer_info.offset = offset;
417 buffer_info.range = data.view.resource.range.length;
418 buffers.push_back(buffer_info);
419
420 const ShaderUniformSlot& uniform = data.slot;
421 auto layout_it = std::find_if(desc_set.begin(), desc_set.end(),
422 [&uniform](DescriptorSetLayout& layout) {
423 return layout.binding == uniform.binding;
424 });
425 if (layout_it == desc_set.end()) {
426 VALIDATION_LOG << "Failed to get descriptor set layout for binding "
427 << uniform.binding;
428 return false;
429 }
430 auto layout = *layout_it;
431
432 vk::WriteDescriptorSet write_set;
433 write_set.dstSet = vk_desc_set.value();
434 write_set.dstBinding = uniform.binding;
435 write_set.descriptorCount = 1u;
436 write_set.descriptorType = ToVKDescriptorType(layout.descriptor_type);
437 write_set.pBufferInfo = &buffers.back();
438
439 writes.push_back(write_set);
440 }
441 return true;
442 };
443
444 if (!bind_buffers(command.vertex_bindings) ||
445 !bind_buffers(command.fragment_bindings) ||
446 !bind_images(command.fragment_bindings)) {
447 return false;
448 }
449
450 context.GetDevice().updateDescriptorSets(writes, {});
451
452 encoder.GetCommandBuffer().bindDescriptorSets(
453 vk::PipelineBindPoint::eGraphics, // bind point
454 pipeline.GetPipelineLayout(), // layout
455 0, // first set
456 {vk::DescriptorSet{*vk_desc_set}}, // sets
457 nullptr // offsets
458 );
459 return true;
460 }
461
462 static void SetViewportAndScissor(const Command& command,
463 const vk::CommandBuffer& cmd_buffer,
464 PassBindingsCache& cmd_buffer_cache,
465 const ISize& target_size) {
466 // Set the viewport.
467 const auto& vp = command.viewport.value_or<Viewport>(
468 {.rect = Rect::MakeSize(target_size)});
469 vk::Viewport viewport = vk::Viewport()
470 .setWidth(vp.rect.size.width)
471 .setHeight(-vp.rect.size.height)
472 .setY(vp.rect.size.height)
473 .setMinDepth(0.0f)
474 .setMaxDepth(1.0f);
475 cmd_buffer_cache.SetViewport(cmd_buffer, 0, 1, &viewport);
476
477 // Set the scissor rect.
478 const auto& sc = command.scissor.value_or(IRect::MakeSize(target_size));
479 vk::Rect2D scissor =
480 vk::Rect2D()
481 .setOffset(vk::Offset2D(sc.origin.x, sc.origin.y))
482 .setExtent(vk::Extent2D(sc.size.width, sc.size.height));
483 cmd_buffer_cache.SetScissor(cmd_buffer, 0, 1, &scissor);
484 }
485
486 static bool EncodeCommand(const Context& context,
487 const Command& command,
488 CommandEncoderVK& encoder,
489 PassBindingsCache& command_buffer_cache,
490 const ISize& target_size,
491 size_t command_count) {
492 if (command.vertex_count == 0u || command.instance_count == 0u) {
493 return true;
494 }
495
496 #ifdef IMPELLER_DEBUG
497 fml::ScopedCleanupClosure pop_marker(
498 [&encoder]() { encoder.PopDebugGroup(); });
499 if (!command.label.empty()) {
500 encoder.PushDebugGroup(command.label.c_str());
501 } else {
502 pop_marker.Release();
503 }
504 #endif // IMPELLER_DEBUG
505
506 const auto& cmd_buffer = encoder.GetCommandBuffer();
507
508 const auto& pipeline_vk = PipelineVK::Cast(*command.pipeline);
509
510 if (!AllocateAndBindDescriptorSets(ContextVK::Cast(context), //
511 command, //
512 encoder, //
513 pipeline_vk, //
514 command_count //
515 )) {
516 return false;
517 }
518
519 command_buffer_cache.BindPipeline(
520 cmd_buffer, vk::PipelineBindPoint::eGraphics, pipeline_vk.GetPipeline());
521
522 // Set the viewport and scissors.
523 SetViewportAndScissor(command, cmd_buffer, command_buffer_cache, target_size);
524
525 // Set the stencil reference.
526 command_buffer_cache.SetStencilReference(
527 cmd_buffer, vk::StencilFaceFlagBits::eVkStencilFrontAndBack,
528 command.stencil_reference);
529
530 // Configure vertex and index and buffers for binding.
531 auto vertex_buffer_view = command.GetVertexBuffer();
532
533 if (!vertex_buffer_view) {
534 return false;
535 }
536
537 auto& allocator = *context.GetResourceAllocator();
538
539 auto vertex_buffer = vertex_buffer_view.buffer->GetDeviceBuffer(allocator);
540
541 if (!vertex_buffer) {
542 VALIDATION_LOG << "Failed to acquire device buffer"
543 << " for vertex buffer view";
544 return false;
545 }
546
547 if (!encoder.Track(vertex_buffer)) {
548 return false;
549 }
550
551 // Bind the vertex buffer.
552 auto vertex_buffer_handle = DeviceBufferVK::Cast(*vertex_buffer).GetBuffer();
553 vk::Buffer vertex_buffers[] = {vertex_buffer_handle};
554 vk::DeviceSize vertex_buffer_offsets[] = {vertex_buffer_view.range.offset};
555 cmd_buffer.bindVertexBuffers(0u, 1u, vertex_buffers, vertex_buffer_offsets);
556
557 if (command.index_type != IndexType::kNone) {
558 // Bind the index buffer.
559 auto index_buffer_view = command.index_buffer;
560 if (!index_buffer_view) {
561 return false;
562 }
563
564 auto index_buffer = index_buffer_view.buffer->GetDeviceBuffer(allocator);
565 if (!index_buffer) {
566 VALIDATION_LOG << "Failed to acquire device buffer"
567 << " for index buffer view";
568 return false;
569 }
570
571 if (!encoder.Track(index_buffer)) {
572 return false;
573 }
574
575 auto index_buffer_handle = DeviceBufferVK::Cast(*index_buffer).GetBuffer();
576 cmd_buffer.bindIndexBuffer(index_buffer_handle,
577 index_buffer_view.range.offset,
578 ToVKIndexType(command.index_type));
579
580 // Engage!
581 cmd_buffer.drawIndexed(command.vertex_count, // index count
582 command.instance_count, // instance count
583 0u, // first index
584 command.base_vertex, // vertex offset
585 0u // first instance
586 );
587 } else {
588 cmd_buffer.draw(command.vertex_count, // vertex count
589 command.instance_count, // instance count
590 command.base_vertex, // vertex offset
591 0u // first instance
592 );
593 }
594 return true;
595 }
596
597 bool RenderPassVK::OnEncodeCommands(const Context& context) const {
598 TRACE_EVENT0("impeller", "RenderPassVK::OnEncodeCommands");
599 if (!IsValid()) {
600 return false;
601 }
602
603 const auto& vk_context = ContextVK::Cast(context);
604
605 auto command_buffer = command_buffer_.lock();
606 if (!command_buffer) {
607 VALIDATION_LOG << "Command buffer died before commands could be encoded.";
608 return false;
609 }
610 auto encoder = command_buffer->GetEncoder();
611 if (!encoder) {
612 return false;
613 }
614
615 fml::ScopedCleanupClosure pop_marker(
616 [&encoder]() { encoder->PopDebugGroup(); });
617 if (!debug_label_.empty()) {
618 encoder->PushDebugGroup(debug_label_.c_str());
619 } else {
620 pop_marker.Release();
621 }
622
623 auto cmd_buffer = encoder->GetCommandBuffer();
624
625 if (!UpdateBindingLayouts(commands_, cmd_buffer)) {
626 return false;
627 }
628
629 render_target_.IterateAllAttachments(
630 [&encoder](const auto& attachment) -> bool {
631 encoder->Track(attachment.texture);
632 encoder->Track(attachment.resolve_texture);
633 return true;
634 });
635
636 const auto& target_size = render_target_.GetRenderTargetSize();
637
638 auto render_pass = CreateVKRenderPass(vk_context, command_buffer);
639 if (!render_pass) {
640 VALIDATION_LOG << "Could not create renderpass.";
641 return false;
642 }
643
644 auto framebuffer = CreateVKFramebuffer(vk_context, *render_pass);
645 if (!framebuffer) {
646 VALIDATION_LOG << "Could not create framebuffer.";
647 return false;
648 }
649
650 if (!encoder->Track(framebuffer) || !encoder->Track(render_pass)) {
651 return false;
652 }
653
654 auto clear_values = GetVKClearValues(render_target_);
655
656 vk::RenderPassBeginInfo pass_info;
657 pass_info.renderPass = *render_pass;
658 pass_info.framebuffer = *framebuffer;
659 pass_info.renderArea.extent.width = static_cast<uint32_t>(target_size.width);
660 pass_info.renderArea.extent.height =
661 static_cast<uint32_t>(target_size.height);
662 pass_info.setClearValues(clear_values);
663
664 {
665 TRACE_EVENT0("impeller", "EncodeRenderPassCommands");
666 cmd_buffer.beginRenderPass(pass_info, vk::SubpassContents::eInline);
667
668 fml::ScopedCleanupClosure end_render_pass(
669 [cmd_buffer]() { cmd_buffer.endRenderPass(); });
670
671 for (const auto& command : commands_) {
672 if (!command.pipeline) {
673 continue;
674 }
675
676 if (!EncodeCommand(context, command, *encoder, pass_bindings_cache_,
677 target_size, commands_.size())) {
678 return false;
679 }
680 }
681 }
682
683 return true;
684 }
685
686 } // namespace impeller
impeller::Command::vertex_count
size_t vertex_count
Definition: command.h:131
impeller::BarrierVK::dst_access
vk::AccessFlags dst_access
Definition: barrier_vk.h:42
impeller::Command
An object used to specify work to the GPU along with references to resources the GPU will used when d...
Definition: command.h:99
impeller::SetViewportAndScissor
static void SetViewportAndScissor(const Command &command, const vk::CommandBuffer &cmd_buffer, PassBindingsCache &cmd_buffer_cache, const ISize &target_size)
Definition: render_pass_vk.cc:462
impeller::Command::scissor
std::optional< IRect > scissor
Definition: command.h:169
impeller::VKClearValueFromDepthStencil
static vk::ClearDepthStencilValue VKClearValueFromDepthStencil(uint32_t stencil, Scalar depth)
Definition: render_pass_vk.cc:205
impeller::DescriptorSetLayout
Definition: shader_types.h:149
impeller::ShaderUniformSlot
Definition: shader_types.h:81
impeller::Attachment::store_action
StoreAction store_action
Definition: formats.h:594
impeller::Scalar
float Scalar
Definition: scalar.h:15
impeller::Command::index_type
IndexType index_type
Definition: command.h:136
barrier_vk.h
impeller::PassBindingsCache::SetStencilReference
void SetStencilReference(vk::CommandBuffer command_buffer, vk::StencilFaceFlags face_mask, uint32_t reference)
Definition: pass_bindings_cache.cc:32
shared_object_vk.h
impeller::CommandEncoderVK::PushDebugGroup
void PushDebugGroup(const char *label) const
Definition: command_encoder_vk.cc:295
impeller::Color
Definition: color.h:122
impeller::PipelineVK::GetPipelineLayout
const vk::PipelineLayout & GetPipelineLayout() const
Definition: pipeline_vk.cc:52
command_encoder_vk.h
impeller::ToVKDescriptorType
constexpr vk::DescriptorType ToVKDescriptorType(DescriptorType type)
Definition: formats_vk.h:273
impeller::BarrierVK::new_layout
vk::ImageLayout new_layout
Definition: barrier_vk.h:22
impeller::ContextVK::GetResourceAllocator
std::shared_ptr< Allocator > GetResourceAllocator() const override
Returns the allocator used to create textures and buffers on the device.
Definition: context_vk.cc:453
impeller::BarrierVK::cmd_buffer
vk::CommandBuffer cmd_buffer
Definition: barrier_vk.h:21
impeller::EncodeCommand
static bool EncodeCommand(const Context &context, const Command &command, CommandEncoderVK &encoder, PassBindingsCache &command_buffer_cache, const ISize &target_size, size_t command_count)
Definition: render_pass_vk.cc:486
formats.h
impeller::Command::viewport
std::optional< Viewport > viewport
Definition: command.h:163
impeller::PipelineVK
Definition: pipeline_vk.h:17
impeller::Color::alpha
Scalar alpha
Definition: color.h:141
impeller::StoreAction::kDontCare
@ kDontCare
impeller::PipelineDescriptor::GetVertexDescriptor
const std::shared_ptr< VertexDescriptor > & GetVertexDescriptor() const
Definition: pipeline_descriptor.cc:213
impeller::Bindings::buffers
std::map< size_t, BufferAndUniformSlot > buffers
Definition: command.h:79
formats_vk.h
impeller::RenderTarget::GetColorAttachments
const std::map< size_t, ColorAttachment > & GetColorAttachments() const
Definition: render_target.cc:209
pipeline_vk.h
render_pass_vk.h
impeller::Command::instance_count
size_t instance_count
Definition: command.h:177
validation.h
impeller::Color::green
Scalar green
Definition: color.h:131
sampler.h
impeller::Command::base_vertex
uint64_t base_vertex
Definition: command.h:156
impeller::SamplerVK
Definition: sampler_vk.h:17
impeller::Command::GetVertexBuffer
BufferView GetVertexBuffer() const
Definition: command.cc:29
impeller::PassBindingsCache::SetScissor
void SetScissor(const IRect &scissor)
Definition: render_pass_mtl.mm:323
impeller::SetTextureLayout
static void SetTextureLayout(const Attachment &attachment, const vk::AttachmentDescription &attachment_desc, const std::shared_ptr< CommandBufferVK > &command_buffer, const std::shared_ptr< Texture > Attachment::*texture_ptr)
Definition: render_pass_vk.cc:69
impeller::CommandEncoderVK::AllocateDescriptorSet
std::optional< vk::DescriptorSet > AllocateDescriptorSet(const vk::DescriptorSetLayout &layout, size_t command_count)
Definition: command_encoder_vk.cc:284
impeller::ShaderUniformSlot::binding
size_t binding
Definition: shader_types.h:85
command_buffer_vk.h
impeller::TSize
Definition: size.h:18
impeller::LoadAction::kClear
@ kClear
impeller::RenderTarget::GetDepthAttachment
const std::optional< DepthAttachment > & GetDepthAttachment() const
Definition: render_target.cc:214
impeller::StorageMode::kDeviceTransient
@ kDeviceTransient
impeller::Command::vertex_bindings
Bindings vertex_bindings
Definition: command.h:108
impeller::BarrierVK
Defines an operations and memory access barrier on a resource.
Definition: barrier_vk.h:20
impeller::GetVKClearValues
static std::vector< vk::ClearValue > GetVKClearValues(const RenderTarget &target)
Definition: render_pass_vk.cc:213
impeller::ToVKIndexType
constexpr vk::IndexType ToVKIndexType(IndexType index_type)
Definition: formats_vk.h:333
impeller::UpdateBindingLayouts
static bool UpdateBindingLayouts(const std::vector< Command > &commands, const vk::CommandBuffer &buffer)
Definition: render_pass_vk.cc:316
impeller::Attachment::texture
std::shared_ptr< Texture > texture
Definition: formats.h:591
impeller::PassBindingsCache
Ensures that bindings on the pass are not redundantly set or updated. Avoids making the driver do add...
Definition: render_pass_mtl.mm:194
impeller::CommandEncoderVK::Track
bool Track(std::shared_ptr< SharedObjectVK > object)
Definition: command_encoder_vk.cc:232
impeller::BufferView::buffer
std::shared_ptr< const Buffer > buffer
Definition: buffer_view.h:14
impeller::SampledImageSlot
Definition: shader_types.h:129
impeller::Color::red
Scalar red
Definition: color.h:126
impeller::Bindings::sampled_images
std::map< size_t, TextureAndSampler > sampled_images
Definition: command.h:78
impeller::BarrierVK::src_access
vk::AccessFlags src_access
Definition: barrier_vk.h:32
impeller::Attachment
Definition: formats.h:590
impeller::RenderTarget
Definition: render_target.h:48
impeller::SamplerVK::GetSampler
vk::Sampler GetSampler() const
Definition: sampler_vk.cc:17
impeller::StoreAction::kStore
@ kStore
impeller::RenderPass::render_target_
const RenderTarget render_target_
Definition: render_pass.h:69
impeller::Pipeline::GetDescriptor
const T & GetDescriptor() const
Get the descriptor that was responsible for creating this pipeline. It may be copied and modified to ...
Definition: pipeline.cc:49
impeller::CommandEncoderVK::PopDebugGroup
void PopDebugGroup() const
Definition: command_encoder_vk.cc:306
texture_vk.h
impeller::ContextVK
Definition: context_vk.h:36
impeller::BarrierVK::dst_stage
vk::PipelineStageFlags dst_stage
Definition: barrier_vk.h:37
impeller::Viewport
Definition: formats.h:352
VALIDATION_LOG
#define VALIDATION_LOG
Definition: validation.h:60
impeller::Command::stencil_reference
uint32_t stencil_reference
Definition: command.h:152
impeller::Attachment::resolve_texture
std::shared_ptr< Texture > resolve_texture
Definition: formats.h:592
impeller::MakeSharedVK
auto MakeSharedVK(vk::UniqueHandle< T, VULKAN_HPP_DEFAULT_DISPATCHER_TYPE > handle)
Definition: shared_object_vk.h:39
impeller::PassBindingsCache::SetViewport
void SetViewport(const Viewport &viewport)
Definition: render_pass_mtl.mm:308
impeller::Context
To do anything rendering related with Impeller, you need a context.
Definition: context.h:47
std
Definition: comparable.h:98
impeller::ContextVK::GetDevice
const vk::Device & GetDevice() const
Definition: context_vk.cc:480
impeller::AllocateAndBindDescriptorSets
static bool AllocateAndBindDescriptorSets(const ContextVK &context, const Command &command, CommandEncoderVK &encoder, const PipelineVK &pipeline, size_t command_count)
Definition: render_pass_vk.cc:326
impeller::Command::fragment_bindings
Bindings fragment_bindings
Definition: command.h:113
impeller::BackendCast< TextureVK, Texture >::Cast
static TextureVK & Cast(Texture &base)
Definition: backend_cast.h:14
impeller::Attachment::load_action
LoadAction load_action
Definition: formats.h:593
device_buffer_vk.h
impeller::kUnusedAttachmentReference
static constexpr vk::AttachmentReference kUnusedAttachmentReference
Definition: formats_vk.h:490
sampler_vk.h
impeller::RenderTarget::GetMaxColorAttacmentBindIndex
size_t GetMaxColorAttacmentBindIndex() const
Definition: render_target.cc:172
impeller::Command::pipeline
std::shared_ptr< Pipeline< PipelineDescriptor > > pipeline
Definition: command.h:103
impeller::SampledImageSlot::binding
size_t binding
Definition: shader_types.h:133
impeller::RenderTarget::GetStencilAttachment
const std::optional< StencilAttachment > & GetStencilAttachment() const
Definition: render_target.cc:218
context_vk.h
impeller::CreateAttachmentDescription
constexpr vk::AttachmentDescription CreateAttachmentDescription(PixelFormat format, SampleCount sample_count, LoadAction load_action, StoreAction store_action, vk::ImageLayout current_layout)
Definition: formats_vk.h:431
impeller::Color::blue
Scalar blue
Definition: color.h:136
impeller::DescriptorSetLayout::descriptor_type
DescriptorType descriptor_type
Definition: shader_types.h:151
impeller::PipelineVK::GetDescriptorSetLayout
const vk::DescriptorSetLayout & GetDescriptorSetLayout() const
Definition: pipeline_vk.cc:56
shader_types.h
impeller::CommandEncoderVK
Definition: command_encoder_vk.h:45
impeller
Definition: aiks_context.cc:10
impeller::PassBindingsCache::BindPipeline
void BindPipeline(vk::CommandBuffer command_buffer, vk::PipelineBindPoint pipeline_bind_point, vk::Pipeline pipeline)
Definition: pass_bindings_cache.cc:8
impeller::CommandEncoderVK::GetCommandBuffer
vk::CommandBuffer GetCommandBuffer() const
Definition: command_encoder_vk.cc:218
impeller::SamplerVK::GetSharedSampler
const std::shared_ptr< SharedObjectVKT< vk::Sampler > > & GetSharedSampler() const
Definition: sampler_vk.cc:22
impeller::Context::GetResourceAllocator
virtual std::shared_ptr< Allocator > GetResourceAllocator() const =0
Returns the allocator used to create textures and buffers on the device.
impeller::BarrierVK::src_stage
vk::PipelineStageFlags src_stage
Definition: barrier_vk.h:27
impeller::Bindings
Definition: command.h:77
impeller::VKClearValueFromColor
static vk::ClearColorValue VKClearValueFromColor(Color color)
Definition: render_pass_vk.cc:198
impeller::Command::index_buffer
BufferView index_buffer
Definition: command.h:121