11 #include "flutter/fml/trace_event.h"
25 #include "vulkan/vulkan_enums.hpp"
26 #include "vulkan/vulkan_handles.hpp"
27 #include "vulkan/vulkan_to_string.hpp"
33 const std::shared_ptr<Texture>
Attachment::*texture_ptr,
34 bool supports_framebuffer_fetch) {
35 const auto& texture = attachment.*texture_ptr;
40 const auto& desc = texture->GetTextureDescriptor();
41 auto current_layout = texture_vk.GetLayout();
46 if (current_layout == vk::ImageLayout::eUndefined) {
57 if (current_layout != vk::ImageLayout::ePresentSrcKHR &&
58 current_layout != vk::ImageLayout::eUndefined) {
60 current_layout = vk::ImageLayout::eGeneral;
68 supports_framebuffer_fetch
74 const vk::AttachmentDescription& attachment_desc,
75 const std::shared_ptr<CommandBufferVK>& command_buffer,
76 const std::shared_ptr<Texture>
Attachment::*texture_ptr) {
77 const auto& texture = attachment.*texture_ptr;
83 if (attachment_desc.initialLayout == vk::ImageLayout::eGeneral) {
85 barrier.
new_layout = vk::ImageLayout::eGeneral;
86 barrier.
cmd_buffer = command_buffer->GetEncoder()->GetCommandBuffer();
87 barrier.
src_access = vk::AccessFlagBits::eShaderRead;
88 barrier.
src_stage = vk::PipelineStageFlagBits::eFragmentShader;
89 barrier.
dst_access = vk::AccessFlagBits::eColorAttachmentWrite |
90 vk::AccessFlagBits::eTransferWrite;
91 barrier.
dst_stage = vk::PipelineStageFlagBits::eColorAttachmentOutput |
92 vk::PipelineStageFlagBits::eTransfer;
94 texture_vk.SetLayout(barrier);
99 texture_vk.SetLayoutWithoutEncoding(attachment_desc.finalLayout);
102 SharedHandleVK<vk::RenderPass> RenderPassVK::CreateVKRenderPass(
103 const ContextVK& context,
104 const std::shared_ptr<CommandBufferVK>& command_buffer,
105 bool supports_framebuffer_fetch)
const {
106 std::vector<vk::AttachmentDescription> attachments;
108 std::vector<vk::AttachmentReference> color_refs;
109 std::vector<vk::AttachmentReference> resolve_refs;
126 color_refs[bind_point] = vk::AttachmentReference{
127 static_cast<uint32_t
>(attachments.size()),
128 supports_framebuffer_fetch ? vk::ImageLayout::eGeneral
129 : vk::ImageLayout::eColorAttachmentOptimal};
134 if (color.resolve_texture) {
135 resolve_refs[bind_point] = vk::AttachmentReference{
136 static_cast<uint32_t
>(attachments.size()),
137 supports_framebuffer_fetch
138 ? vk::ImageLayout::eGeneral
139 : vk::ImageLayout::eColorAttachmentOptimal};
148 depth_stencil_ref = vk::AttachmentReference{
149 static_cast<uint32_t
>(attachments.size()),
150 vk::ImageLayout::eDepthStencilAttachmentOptimal};
158 stencil.has_value()) {
159 depth_stencil_ref = vk::AttachmentReference{
160 static_cast<uint32_t
>(attachments.size()),
161 vk::ImageLayout::eDepthStencilAttachmentOptimal};
168 vk::SubpassDescription subpass_desc;
169 subpass_desc.pipelineBindPoint = vk::PipelineBindPoint::eGraphics;
170 subpass_desc.setColorAttachments(color_refs);
171 subpass_desc.setResolveAttachments(resolve_refs);
172 subpass_desc.setPDepthStencilAttachment(&depth_stencil_ref);
174 std::vector<vk::SubpassDependency> subpass_dependencies;
175 std::vector<vk::AttachmentReference> subpass_color_ref;
176 subpass_color_ref.push_back(vk::AttachmentReference{
177 static_cast<uint32_t
>(0), vk::ImageLayout::eColorAttachmentOptimal});
178 if (supports_framebuffer_fetch) {
179 subpass_desc.setFlags(vk::SubpassDescriptionFlagBits::
180 eRasterizationOrderAttachmentColorAccessARM);
181 subpass_desc.setInputAttachments(subpass_color_ref);
184 vk::RenderPassCreateInfo render_pass_desc;
185 render_pass_desc.setAttachments(attachments);
186 render_pass_desc.setPSubpasses(&subpass_desc);
187 render_pass_desc.setSubpassCount(1u);
189 auto [result, pass] =
190 context.GetDevice().createRenderPassUnique(render_pass_desc);
191 if (result != vk::Result::eSuccess) {
192 VALIDATION_LOG <<
"Failed to create render pass: " << vk::to_string(result);
195 context.SetDebugName(pass.get(), debug_label_.c_str());
199 RenderPassVK::RenderPassVK(
const std::shared_ptr<const Context>& context,
200 const RenderTarget& target,
201 std::weak_ptr<CommandBufferVK> command_buffer)
202 : RenderPass(context, target), command_buffer_(
std::move(command_buffer)) {
206 RenderPassVK::~RenderPassVK() =
default;
208 bool RenderPassVK::IsValid()
const {
212 void RenderPassVK::OnSetLabel(std::string label) {
213 debug_label_ = std::move(label);
217 vk::ClearColorValue value;
225 vk::ClearDepthStencilValue value;
227 value.stencil = stencil;
233 std::vector<vk::ClearValue> clears;
237 if (color.resolve_texture) {
245 if (depth.has_value()) {
247 stencil ? stencil->clear_stencil : 0u, depth->clear_depth));
250 if (stencil.has_value()) {
252 stencil->clear_stencil, depth ? depth->clear_depth : 0.0f));
258 SharedHandleVK<vk::Framebuffer> RenderPassVK::CreateVKFramebuffer(
259 const ContextVK& context,
260 const vk::RenderPass& pass)
const {
261 vk::FramebufferCreateInfo fb_info;
263 fb_info.renderPass = pass;
265 const auto target_size = render_target_.GetRenderTargetSize();
266 fb_info.width = target_size.width;
267 fb_info.height = target_size.height;
270 std::vector<vk::ImageView> attachments;
274 for (
const auto& [_, color] : render_target_.GetColorAttachments()) {
277 attachments.emplace_back(TextureVK::Cast(*color.texture).GetImageView());
278 if (color.resolve_texture) {
279 attachments.emplace_back(
280 TextureVK::Cast(*color.resolve_texture).GetImageView());
283 if (
auto depth = render_target_.GetDepthAttachment(); depth.has_value()) {
284 attachments.emplace_back(TextureVK::Cast(*depth->texture).GetImageView());
286 if (
auto stencil = render_target_.GetStencilAttachment();
287 stencil.has_value()) {
288 attachments.emplace_back(TextureVK::Cast(*stencil->texture).GetImageView());
291 fb_info.setAttachments(attachments);
293 auto [result, framebuffer] =
294 context.GetDevice().createFramebufferUnique(fb_info);
296 if (result != vk::Result::eSuccess) {
297 VALIDATION_LOG <<
"Could not create framebuffer: " << vk::to_string(result);
305 const vk::CommandBuffer& buffer) {
310 barrier.
src_access = vk::AccessFlagBits::eColorAttachmentWrite |
311 vk::AccessFlagBits::eTransferWrite;
312 barrier.
src_stage = vk::PipelineStageFlagBits::eColorAttachmentOutput |
313 vk::PipelineStageFlagBits::eTransfer;
314 barrier.
dst_access = vk::AccessFlagBits::eShaderRead;
315 barrier.
dst_stage = vk::PipelineStageFlagBits::eFragmentShader;
317 barrier.
new_layout = vk::ImageLayout::eShaderReadOnlyOptimal;
328 const vk::CommandBuffer& buffer) {
334 const vk::CommandBuffer& buffer) {
335 for (
const Command& command : commands) {
344 const vk::CommandBuffer& cmd_buffer,
346 const ISize& target_size) {
349 {.rect = Rect::MakeSize(target_size)});
350 vk::Viewport viewport = vk::Viewport()
351 .setWidth(vp.rect.GetWidth())
352 .setHeight(-vp.rect.GetHeight())
353 .setY(vp.rect.GetHeight())
356 cmd_buffer_cache.
SetViewport(cmd_buffer, 0, 1, &viewport);
359 const auto& sc = command.
scissor.value_or(IRect::MakeSize(target_size));
362 .setOffset(vk::Offset2D(sc.GetX(), sc.GetY()))
363 .setExtent(vk::Extent2D(sc.GetWidth(), sc.GetHeight()));
364 cmd_buffer_cache.
SetScissor(cmd_buffer, 0, 1, &scissor);
371 const ISize& target_size,
372 const vk::DescriptorSet vk_desc_set) {
373 #ifdef IMPELLER_DEBUG
374 fml::ScopedCleanupClosure pop_marker(
376 if (!command.label.empty()) {
379 pop_marker.Release();
381 #endif // IMPELLER_DEBUG
384 const auto& pipeline_vk = PipelineVK::Cast(*command.
pipeline);
387 vk::PipelineBindPoint::eGraphics,
388 pipeline_vk.GetPipelineLayout(),
390 {vk::DescriptorSet{vk_desc_set}},
394 command_buffer_cache.BindPipeline(
395 cmd_buffer, vk::PipelineBindPoint::eGraphics, pipeline_vk.GetPipeline());
401 command_buffer_cache.SetStencilReference(
402 cmd_buffer, vk::StencilFaceFlagBits::eVkStencilFrontAndBack,
403 command.stencil_reference);
406 auto& vertex_buffer_view = command.vertex_buffer.vertex_buffer;
408 if (!vertex_buffer_view) {
412 auto& allocator = *context.GetResourceAllocator();
413 auto vertex_buffer = vertex_buffer_view.buffer->GetDeviceBuffer(allocator);
415 if (!vertex_buffer) {
417 <<
" for vertex buffer view";
421 if (!encoder.Track(vertex_buffer)) {
426 auto vertex_buffer_handle = DeviceBufferVK::Cast(*vertex_buffer).GetBuffer();
427 vk::Buffer vertex_buffers[] = {vertex_buffer_handle};
428 vk::DeviceSize vertex_buffer_offsets[] = {vertex_buffer_view.range.offset};
429 cmd_buffer.bindVertexBuffers(0u, 1u, vertex_buffers, vertex_buffer_offsets);
431 if (command.vertex_buffer.index_type != IndexType::kNone) {
433 auto index_buffer_view = command.vertex_buffer.index_buffer;
434 if (!index_buffer_view) {
438 auto index_buffer = index_buffer_view.buffer->GetDeviceBuffer(allocator);
441 <<
" for index buffer view";
445 if (!encoder.Track(index_buffer)) {
449 auto index_buffer_handle = DeviceBufferVK::Cast(*index_buffer).GetBuffer();
450 cmd_buffer.bindIndexBuffer(index_buffer_handle,
451 index_buffer_view.range.offset,
455 cmd_buffer.drawIndexed(command.vertex_buffer.vertex_count,
456 command.instance_count,
462 cmd_buffer.draw(command.vertex_buffer.vertex_count,
463 command.instance_count,
471 bool RenderPassVK::OnEncodeCommands(
const Context& context)
const {
472 TRACE_EVENT0(
"impeller",
"RenderPassVK::OnEncodeCommands");
477 const auto& vk_context = ContextVK::Cast(context);
479 auto command_buffer = command_buffer_.lock();
480 if (!command_buffer) {
481 VALIDATION_LOG <<
"Command buffer died before commands could be encoded.";
484 auto encoder = command_buffer->GetEncoder();
489 fml::ScopedCleanupClosure pop_marker(
490 [&encoder]() { encoder->PopDebugGroup(); });
491 if (!debug_label_.empty()) {
492 encoder->PushDebugGroup(debug_label_.c_str());
494 pop_marker.Release();
497 auto cmd_buffer = encoder->GetCommandBuffer();
503 render_target_.IterateAllAttachments(
504 [&encoder](
const auto& attachment) ->
bool {
505 encoder->Track(attachment.texture);
506 encoder->Track(attachment.resolve_texture);
510 const auto& target_size = render_target_.GetRenderTargetSize();
512 auto render_pass = CreateVKRenderPass(
513 vk_context, command_buffer,
514 vk_context.GetCapabilities()->SupportsFramebufferFetch());
520 auto framebuffer = CreateVKFramebuffer(vk_context, *render_pass);
526 if (!encoder->Track(framebuffer) || !encoder->Track(render_pass)) {
532 vk::RenderPassBeginInfo pass_info;
533 pass_info.renderPass = *render_pass;
534 pass_info.framebuffer = *framebuffer;
535 pass_info.renderArea.extent.width =
static_cast<uint32_t
>(target_size.width);
536 pass_info.renderArea.extent.height =
537 static_cast<uint32_t
>(target_size.height);
538 pass_info.setClearValues(clear_values);
540 const auto& color_image_vk = TextureVK::Cast(
541 *render_target_.GetColorAttachments().find(0u)->second.texture);
543 vk_context, encoder, commands_, color_image_vk);
544 if (!desc_sets_result.ok()) {
547 auto desc_sets = desc_sets_result.value();
550 TRACE_EVENT0(
"impeller",
"EncodeRenderPassCommands");
551 cmd_buffer.beginRenderPass(pass_info, vk::SubpassContents::eInline);
553 fml::ScopedCleanupClosure end_render_pass(
554 [cmd_buffer]() { cmd_buffer.endRenderPass(); });
556 auto desc_index = 0u;
557 for (
const auto& command : commands_) {
558 if (!
EncodeCommand(context, command, *encoder, pass_bindings_cache_,
559 target_size, desc_sets[desc_index])) {