Flutter Engine
 
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
340 pipeline_uses_input_attachments_ =
341 pipeline_->GetDescriptor().GetVertexDescriptor()->UsesInputAttacments();
342
343 if (pipeline_uses_input_attachments_) {
344 if (bound_image_offset_ >= kMaxBindings) {
345 pipeline_ = PipelineRef(nullptr);
346 return;
347 }
348 vk::DescriptorImageInfo image_info;
349 image_info.imageLayout = vk::ImageLayout::eGeneral;
350 image_info.sampler = VK_NULL_HANDLE;
351 image_info.imageView = TextureVK::Cast(*color_image_vk_).GetImageView();
352 image_workspace_[bound_image_offset_++] = image_info;
353
354 vk::WriteDescriptorSet write_set;
355 write_set.dstBinding = kMagicSubpassInputBinding;
356 write_set.descriptorCount = 1u;
357 write_set.descriptorType = vk::DescriptorType::eInputAttachment;
358 write_set.pImageInfo = &image_workspace_[bound_image_offset_ - 1];
359
360 write_workspace_[descriptor_write_offset_++] = write_set;
361 }
362}
363
364// |RenderPass|
365void RenderPassVK::SetCommandLabel(std::string_view label) {
366#ifdef IMPELLER_DEBUG
367 command_buffer_->PushDebugGroup(label);
368 has_label_ = true;
369#endif // IMPELLER_DEBUG
370}
371
372// |RenderPass|
373void RenderPassVK::SetStencilReference(uint32_t value) {
374 if (current_stencil_ == value) {
375 return;
376 }
377 current_stencil_ = value;
378 command_buffer_vk_.setStencilReference(
379 vk::StencilFaceFlagBits::eVkStencilFrontAndBack, value);
380}
381
382// |RenderPass|
383void RenderPassVK::SetBaseVertex(uint64_t value) {
384 base_vertex_ = value;
385}
386
387// |RenderPass|
388void RenderPassVK::SetViewport(Viewport viewport) {
389 vk::Viewport viewport_vk = vk::Viewport()
390 .setWidth(viewport.rect.GetWidth())
391 .setHeight(-viewport.rect.GetHeight())
392 .setY(viewport.rect.GetHeight())
393 .setMinDepth(0.0f)
394 .setMaxDepth(1.0f);
395 command_buffer_vk_.setViewport(0, 1, &viewport_vk);
396}
397
398// |RenderPass|
399void RenderPassVK::SetScissor(IRect32 scissor) {
400 vk::Rect2D scissor_vk =
401 vk::Rect2D()
402 .setOffset(vk::Offset2D(scissor.GetX(), scissor.GetY()))
403 .setExtent(vk::Extent2D(scissor.GetWidth(), scissor.GetHeight()));
404 command_buffer_vk_.setScissor(0, 1, &scissor_vk);
405}
406
407// |RenderPass|
408void RenderPassVK::SetElementCount(size_t count) {
409 element_count_ = count;
410}
411
412// |RenderPass|
413void RenderPassVK::SetInstanceCount(size_t count) {
414 instance_count_ = count;
415}
416
417// |RenderPass|
418bool RenderPassVK::SetVertexBuffer(BufferView vertex_buffers[],
419 size_t vertex_buffer_count) {
420 if (!ValidateVertexBuffers(vertex_buffers, vertex_buffer_count)) {
421 return false;
422 }
423
424 vk::Buffer buffers[kMaxVertexBuffers];
425 vk::DeviceSize vertex_buffer_offsets[kMaxVertexBuffers];
426 for (size_t i = 0; i < vertex_buffer_count; i++) {
427 buffers[i] =
428 DeviceBufferVK::Cast(*vertex_buffers[i].GetBuffer()).GetBuffer();
429 vertex_buffer_offsets[i] = vertex_buffers[i].GetRange().offset;
430 std::shared_ptr<const DeviceBuffer> device_buffer =
431 vertex_buffers[i].TakeBuffer();
432 if (device_buffer) {
433 command_buffer_->Track(device_buffer);
434 }
435 }
436
437 // Bind the vertex buffers.
438 command_buffer_vk_.bindVertexBuffers(0u, vertex_buffer_count, buffers,
439 vertex_buffer_offsets);
440
441 return true;
442}
443
444// |RenderPass|
445bool RenderPassVK::SetIndexBuffer(BufferView index_buffer,
446 IndexType index_type) {
447 if (!ValidateIndexBuffer(index_buffer, index_type)) {
448 return false;
449 }
450
451 if (index_type != IndexType::kNone) {
452 has_index_buffer_ = true;
453
454 BufferView index_buffer_view = std::move(index_buffer);
455 if (!index_buffer_view) {
456 return false;
457 }
458
459 if (!index_buffer_view.GetBuffer()) {
460 VALIDATION_LOG << "Failed to acquire device buffer"
461 << " for index buffer view";
462 return false;
463 }
464
465 std::shared_ptr<const DeviceBuffer> index_buffer =
466 index_buffer_view.TakeBuffer();
467 if (index_buffer && !command_buffer_->Track(index_buffer)) {
468 return false;
469 }
470
471 vk::Buffer index_buffer_handle =
472 DeviceBufferVK::Cast(*index_buffer_view.GetBuffer()).GetBuffer();
473 command_buffer_vk_.bindIndexBuffer(index_buffer_handle,
474 index_buffer_view.GetRange().offset,
475 ToVKIndexType(index_type));
476 } else {
477 has_index_buffer_ = false;
478 }
479
480 return true;
481}
482
483// |RenderPass|
484fml::Status RenderPassVK::Draw() {
485 if (!pipeline_) {
487 "No valid pipeline is bound to the RenderPass.");
488 }
489
490 //----------------------------------------------------------------------------
491 /// If there are immutable samplers referenced in the render pass, the base
492 /// pipeline variant is no longer valid and needs to be re-constructed to
493 /// reference the samplers.
494 ///
495 /// This is an instance of JIT creation of PSOs that can cause jank. It is
496 /// unavoidable because it isn't possible to know all possible combinations of
497 /// target YUV conversions. Fortunately, this will only ever happen when
498 /// rendering to external textures. Like Android Hardware Buffers on Android.
499 ///
500 /// Even when JIT creation is unavoidable, pipelines will cache their variants
501 /// when able and all pipeline creation will happen via a base pipeline cache
502 /// anyway. So the jank can be mostly entirely ameliorated and it should only
503 /// ever happen when the first unknown YUV conversion is encountered.
504 ///
505 /// Jank can be completely eliminated by pre-populating known YUV conversion
506 /// pipelines.
507 if (immutable_sampler_) {
508 std::shared_ptr<Pipeline<PipelineDescriptor>> pipeline_variant =
509 PipelineVK::Cast(*pipeline_)
510 .CreateVariantForImmutableSamplers(immutable_sampler_);
511 if (!pipeline_variant) {
512 return fml::Status(
514 "Could not create pipeline variant with immutable sampler.");
515 }
516 pipeline_ = raw_ptr(pipeline_variant);
517 }
518
519 const auto& context_vk = ContextVK::Cast(*context_);
520 const auto& pipeline_vk = PipelineVK::Cast(*pipeline_);
521
522 auto descriptor_result = command_buffer_->AllocateDescriptorSets(
523 pipeline_vk.GetDescriptorSetLayout(), pipeline_vk.GetPipelineKey(),
524 context_vk);
525 if (!descriptor_result.ok()) {
527 "Could not allocate descriptor sets.");
528 }
529 const auto descriptor_set = descriptor_result.value();
530 const auto pipeline_layout = pipeline_vk.GetPipelineLayout();
531 command_buffer_vk_.bindPipeline(vk::PipelineBindPoint::eGraphics,
532 pipeline_vk.GetPipeline());
533
534 for (auto i = 0u; i < descriptor_write_offset_; i++) {
535 write_workspace_[i].dstSet = descriptor_set;
536 }
537
538 context_vk.GetDevice().updateDescriptorSets(descriptor_write_offset_,
539 write_workspace_.data(), 0u, {});
540
541 command_buffer_vk_.bindDescriptorSets(
542 vk::PipelineBindPoint::eGraphics, // bind point
543 pipeline_layout, // layout
544 0, // first set
545 1, // set count
546 &descriptor_set, // sets
547 0, // offset count
548 nullptr // offsets
549 );
550
551 if (pipeline_uses_input_attachments_) {
553 command_buffer_vk_, TextureVK::Cast(*color_image_vk_).GetImage());
554 }
555
556 if (has_index_buffer_) {
557 command_buffer_vk_.drawIndexed(element_count_, // index count
558 instance_count_, // instance count
559 0u, // first index
560 base_vertex_, // vertex offset
561 0u // first instance
562 );
563 } else {
564 command_buffer_vk_.draw(element_count_, // vertex count
565 instance_count_, // instance count
566 base_vertex_, // vertex offset
567 0u // first instance
568 );
569 }
570
571#ifdef IMPELLER_DEBUG
572 if (has_label_) {
573 command_buffer_->PopDebugGroup();
574 }
575#endif // IMPELLER_DEBUG
576 has_label_ = false;
577 has_index_buffer_ = false;
578 bound_image_offset_ = 0u;
579 bound_buffer_offset_ = 0u;
580 descriptor_write_offset_ = 0u;
581 instance_count_ = 1u;
582 base_vertex_ = 0u;
583 element_count_ = 0u;
584 pipeline_ = PipelineRef(nullptr);
585 pipeline_uses_input_attachments_ = false;
586 immutable_sampler_ = nullptr;
587 return fml::Status();
588}
589
590// The RenderPassVK binding methods only need the binding, set, and buffer type
591// information.
592bool RenderPassVK::BindResource(ShaderStage stage,
593 DescriptorType type,
594 const ShaderUniformSlot& slot,
595 const ShaderMetadata* metadata,
596 BufferView view) {
597 return BindResource(slot.binding, type, view);
598}
599
600bool RenderPassVK::BindDynamicResource(ShaderStage stage,
601 DescriptorType type,
602 const ShaderUniformSlot& slot,
603 std::unique_ptr<ShaderMetadata> metadata,
604 BufferView view) {
605 return BindResource(slot.binding, type, view);
606}
607
608bool RenderPassVK::BindResource(size_t binding,
609 DescriptorType type,
610 BufferView view) {
611 if (bound_buffer_offset_ >= kMaxBindings) {
612 return false;
613 }
614
615 auto buffer = DeviceBufferVK::Cast(*view.GetBuffer()).GetBuffer();
616 if (!buffer) {
617 return false;
618 }
619
620 std::shared_ptr<const DeviceBuffer> device_buffer = view.TakeBuffer();
621 if (device_buffer && !command_buffer_->Track(device_buffer)) {
622 return false;
623 }
624
625 uint32_t offset = view.GetRange().offset;
626
627 vk::DescriptorBufferInfo buffer_info;
628 buffer_info.buffer = buffer;
629 buffer_info.offset = offset;
630 buffer_info.range = view.GetRange().length;
631 buffer_workspace_[bound_buffer_offset_++] = buffer_info;
632
633 vk::WriteDescriptorSet write_set;
634 write_set.dstBinding = binding;
635 write_set.descriptorCount = 1u;
636 write_set.descriptorType = ToVKDescriptorType(type);
637 write_set.pBufferInfo = &buffer_workspace_[bound_buffer_offset_ - 1];
638
639 write_workspace_[descriptor_write_offset_++] = write_set;
640 return true;
641}
642
643bool RenderPassVK::BindDynamicResource(ShaderStage stage,
644 DescriptorType type,
645 const SampledImageSlot& slot,
646 std::unique_ptr<ShaderMetadata> metadata,
647 std::shared_ptr<const Texture> texture,
648 raw_ptr<const Sampler> sampler) {
649 return BindResource(stage, type, slot, nullptr, texture, sampler);
650}
651
652bool RenderPassVK::BindResource(ShaderStage stage,
653 DescriptorType type,
654 const SampledImageSlot& slot,
655 const ShaderMetadata* metadata,
656 std::shared_ptr<const Texture> texture,
657 raw_ptr<const Sampler> sampler) {
658 if (bound_buffer_offset_ >= kMaxBindings) {
659 return false;
660 }
661 if (!texture || !texture->IsValid() || !sampler) {
662 return false;
663 }
664 const TextureVK& texture_vk = TextureVK::Cast(*texture);
665 const SamplerVK& sampler_vk = SamplerVK::Cast(*sampler);
666
667 if (!command_buffer_->Track(texture)) {
668 return false;
669 }
670
671 if (!immutable_sampler_) {
672 immutable_sampler_ = texture_vk.GetImmutableSamplerVariant(sampler_vk);
673 }
674
675 vk::DescriptorImageInfo image_info;
676 image_info.imageLayout = vk::ImageLayout::eShaderReadOnlyOptimal;
677 image_info.sampler = sampler_vk.GetSampler();
678 image_info.imageView = texture_vk.GetImageView();
679 image_workspace_[bound_image_offset_++] = image_info;
680
681 vk::WriteDescriptorSet write_set;
682 write_set.dstBinding = slot.binding;
683 write_set.descriptorCount = 1u;
684 write_set.descriptorType = vk::DescriptorType::eCombinedImageSampler;
685 write_set.pImageInfo = &image_workspace_[bound_image_offset_ - 1];
686
687 write_workspace_[descriptor_write_offset_++] = write_set;
688 return true;
689}
690
691bool RenderPassVK::OnEncodeCommands(const Context& context) const {
692 command_buffer_->GetCommandBuffer().endRenderPass();
693 return true;
694}
695
696} // 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:355
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:292
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:658
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