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