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 #ifdef RS_ENABLE_VK
10 #include "flutter/vulkan/vulkan_hilog.h"
11 #endif
12 #include "flutter/vulkan/vulkan_proc_table.h"
13 #include "third_party/skia/include/gpu/vk/GrVkTypes.h"
14 #include "vulkan/vulkan.h"
15
16 namespace vulkan {
17
VulkanBackbuffer(const VulkanProcTable & p_vk,const VulkanHandle<VkDevice> & device,const VulkanHandle<VkCommandPool> & pool)18 VulkanBackbuffer::VulkanBackbuffer(const VulkanProcTable& p_vk,
19 const VulkanHandle<VkDevice>& device,
20 const VulkanHandle<VkCommandPool>& pool)
21 : vk(p_vk),
22 device_(device),
23 usage_command_buffer_(p_vk, device, pool),
24 render_command_buffer_(p_vk, device, pool),
25 valid_(false) {
26 if (!usage_command_buffer_.IsValid() || !render_command_buffer_.IsValid()) {
27 #ifdef RS_ENABLE_VK
28 LOGE("Command buffers were not valid.");
29 #else
30 FML_DLOG(INFO) << "Command buffers were not valid.";
31 #endif
32 return;
33 }
34
35 if (!CreateSemaphores()) {
36 #ifdef RS_ENABLE_VK
37 LOGE("Could not create semaphores.");
38 #else
39 FML_DLOG(INFO) << "Could not create semaphores.";
40 #endif
41 return;
42 }
43
44 if (!CreateFences()) {
45 #ifdef RS_ENABLE_VK
46 LOGE("Could not create fences.");
47 #else
48 FML_DLOG(INFO) << "Could not create fences.";
49 #endif
50 return;
51 }
52
53 valid_ = true;
54 }
55
~VulkanBackbuffer()56 VulkanBackbuffer::~VulkanBackbuffer() {
57 #ifdef RS_ENABLE_VK
58 WaitFences();
59 #else
60 FML_ALLOW_UNUSED_LOCAL(WaitFences());
61 #endif
62 }
63
IsValid() const64 bool VulkanBackbuffer::IsValid() const {
65 return valid_;
66 }
67
CreateSemaphores()68 bool VulkanBackbuffer::CreateSemaphores() {
69 const VkSemaphoreCreateInfo create_info = {
70 .sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO,
71 .pNext = nullptr,
72 .flags = 0,
73 };
74
75 auto semaphore_collect = [this](VkSemaphore semaphore) {
76 vk.DestroySemaphore(device_, semaphore, nullptr);
77 };
78
79 for (size_t i = 0; i < semaphores_.size(); i++) {
80 VkSemaphore semaphore = VK_NULL_HANDLE;
81
82 if (VK_CALL_LOG_ERROR(vk.CreateSemaphore(device_, &create_info, nullptr,
83 &semaphore)) != VK_SUCCESS) {
84 return false;
85 }
86
87 semaphores_[i] = {semaphore, semaphore_collect};
88 }
89
90 return true;
91 }
92
CreateFences()93 bool VulkanBackbuffer::CreateFences() {
94 const VkFenceCreateInfo create_info = {
95 .sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO,
96 .pNext = nullptr,
97 .flags = VK_FENCE_CREATE_SIGNALED_BIT,
98 };
99
100 auto fence_collect = [this](VkFence fence) {
101 vk.DestroyFence(device_, fence, nullptr);
102 };
103
104 for (size_t i = 0; i < use_fences_.size(); i++) {
105 VkFence fence = VK_NULL_HANDLE;
106
107 if (VK_CALL_LOG_ERROR(vk.CreateFence(device_, &create_info, nullptr,
108 &fence)) != VK_SUCCESS) {
109 return false;
110 }
111
112 use_fences_[i] = {fence, fence_collect};
113 }
114
115 return true;
116 }
117
WaitFences()118 bool VulkanBackbuffer::WaitFences() {
119 VkFence fences[use_fences_.size()];
120
121 for (size_t i = 0; i < use_fences_.size(); i++) {
122 fences[i] = use_fences_[i];
123 }
124
125 return VK_CALL_LOG_ERROR(vk.WaitForFences(
126 device_, static_cast<uint32_t>(use_fences_.size()), fences, true,
127 std::numeric_limits<uint64_t>::max())) == VK_SUCCESS;
128 }
129
ResetFences()130 bool VulkanBackbuffer::ResetFences() {
131 VkFence fences[use_fences_.size()];
132
133 for (size_t i = 0; i < use_fences_.size(); i++) {
134 fences[i] = use_fences_[i];
135 }
136
137 return VK_CALL_LOG_ERROR(vk.ResetFences(
138 device_, static_cast<uint32_t>(use_fences_.size()), fences)) ==
139 VK_SUCCESS;
140 }
141
GetUsageFence() const142 const VulkanHandle<VkFence>& VulkanBackbuffer::GetUsageFence() const {
143 return use_fences_[0];
144 }
145
GetRenderFence() const146 const VulkanHandle<VkFence>& VulkanBackbuffer::GetRenderFence() const {
147 return use_fences_[1];
148 }
149
GetUsageSemaphore() const150 const VulkanHandle<VkSemaphore>& VulkanBackbuffer::GetUsageSemaphore() const {
151 return semaphores_[0];
152 }
153
GetRenderSemaphore() const154 const VulkanHandle<VkSemaphore>& VulkanBackbuffer::GetRenderSemaphore() const {
155 return semaphores_[1];
156 }
157
GetUsageCommandBuffer()158 VulkanCommandBuffer& VulkanBackbuffer::GetUsageCommandBuffer() {
159 return usage_command_buffer_;
160 }
161
GetRenderCommandBuffer()162 VulkanCommandBuffer& VulkanBackbuffer::GetRenderCommandBuffer() {
163 return render_command_buffer_;
164 }
165
166 } // namespace vulkan
167