// 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 namespace vulkan { VulkanBackbuffer::VulkanBackbuffer(VulkanProcTable& p_vk, VulkanHandle& device, VulkanHandle& pool, VulkanHandle 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(use_fences_.size()), fences, true, std::numeric_limits::max()); } } // namespace vulkan