10 #include "fml/status.h" 
   38   vk::ClearColorValue 
value;
 
   46   vk::ClearDepthStencilValue 
value;
 
   48   value.stencil = stencil;
 
   54     std::array<vk::ClearValue, kMaxAttachments>& values) {
 
   57       [&values, &offset](
size_t index,
 
   61           values.at(offset++) = VKClearValueFromColor(attachment.clear_color);
 
   69   if (depth.has_value()) {
 
   71         stencil ? stencil->clear_stencil : 0u, depth->clear_depth);
 
   72   } 
else if (stencil.has_value()) {
 
   74         stencil->clear_stencil, depth ? depth->clear_depth : 0.0f);
 
   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;
 
   88   RenderPassBuilderVK builder;
 
   90                                                 const ColorAttachment&
 
   92     builder.SetColorAttachment(
 
   94         attachment.texture->GetTextureDescriptor().format,                    
 
   95         attachment.texture->GetTextureDescriptor().sample_count,              
 
   96         attachment.load_action,                                               
 
   97         attachment.store_action,                                              
 
  104     builder.SetDepthStencilAttachment(
 
  105         depth->texture->GetTextureDescriptor().format,        
 
  106         depth->texture->GetTextureDescriptor().sample_count,  
 
  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                                   
 
  120   auto pass = builder.Build(context.GetDevice());
 
  123     VALIDATION_LOG << 
"Failed to create render pass for framebuffer.";
 
  127   context.SetDebugName(pass.get(), debug_label_.c_str());
 
  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;
 
  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);
 
  148   FramebufferAndRenderPass frame_data;
 
  149   bool is_swapchain = 
false;
 
  151       color_image_vk_->GetTextureDescriptor().sample_count;
 
  152   if (resolve_image_vk_) {
 
  162   const auto& target_size = render_target_.GetRenderTargetSize();
 
  164   render_pass_ = CreateVKRenderPass(vk_context, frame_data.render_pass,
 
  165                                     command_buffer_, is_swapchain);
 
  172   auto framebuffer = (frame_data.framebuffer == 
nullptr)
 
  173                          ? CreateVKFramebuffer(vk_context, *render_pass_)
 
  174                          : frame_data.framebuffer;
 
  181   if (!command_buffer_->Track(framebuffer) ||
 
  182       !command_buffer_->Track(render_pass_)) {
 
  187   frame_data.framebuffer = framebuffer;
 
  188   frame_data.render_pass = render_pass_;
 
  190   if (resolve_image_vk_) {
 
  200   if (resolve_image_vk_ &&
 
  201       resolve_image_vk_->GetTextureDescriptor().mip_count > 1) {
 
  203         vk::ImageLayout::eUndefined) {
 
  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;
 
  216   std::array<vk::ClearValue, kMaxAttachments> clears;
 
  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);
 
  228   command_buffer_vk_.beginRenderPass(pass_info, vk::SubpassContents::eInline);
 
  230   if (resolve_image_vk_) {
 
  233             is_swapchain ? vk::ImageLayout::eGeneral
 
  234                          : vk::ImageLayout::eShaderReadOnlyOptimal);
 
  236   if (color_image_vk_) {
 
  243   vk::Viewport viewport = vk::Viewport()
 
  244                               .setWidth(vp.rect.GetWidth())
 
  245                               .setHeight(-vp.rect.GetHeight())
 
  246                               .setY(vp.rect.GetHeight())
 
  249   command_buffer_vk_.setViewport(0, 1, &viewport);
 
  255           .setOffset(vk::Offset2D(sc.GetX(), sc.GetY()))
 
  256           .setExtent(vk::Extent2D(sc.GetWidth(), sc.GetHeight()));
 
  257   command_buffer_vk_.setScissor(0, 1, &scissor);
 
  260   command_buffer_vk_.setStencilReference(
 
  261       vk::StencilFaceFlagBits::eVkStencilFrontAndBack, 0u);
 
  266 RenderPassVK::~RenderPassVK() = 
default;
 
  268 bool RenderPassVK::IsValid()
 const {
 
  272 void RenderPassVK::OnSetLabel(std::string_view label) {
 
  273 #ifdef IMPELLER_DEBUG 
  274   ContextVK::Cast(*context_).SetDebugName(render_pass_->Get(), label.data());
 
  278 SharedHandleVK<vk::Framebuffer> RenderPassVK::CreateVKFramebuffer(
 
  279     const ContextVK& context,
 
  280     const vk::RenderPass& pass)
 const {
 
  281   vk::FramebufferCreateInfo fb_info;
 
  283   fb_info.renderPass = pass;
 
  285   const auto target_size = render_target_.GetRenderTargetSize();
 
  286   fb_info.width = target_size.width;
 
  287   fb_info.height = target_size.height;
 
  290   std::array<vk::ImageView, kMaxAttachments> attachments;
 
  296   render_target_.IterateAllColorAttachments(
 
  297       [&attachments, &count](
size_t index,
 
  298                              const ColorAttachment& attachment) -> 
bool {
 
  301         attachments[count++] =
 
  302             TextureVK::Cast(*attachment.texture).GetRenderTargetView();
 
  303         if (attachment.resolve_texture) {
 
  304           attachments[count++] = TextureVK::Cast(*attachment.resolve_texture)
 
  305                                      .GetRenderTargetView();
 
  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();
 
  319   fb_info.setPAttachments(attachments.data());
 
  320   fb_info.setAttachmentCount(count);
 
  322   auto [result, framebuffer] =
 
  323       context.GetDevice().createFramebufferUnique(fb_info);
 
  325   if (result != vk::Result::eSuccess) {
 
  326     VALIDATION_LOG << 
"Could not create framebuffer: " << vk::to_string(result);
 
  334 void RenderPassVK::SetPipeline(
PipelineRef pipeline) {
 
  335   pipeline_ = pipeline;
 
  340   pipeline_uses_input_attachments_ =
 
  341       pipeline_->GetDescriptor().GetVertexDescriptor()->UsesInputAttacments();
 
  343   if (pipeline_uses_input_attachments_) {
 
  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;
 
  354     vk::WriteDescriptorSet write_set;
 
  356     write_set.descriptorCount = 1u;
 
  357     write_set.descriptorType = vk::DescriptorType::eInputAttachment;
 
  358     write_set.pImageInfo = &image_workspace_[bound_image_offset_ - 1];
 
  360     write_workspace_[descriptor_write_offset_++] = write_set;
 
  365 void RenderPassVK::SetCommandLabel(std::string_view label) {
 
  366 #ifdef IMPELLER_DEBUG 
  367   command_buffer_->PushDebugGroup(label);
 
  373 void RenderPassVK::SetStencilReference(uint32_t 
value) {
 
  374   if (current_stencil_ == 
value) {
 
  377   current_stencil_ = 
value;
 
  378   command_buffer_vk_.setStencilReference(
 
  379       vk::StencilFaceFlagBits::eVkStencilFrontAndBack, 
value);
 
  383 void RenderPassVK::SetBaseVertex(uint64_t 
value) {
 
  384   base_vertex_ = 
value;
 
  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())
 
  395   command_buffer_vk_.setViewport(0, 1, &viewport_vk);
 
  399 void RenderPassVK::SetScissor(
IRect scissor) {
 
  400   vk::Rect2D scissor_vk =
 
  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);
 
  408 void RenderPassVK::SetElementCount(
size_t count) {
 
  409   element_count_ = count;
 
  413 void RenderPassVK::SetInstanceCount(
size_t count) {
 
  414   instance_count_ = count;
 
  418 bool RenderPassVK::SetVertexBuffer(BufferView vertex_buffers[],
 
  419                                    size_t vertex_buffer_count) {
 
  420   if (!ValidateVertexBuffers(vertex_buffers, vertex_buffer_count)) {
 
  426   for (
size_t i = 0; i < vertex_buffer_count; 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();
 
  433       command_buffer_->Track(device_buffer);
 
  438   command_buffer_vk_.bindVertexBuffers(0u, vertex_buffer_count, buffers,
 
  439                                        vertex_buffer_offsets);
 
  445 bool RenderPassVK::SetIndexBuffer(BufferView index_buffer,
 
  447   if (!ValidateIndexBuffer(index_buffer, index_type)) {
 
  451   if (index_type != IndexType::kNone) {
 
  452     has_index_buffer_ = 
true;
 
  454     BufferView index_buffer_view = std::move(index_buffer);
 
  455     if (!index_buffer_view) {
 
  459     if (!index_buffer_view.GetBuffer()) {
 
  461                      << 
" for index buffer view";
 
  465     std::shared_ptr<const DeviceBuffer> index_buffer =
 
  466         index_buffer_view.TakeBuffer();
 
  467     if (index_buffer && !command_buffer_->Track(index_buffer)) {
 
  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,
 
  477     has_index_buffer_ = 
false;
 
  484 fml::Status RenderPassVK::Draw() {
 
  486     return fml::Status(fml::StatusCode::kCancelled,
 
  487                        "No valid pipeline is bound to the RenderPass.");
 
  507   if (immutable_sampler_) {
 
  508     std::shared_ptr<Pipeline<PipelineDescriptor>> pipeline_variant =
 
  509         PipelineVK::Cast(*pipeline_)
 
  510             .CreateVariantForImmutableSamplers(immutable_sampler_);
 
  511     if (!pipeline_variant) {
 
  513           fml::StatusCode::kAborted,
 
  514           "Could not create pipeline variant with immutable sampler.");
 
  516     pipeline_ = raw_ptr(pipeline_variant);
 
  519   const auto& context_vk = ContextVK::Cast(*context_);
 
  520   const auto& pipeline_vk = PipelineVK::Cast(*pipeline_);
 
  522   auto descriptor_result = command_buffer_->AllocateDescriptorSets(
 
  523       pipeline_vk.GetDescriptorSetLayout(), pipeline_vk.GetPipelineKey(),
 
  525   if (!descriptor_result.ok()) {
 
  526     return fml::Status(fml::StatusCode::kAborted,
 
  527                        "Could not allocate descriptor sets.");
 
  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());
 
  534   for (
auto i = 0u; i < descriptor_write_offset_; i++) {
 
  535     write_workspace_[i].dstSet = descriptor_set;
 
  538   context_vk.GetDevice().updateDescriptorSets(descriptor_write_offset_,
 
  539                                               write_workspace_.data(), 0u, {});
 
  541   command_buffer_vk_.bindDescriptorSets(
 
  542       vk::PipelineBindPoint::eGraphics,  
 
  551   if (pipeline_uses_input_attachments_) {
 
  553         command_buffer_vk_, TextureVK::Cast(*color_image_vk_).GetImage());
 
  556   if (has_index_buffer_) {
 
  557     command_buffer_vk_.drawIndexed(element_count_,   
 
  564     command_buffer_vk_.draw(element_count_,   
 
  571 #ifdef IMPELLER_DEBUG 
  573     command_buffer_->PopDebugGroup();
 
  577   has_index_buffer_ = 
false;
 
  578   bound_image_offset_ = 0u;
 
  579   bound_buffer_offset_ = 0u;
 
  580   descriptor_write_offset_ = 0u;
 
  581   instance_count_ = 1u;
 
  585   pipeline_uses_input_attachments_ = 
false;
 
  586   immutable_sampler_ = 
nullptr;
 
  587   return fml::Status();
 
  594                                 const ShaderUniformSlot& slot,
 
  595                                 const ShaderMetadata* metadata,
 
  597   return BindResource(slot.binding, 
type, view);
 
  600 bool RenderPassVK::BindDynamicResource(
ShaderStage stage,
 
  602                                        const ShaderUniformSlot& slot,
 
  603                                        std::unique_ptr<ShaderMetadata> metadata,
 
  605   return BindResource(slot.binding, 
type, view);
 
  608 bool RenderPassVK::BindResource(
size_t binding,
 
  615   auto buffer = DeviceBufferVK::Cast(*view.GetBuffer()).GetBuffer();
 
  620   std::shared_ptr<const DeviceBuffer> device_buffer = view.TakeBuffer();
 
  621   if (device_buffer && !command_buffer_->Track(device_buffer)) {
 
  625   uint32_t offset = view.GetRange().offset;
 
  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;
 
  633   vk::WriteDescriptorSet write_set;
 
  634   write_set.dstBinding = binding;
 
  635   write_set.descriptorCount = 1u;
 
  637   write_set.pBufferInfo = &buffer_workspace_[bound_buffer_offset_ - 1];
 
  639   write_workspace_[descriptor_write_offset_++] = write_set;
 
  643 bool RenderPassVK::BindDynamicResource(
ShaderStage stage,
 
  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);
 
  654                                 const SampledImageSlot& slot,
 
  655                                 const ShaderMetadata* metadata,
 
  656                                 std::shared_ptr<const Texture> texture,
 
  657                                 raw_ptr<const Sampler> sampler) {
 
  661   if (!texture || !texture->IsValid() || !sampler) {
 
  664   const TextureVK& texture_vk = TextureVK::Cast(*texture);
 
  665   const SamplerVK& sampler_vk = SamplerVK::Cast(*sampler);
 
  667   if (!command_buffer_->Track(texture)) {
 
  671   if (!immutable_sampler_) {
 
  672     immutable_sampler_ = texture_vk.GetImmutableSamplerVariant(sampler_vk);
 
  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;
 
  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];
 
  687   write_workspace_[descriptor_write_offset_++] = write_set;
 
  691 bool RenderPassVK::OnEncodeCommands(
const Context& context)
 const {
 
  692   command_buffer_->GetCommandBuffer().endRenderPass();
 
static TextureVK & Cast(Texture &base)
const RenderTarget render_target_
bool IterateAllColorAttachments(const std::function< bool(size_t index, const ColorAttachment &attachment)> &iterator) const
const std::optional< DepthAttachment > & GetDepthAttachment() const
const std::optional< StencilAttachment > & GetStencilAttachment() const
bool IsSwapchainImage() const
const FramebufferAndRenderPass & GetCachedFrameData(SampleCount sample_count) const
vk::ImageLayout SetLayoutWithoutEncoding(vk::ImageLayout layout) const
bool SetLayout(const BarrierVK &barrier) const
vk::ImageLayout GetLayout() const
void SetCachedFrameData(const FramebufferAndRenderPass &data, SampleCount sample_count)
constexpr vk::IndexType ToVKIndexType(IndexType index_type)
raw_ptr< Pipeline< PipelineDescriptor > > PipelineRef
A raw ptr to a pipeline object.
constexpr vk::DescriptorType ToVKDescriptorType(DescriptorType type)
static constexpr size_t kMaxBindings
constexpr size_t kMaxVertexBuffers
static constexpr size_t kMagicSubpassInputBinding
static vk::ClearDepthStencilValue VKClearValueFromDepthStencil(uint32_t stencil, Scalar depth)
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...
static size_t GetVKClearValues(const RenderTarget &target, std::array< vk::ClearValue, kMaxAttachments > &values)
static vk::ClearColorValue VKClearValueFromColor(Color color)
auto MakeSharedVK(vk::UniqueHandle< T, VULKAN_HPP_DEFAULT_DISPATCHER_TYPE > handle)
std::shared_ptr< Texture > resolve_texture
constexpr static TRect MakeSize(const TSize< U > &size)