|  | // Copyright 2016 The Chromium 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> | 
|  |  | 
|  | namespace vulkan { | 
|  |  | 
|  | VulkanBackbuffer::VulkanBackbuffer(VulkanProcTable& p_vk, | 
|  | VulkanHandle<VkDevice>& device, | 
|  | VulkanHandle<VkCommandPool>& pool, | 
|  | VulkanHandle<VkImage> image) | 
|  | : vk(p_vk), | 
|  | device_(device), | 
|  | pool_(pool), | 
|  | image_(std::move(image)), | 
|  | valid_(false) { | 
|  | if (!device_ || !pool_ || !image_) { | 
|  | return; | 
|  | } | 
|  |  | 
|  | if (!CreateSemaphores()) { | 
|  | return; | 
|  | } | 
|  |  | 
|  | if (!CreateTransitionBuffers()) { | 
|  | return; | 
|  | } | 
|  |  | 
|  | if (!CreateFences()) { | 
|  | return; | 
|  | } | 
|  |  | 
|  | valid_ = true; | 
|  | } | 
|  |  | 
|  | VulkanBackbuffer::~VulkanBackbuffer() { | 
|  | 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.createSemaphore(device_, &create_info, nullptr, &semaphore) != | 
|  | VK_SUCCESS) { | 
|  | return false; | 
|  | } | 
|  |  | 
|  | semaphores_[i] = {semaphore, semaphore_collect}; | 
|  | } | 
|  |  | 
|  | return true; | 
|  | } | 
|  |  | 
|  | bool VulkanBackbuffer::CreateTransitionBuffers() { | 
|  | const VkCommandBufferAllocateInfo allocate_info = { | 
|  | .sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO, | 
|  | .pNext = nullptr, | 
|  | .commandPool = pool_, | 
|  | .level = VK_COMMAND_BUFFER_LEVEL_PRIMARY, | 
|  | .commandBufferCount = 1, | 
|  | }; | 
|  |  | 
|  | auto buffer_collect = [this](VkCommandBuffer buffer) { | 
|  | vk.freeCommandBuffers(device_, pool_, 1, &buffer); | 
|  | }; | 
|  |  | 
|  | for (size_t i = 0; i < transition_buffers_.size(); i++) { | 
|  | VkCommandBuffer buffer = VK_NULL_HANDLE; | 
|  |  | 
|  | if (vk.allocateCommandBuffers(device_, &allocate_info, &buffer) != | 
|  | VK_SUCCESS) { | 
|  | return false; | 
|  | } | 
|  |  | 
|  | transition_buffers_[i] = {buffer, buffer_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.createFence(device_, &create_info, nullptr, &fence) != VK_SUCCESS) { | 
|  | return false; | 
|  | } | 
|  |  | 
|  | use_fences_[i] = {fence, fence_collect}; | 
|  | } | 
|  |  | 
|  | return true; | 
|  | } | 
|  |  | 
|  | void VulkanBackbuffer::WaitFences() { | 
|  | VkFence fences[use_fences_.size()]; | 
|  |  | 
|  | for (size_t i = 0; i < use_fences_.size(); i++) { | 
|  | fences[i] = use_fences_[i]; | 
|  | } | 
|  |  | 
|  | vk.waitForFences(device_, static_cast<uint32_t>(use_fences_.size()), fences, | 
|  | true, std::numeric_limits<uint64_t>::max()); | 
|  | } | 
|  |  | 
|  | }  // namespace vulkan |