Flutter Engine Uber Docs
Docs for the entire Flutter Engine repo.
 
Loading...
Searching...
No Matches
render_pass_vk.cc
Go to the documentation of this file.
1// Copyright 2013 The Flutter Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
6
7#include <array>
8#include <cstdint>
9
10#include "fml/status.h"
27
28namespace impeller {
29
30// Warning: if any of the constant values or layouts are changed in the
31// framebuffer fetch shader, then this input binding may need to be
32// manually changed.
33//
34// See: impeller/entity/shaders/blending/framebuffer_blend.frag
35static constexpr size_t kMagicSubpassInputBinding = 64u;
36
37static vk::ClearColorValue VKClearValueFromColor(Color color) {
38 vk::ClearColorValue value;
39 value.setFloat32(
40 std::array<float, 4>{color.red, color.green, color.blue, color.alpha});
41 return value;
42}
43
44static vk::ClearDepthStencilValue VKClearValueFromDepthStencil(uint32_t stencil,
45 Scalar depth) {
46 vk::ClearDepthStencilValue value;
47 value.depth = depth;
48 value.stencil = stencil;
49 return value;
50}
51
52/// Converts an Impeller `Viewport` to a `vk::Viewport`. Impeller specifies
53/// viewports in top-left-origin framebuffer coordinates, so the
54/// negative-height trick from VK_KHR_maintenance1 is used to flip the Y axis
55/// to match the GL convention that the rest of the engine assumes (NDC +Y
56/// maps to the smaller framebuffer Y).
57static vk::Viewport ToVkViewport(const Viewport& viewport) {
58 const auto& rect = viewport.rect;
59 return vk::Viewport()
60 .setX(rect.GetX())
61 .setY(rect.GetY() + rect.GetHeight())
62 .setWidth(rect.GetWidth())
63 .setHeight(-rect.GetHeight())
64 .setMinDepth(viewport.depth_range.z_near)
65 .setMaxDepth(viewport.depth_range.z_far);
66}
67
68static size_t GetVKClearValues(
69 const RenderTarget& target,
70 std::array<vk::ClearValue, kMaxAttachments>& values) {
71 size_t offset = 0u;
72 target.IterateAllColorAttachments(
73 [&values, &offset](size_t index,
74 const ColorAttachment& attachment) -> bool {
75 values.at(offset++) = VKClearValueFromColor(attachment.clear_color);
76 if (attachment.resolve_texture) {
77 values.at(offset++) = VKClearValueFromColor(attachment.clear_color);
78 }
79 return true;
80 });
81
82 const auto& depth = target.GetDepthAttachment();
83 const auto& stencil = target.GetStencilAttachment();
84
85 if (depth.has_value()) {
86 values.at(offset++) = VKClearValueFromDepthStencil(
87 stencil ? stencil->clear_stencil : 0u, depth->clear_depth);
88 } else if (stencil.has_value()) {
89 values.at(offset++) = VKClearValueFromDepthStencil(
90 stencil->clear_stencil, depth ? depth->clear_depth : 0.0f);
91 }
92 return offset;
93}
94
95SharedHandleVK<vk::RenderPass> RenderPassVK::CreateVKRenderPass(
96 const ContextVK& context,
97 const SharedHandleVK<vk::RenderPass>& recycled_renderpass,
98 const std::shared_ptr<CommandBufferVK>& command_buffer,
99 bool is_swapchain) const {
100 if (recycled_renderpass != nullptr) {
101 return recycled_renderpass;
102 }
103
104 RenderPassBuilderVK builder;
105 render_target_.IterateAllColorAttachments([&](size_t bind_point,
106 const ColorAttachment&
107 attachment) -> bool {
108 builder.SetColorAttachment(
109 bind_point, //
110 attachment.texture->GetTextureDescriptor().format, //
111 attachment.texture->GetTextureDescriptor().sample_count, //
112 attachment.load_action, //
113 attachment.store_action, //
114 /*current_layout=*/TextureVK::Cast(*attachment.texture).GetLayout(), //
115 /*is_swapchain=*/is_swapchain);
116 return true;
117 });
118
119 if (auto depth = render_target_.GetDepthAttachment(); depth.has_value()) {
120 builder.SetDepthStencilAttachment(
121 depth->texture->GetTextureDescriptor().format, //
122 depth->texture->GetTextureDescriptor().sample_count, //
123 depth->load_action, //
124 depth->store_action //
125 );
126 } else if (auto stencil = render_target_.GetStencilAttachment();
127 stencil.has_value()) {
128 builder.SetStencilAttachment(
129 stencil->texture->GetTextureDescriptor().format, //
130 stencil->texture->GetTextureDescriptor().sample_count, //
131 stencil->load_action, //
132 stencil->store_action //
133 );
134 }
135
136 auto pass = builder.Build(context.GetDevice());
137
138 if (!pass) {
139 VALIDATION_LOG << "Failed to create render pass for framebuffer.";
140 return {};
141 }
142
143 context.SetDebugName(pass.get(), debug_label_.c_str());
144
145 return MakeSharedVK(std::move(pass));
146}
147
148RenderPassVK::RenderPassVK(const std::shared_ptr<const Context>& context,
149 const RenderTarget& target,
150 std::shared_ptr<CommandBufferVK> command_buffer)
151 : RenderPass(context, target), command_buffer_(std::move(command_buffer)) {
152 const ColorAttachment& color0 = render_target_.GetColorAttachment(0);
153 color_image_vk_ = color0.texture;
154 resolve_image_vk_ = color0.resolve_texture;
155
156 const auto& vk_context = ContextVK::Cast(*context);
157 command_buffer_vk_ = command_buffer_->GetCommandBuffer();
158 render_target_.IterateAllAttachments([&](const auto& attachment) -> bool {
159 command_buffer_->Track(attachment.texture);
160 command_buffer_->Track(attachment.resolve_texture);
161 return true;
162 });
163
164 FramebufferAndRenderPass frame_data;
165 bool is_swapchain = false;
166 SampleCount sample_count =
167 color_image_vk_->GetTextureDescriptor().sample_count;
168 if (resolve_image_vk_) {
169 frame_data =
170 TextureVK::Cast(*resolve_image_vk_).GetCachedFrameData(sample_count);
171 is_swapchain = TextureVK::Cast(*resolve_image_vk_).IsSwapchainImage();
172 } else {
173 frame_data =
174 TextureVK::Cast(*color_image_vk_).GetCachedFrameData(sample_count);
175 is_swapchain = TextureVK::Cast(*color_image_vk_).IsSwapchainImage();
176 }
177
178 const auto& target_size = render_target_.GetRenderTargetSize();
179
180 render_pass_ = CreateVKRenderPass(vk_context, frame_data.render_pass,
181 command_buffer_, is_swapchain);
182 if (!render_pass_) {
183 VALIDATION_LOG << "Could not create renderpass.";
184 is_valid_ = false;
185 return;
186 }
187
188 auto framebuffer = (frame_data.framebuffer == nullptr)
189 ? CreateVKFramebuffer(vk_context, *render_pass_)
190 : frame_data.framebuffer;
191 if (!framebuffer) {
192 VALIDATION_LOG << "Could not create framebuffer.";
193 is_valid_ = false;
194 return;
195 }
196
197 if (!command_buffer_->Track(framebuffer) ||
198 !command_buffer_->Track(render_pass_)) {
199 is_valid_ = false;
200 return;
201 }
202
203 frame_data.framebuffer = framebuffer;
204 frame_data.render_pass = render_pass_;
205
206 if (resolve_image_vk_) {
207 TextureVK::Cast(*resolve_image_vk_)
208 .SetCachedFrameData(frame_data, sample_count);
209 } else {
210 TextureVK::Cast(*color_image_vk_)
211 .SetCachedFrameData(frame_data, sample_count);
212 }
213
214 // If the resolve image exists and has mipmaps, transition mip levels besides
215 // the base to shader read only in preparation for mipmap generation.
216 if (resolve_image_vk_ &&
217 resolve_image_vk_->GetTextureDescriptor().mip_count > 1) {
218 if (TextureVK::Cast(*resolve_image_vk_).GetLayout() ==
219 vk::ImageLayout::eUndefined) {
220 BarrierVK barrier;
221 barrier.new_layout = vk::ImageLayout::eShaderReadOnlyOptimal;
222 barrier.cmd_buffer = command_buffer_->GetCommandBuffer();
223 barrier.src_stage = vk::PipelineStageFlagBits::eBottomOfPipe;
224 barrier.src_access = {};
225 barrier.dst_stage = vk::PipelineStageFlagBits::eFragmentShader;
226 barrier.dst_access = vk::AccessFlagBits::eShaderRead;
227 barrier.base_mip_level = 1;
228 TextureVK::Cast(*resolve_image_vk_).SetLayout(barrier);
229 }
230 }
231
232 std::array<vk::ClearValue, kMaxAttachments> clears;
233 size_t clear_count = GetVKClearValues(render_target_, clears);
234
235 vk::RenderPassBeginInfo pass_info;
236 pass_info.renderPass = *render_pass_;
237 pass_info.framebuffer = *framebuffer;
238 pass_info.renderArea.extent.width = static_cast<uint32_t>(target_size.width);
239 pass_info.renderArea.extent.height =
240 static_cast<uint32_t>(target_size.height);
241 pass_info.setPClearValues(clears.data());
242 pass_info.setClearValueCount(clear_count);
243
244 command_buffer_vk_.beginRenderPass(pass_info, vk::SubpassContents::eInline);
245
246 if (resolve_image_vk_) {
247 TextureVK::Cast(*resolve_image_vk_)
249 is_swapchain ? vk::ImageLayout::eGeneral
250 : vk::ImageLayout::eShaderReadOnlyOptimal);
251 }
252 if (color_image_vk_) {
253 // Mirror the Vulkan render pass's `finalLayout` for the color attachment
254 // (see ComputeFinalLayout in render_pass_builder_vk.cc): swapchain and
255 // MSAA targets stay in eGeneral, but a non-swapchain, single-sampled
256 // color attachment transitions to eShaderReadOnlyOptimal on
257 // endRenderPass. Tracking it as eGeneral here desyncs the bookkeeping
258 // and produces an incorrect oldLayout on the next barrier (caught by
259 // Vulkan validation as VUID-vkCmdDraw-None-09600).
260 TextureVK::Cast(*color_image_vk_)
262 (is_swapchain || sample_count != SampleCount::kCount1)
263 ? vk::ImageLayout::eGeneral
264 : vk::ImageLayout::eShaderReadOnlyOptimal);
265 }
266
267 // Set the initial viewport.
268 const auto vp = Viewport{.rect = Rect::MakeSize(target_size)};
269 vk::Viewport viewport = ToVkViewport(vp);
270 command_buffer_vk_.setViewport(0, 1, &viewport);
271
272 // Set the initial scissor.
273 const auto sc = IRect32::MakeSize(target_size);
274 vk::Rect2D scissor =
275 vk::Rect2D()
276 .setOffset(vk::Offset2D(sc.GetX(), sc.GetY()))
277 .setExtent(vk::Extent2D(sc.GetWidth(), sc.GetHeight()));
278 command_buffer_vk_.setScissor(0, 1, &scissor);
279
280 // Set the initial stencil reference.
281 command_buffer_vk_.setStencilReference(vk::StencilFaceFlagBits::eFrontAndBack,
282 0u);
283
284 is_valid_ = true;
285}
286
287RenderPassVK::~RenderPassVK() = default;
288
289bool RenderPassVK::IsValid() const {
290 return is_valid_;
291}
292
293void RenderPassVK::OnSetLabel(std::string_view label) {
294#ifdef IMPELLER_DEBUG
295 ContextVK::Cast(*context_).SetDebugName(render_pass_->Get(), label.data());
296#endif // IMPELLER_DEBUG
297}
298
299SharedHandleVK<vk::Framebuffer> RenderPassVK::CreateVKFramebuffer(
300 const ContextVK& context,
301 const vk::RenderPass& pass) const {
302 vk::FramebufferCreateInfo fb_info;
303
304 fb_info.renderPass = pass;
305
306 const auto target_size = render_target_.GetRenderTargetSize();
307 fb_info.width = target_size.width;
308 fb_info.height = target_size.height;
309 fb_info.layers = 1u;
310
311 std::array<vk::ImageView, kMaxAttachments> attachments;
312 size_t count = 0;
313
314 // This bit must be consistent to ensure compatibility with the pass created
315 // earlier. Follow this order: Color attachments, then depth-stencil, then
316 // stencil.
317 render_target_.IterateAllColorAttachments(
318 [&attachments, &count](size_t index,
319 const ColorAttachment& attachment) -> bool {
320 // The bind point doesn't matter here since that information is present
321 // in the render pass.
322 attachments[count++] =
323 TextureVK::Cast(*attachment.texture).GetRenderTargetView();
324 if (attachment.resolve_texture) {
325 attachments[count++] = TextureVK::Cast(*attachment.resolve_texture)
326 .GetRenderTargetView();
327 }
328 return true;
329 });
330
331 if (auto depth = render_target_.GetDepthAttachment(); depth.has_value()) {
332 attachments[count++] =
333 TextureVK::Cast(*depth->texture).GetRenderTargetView();
334 } else if (auto stencil = render_target_.GetStencilAttachment();
335 stencil.has_value()) {
336 attachments[count++] =
337 TextureVK::Cast(*stencil->texture).GetRenderTargetView();
338 }
339
340 fb_info.setPAttachments(attachments.data());
341 fb_info.setAttachmentCount(count);
342
343 auto [result, framebuffer] =
344 context.GetDevice().createFramebufferUnique(fb_info);
345
346 if (result != vk::Result::eSuccess) {
347 VALIDATION_LOG << "Could not create framebuffer: " << vk::to_string(result);
348 return {};
349 }
350
351 return MakeSharedVK(std::move(framebuffer));
352}
353
354// |RenderPass|
355void RenderPassVK::SetPipeline(PipelineRef pipeline) {
356 pipeline_ = pipeline;
357 if (!pipeline_) {
358 return;
359 }
360 context_->GetPipelineLibrary()->LogPipelineUsage(pipeline->GetDescriptor());
361
362 pipeline_uses_input_attachments_ =
363 pipeline_->GetDescriptor().GetVertexDescriptor()->UsesInputAttachments();
364
365 if (pipeline_uses_input_attachments_) {
366 if (bound_image_offset_ >= kMaxBindings) {
367 pipeline_ = PipelineRef(nullptr);
368 return;
369 }
370 vk::DescriptorImageInfo image_info;
371 image_info.imageLayout = vk::ImageLayout::eGeneral;
372 image_info.sampler = VK_NULL_HANDLE;
373 image_info.imageView = TextureVK::Cast(*color_image_vk_).GetImageView();
374 image_workspace_[bound_image_offset_++] = image_info;
375
376 vk::WriteDescriptorSet write_set;
377 write_set.dstBinding = kMagicSubpassInputBinding;
378 write_set.descriptorCount = 1u;
379 write_set.descriptorType = vk::DescriptorType::eInputAttachment;
380 write_set.pImageInfo = &image_workspace_[bound_image_offset_ - 1];
381
382 write_workspace_[descriptor_write_offset_++] = write_set;
383 }
384}
385
386// |RenderPass|
387void RenderPassVK::SetCommandLabel(std::string_view label) {
388#ifdef IMPELLER_DEBUG
389 command_buffer_->PushDebugGroup(label);
390 has_label_ = true;
391#endif // IMPELLER_DEBUG
392}
393
394// |RenderPass|
395void RenderPassVK::SetStencilReference(uint32_t value) {
396 if (current_stencil_ == value) {
397 return;
398 }
399 current_stencil_ = value;
400 command_buffer_vk_.setStencilReference(vk::StencilFaceFlagBits::eFrontAndBack,
401 value);
402}
403
404// |RenderPass|
405void RenderPassVK::SetBaseVertex(uint64_t value) {
406 base_vertex_ = value;
407}
408
409// |RenderPass|
410void RenderPassVK::SetViewport(Viewport viewport) {
411 vk::Viewport viewport_vk = ToVkViewport(viewport);
412 command_buffer_vk_.setViewport(0, 1, &viewport_vk);
413}
414
415// |RenderPass|
416void RenderPassVK::SetScissor(IRect32 scissor) {
417 vk::Rect2D scissor_vk =
418 vk::Rect2D()
419 .setOffset(vk::Offset2D(scissor.GetX(), scissor.GetY()))
420 .setExtent(vk::Extent2D(scissor.GetWidth(), scissor.GetHeight()));
421 command_buffer_vk_.setScissor(0, 1, &scissor_vk);
422}
423
424// |RenderPass|
425void RenderPassVK::SetElementCount(size_t count) {
426 element_count_ = count;
427}
428
429// |RenderPass|
430void RenderPassVK::SetInstanceCount(size_t count) {
431 instance_count_ = count;
432}
433
434// |RenderPass|
435bool RenderPassVK::SetVertexBuffer(BufferView vertex_buffers[],
436 size_t vertex_buffer_count) {
437 if (!ValidateVertexBuffers(vertex_buffers, vertex_buffer_count)) {
438 return false;
439 }
440
441 vk::Buffer buffers[kMaxVertexBuffers];
442 vk::DeviceSize vertex_buffer_offsets[kMaxVertexBuffers];
443 for (size_t i = 0; i < vertex_buffer_count; i++) {
444 buffers[i] =
445 DeviceBufferVK::Cast(*vertex_buffers[i].GetBuffer()).GetBuffer();
446 vertex_buffer_offsets[i] = vertex_buffers[i].GetRange().offset;
447 std::shared_ptr<const DeviceBuffer> device_buffer =
448 vertex_buffers[i].TakeBuffer();
449 if (device_buffer) {
450 command_buffer_->Track(device_buffer);
451 }
452 }
453
454 // Bind the vertex buffers.
455 command_buffer_vk_.bindVertexBuffers(0u, vertex_buffer_count, buffers,
456 vertex_buffer_offsets);
457
458 return true;
459}
460
461// |RenderPass|
462bool RenderPassVK::SetIndexBuffer(BufferView index_buffer,
463 IndexType index_type) {
464 if (!ValidateIndexBuffer(index_buffer, index_type)) {
465 return false;
466 }
467
468 if (index_type != IndexType::kNone) {
469 has_index_buffer_ = true;
470
471 BufferView index_buffer_view = std::move(index_buffer);
472 if (!index_buffer_view) {
473 return false;
474 }
475
476 if (!index_buffer_view.GetBuffer()) {
477 VALIDATION_LOG << "Failed to acquire device buffer"
478 << " for index buffer view";
479 return false;
480 }
481
482 std::shared_ptr<const DeviceBuffer> index_buffer =
483 index_buffer_view.TakeBuffer();
484 if (index_buffer && !command_buffer_->Track(index_buffer)) {
485 return false;
486 }
487
488 vk::Buffer index_buffer_handle =
489 DeviceBufferVK::Cast(*index_buffer_view.GetBuffer()).GetBuffer();
490 command_buffer_vk_.bindIndexBuffer(index_buffer_handle,
491 index_buffer_view.GetRange().offset,
492 ToVKIndexType(index_type));
493 } else {
494 has_index_buffer_ = false;
495 }
496
497 return true;
498}
499
500// |RenderPass|
501fml::Status RenderPassVK::Draw() {
502 if (!pipeline_) {
504 "No valid pipeline is bound to the RenderPass.");
505 }
506
507 //----------------------------------------------------------------------------
508 /// If there are immutable samplers referenced in the render pass, the base
509 /// pipeline variant is no longer valid and needs to be re-constructed to
510 /// reference the samplers.
511 ///
512 /// This is an instance of JIT creation of PSOs that can cause jank. It is
513 /// unavoidable because it isn't possible to know all possible combinations of
514 /// target YUV conversions. Fortunately, this will only ever happen when
515 /// rendering to external textures. Like Android Hardware Buffers on Android.
516 ///
517 /// Even when JIT creation is unavoidable, pipelines will cache their variants
518 /// when able and all pipeline creation will happen via a base pipeline cache
519 /// anyway. So the jank can be mostly entirely ameliorated and it should only
520 /// ever happen when the first unknown YUV conversion is encountered.
521 ///
522 /// Jank can be completely eliminated by pre-populating known YUV conversion
523 /// pipelines.
524 if (immutable_sampler_) {
525 std::shared_ptr<Pipeline<PipelineDescriptor>> pipeline_variant =
526 PipelineVK::Cast(*pipeline_)
527 .CreateVariantForImmutableSamplers(immutable_sampler_);
528 if (!pipeline_variant) {
529 return fml::Status(
531 "Could not create pipeline variant with immutable sampler.");
532 }
533 pipeline_ = raw_ptr(pipeline_variant);
534 }
535
536 const auto& context_vk = ContextVK::Cast(*context_);
537 const auto& pipeline_vk = PipelineVK::Cast(*pipeline_);
538
539 auto descriptor_result = command_buffer_->AllocateDescriptorSets(
540 pipeline_vk.GetDescriptorSetLayout(), pipeline_vk.GetPipelineKey(),
541 context_vk);
542 if (!descriptor_result.ok()) {
544 "Could not allocate descriptor sets.");
545 }
546 const auto descriptor_set = descriptor_result.value();
547 const auto pipeline_layout = pipeline_vk.GetPipelineLayout();
548 command_buffer_vk_.bindPipeline(vk::PipelineBindPoint::eGraphics,
549 pipeline_vk.GetPipeline());
550
551 for (auto i = 0u; i < descriptor_write_offset_; i++) {
552 write_workspace_[i].dstSet = descriptor_set;
553 }
554
555 context_vk.GetDevice().updateDescriptorSets(descriptor_write_offset_,
556 write_workspace_.data(), 0u, {});
557
558 command_buffer_vk_.bindDescriptorSets(
559 vk::PipelineBindPoint::eGraphics, // bind point
560 pipeline_layout, // layout
561 0, // first set
562 1, // set count
563 &descriptor_set, // sets
564 0, // offset count
565 nullptr // offsets
566 );
567
568 if (pipeline_uses_input_attachments_) {
570 command_buffer_vk_, TextureVK::Cast(*color_image_vk_).GetImage());
571 }
572
573 if (has_index_buffer_) {
574 command_buffer_vk_.drawIndexed(element_count_, // index count
575 instance_count_, // instance count
576 0u, // first index
577 base_vertex_, // vertex offset
578 0u // first instance
579 );
580 } else {
581 command_buffer_vk_.draw(element_count_, // vertex count
582 instance_count_, // instance count
583 base_vertex_, // vertex offset
584 0u // first instance
585 );
586 }
587
588#ifdef IMPELLER_DEBUG
589 if (has_label_) {
590 command_buffer_->PopDebugGroup();
591 }
592#endif // IMPELLER_DEBUG
593 has_label_ = false;
594 has_index_buffer_ = false;
595 bound_image_offset_ = 0u;
596 bound_buffer_offset_ = 0u;
597 descriptor_write_offset_ = 0u;
598 instance_count_ = 1u;
599 base_vertex_ = 0u;
600 element_count_ = 0u;
601 pipeline_ = PipelineRef(nullptr);
602 pipeline_uses_input_attachments_ = false;
603 immutable_sampler_ = nullptr;
604 return fml::Status();
605}
606
607// The RenderPassVK binding methods only need the binding, set, and buffer type
608// information.
609bool RenderPassVK::BindResource(ShaderStage stage,
610 DescriptorType type,
611 const ShaderUniformSlot& slot,
612 const ShaderMetadata* metadata,
613 BufferView view) {
614 return BindResource(slot.binding, type, view);
615}
616
617bool RenderPassVK::BindDynamicResource(ShaderStage stage,
618 DescriptorType type,
619 const ShaderUniformSlot& slot,
620 std::unique_ptr<ShaderMetadata> metadata,
621 BufferView view) {
622 return BindResource(slot.binding, type, view);
623}
624
625bool RenderPassVK::BindResource(size_t binding,
626 DescriptorType type,
627 BufferView view) {
628 if (bound_buffer_offset_ >= kMaxBindings) {
629 return false;
630 }
631
632 auto buffer = DeviceBufferVK::Cast(*view.GetBuffer()).GetBuffer();
633 if (!buffer) {
634 return false;
635 }
636
637 std::shared_ptr<const DeviceBuffer> device_buffer = view.TakeBuffer();
638 if (device_buffer && !command_buffer_->Track(device_buffer)) {
639 return false;
640 }
641
642 uint32_t offset = view.GetRange().offset;
643
644 vk::DescriptorBufferInfo buffer_info;
645 buffer_info.buffer = buffer;
646 buffer_info.offset = offset;
647 buffer_info.range = view.GetRange().length;
648 buffer_workspace_[bound_buffer_offset_++] = buffer_info;
649
650 vk::WriteDescriptorSet write_set;
651 write_set.dstBinding = binding;
652 write_set.descriptorCount = 1u;
653 write_set.descriptorType = ToVKDescriptorType(type);
654 write_set.pBufferInfo = &buffer_workspace_[bound_buffer_offset_ - 1];
655
656 write_workspace_[descriptor_write_offset_++] = write_set;
657 return true;
658}
659
660bool RenderPassVK::BindDynamicResource(ShaderStage stage,
661 DescriptorType type,
662 const SampledImageSlot& slot,
663 std::unique_ptr<ShaderMetadata> metadata,
664 std::shared_ptr<const Texture> texture,
665 raw_ptr<const Sampler> sampler) {
666 return BindResource(stage, type, slot, nullptr, texture, sampler);
667}
668
669bool RenderPassVK::BindResource(ShaderStage stage,
670 DescriptorType type,
671 const SampledImageSlot& slot,
672 const ShaderMetadata* metadata,
673 std::shared_ptr<const Texture> texture,
674 raw_ptr<const Sampler> sampler) {
675 if (bound_buffer_offset_ >= kMaxBindings) {
676 return false;
677 }
678 if (!texture || !texture->IsValid() || !sampler) {
679 return false;
680 }
681 const TextureVK& texture_vk = TextureVK::Cast(*texture);
682 const SamplerVK& sampler_vk = SamplerVK::Cast(*sampler);
683
684 if (!command_buffer_->Track(texture)) {
685 return false;
686 }
687
688 if (!immutable_sampler_) {
689 immutable_sampler_ = texture_vk.GetImmutableSamplerVariant(sampler_vk);
690 }
691
692 vk::DescriptorImageInfo image_info;
693 image_info.imageLayout = vk::ImageLayout::eShaderReadOnlyOptimal;
694 image_info.sampler = sampler_vk.GetSampler();
695 image_info.imageView = texture_vk.GetImageView();
696 image_workspace_[bound_image_offset_++] = image_info;
697
698 vk::WriteDescriptorSet write_set;
699 write_set.dstBinding = slot.binding;
700 write_set.descriptorCount = 1u;
701 write_set.descriptorType = vk::DescriptorType::eCombinedImageSampler;
702 write_set.pImageInfo = &image_workspace_[bound_image_offset_ - 1];
703
704 write_workspace_[descriptor_write_offset_++] = write_set;
705 return true;
706}
707
708bool RenderPassVK::OnEncodeCommands(const Context& context) const {
709 command_buffer_->GetCommandBuffer().endRenderPass();
710 return true;
711}
712
713} // namespace impeller
static TextureVK & Cast(Texture &base)
const RenderTarget render_target_
bool IterateAllColorAttachments(const std::function< bool(size_t index, const ColorAttachment &attachment)> &iterator) const
const std::optional< DepthAttachment > & GetDepthAttachment() const
const std::optional< StencilAttachment > & GetStencilAttachment() const
bool IsSwapchainImage() const
const FramebufferAndRenderPass & GetCachedFrameData(SampleCount sample_count) const
vk::ImageLayout SetLayoutWithoutEncoding(vk::ImageLayout layout) const
bool SetLayout(const BarrierVK &barrier) const
vk::ImageLayout GetLayout() const
void SetCachedFrameData(const FramebufferAndRenderPass &data, SampleCount sample_count)
int32_t value
FlView * view
uint32_t * target
FlTexture * texture
DEF_SWITCHES_START aot vmservice shared library Name of the *so containing AOT compiled Dart assets for launching the service isolate vm snapshot The VM snapshot data that will be memory mapped as read only SnapshotAssetPath must be present isolate snapshot The isolate snapshot data that will be memory mapped as read only SnapshotAssetPath must be present cache dir Path to the cache directory This is different from the persistent_cache_path in embedder which is used for Skia shader cache icu native lib Path to the library file that exports the ICU data vm service The hostname IP address on which the Dart VM Service should be served If not defaults to or::depending on whether ipv6 is specified disable vm Disable the Dart VM Service The Dart VM Service is never available in release mode Bind to the IPv6 localhost address for the Dart VM Service Ignored if vm service host is set profile Make the profiler discard new samples once the profiler sample buffer is full When this flag is not the profiler sample buffer is used as a ring buffer
Definition switch_defs.h:98
static vk::Viewport ToVkViewport(const Viewport &viewport)
float Scalar
Definition scalar.h:19
constexpr vk::IndexType ToVKIndexType(IndexType index_type)
Definition formats_vk.h:357
raw_ptr< Pipeline< PipelineDescriptor > > PipelineRef
A raw ptr to a pipeline object.
Definition pipeline.h:89
constexpr vk::DescriptorType ToVKDescriptorType(DescriptorType type)
Definition formats_vk.h:294
constexpr size_t kMaxVertexBuffers
static constexpr size_t kMagicSubpassInputBinding
static vk::ClearDepthStencilValue VKClearValueFromDepthStencil(uint32_t stencil, Scalar depth)
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...
static size_t GetVKClearValues(const RenderTarget &target, std::array< vk::ClearValue, kMaxAttachments > &values)
static vk::ClearColorValue VKClearValueFromColor(Color color)
auto MakeSharedVK(vk::UniqueHandle< T, VULKAN_HPP_DEFAULT_DISPATCHER_TYPE > handle)
Definition ref_ptr.h:261
impeller::ShaderType type
std::shared_ptr< Texture > resolve_texture
Definition formats.h:662
Scalar blue
Definition color.h:138
Scalar alpha
Definition color.h:143
Scalar red
Definition color.h:128
Scalar green
Definition color.h:133
static constexpr TRect MakeSize(const TSize< U > &size)
Definition rect.h:150
DepthRange depth_range
Definition formats.h:408
#define VALIDATION_LOG
Definition validation.h:91