|  | // Copyright 2013 The Flutter Authors. All rights reserved. | 
|  | // Use of this source code is governed by a BSD-style license that can be | 
|  | // found in the LICENSE file. | 
|  |  | 
|  | #include "vulkan_backbuffer.h" | 
|  |  | 
|  | #include <limits> | 
|  |  | 
|  | #include "third_party/skia/include/gpu/vk/GrVkTypes.h" | 
|  | #include "vulkan/vulkan.h" | 
|  | #include "vulkan_proc_table.h" | 
|  |  | 
|  | namespace vulkan { | 
|  |  | 
|  | VulkanBackbuffer::VulkanBackbuffer(const VulkanProcTable& p_vk, | 
|  | const VulkanHandle<VkDevice>& device, | 
|  | const VulkanHandle<VkCommandPool>& pool) | 
|  | : vk(p_vk), | 
|  | device_(device), | 
|  | usage_command_buffer_(p_vk, device, pool), | 
|  | render_command_buffer_(p_vk, device, pool), | 
|  | valid_(false) { | 
|  | if (!usage_command_buffer_.IsValid() || !render_command_buffer_.IsValid()) { | 
|  | FML_DLOG(INFO) << "Command buffers were not valid."; | 
|  | return; | 
|  | } | 
|  |  | 
|  | if (!CreateSemaphores()) { | 
|  | FML_DLOG(INFO) << "Could not create semaphores."; | 
|  | return; | 
|  | } | 
|  |  | 
|  | if (!CreateFences()) { | 
|  | FML_DLOG(INFO) << "Could not create fences."; | 
|  | return; | 
|  | } | 
|  |  | 
|  | valid_ = true; | 
|  | } | 
|  |  | 
|  | VulkanBackbuffer::~VulkanBackbuffer() { | 
|  | FML_ALLOW_UNUSED_LOCAL(WaitFences()); | 
|  | } | 
|  |  | 
|  | bool VulkanBackbuffer::IsValid() const { | 
|  | return valid_; | 
|  | } | 
|  |  | 
|  | bool VulkanBackbuffer::CreateSemaphores() { | 
|  | const VkSemaphoreCreateInfo create_info = { | 
|  | .sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO, | 
|  | .pNext = nullptr, | 
|  | .flags = 0, | 
|  | }; | 
|  |  | 
|  | auto semaphore_collect = [this](VkSemaphore semaphore) { | 
|  | vk.DestroySemaphore(device_, semaphore, nullptr); | 
|  | }; | 
|  |  | 
|  | for (size_t i = 0; i < semaphores_.size(); i++) { | 
|  | VkSemaphore semaphore = VK_NULL_HANDLE; | 
|  |  | 
|  | if (VK_CALL_LOG_ERROR(vk.CreateSemaphore(device_, &create_info, nullptr, | 
|  | &semaphore)) != VK_SUCCESS) { | 
|  | return false; | 
|  | } | 
|  |  | 
|  | semaphores_[i] = {semaphore, semaphore_collect}; | 
|  | } | 
|  |  | 
|  | return true; | 
|  | } | 
|  |  | 
|  | bool VulkanBackbuffer::CreateFences() { | 
|  | const VkFenceCreateInfo create_info = { | 
|  | .sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO, | 
|  | .pNext = nullptr, | 
|  | .flags = VK_FENCE_CREATE_SIGNALED_BIT, | 
|  | }; | 
|  |  | 
|  | auto fence_collect = [this](VkFence fence) { | 
|  | vk.DestroyFence(device_, fence, nullptr); | 
|  | }; | 
|  |  | 
|  | for (size_t i = 0; i < use_fences_.size(); i++) { | 
|  | VkFence fence = VK_NULL_HANDLE; | 
|  |  | 
|  | if (VK_CALL_LOG_ERROR(vk.CreateFence(device_, &create_info, nullptr, | 
|  | &fence)) != VK_SUCCESS) { | 
|  | return false; | 
|  | } | 
|  |  | 
|  | use_fences_[i] = {fence, fence_collect}; | 
|  | } | 
|  |  | 
|  | return true; | 
|  | } | 
|  |  | 
|  | bool VulkanBackbuffer::WaitFences() { | 
|  | VkFence fences[use_fences_.size()]; | 
|  |  | 
|  | for (size_t i = 0; i < use_fences_.size(); i++) { | 
|  | fences[i] = use_fences_[i]; | 
|  | } | 
|  |  | 
|  | return VK_CALL_LOG_ERROR(vk.WaitForFences( | 
|  | device_, static_cast<uint32_t>(use_fences_.size()), fences, true, | 
|  | std::numeric_limits<uint64_t>::max())) == VK_SUCCESS; | 
|  | } | 
|  |  | 
|  | bool VulkanBackbuffer::ResetFences() { | 
|  | VkFence fences[use_fences_.size()]; | 
|  |  | 
|  | for (size_t i = 0; i < use_fences_.size(); i++) { | 
|  | fences[i] = use_fences_[i]; | 
|  | } | 
|  |  | 
|  | return VK_CALL_LOG_ERROR(vk.ResetFences( | 
|  | device_, static_cast<uint32_t>(use_fences_.size()), fences)) == | 
|  | VK_SUCCESS; | 
|  | } | 
|  |  | 
|  | const VulkanHandle<VkFence>& VulkanBackbuffer::GetUsageFence() const { | 
|  | return use_fences_[0]; | 
|  | } | 
|  |  | 
|  | const VulkanHandle<VkFence>& VulkanBackbuffer::GetRenderFence() const { | 
|  | return use_fences_[1]; | 
|  | } | 
|  |  | 
|  | const VulkanHandle<VkSemaphore>& VulkanBackbuffer::GetUsageSemaphore() const { | 
|  | return semaphores_[0]; | 
|  | } | 
|  |  | 
|  | const VulkanHandle<VkSemaphore>& VulkanBackbuffer::GetRenderSemaphore() const { | 
|  | return semaphores_[1]; | 
|  | } | 
|  |  | 
|  | VulkanCommandBuffer& VulkanBackbuffer::GetUsageCommandBuffer() { | 
|  | return usage_command_buffer_; | 
|  | } | 
|  |  | 
|  | VulkanCommandBuffer& VulkanBackbuffer::GetRenderCommandBuffer() { | 
|  | return render_command_buffer_; | 
|  | } | 
|  |  | 
|  | }  // namespace vulkan |