1// Copyright 2013 The Flutter Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include "vulkan_backbuffer.h"
6
7#include <limits>
8
9#include "third_party/skia/include/gpu/vk/GrVkTypes.h"
10#include "vulkan/vulkan.h"
11#include "vulkan_proc_table.h"
12
13namespace vulkan {
14
15VulkanBackbuffer::VulkanBackbuffer(const VulkanProcTable& p_vk,
16 const VulkanHandle<VkDevice>& device,
17 const VulkanHandle<VkCommandPool>& pool)
18 : vk(p_vk),
19 device_(device),
20 usage_command_buffer_(p_vk, device, pool),
21 render_command_buffer_(p_vk, device, pool),
22 valid_(false) {
23 if (!usage_command_buffer_.IsValid() || !render_command_buffer_.IsValid()) {
24 FML_DLOG(INFO) << "Command buffers were not valid.";
25 return;
26 }
27
28 if (!CreateSemaphores()) {
29 FML_DLOG(INFO) << "Could not create semaphores.";
30 return;
31 }
32
33 if (!CreateFences()) {
34 FML_DLOG(INFO) << "Could not create fences.";
35 return;
36 }
37
38 valid_ = true;
39}
40
41VulkanBackbuffer::~VulkanBackbuffer() {
42 FML_ALLOW_UNUSED_LOCAL(WaitFences());
43}
44
45bool VulkanBackbuffer::IsValid() const {
46 return valid_;
47}
48
49bool VulkanBackbuffer::CreateSemaphores() {
50 const VkSemaphoreCreateInfo create_info = {
51 .sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO,
52 .pNext = nullptr,
53 .flags = 0,
54 };
55
56 auto semaphore_collect = [this](VkSemaphore semaphore) {
57 vk.DestroySemaphore(device_, semaphore, nullptr);
58 };
59
60 for (size_t i = 0; i < semaphores_.size(); i++) {
61 VkSemaphore semaphore = VK_NULL_HANDLE;
62
63 if (VK_CALL_LOG_ERROR(vk.CreateSemaphore(device_, &create_info, nullptr,
64 &semaphore)) != VK_SUCCESS) {
65 return false;
66 }
67
68 semaphores_[i] = {semaphore, semaphore_collect};
69 }
70
71 return true;
72}
73
74bool VulkanBackbuffer::CreateFences() {
75 const VkFenceCreateInfo create_info = {
76 .sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO,
77 .pNext = nullptr,
78 .flags = VK_FENCE_CREATE_SIGNALED_BIT,
79 };
80
81 auto fence_collect = [this](VkFence fence) {
82 vk.DestroyFence(device_, fence, nullptr);
83 };
84
85 for (size_t i = 0; i < use_fences_.size(); i++) {
86 VkFence fence = VK_NULL_HANDLE;
87
88 if (VK_CALL_LOG_ERROR(vk.CreateFence(device_, &create_info, nullptr,
89 &fence)) != VK_SUCCESS) {
90 return false;
91 }
92
93 use_fences_[i] = {fence, fence_collect};
94 }
95
96 return true;
97}
98
99bool VulkanBackbuffer::WaitFences() {
100 VkFence fences[use_fences_.size()];
101
102 for (size_t i = 0; i < use_fences_.size(); i++) {
103 fences[i] = use_fences_[i];
104 }
105
106 return VK_CALL_LOG_ERROR(vk.WaitForFences(
107 device_, static_cast<uint32_t>(use_fences_.size()), fences, true,
108 std::numeric_limits<uint64_t>::max())) == VK_SUCCESS;
109}
110
111bool VulkanBackbuffer::ResetFences() {
112 VkFence fences[use_fences_.size()];
113
114 for (size_t i = 0; i < use_fences_.size(); i++) {
115 fences[i] = use_fences_[i];
116 }
117
118 return VK_CALL_LOG_ERROR(vk.ResetFences(
119 device_, static_cast<uint32_t>(use_fences_.size()), fences)) ==
120 VK_SUCCESS;
121}
122
123const VulkanHandle<VkFence>& VulkanBackbuffer::GetUsageFence() const {
124 return use_fences_[0];
125}
126
127const VulkanHandle<VkFence>& VulkanBackbuffer::GetRenderFence() const {
128 return use_fences_[1];
129}
130
131const VulkanHandle<VkSemaphore>& VulkanBackbuffer::GetUsageSemaphore() const {
132 return semaphores_[0];
133}
134
135const VulkanHandle<VkSemaphore>& VulkanBackbuffer::GetRenderSemaphore() const {
136 return semaphores_[1];
137}
138
139VulkanCommandBuffer& VulkanBackbuffer::GetUsageCommandBuffer() {
140 return usage_command_buffer_;
141}
142
143VulkanCommandBuffer& VulkanBackbuffer::GetRenderCommandBuffer() {
144 return render_command_buffer_;
145}
146
147} // namespace vulkan
148