| 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/barrier_vk.h"
18 #include "impeller/renderer/backend/vulkan/command_buffer_vk.h"
19 #include "impeller/renderer/backend/vulkan/context_vk.h"
20 #include "impeller/renderer/backend/vulkan/device_buffer_vk.h"
21 #include "impeller/renderer/backend/vulkan/formats_vk.h"
22 #include "impeller/renderer/backend/vulkan/pipeline_vk.h"
23 #include "impeller/renderer/backend/vulkan/render_pass_builder_vk.h"
24 #include "impeller/renderer/backend/vulkan/sampler_vk.h"
25 #include "impeller/renderer/backend/vulkan/shared_object_vk.h"
26 #include "impeller/renderer/backend/vulkan/texture_vk.h"
27
28 namespace 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
35 static constexpr size_t kMagicSubpassInputBinding = 64u;
36
37 static 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
44 static 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 static 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
79 SharedHandleVK<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
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 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_)
232 .SetLayoutWithoutEncoding(
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
266 RenderPassVK::~RenderPassVK() = default;
267
268 bool RenderPassVK::IsValid() const {
269 return is_valid_;
270 }
271
272 void 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
278 SharedHandleVK<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|
334 void 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|
365 void 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|
373 void 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|
383 void RenderPassVK::SetBaseVertex(uint64_t value) {
384 base_vertex_ = value;
385 }
386
387 // |RenderPass|
388 void 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|
399 void 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|
408 void RenderPassVK::SetElementCount(size_t count) {
409 element_count_ = count;
410 }
411
412 // |RenderPass|
413 void RenderPassVK::SetInstanceCount(size_t count) {
414 instance_count_ = count;
415 }
416
417 // |RenderPass|
418 bool 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|
445 bool 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|
484 fml::Status RenderPassVK::Draw() {
485 if (!pipeline_) {
486 return fml::Status(fml::StatusCode::kCancelled,
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(
513 fml::StatusCode::kAborted,
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()) {
526 return fml::Status(fml::StatusCode::kAborted,
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_) {
552 InsertBarrierForInputAttachmentRead(
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.
592 bool 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
600 bool 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
608 bool 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
643 bool 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
652 bool 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
691 bool RenderPassVK::OnEncodeCommands(const Context& context) const {
692 command_buffer_->GetCommandBuffer().endRenderPass();
693 return true;
694 }
695
696 } // namespace impeller
barrier_vk.h
type
GLenum type
Definition: blit_command_gles.cc:153
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:214
impeller::TextureVK::GetCachedFrameData
const FramebufferAndRenderPass & GetCachedFrameData(SampleCount sample_count) const
Definition: texture_vk.cc:205
impeller::TextureVK::SetLayoutWithoutEncoding
vk::ImageLayout SetLayoutWithoutEncoding(vk::ImageLayout layout) const
Definition: texture_vk.cc:186
impeller::TextureVK::SetLayout
bool SetLayout(const BarrierVK &barrier) const
Definition: texture_vk.cc:182
impeller::TextureVK::GetLayout
vk::ImageLayout GetLayout() const
Definition: texture_vk.cc:192
impeller::TextureVK::SetCachedFrameData
void SetCachedFrameData(const FramebufferAndRenderPass &data, SampleCount sample_count)
Definition: texture_vk.cc:200
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::IRect32
TRect< int32_t > IRect32
Definition: rect.h:789
impeller::Scalar
float Scalar
Definition: scalar.h:19
impeller::IndexType
IndexType
Definition: formats.h:343
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::kMagicSubpassInputBinding
static constexpr size_t kMagicSubpassInputBinding
Definition: render_pass_vk.cc:35
impeller::VKClearValueFromDepthStencil
static vk::ClearDepthStencilValue VKClearValueFromDepthStencil(uint32_t stencil, Scalar depth)
Definition: render_pass_vk.cc:44
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:52
impeller::VKClearValueFromColor
static vk::ClearColorValue VKClearValueFromColor(Color color)
Definition: render_pass_vk.cc:37
impeller::MakeSharedVK
auto MakeSharedVK(vk::UniqueHandle< T, VULKAN_HPP_DEFAULT_DISPATCHER_TYPE > handle)
Definition: shared_object_vk.h:44
impeller::SampleCount
SampleCount
Definition: formats.h:295
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
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