| 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 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|
366 void 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|
374 void 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|
384 void RenderPassVK::SetBaseVertex(uint64_t value) {
385 base_vertex_ = value;
386 }
387
388 // |RenderPass|
389 void 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|
400 void 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|
409 void RenderPassVK::SetElementCount(size_t count) {
410 element_count_ = count;
411 }
412
413 // |RenderPass|
414 void RenderPassVK::SetInstanceCount(size_t count) {
415 instance_count_ = count;
416 }
417
418 // |RenderPass|
419 bool 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|
446 bool 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|
485 fml::Status RenderPassVK::Draw() {
486 if (!pipeline_) {
487 return fml::Status(fml::StatusCode::kCancelled,
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(
514 fml::StatusCode::kAborted,
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()) {
527 return fml::Status(fml::StatusCode::kAborted,
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_) {
553 InsertBarrierForInputAttachmentRead(
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.
593 bool 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
601 bool 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
609 bool 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
644 bool 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
653 bool 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
692 bool RenderPassVK::OnEncodeCommands(const Context& context) const {
693 command_buffer_->GetCommandBuffer().endRenderPass();
694 return true;
695 }
696
697 } // 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:346
impeller::ToVKIndexType
constexpr vk::IndexType ToVKIndexType(IndexType index_type)
Definition: formats_vk.h:357
impeller::PipelineRef
raw_ptr< Pipeline< PipelineDescriptor > > PipelineRef
A raw ptr to a pipeline object.
Definition: pipeline.h:89
impeller::ToVKDescriptorType
constexpr vk::DescriptorType ToVKDescriptorType(DescriptorType type)
Definition: formats_vk.h:294
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:298
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:662
impeller::ColorAttachment
Definition: formats.h:669
impeller::ColorAttachment::clear_color
Color clear_color
Definition: formats.h:670
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