1 /*
2 * Copyright (c) 2024 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 #include "render_frame_sync_vk.h"
17
18 #include <cinttypes>
19 #include <cstdint>
20 #include <vulkan/vulkan_core.h>
21
22 #include <render/namespace.h>
23
24 #include "device/device.h"
25 #include "device/render_frame_sync.h"
26 #include "util/log.h"
27 #include "vulkan/device_vk.h"
28 #include "vulkan/validate_vk.h"
29
RENDER_BEGIN_NAMESPACE()30 RENDER_BEGIN_NAMESPACE()
31 RenderFrameSyncVk::RenderFrameSyncVk(Device& dev) : RenderFrameSync(), device_ { dev }
32 {
33 const VkDevice device = ((const DevicePlatformDataVk&)device_.GetPlatformData()).device;
34
35 frameFences_.resize(device_.GetCommandBufferingCount());
36
37 constexpr VkFenceCreateFlags fenceCreateFlags { VK_FENCE_CREATE_SIGNALED_BIT };
38 const VkFenceCreateInfo fenceCreateInfo {
39 VK_STRUCTURE_TYPE_FENCE_CREATE_INFO, // sType
40 nullptr, // pNext
41 fenceCreateFlags, // flags
42 };
43 for (auto& ref : frameFences_) {
44 VALIDATE_VK_RESULT(vkCreateFence(device, // device
45 &fenceCreateInfo, // pCreateInfo
46 nullptr, // pAllocator
47 &ref.fence)); // pFence
48 }
49 }
50
~RenderFrameSyncVk()51 RenderFrameSyncVk::~RenderFrameSyncVk()
52 {
53 const VkDevice device = ((const DevicePlatformDataVk&)device_.GetPlatformData()).device;
54
55 for (auto& ref : frameFences_) {
56 if (ref.fence) {
57 vkDestroyFence(device, // device
58 ref.fence, // fence
59 nullptr); // pAllocator
60 }
61 }
62 }
63
BeginFrame()64 void RenderFrameSyncVk::BeginFrame()
65 {
66 bufferingIndex_ = (bufferingIndex_ + 1) % static_cast<uint32_t>(frameFences_.size());
67 }
68
WaitForFrameFence()69 void RenderFrameSyncVk::WaitForFrameFence()
70 {
71 const VkDevice device = ((const DevicePlatformDataVk&)device_.GetPlatformData()).device;
72
73 if (frameFences_[bufferingIndex_].signalled) {
74 VkFence fence = frameFences_[bufferingIndex_].fence;
75 if (fence) {
76 const VkResult res = vkWaitForFences(device, // device
77 1U, // fenceCount
78 &fence, // pFences
79 VK_TRUE, // waitAll
80 UINT64_MAX); // timeout
81 if (res == VK_SUCCESS) {
82 VALIDATE_VK_RESULT(vkResetFences(device, // device
83 1, // fenceCount
84 &fence)); // pFences
85
86 frameFences_[bufferingIndex_].signalled = false;
87 } else {
88 PLUGIN_LOG_E("vkWaitForFences VkResult: %i. Frame count: %" PRIu64 ". Device invalidated.", res,
89 device_.GetFrameCount());
90 device_.SetDeviceStatus(false);
91 }
92 }
93 }
94 }
95
GetFrameFence() const96 LowLevelFenceVk RenderFrameSyncVk::GetFrameFence() const
97 {
98 return { frameFences_[bufferingIndex_].fence };
99 }
100
FrameFenceIsSignalled()101 void RenderFrameSyncVk::FrameFenceIsSignalled()
102 {
103 frameFences_[bufferingIndex_].signalled = true;
104 }
105 RENDER_END_NAMESPACE()
106