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 "device.h"
17
18 #include <algorithm>
19 #include <cstdint>
20
21 #include <render/datastore/intf_render_data_store_manager.h>
22 #include <render/datastore/intf_render_data_store_pod.h>
23 #include <render/device/pipeline_layout_desc.h>
24 #include <render/namespace.h>
25
26 #include "default_engine_constants.h"
27 #include "device/gpu_resource_manager.h"
28 #include "device/shader_manager.h"
29 #include "device/swapchain.h"
30 #include "render_context.h"
31 #include "util/log.h"
32 #include "util/string_util.h"
33
34 #if (RENDER_HAS_VULKAN_BACKEND)
35 #include "vulkan/device_vk.h"
36 #endif
37
38 #if (RENDER_HAS_GL_BACKEND) || (RENDER_HAS_GLES_BACKEND)
39 #include "gles/device_gles.h"
40 #include "gles/swapchain_gles.h"
41 #endif
42
43 using namespace BASE_NS;
44
45 RENDER_BEGIN_NAMESPACE()
46 namespace {
47 static constexpr uint32_t MIN_BUFFERING_COUNT { 2 };
48 static constexpr uint32_t MAX_BUFFERING_COUNT { 4 };
49
CreateDepthBuffer(const DeviceBackendType backendType,const Swapchain & swapchain,GpuResourceManager & gpuResourceManager,vector<RenderHandleReference> & defaultGpuResources)50 void CreateDepthBuffer(const DeviceBackendType backendType, const Swapchain& swapchain,
51 GpuResourceManager& gpuResourceManager, vector<RenderHandleReference>& defaultGpuResources)
52 {
53 // NOTE: special handling of CORE_DEFAULT_BACKBUFFER_DEPTH for different backend types.
54 #if (RENDER_HAS_VULKAN_BACKEND)
55 if (backendType == DeviceBackendType::VULKAN) {
56 gpuResourceManager.Create(
57 DefaultEngineGpuResourceConstants::CORE_DEFAULT_BACKBUFFER_DEPTH, swapchain.GetDescDepthBuffer());
58 }
59 #endif
60 #if (RENDER_HAS_GL_BACKEND) || (RENDER_HAS_GLES_BACKEND)
61 if ((backendType == DeviceBackendType::OPENGL) || (backendType == DeviceBackendType::OPENGLES)) {
62 auto& platformData = static_cast<const SwapchainGLES&>(swapchain).GetPlatformData();
63 defaultGpuResources.emplace_back(
64 gpuResourceManager.CreateView(DefaultEngineGpuResourceConstants::CORE_DEFAULT_BACKBUFFER_DEPTH,
65 swapchain.GetDescDepthBuffer(), platformData.depthPlatformData));
66 }
67 #endif
68 }
69 } // namespace
70
Device(RenderContext & renderContext,const DeviceCreateInfo & deviceCreateInfo)71 Device::Device(RenderContext& renderContext, const DeviceCreateInfo& deviceCreateInfo) : renderContext_(renderContext)
72 {
73 if ((deviceConfiguration_.bufferingCount < MIN_BUFFERING_COUNT) ||
74 (deviceConfiguration_.bufferingCount > MAX_BUFFERING_COUNT)) {
75 deviceConfiguration_.bufferingCount =
76 std::clamp(deviceConfiguration_.bufferingCount, MIN_BUFFERING_COUNT, MAX_BUFFERING_COUNT);
77 PLUGIN_LOG_D("buffering count clamped to: %u", deviceConfiguration_.bufferingCount);
78 }
79 }
80
CreateSwapchain(const SwapchainCreateInfo & swapchainCreateInfo)81 void Device::CreateSwapchain(const SwapchainCreateInfo& swapchainCreateInfo)
82 {
83 Activate();
84 CreateDeviceSwapchain(swapchainCreateInfo);
85 if (!swapchain_) {
86 Deactivate();
87 return;
88 }
89
90 {
91 vector<unique_ptr<GpuImage>> swapchainGpuImages = CreateGpuImageViews(*swapchain_);
92 Deactivate();
93 for (uint32_t idx = 0; idx < swapchainGpuImages.size(); ++idx) {
94 const auto& ref = swapchainGpuImages[idx];
95 defaultGpuResources_.emplace_back(
96 gpuResourceMgr_->CreateView(DefaultEngineGpuResourceConstants::CORE_DEFAULT_SWAPCHAIN + to_string(idx),
97 ref->GetDesc(), ref->GetBasePlatformData()));
98 }
99 Activate();
100 }
101 {
102 Deactivate();
103 const RenderHandle firstSwapchain = gpuResourceMgr_->GetImageRawHandle(
104 DefaultEngineGpuResourceConstants::CORE_DEFAULT_SWAPCHAIN + string_view("0"));
105 const RenderHandle shallowHandle =
106 gpuResourceMgr_->GetImageRawHandle(DefaultEngineGpuResourceConstants::CORE_DEFAULT_BACKBUFFER);
107 gpuResourceMgr_->RemapGpuImageHandle(shallowHandle, firstSwapchain);
108 SetBackbufferHandle(shallowHandle); // store backbuffer client handle
109 }
110
111 // configure automatically backbuffer as swapchain
112 {
113 IRenderDataStoreManager& rdsm = renderContext_.GetRenderDataStoreManager();
114 auto dataStorePod = static_cast<IRenderDataStorePod*>(rdsm.GetRenderDataStore("RenderDataStorePod"));
115 if (dataStorePod) {
116 auto const dataView = dataStorePod->Get("NodeGraphBackBufferConfiguration");
117 PLUGIN_ASSERT(dataView.size_bytes() == sizeof(NodeGraphBackBufferConfiguration));
118 NodeGraphBackBufferConfiguration ngbbc = *(const NodeGraphBackBufferConfiguration*)dataView.data();
119 StringUtil::CopyStringToArray(DefaultEngineGpuResourceConstants::CORE_DEFAULT_BACKBUFFER,
120 ngbbc.backBufferName, NodeGraphBackBufferConfiguration::CORE_MAX_BACK_BUFFER_NAME_LENGTH);
121 ngbbc.backBufferType = NodeGraphBackBufferConfiguration::BackBufferType::SWAPCHAIN;
122 ngbbc.present = true;
123 dataStorePod->Set("NodeGraphBackBufferConfiguration", arrayviewU8(ngbbc));
124 }
125 }
126
127 if (swapchainCreateInfo.swapchainFlags & SwapchainFlagBits::CORE_SWAPCHAIN_DEPTH_BUFFER_BIT) {
128 CreateDepthBuffer(GetBackendType(), *swapchain_, *gpuResourceMgr_, defaultGpuResources_);
129 }
130 }
131
DestroySwapchain()132 void Device::DestroySwapchain()
133 {
134 // NOTE: Clear image resource handles.
135 Activate();
136 DestroyDeviceSwapchain();
137 SetBackbufferHandle({});
138 // remove swapchain configuration from the backbuffer
139 {
140 IRenderDataStoreManager& rdsm = renderContext_.GetRenderDataStoreManager();
141 auto dataStorePod = static_cast<IRenderDataStorePod*>(rdsm.GetRenderDataStore("RenderDataStorePod"));
142 if (dataStorePod) {
143 auto const dataView = dataStorePod->Get("NodeGraphBackBufferConfiguration");
144 PLUGIN_ASSERT(dataView.size_bytes() == sizeof(NodeGraphBackBufferConfiguration));
145 NodeGraphBackBufferConfiguration ngbbc = *(const NodeGraphBackBufferConfiguration*)dataView.data();
146 if (ngbbc.backBufferType == NodeGraphBackBufferConfiguration::BackBufferType::SWAPCHAIN) {
147 ngbbc.backBufferType = NodeGraphBackBufferConfiguration::BackBufferType::UNDEFINED;
148 ngbbc.present = false;
149 }
150 dataStorePod->Set("NodeGraphBackBufferConfiguration", arrayviewU8(ngbbc));
151 }
152 }
153 Deactivate();
154 }
155
FrameStart()156 void Device::FrameStart()
157 {
158 ++frameCount_;
159 }
160
FrameEnd()161 void Device::FrameEnd() {}
162
SetDeviceStatus(const bool status)163 void Device::SetDeviceStatus(const bool status)
164 {
165 deviceStatus_.store(status);
166 }
167
GetDeviceStatus() const168 bool Device::GetDeviceStatus() const
169 {
170 return deviceStatus_.load();
171 }
172
GetFrameCount() const173 uint64_t Device::GetFrameCount() const
174 {
175 return frameCount_;
176 }
177
GetSharedMemoryPropertyFlags() const178 MemoryPropertyFlags Device::GetSharedMemoryPropertyFlags() const
179 {
180 return deviceSharedMemoryPropertyFlags_;
181 }
182
GetDeviceConfiguration() const183 DeviceConfiguration Device::GetDeviceConfiguration() const
184 {
185 return deviceConfiguration_;
186 }
187
GetCommandBufferingCount() const188 uint32_t Device::GetCommandBufferingCount() const
189 {
190 return deviceConfiguration_.bufferingCount;
191 }
192
HasSwapchain() const193 bool Device::HasSwapchain() const
194 {
195 return (swapchain_) ? true : false;
196 }
197
GetSwapchain() const198 const Swapchain* Device::GetSwapchain() const
199 {
200 return swapchain_.get();
201 }
202
SetBackbufferHandle(const RenderHandle handle)203 void Device::SetBackbufferHandle(const RenderHandle handle)
204 {
205 backbufferHandle_ = handle;
206 }
207
GetBackbufferHandle() const208 RenderHandle Device::GetBackbufferHandle() const
209 {
210 return backbufferHandle_;
211 }
212
SetLockResourceBackendAccess(const bool value)213 void Device::SetLockResourceBackendAccess(const bool value)
214 {
215 isBackendResourceAccessLocked_ = value;
216 }
217
GetLockResourceBackendAccess() const218 bool Device::GetLockResourceBackendAccess() const
219 {
220 return isBackendResourceAccessLocked_;
221 }
222
SetRenderBackendRunning(const bool value)223 void Device::SetRenderBackendRunning(const bool value)
224 {
225 isRenderbackendRunning_ = value;
226 }
227
GetGpuResourceManager() const228 IGpuResourceManager& Device::GetGpuResourceManager() const
229 {
230 return *gpuResourceMgr_;
231 }
232
GetShaderManager() const233 IShaderManager& Device::GetShaderManager() const
234 {
235 return *shaderMgr_;
236 }
237 RENDER_END_NAMESPACE()
238