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 "flutter/vulkan/vulkan_backbuffer.h"
6
7 #include <limits>
8
9 #include "flutter/vulkan/vulkan_proc_table.h"
10 #include "third_party/skia/include/gpu/vk/GrVkTypes.h"
11 #include "vulkan/vulkan.h"
12
13 namespace vulkan {
14
VulkanBackbuffer(const VulkanProcTable & p_vk,const VulkanHandle<VkDevice> & device,const VulkanHandle<VkCommandPool> & pool)15 VulkanBackbuffer::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
~VulkanBackbuffer()41 VulkanBackbuffer::~VulkanBackbuffer() {
42 FML_ALLOW_UNUSED_LOCAL(WaitFences());
43 }
44
IsValid() const45 bool VulkanBackbuffer::IsValid() const {
46 return valid_;
47 }
48
CreateSemaphores()49 bool 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
CreateFences()74 bool 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
WaitFences()99 bool 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
ResetFences()111 bool 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
GetUsageFence() const123 const VulkanHandle<VkFence>& VulkanBackbuffer::GetUsageFence() const {
124 return use_fences_[0];
125 }
126
GetRenderFence() const127 const VulkanHandle<VkFence>& VulkanBackbuffer::GetRenderFence() const {
128 return use_fences_[1];
129 }
130
GetUsageSemaphore() const131 const VulkanHandle<VkSemaphore>& VulkanBackbuffer::GetUsageSemaphore() const {
132 return semaphores_[0];
133 }
134
GetRenderSemaphore() const135 const VulkanHandle<VkSemaphore>& VulkanBackbuffer::GetRenderSemaphore() const {
136 return semaphores_[1];
137 }
138
GetUsageCommandBuffer()139 VulkanCommandBuffer& VulkanBackbuffer::GetUsageCommandBuffer() {
140 return usage_command_buffer_;
141 }
142
GetRenderCommandBuffer()143 VulkanCommandBuffer& VulkanBackbuffer::GetRenderCommandBuffer() {
144 return render_command_buffer_;
145 }
146
147 } // namespace vulkan
148