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