1 /*
2 * Copyright (C) 2023 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.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 vkDestroyFence(device, // device
57 ref.fence, // fence
58 nullptr); // pAllocator
59 }
60 }
61
BeginFrame()62 void RenderFrameSyncVk::BeginFrame()
63 {
64 bufferingIndex_ = (bufferingIndex_ + 1) % (uint32_t)frameFences_.size();
65 }
66
WaitForFrameFence()67 void RenderFrameSyncVk::WaitForFrameFence()
68 {
69 const VkDevice device = ((const DevicePlatformDataVk&)device_.GetPlatformData()).device;
70
71 if (frameFences_[bufferingIndex_].signalled) {
72 VkFence fence = frameFences_[bufferingIndex_].fence;
73 const VkResult res = vkWaitForFences(device, // device
74 1, // fenceCount
75 &fence, // pFences
76 VK_TRUE, // waitAll
77 UINT64_MAX); // timeout
78 if (res == VK_SUCCESS) {
79 VALIDATE_VK_RESULT(vkResetFences(device, // device
80 1, // fenceCount
81 &fence)); // pFences
82
83 frameFences_[bufferingIndex_].signalled = false;
84 } else {
85 PLUGIN_LOG_E("vkWaitForFences VkResult: %i. Frame count: %" PRIu64 ". Device invalidated.", res,
86 device_.GetFrameCount());
87 device_.SetDeviceStatus(false);
88 PLUGIN_ASSERT(false);
89 }
90 }
91 }
92
GetFrameFence() const93 LowLevelFenceVk RenderFrameSyncVk::GetFrameFence() const
94 {
95 return { frameFences_[bufferingIndex_].fence };
96 }
97
FrameFenceIsSignalled()98 void RenderFrameSyncVk::FrameFenceIsSignalled()
99 {
100 frameFences_[bufferingIndex_].signalled = true;
101 }
102 RENDER_END_NAMESPACE()
103