| Flutter Impeller |

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