blob: e28a1f20bb48e2b21bc29f2e3c37156a8d070273 [file] [log] [blame]
// 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