@@ -125,6 +125,12 @@ bool RenderPassVK::OnEncodeCommands(const Context& context) const {
125125 }
126126 }
127127
128+ if (!TransitionImageLayout (frame_num, tex_info.swapchain_image ->GetImage (),
129+ vk::ImageLayout::eUndefined,
130+ vk::ImageLayout::eColorAttachmentOptimal)) {
131+ return false ;
132+ }
133+
128134 command_buffer_->endRenderPass ();
129135
130136 return const_cast <RenderPassVK*>(this )->EndCommandBuffer (frame_num);
@@ -312,12 +318,20 @@ bool RenderPassVK::UpdateDescriptorSets(uint32_t frame_num,
312318
313319 if (!TransitionImageLayout (frame_num, texture_vk.GetImage (),
314320 vk::ImageLayout::eUndefined,
315- vk::ImageLayout::eGeneral)) {
321+ vk::ImageLayout::eTransferDstOptimal)) {
322+ return false ;
323+ }
324+
325+ CopyBufferToImage (frame_num, texture_vk);
326+
327+ if (!TransitionImageLayout (frame_num, texture_vk.GetImage (),
328+ vk::ImageLayout::eTransferDstOptimal,
329+ vk::ImageLayout::eShaderReadOnlyOptimal)) {
316330 return false ;
317331 }
318332
319333 vk::DescriptorImageInfo desc_image_info;
320- desc_image_info.setImageLayout (vk::ImageLayout::eGeneral );
334+ desc_image_info.setImageLayout (vk::ImageLayout::eShaderReadOnlyOptimal );
321335 desc_image_info.setSampler (sampler_vk.GetSamplerVK ());
322336 desc_image_info.setImageView (texture_vk.GetImageView ());
323337 image_infos.push_back (desc_image_info);
@@ -404,8 +418,10 @@ bool RenderPassVK::TransitionImageLayout(uint32_t frame_num,
404418
405419 vk::ImageMemoryBarrier barrier =
406420 vk::ImageMemoryBarrier ()
407- .setSrcAccessMask (vk::AccessFlagBits::eColorAttachmentRead)
408- .setDstAccessMask (vk::AccessFlagBits::eColorAttachmentWrite)
421+ .setSrcAccessMask (vk::AccessFlagBits::eColorAttachmentWrite |
422+ vk::AccessFlagBits::eTransferWrite)
423+ .setDstAccessMask (vk::AccessFlagBits::eColorAttachmentRead |
424+ vk::AccessFlagBits::eShaderRead)
409425 .setOldLayout (layout_old)
410426 .setNewLayout (layout_new)
411427 .setSrcQueueFamilyIndex (VK_QUEUE_FAMILY_IGNORED)
@@ -418,10 +434,9 @@ bool RenderPassVK::TransitionImageLayout(uint32_t frame_num,
418434 .setLevelCount (1 )
419435 .setBaseArrayLayer (0 )
420436 .setLayerCount (1 ));
421- transition_cmd->pipelineBarrier (
422- vk::PipelineStageFlagBits::eColorAttachmentOutput,
423- vk::PipelineStageFlagBits::eColorAttachmentOutput, {}, nullptr , nullptr ,
424- barrier);
437+ transition_cmd->pipelineBarrier (vk::PipelineStageFlagBits::eAllGraphics,
438+ vk::PipelineStageFlagBits::eAllGraphics, {},
439+ nullptr , nullptr , barrier);
425440
426441 res = transition_cmd->end ();
427442 if (res != vk::Result::eSuccess) {
@@ -433,4 +448,60 @@ bool RenderPassVK::TransitionImageLayout(uint32_t frame_num,
433448 return true ;
434449}
435450
451+ bool RenderPassVK::CopyBufferToImage (uint32_t frame_num,
452+ const TextureVK& texture_vk) const {
453+ auto pool = command_buffer_.getPool ();
454+ vk::CommandBufferAllocateInfo alloc_info =
455+ vk::CommandBufferAllocateInfo ()
456+ .setCommandPool (pool)
457+ .setLevel (vk::CommandBufferLevel::ePrimary)
458+ .setCommandBufferCount (1 );
459+ auto cmd_buf_res = device_.allocateCommandBuffersUnique (alloc_info);
460+ if (cmd_buf_res.result != vk::Result::eSuccess) {
461+ VALIDATION_LOG << " Failed to allocate command buffer: "
462+ << vk::to_string (cmd_buf_res.result );
463+ return false ;
464+ }
465+
466+ auto copy_cmd = std::move (cmd_buf_res.value [0 ]);
467+
468+ const auto & size = texture_vk.GetTextureDescriptor ().size ;
469+
470+ // actual copy happens here
471+ vk::BufferImageCopy region =
472+ vk::BufferImageCopy ()
473+ .setBufferOffset (0 )
474+ .setBufferRowLength (0 )
475+ .setBufferImageHeight (0 )
476+ .setImageSubresource (
477+ vk::ImageSubresourceLayers ()
478+ .setAspectMask (vk::ImageAspectFlagBits::eColor)
479+ .setMipLevel (0 )
480+ .setBaseArrayLayer (0 )
481+ .setLayerCount (1 ))
482+ .setImageOffset (vk::Offset3D (0 , 0 , 0 ))
483+ .setImageExtent (vk::Extent3D (size.width , size.height , 1 ));
484+
485+ vk::CommandBufferBeginInfo begin_info;
486+ auto res = copy_cmd->begin (begin_info);
487+
488+ if (res != vk::Result::eSuccess) {
489+ VALIDATION_LOG << " Failed to begin command buffer: " << vk::to_string (res);
490+ return false ;
491+ }
492+
493+ copy_cmd->copyBufferToImage (texture_vk.GetStagingBuffer (),
494+ texture_vk.GetImage (),
495+ vk::ImageLayout::eTransferDstOptimal, region);
496+
497+ res = copy_cmd->end ();
498+ if (res != vk::Result::eSuccess) {
499+ VALIDATION_LOG << " Failed to end command buffer: " << vk::to_string (res);
500+ return false ;
501+ }
502+
503+ surface_producer_->QueueCommandBuffer (frame_num, std::move (copy_cmd));
504+ return true ;
505+ }
506+
436507} // namespace impeller
0 commit comments