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 // The framebuffer references attachment views bound to a specific
169 // subresource, so the cache is keyed on color0's (mip_level, slice) as
170 // well as sample count. Caller-side invariants on the rest of the
171 // attachment set are the same as before.
172 const uint32_t cache_mip_level = color0.mip_level;
173 const uint32_t cache_slice = color0.slice;
174 TextureVK& frame_data_texture = TextureVK::Cast(
175 resolve_image_vk_ ? *resolve_image_vk_ : *color_image_vk_);
176 is_swapchain = frame_data_texture.IsSwapchainImage();
177 frame_data = frame_data_texture.GetCachedFrameData(
178 sample_count, cache_mip_level, cache_slice);
179
180 const auto& target_size = render_target_.GetRenderTargetSize();
181
182 render_pass_ = CreateVKRenderPass(vk_context, frame_data.render_pass,
183 command_buffer_, is_swapchain);
184 if (!render_pass_) {
185 VALIDATION_LOG << "Could not create renderpass.";
186 is_valid_ = false;
187 return;
188 }
189
190 auto framebuffer = (frame_data.framebuffer == nullptr)
191 ? CreateVKFramebuffer(vk_context, *render_pass_)
192 : frame_data.framebuffer;
193 if (!framebuffer) {
194 VALIDATION_LOG << "Could not create framebuffer.";
195 is_valid_ = false;
196 return;
197 }
198
199 if (!command_buffer_->Track(framebuffer) ||
200 !command_buffer_->Track(render_pass_)) {
201 is_valid_ = false;
202 return;
203 }
204
205 frame_data.framebuffer = framebuffer;
206 frame_data.render_pass = render_pass_;
207
208 frame_data_texture.SetCachedFrameData(frame_data, sample_count,
209 cache_mip_level, cache_slice);
210
211 // If the resolve image exists and has mipmaps, transition mip levels besides
212 // the base to shader read only in preparation for mipmap generation.
213 if (resolve_image_vk_ &&
214 resolve_image_vk_->GetTextureDescriptor().mip_count > 1) {
215 if (TextureVK::Cast(*resolve_image_vk_).GetLayout() ==
216 vk::ImageLayout::eUndefined) {
217 BarrierVK barrier;
218 barrier.new_layout = vk::ImageLayout::eShaderReadOnlyOptimal;
219 barrier.cmd_buffer = command_buffer_->GetCommandBuffer();
220 barrier.src_stage = vk::PipelineStageFlagBits::eBottomOfPipe;
221 barrier.src_access = {};
222 barrier.dst_stage = vk::PipelineStageFlagBits::eFragmentShader;
223 barrier.dst_access = vk::AccessFlagBits::eShaderRead;
224 barrier.base_mip_level = 1;
225 TextureVK::Cast(*resolve_image_vk_).SetLayout(barrier);
226 }
227 }
228
229 std::array<vk::ClearValue, kMaxAttachments> clears;
230 size_t clear_count = GetVKClearValues(render_target_, clears);
231
232 vk::RenderPassBeginInfo pass_info;
233 pass_info.renderPass = *render_pass_;
234 pass_info.framebuffer = *framebuffer;
235 pass_info.renderArea.extent.width = static_cast<uint32_t>(target_size.width);
236 pass_info.renderArea.extent.height =
237 static_cast<uint32_t>(target_size.height);
238 pass_info.setPClearValues(clears.data());
239 pass_info.setClearValueCount(clear_count);
240
241 command_buffer_vk_.beginRenderPass(pass_info, vk::SubpassContents::eInline);
242
243 if (resolve_image_vk_) {
244 TextureVK::Cast(*resolve_image_vk_)
246 is_swapchain ? vk::ImageLayout::eGeneral
247 : vk::ImageLayout::eShaderReadOnlyOptimal);
248 }
249 if (color_image_vk_) {
250 // Mirror the Vulkan render pass's `finalLayout` for the color attachment
251 // (see ComputeFinalLayout in render_pass_builder_vk.cc): swapchain and
252 // MSAA targets stay in eGeneral, but a non-swapchain, single-sampled
253 // color attachment transitions to eShaderReadOnlyOptimal on
254 // endRenderPass. Tracking it as eGeneral here desyncs the bookkeeping
255 // and produces an incorrect oldLayout on the next barrier (caught by
256 // Vulkan validation as VUID-vkCmdDraw-None-09600).
257 TextureVK::Cast(*color_image_vk_)
259 (is_swapchain || sample_count != SampleCount::kCount1)
260 ? vk::ImageLayout::eGeneral
261 : vk::ImageLayout::eShaderReadOnlyOptimal);
262 }
263
264 // Set the initial viewport.
265 const auto vp = Viewport{.rect = Rect::MakeSize(target_size)};
266 vk::Viewport viewport = ToVkViewport(vp);
267 command_buffer_vk_.setViewport(0, 1, &viewport);
268
269 // Set the initial scissor.
270 const auto sc = IRect32::MakeSize(target_size);
271 vk::Rect2D scissor =
272 vk::Rect2D()
273 .setOffset(vk::Offset2D(sc.GetX(), sc.GetY()))
274 .setExtent(vk::Extent2D(sc.GetWidth(), sc.GetHeight()));
275 command_buffer_vk_.setScissor(0, 1, &scissor);
276
277 // Set the initial stencil reference.
278 command_buffer_vk_.setStencilReference(vk::StencilFaceFlagBits::eFrontAndBack,
279 0u);
280
281 is_valid_ = true;
282}
283
284RenderPassVK::~RenderPassVK() = default;
285
286bool RenderPassVK::IsValid() const {
287 return is_valid_;
288}
289
290void RenderPassVK::OnSetLabel(std::string_view label) {
291#ifdef IMPELLER_DEBUG
292 ContextVK::Cast(*context_).SetDebugName(render_pass_->Get(), label.data());
293#endif // IMPELLER_DEBUG
294}
295
296SharedHandleVK<vk::Framebuffer> RenderPassVK::CreateVKFramebuffer(
297 const ContextVK& context,
298 const vk::RenderPass& pass) const {
299 vk::FramebufferCreateInfo fb_info;
300
301 fb_info.renderPass = pass;
302
303 const auto target_size = render_target_.GetRenderTargetSize();
304 fb_info.width = target_size.width;
305 fb_info.height = target_size.height;
306 fb_info.layers = 1u;
307
308 std::array<vk::ImageView, kMaxAttachments> attachments;
309 size_t count = 0;
310
311 // This bit must be consistent to ensure compatibility with the pass created
312 // earlier. Follow this order: Color attachments, then depth-stencil, then
313 // stencil.
314 render_target_.IterateAllColorAttachments(
315 [&attachments, &count](size_t index,
316 const ColorAttachment& attachment) -> bool {
317 // The bind point doesn't matter here since that information is present
318 // in the render pass.
319 attachments[count++] =
320 TextureVK::Cast(*attachment.texture)
321 .GetRenderTargetView(attachment.mip_level, attachment.slice);
322 if (attachment.resolve_texture) {
323 // The resolve texture resolves into its own base level/layer.
324 attachments[count++] = TextureVK::Cast(*attachment.resolve_texture)
325 .GetRenderTargetView();
326 }
327 return true;
328 });
329
330 if (auto depth = render_target_.GetDepthAttachment(); depth.has_value()) {
331 attachments[count++] =
332 TextureVK::Cast(*depth->texture)
333 .GetRenderTargetView(depth->mip_level, depth->slice);
334 } else if (auto stencil = render_target_.GetStencilAttachment();
335 stencil.has_value()) {
336 attachments[count++] =
337 TextureVK::Cast(*stencil->texture)
338 .GetRenderTargetView(stencil->mip_level, stencil->slice);
339 }
340
341 fb_info.setPAttachments(attachments.data());
342 fb_info.setAttachmentCount(count);
343
344 auto [result, framebuffer] =
345 context.GetDevice().createFramebufferUnique(fb_info);
346
347 if (result != vk::Result::eSuccess) {
348 VALIDATION_LOG << "Could not create framebuffer: " << vk::to_string(result);
349 return {};
350 }
351
352 return MakeSharedVK(std::move(framebuffer));
353}
354
355// |RenderPass|
356void RenderPassVK::SetPipeline(PipelineRef pipeline) {
357 pipeline_ = pipeline;
358 if (!pipeline_) {
359 return;
360 }
361 context_->GetPipelineLibrary()->LogPipelineUsage(pipeline->GetDescriptor());
362
363 pipeline_uses_input_attachments_ =
364 pipeline_->GetDescriptor().GetVertexDescriptor()->UsesInputAttachments();
365
366 if (pipeline_uses_input_attachments_) {
367 if (bound_image_offset_ >= kMaxBindings) {
368 pipeline_ = PipelineRef(nullptr);
369 return;
370 }
371 vk::DescriptorImageInfo image_info;
372 image_info.imageLayout = vk::ImageLayout::eGeneral;
373 image_info.sampler = VK_NULL_HANDLE;
374 image_info.imageView = TextureVK::Cast(*color_image_vk_).GetImageView();
375 image_workspace_[bound_image_offset_++] = image_info;
376
377 vk::WriteDescriptorSet write_set;
378 write_set.dstBinding = kMagicSubpassInputBinding;
379 write_set.descriptorCount = 1u;
380 write_set.descriptorType = vk::DescriptorType::eInputAttachment;
381 write_set.pImageInfo = &image_workspace_[bound_image_offset_ - 1];
382
383 write_workspace_[descriptor_write_offset_++] = write_set;
384 }
385}
386
387// |RenderPass|
388void RenderPassVK::SetCommandLabel(std::string_view label) {
389#ifdef IMPELLER_DEBUG
390 command_buffer_->PushDebugGroup(label);
391 has_label_ = true;
392#endif // IMPELLER_DEBUG
393}
394
395// |RenderPass|
396void RenderPassVK::SetStencilReference(uint32_t value) {
397 if (current_stencil_ == value) {
398 return;
399 }
400 current_stencil_ = value;
401 command_buffer_vk_.setStencilReference(vk::StencilFaceFlagBits::eFrontAndBack,
402 value);
403}
404
405// |RenderPass|
406void RenderPassVK::SetBaseVertex(uint64_t value) {
407 base_vertex_ = value;
408}
409
410// |RenderPass|
411void RenderPassVK::SetViewport(Viewport viewport) {
412 vk::Viewport viewport_vk = ToVkViewport(viewport);
413 command_buffer_vk_.setViewport(0, 1, &viewport_vk);
414}
415
416// |RenderPass|
417void RenderPassVK::SetScissor(IRect32 scissor) {
418 vk::Rect2D scissor_vk =
419 vk::Rect2D()
420 .setOffset(vk::Offset2D(scissor.GetX(), scissor.GetY()))
421 .setExtent(vk::Extent2D(scissor.GetWidth(), scissor.GetHeight()));
422 command_buffer_vk_.setScissor(0, 1, &scissor_vk);
423}
424
425// |RenderPass|
426void RenderPassVK::SetElementCount(size_t count) {
427 element_count_ = count;
428}
429
430// |RenderPass|
431void RenderPassVK::SetInstanceCount(size_t count) {
432 instance_count_ = count;
433}
434
435// |RenderPass|
436bool RenderPassVK::SetVertexBuffer(BufferView vertex_buffers[],
437 size_t vertex_buffer_count) {
438 if (!ValidateVertexBuffers(vertex_buffers, vertex_buffer_count)) {
439 return false;
440 }
441
442 vk::Buffer buffers[kMaxVertexBuffers];
443 vk::DeviceSize vertex_buffer_offsets[kMaxVertexBuffers];
444 for (size_t i = 0; i < vertex_buffer_count; i++) {
445 buffers[i] =
446 DeviceBufferVK::Cast(*vertex_buffers[i].GetBuffer()).GetBuffer();
447 vertex_buffer_offsets[i] = vertex_buffers[i].GetRange().offset;
448 std::shared_ptr<const DeviceBuffer> device_buffer =
449 vertex_buffers[i].TakeBuffer();
450 if (device_buffer) {
451 command_buffer_->Track(device_buffer);
452 }
453 }
454
455 // Bind the vertex buffers.
456 command_buffer_vk_.bindVertexBuffers(0u, vertex_buffer_count, buffers,
457 vertex_buffer_offsets);
458
459 return true;
460}
461
462// |RenderPass|
463bool RenderPassVK::SetIndexBuffer(BufferView index_buffer,
464 IndexType index_type) {
465 if (!ValidateIndexBuffer(index_buffer, index_type)) {
466 return false;
467 }
468
469 if (index_type != IndexType::kNone) {
470 has_index_buffer_ = true;
471
472 BufferView index_buffer_view = std::move(index_buffer);
473 if (!index_buffer_view) {
474 return false;
475 }
476
477 if (!index_buffer_view.GetBuffer()) {
478 VALIDATION_LOG << "Failed to acquire device buffer"
479 << " for index buffer view";
480 return false;
481 }
482
483 std::shared_ptr<const DeviceBuffer> index_buffer =
484 index_buffer_view.TakeBuffer();
485 if (index_buffer && !command_buffer_->Track(index_buffer)) {
486 return false;
487 }
488
489 vk::Buffer index_buffer_handle =
490 DeviceBufferVK::Cast(*index_buffer_view.GetBuffer()).GetBuffer();
491 command_buffer_vk_.bindIndexBuffer(index_buffer_handle,
492 index_buffer_view.GetRange().offset,
493 ToVKIndexType(index_type));
494 } else {
495 has_index_buffer_ = false;
496 }
497
498 return true;
499}
500
501// |RenderPass|
502fml::Status RenderPassVK::Draw() {
503 if (!pipeline_) {
505 "No valid pipeline is bound to the RenderPass.");
506 }
507
508 //----------------------------------------------------------------------------
509 /// If there are immutable samplers referenced in the render pass, the base
510 /// pipeline variant is no longer valid and needs to be re-constructed to
511 /// reference the samplers.
512 ///
513 /// This is an instance of JIT creation of PSOs that can cause jank. It is
514 /// unavoidable because it isn't possible to know all possible combinations of
515 /// target YUV conversions. Fortunately, this will only ever happen when
516 /// rendering to external textures. Like Android Hardware Buffers on Android.
517 ///
518 /// Even when JIT creation is unavoidable, pipelines will cache their variants
519 /// when able and all pipeline creation will happen via a base pipeline cache
520 /// anyway. So the jank can be mostly entirely ameliorated and it should only
521 /// ever happen when the first unknown YUV conversion is encountered.
522 ///
523 /// Jank can be completely eliminated by pre-populating known YUV conversion
524 /// pipelines.
525 if (immutable_sampler_) {
526 std::shared_ptr<Pipeline<PipelineDescriptor>> pipeline_variant =
527 PipelineVK::Cast(*pipeline_)
528 .CreateVariantForImmutableSamplers(immutable_sampler_);
529 if (!pipeline_variant) {
530 return fml::Status(
532 "Could not create pipeline variant with immutable sampler.");
533 }
534 pipeline_ = raw_ptr(pipeline_variant);
535 }
536
537 const auto& context_vk = ContextVK::Cast(*context_);
538 const auto& pipeline_vk = PipelineVK::Cast(*pipeline_);
539
540 auto descriptor_result = command_buffer_->AllocateDescriptorSets(
541 pipeline_vk.GetDescriptorSetLayout(), pipeline_vk.GetPipelineKey(),
542 context_vk);
543 if (!descriptor_result.ok()) {
545 "Could not allocate descriptor sets.");
546 }
547 const auto descriptor_set = descriptor_result.value();
548 const auto pipeline_layout = pipeline_vk.GetPipelineLayout();
549 command_buffer_vk_.bindPipeline(vk::PipelineBindPoint::eGraphics,
550 pipeline_vk.GetPipeline());
551
552 for (auto i = 0u; i < descriptor_write_offset_; i++) {
553 write_workspace_[i].dstSet = descriptor_set;
554 }
555
556 context_vk.GetDevice().updateDescriptorSets(descriptor_write_offset_,
557 write_workspace_.data(), 0u, {});
558
559 command_buffer_vk_.bindDescriptorSets(
560 vk::PipelineBindPoint::eGraphics, // bind point
561 pipeline_layout, // layout
562 0, // first set
563 1, // set count
564 &descriptor_set, // sets
565 0, // offset count
566 nullptr // offsets
567 );
568
569 if (pipeline_uses_input_attachments_) {
571 command_buffer_vk_, TextureVK::Cast(*color_image_vk_).GetImage());
572 }
573
574 if (has_index_buffer_) {
575 command_buffer_vk_.drawIndexed(element_count_, // index count
576 instance_count_, // instance count
577 0u, // first index
578 base_vertex_, // vertex offset
579 0u // first instance
580 );
581 } else {
582 command_buffer_vk_.draw(element_count_, // vertex count
583 instance_count_, // instance count
584 base_vertex_, // vertex offset
585 0u // first instance
586 );
587 }
588
589#ifdef IMPELLER_DEBUG
590 if (has_label_) {
591 command_buffer_->PopDebugGroup();
592 }
593#endif // IMPELLER_DEBUG
594 has_label_ = false;
595 has_index_buffer_ = false;
596 bound_image_offset_ = 0u;
597 bound_buffer_offset_ = 0u;
598 descriptor_write_offset_ = 0u;
599 instance_count_ = 1u;
600 base_vertex_ = 0u;
601 element_count_ = 0u;
602 pipeline_ = PipelineRef(nullptr);
603 pipeline_uses_input_attachments_ = false;
604 immutable_sampler_ = nullptr;
605 return fml::Status();
606}
607
608// The RenderPassVK binding methods only need the binding, set, and buffer type
609// information.
610bool RenderPassVK::BindResource(ShaderStage stage,
611 DescriptorType type,
612 const ShaderUniformSlot& slot,
613 const ShaderMetadata* metadata,
614 BufferView view) {
615 return BindResource(slot.binding, type, view);
616}
617
618bool RenderPassVK::BindDynamicResource(ShaderStage stage,
619 DescriptorType type,
620 const ShaderUniformSlot& slot,
621 std::unique_ptr<ShaderMetadata> metadata,
622 BufferView view) {
623 return BindResource(slot.binding, type, view);
624}
625
626bool RenderPassVK::BindResource(size_t binding,
627 DescriptorType type,
628 BufferView view) {
629 if (bound_buffer_offset_ >= kMaxBindings) {
630 return false;
631 }
632
633 auto buffer = DeviceBufferVK::Cast(*view.GetBuffer()).GetBuffer();
634 if (!buffer) {
635 return false;
636 }
637
638 std::shared_ptr<const DeviceBuffer> device_buffer = view.TakeBuffer();
639 if (device_buffer && !command_buffer_->Track(device_buffer)) {
640 return false;
641 }
642
643 uint32_t offset = view.GetRange().offset;
644
645 vk::DescriptorBufferInfo buffer_info;
646 buffer_info.buffer = buffer;
647 buffer_info.offset = offset;
648 buffer_info.range = view.GetRange().length;
649 buffer_workspace_[bound_buffer_offset_++] = buffer_info;
650
651 vk::WriteDescriptorSet write_set;
652 write_set.dstBinding = binding;
653 write_set.descriptorCount = 1u;
654 write_set.descriptorType = ToVKDescriptorType(type);
655 write_set.pBufferInfo = &buffer_workspace_[bound_buffer_offset_ - 1];
656
657 write_workspace_[descriptor_write_offset_++] = write_set;
658 return true;
659}
660
661bool RenderPassVK::BindDynamicResource(ShaderStage stage,
662 DescriptorType type,
663 const SampledImageSlot& slot,
664 std::unique_ptr<ShaderMetadata> metadata,
665 std::shared_ptr<const Texture> texture,
666 raw_ptr<const Sampler> sampler) {
667 return BindResource(stage, type, slot, nullptr, texture, sampler);
668}
669
670bool RenderPassVK::BindResource(ShaderStage stage,
671 DescriptorType type,
672 const SampledImageSlot& slot,
673 const ShaderMetadata* metadata,
674 std::shared_ptr<const Texture> texture,
675 raw_ptr<const Sampler> sampler) {
676 if (bound_buffer_offset_ >= kMaxBindings) {
677 return false;
678 }
679 if (!texture || !texture->IsValid() || !sampler) {
680 return false;
681 }
682 const TextureVK& texture_vk = TextureVK::Cast(*texture);
683 const SamplerVK& sampler_vk = SamplerVK::Cast(*sampler);
684
685 if (!command_buffer_->Track(texture)) {
686 return false;
687 }
688
689 if (!immutable_sampler_) {
690 immutable_sampler_ = texture_vk.GetImmutableSamplerVariant(sampler_vk);
691 }
692
693 vk::DescriptorImageInfo image_info;
694 image_info.imageLayout = vk::ImageLayout::eShaderReadOnlyOptimal;
695 image_info.sampler = sampler_vk.GetSampler();
696 image_info.imageView = texture_vk.GetImageView();
697 image_workspace_[bound_image_offset_++] = image_info;
698
699 vk::WriteDescriptorSet write_set;
700 write_set.dstBinding = slot.binding;
701 write_set.descriptorCount = 1u;
702 write_set.descriptorType = vk::DescriptorType::eCombinedImageSampler;
703 write_set.pImageInfo = &image_workspace_[bound_image_offset_ - 1];
704
705 write_workspace_[descriptor_write_offset_++] = write_set;
706 return true;
707}
708
709bool RenderPassVK::OnEncodeCommands(const Context& context) const {
710 command_buffer_->GetCommandBuffer().endRenderPass();
711 return true;
712}
713
714} // 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
vk::ImageLayout SetLayoutWithoutEncoding(vk::ImageLayout layout) const
bool SetLayout(const BarrierVK &barrier) const
vk::ImageLayout GetLayout() const
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:391
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:328
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
std::shared_ptr< ContextGLES > context
std::shared_ptr< PipelineGLES > pipeline
std::shared_ptr< CommandBuffer > command_buffer
impeller::ShaderType type
std::shared_ptr< Texture > resolve_texture
Definition formats.h:910
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:582
#define VALIDATION_LOG
Definition validation.h:91