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 "device.h"
17
18 #include <algorithm>
19 #include <cinttypes>
20 #include <cstdint>
21
22 #include <base/containers/array_view.h>
23 #include <base/containers/fixed_string.h>
24 #include <base/containers/string.h>
25 #include <base/containers/string_view.h>
26 #include <base/containers/type_traits.h>
27 #include <base/containers/unique_ptr.h>
28 #include <base/containers/vector.h>
29 #include <base/util/formats.h>
30 #include <render/datastore/intf_render_data_store_manager.h>
31 #include <render/datastore/render_data_store_render_pods.h>
32 #include <render/device/intf_device.h>
33 #include <render/device/pipeline_state_desc.h>
34 #include <render/namespace.h>
35 #include <render/resource_handle.h>
36
37 #include "datastore/render_data_store_pod.h"
38 #include "default_engine_constants.h"
39 #include "device/gpu_resource_manager.h"
40 #include "device/shader_manager.h"
41 #include "device/swapchain.h"
42 #include "render_context.h"
43 #include "util/log.h"
44 #include "util/string_util.h"
45
46 #if (RENDER_HAS_VULKAN_BACKEND)
47 #include "vulkan/device_vk.h"
48 #include "vulkan/swapchain_vk.h"
49 #endif
50
51 #if (RENDER_HAS_GL_BACKEND) || (RENDER_HAS_GLES_BACKEND)
52 #include "gles/device_gles.h"
53 #include "gles/swapchain_gles.h"
54 #endif
55
56 using namespace BASE_NS;
57
58 RENDER_BEGIN_NAMESPACE()
59 class IGpuResourceManager;
60 class IShaderManager;
61 PLUGIN_STATIC_ASSERT(BASE_NS::Format::BASE_FORMAT_ASTC_12x12_SRGB_BLOCK == 184u);
62 PLUGIN_STATIC_ASSERT(BASE_NS::Format::BASE_FORMAT_G8B8G8R8_422_UNORM == 1000156000u);
63
64 namespace {
65 static constexpr uint32_t MIN_BUFFERING_COUNT { 2 };
66 static constexpr uint32_t MAX_BUFFERING_COUNT { 4 };
67
68 constexpr const Format FALLBACK_FORMATS[] = {
69 BASE_FORMAT_UNDEFINED,
70
71 // R4G4 UNORM PACK8
72 BASE_FORMAT_R8_UNORM,
73
74 // R4G4B4A4 UNORM PACK16
75 BASE_FORMAT_R16_UNORM,
76 // B4G4R4A4 UNORM PACK16
77 BASE_FORMAT_R4G4B4A4_UNORM_PACK16,
78
79 // R5G6B5 UNORM PACK16
80 BASE_FORMAT_R16_UNORM,
81 // B5G6R5 UNORM PACK16
82 BASE_FORMAT_R5G6B5_UNORM_PACK16,
83
84 // R5G5B5A1 UNORM PACK16
85 BASE_FORMAT_R5G6B5_UNORM_PACK16,
86 // B5G5R5A1 UNORM PACK16
87 BASE_FORMAT_R5G5B5A1_UNORM_PACK16,
88 // A1R5G5B5 UNORM PACK16
89 BASE_FORMAT_R5G5B5A1_UNORM_PACK16,
90
91 // R8 UNORM
92 BASE_FORMAT_UNDEFINED, // undefined
93 // R8 SNORM
94 BASE_FORMAT_R8_UNORM,
95 // R8 USCALED
96 BASE_FORMAT_R8_UNORM,
97 // R8 SSCALED
98 BASE_FORMAT_R8_SNORM,
99 // R8 UINT
100 BASE_FORMAT_R8_UNORM,
101 // R8 SINT
102 BASE_FORMAT_R8_UINT,
103 // R8 SRGB
104 BASE_FORMAT_R8_UNORM,
105
106 // R8G8 UNORM
107 BASE_FORMAT_R8G8B8A8_UNORM, // fallback to 32 bits
108 // R8G8 SNORM
109 BASE_FORMAT_R8G8_UNORM,
110 // R8G8 USCALED
111 BASE_FORMAT_R8G8_UNORM,
112 // R8G8 SSCALED
113 BASE_FORMAT_R8G8_SNORM,
114 // R8G8 UINT
115 BASE_FORMAT_R8G8_UNORM,
116 // R8G8 SINT
117 BASE_FORMAT_R8G8_UINT,
118 // R8G8 SRGB
119 BASE_FORMAT_R8G8_UNORM,
120
121 // R8G8B8 UNORM
122 BASE_FORMAT_R8G8B8A8_UNORM, // fallback to 32 bits
123 // R8G8B8 SNORM
124 BASE_FORMAT_R8G8B8_UNORM,
125 // R8G8B8 USCALED
126 BASE_FORMAT_R8G8B8_UNORM,
127 // R8G8B8 SSCALED
128 BASE_FORMAT_R8G8B8_SNORM,
129 // R8G8B8 UINT
130 BASE_FORMAT_R8G8B8_UNORM,
131 // R8G8B8 SINT
132 BASE_FORMAT_R8G8B8_UINT,
133 // R8G8B8 SRGB
134 BASE_FORMAT_R8G8B8_UNORM,
135
136 // B8G8R8 UNORM
137 BASE_FORMAT_B8G8R8A8_UNORM, // fallback to 32 bits
138 // B8G8R8 SNORM
139 BASE_FORMAT_B8G8R8_UNORM,
140 // B8G8R8 USCALED
141 BASE_FORMAT_B8G8R8_UNORM,
142 // B8G8R8 SSCALED
143 BASE_FORMAT_B8G8R8_SNORM,
144 // B8G8R8 UINT
145 BASE_FORMAT_B8G8R8_UNORM,
146 // B8G8R8 SINT
147 BASE_FORMAT_B8G8R8_UINT,
148 // B8G8R8 SRGB
149 BASE_FORMAT_B8G8R8_UNORM,
150
151 // R8G8B8A8 UNORM
152 BASE_FORMAT_UNDEFINED, // undefined
153 // R8G8B8A8 SNORM
154 BASE_FORMAT_R8G8B8A8_UNORM,
155 // R8G8B8A8 USCALED
156 BASE_FORMAT_R8G8B8A8_UNORM,
157 // R8G8B8A8 SSCALED
158 BASE_FORMAT_R8G8B8A8_SNORM,
159 // R8G8B8A8 UINT
160 BASE_FORMAT_R8G8B8A8_UNORM,
161 // R8G8B8A8 SINT
162 BASE_FORMAT_R8G8B8A8_UINT,
163 // R8G8B8A8 SRGB
164 BASE_FORMAT_R8G8B8A8_UNORM,
165
166 // B8G8R8A8 UNORM
167 BASE_FORMAT_R8G8B8A8_UNORM,
168 // B8G8R8A8 SNORM
169 BASE_FORMAT_B8G8R8A8_UNORM,
170 // B8G8R8A8 USCALED
171 BASE_FORMAT_B8G8R8A8_UNORM,
172 // B8G8R8A8 SSCALED
173 BASE_FORMAT_B8G8R8A8_SNORM,
174 // B8G8R8A8 UINT
175 BASE_FORMAT_B8G8R8A8_UNORM,
176 // B8G8R8A8 SINT
177 BASE_FORMAT_B8G8R8A8_UINT,
178 // FORMAT B8G8R8A8 SRGB
179 BASE_FORMAT_B8G8R8A8_SRGB,
180
181 // A8B8G8R8 UNORM PACK32
182 BASE_FORMAT_R8G8B8A8_UNORM,
183 // A8B8G8R8 SNORM PACK32
184 BASE_FORMAT_A8B8G8R8_UNORM_PACK32,
185 // A8B8G8R8 USCALED PACK32
186 BASE_FORMAT_A8B8G8R8_UNORM_PACK32,
187 // A8B8G8R8 SSCALED PACK32
188 BASE_FORMAT_A8B8G8R8_SNORM_PACK32,
189 // A8B8G8R8 UINT PACK32
190 BASE_FORMAT_A8B8G8R8_UNORM_PACK32,
191 // A8B8G8R8 SINT PACK32
192 BASE_FORMAT_A8B8G8R8_UINT_PACK32,
193 // A8B8G8R8 SRGB PACK32
194 BASE_FORMAT_A8B8G8R8_UNORM_PACK32,
195
196 // A2R10G10B10 UNORM PACK32
197 BASE_FORMAT_R8G8B8A8_UNORM,
198 // A2R10G10B10 SNORM PACK32
199 BASE_FORMAT_A2R10G10B10_UNORM_PACK32,
200 // A2R10G10B10 USCALED PACK32
201 BASE_FORMAT_A2R10G10B10_UNORM_PACK32,
202 // A2R10G10B10 SSCALED PACK32
203 BASE_FORMAT_A2R10G10B10_SNORM_PACK32,
204 // A2R10G10B10 UINT PACK32
205 BASE_FORMAT_A2R10G10B10_UNORM_PACK32,
206 // A2R10G10B10 SINT PACK32
207 BASE_FORMAT_A2R10G10B10_UINT_PACK32,
208
209 // A2B10G10R10 UNORM PACK32
210 BASE_FORMAT_R8G8B8A8_UNORM,
211 // A2B10G10R10 SNORM PACK32
212 BASE_FORMAT_A2B10G10R10_UNORM_PACK32,
213 // A2B10G10R10 USCALED PACK32
214 BASE_FORMAT_A2B10G10R10_UNORM_PACK32,
215 // A2B10G10R10 SSCALED PACK32
216 BASE_FORMAT_A2B10G10R10_SNORM_PACK32,
217 // A2B10G10R10 UINT PACK32
218 BASE_FORMAT_A2B10G10R10_UNORM_PACK32,
219 // A2B10G10R10 SINT PACK32
220 BASE_FORMAT_A2B10G10R10_UINT_PACK32,
221
222 // R16 UNORM
223 BASE_FORMAT_R8_UNORM, // fallback to 8 bit channel
224 // R16 SNORM
225 BASE_FORMAT_R16_UNORM,
226 // R16 USCALED
227 BASE_FORMAT_R16_UNORM,
228 // R16 SSCALED
229 BASE_FORMAT_R16_SNORM,
230 // R16 UINT
231 BASE_FORMAT_R16_UNORM,
232 // R16 SINT
233 BASE_FORMAT_R16_UINT,
234 // R16 SFLOAT
235 BASE_FORMAT_R16_UNORM,
236
237 // R16G16 UNORM
238 BASE_FORMAT_R16G16B16A16_UNORM, // fallback to 4 channel
239 // R16G16 SNORM
240 BASE_FORMAT_R16G16_UNORM,
241 // R16G16 USCALED
242 BASE_FORMAT_R16G16_UNORM,
243 // R16G16 SSCALED
244 BASE_FORMAT_R16G16_SNORM,
245 // R16G16 UINT
246 BASE_FORMAT_R16G16_UNORM,
247 // R16G16 SINT
248 BASE_FORMAT_R16G16_UINT,
249 // R16G16 SFLOAT
250 BASE_FORMAT_R16G16_UNORM,
251
252 // R16G16B16 UNORM
253 BASE_FORMAT_R16G16B16A16_UNORM, // fallback to 4 channel
254 // R16G16B16 SNORM
255 BASE_FORMAT_R16G16B16_UNORM,
256 // R16G16B16 USCALED
257 BASE_FORMAT_R16G16B16_UNORM,
258 // R16G16B16 SSCALED
259 BASE_FORMAT_R16G16B16_SNORM,
260 // R16G16B16 UINT
261 BASE_FORMAT_R16G16B16_UNORM,
262 // R16G16B16 SINT
263 BASE_FORMAT_R16G16B16_UINT,
264 // R16G16B16 SFLOAT
265 BASE_FORMAT_R16G16B16_UNORM,
266
267 // R16G16B16A16 UNORM
268 BASE_FORMAT_R8G8B8A8_UNORM, // fallback to 8 bit channels
269 // R16G16B16A16 SNORM
270 BASE_FORMAT_R16G16B16A16_UNORM,
271 // R16G16B16A16 USCALED
272 BASE_FORMAT_R16G16B16A16_UNORM,
273 // R16G16B16A16 SSCALED
274 BASE_FORMAT_R16G16B16A16_SNORM,
275 // R16G16B16A16 UINT
276 BASE_FORMAT_R16G16B16A16_UNORM,
277 // R16G16B16A16 SINT
278 BASE_FORMAT_R16G16B16A16_UINT,
279 // R16G16B16A16 SFLOAT
280 BASE_FORMAT_R16G16B16A16_UNORM,
281
282 // R32 UINT
283 BASE_FORMAT_R16_UINT, // fallback to 16 bit channel
284 // R32 SINT
285 BASE_FORMAT_R32_UINT,
286 // R32 SFLOAT
287 BASE_FORMAT_R32_UINT,
288
289 // R32G32 UINT
290 BASE_FORMAT_R16G16_UINT, // fallback to 16 bit channels
291 // R32G32 SINT
292 BASE_FORMAT_R32G32_UINT,
293 // R32G32 SFLOAT
294 BASE_FORMAT_R32G32_UINT,
295
296 // R32G32B32 UINT
297 BASE_FORMAT_R32G32B32A32_UINT, // fallback to 4 channels
298 // R32G32B32 SINT
299 BASE_FORMAT_R32G32B32_UINT,
300 // R32G32B32 SFLOAT
301 BASE_FORMAT_R32G32B32_UINT,
302
303 // R32G32B32A32 UINT
304 BASE_FORMAT_R16G16B16A16_UINT, // fallback to 16 bit channels
305 // R32G32B32A32 SINT
306 BASE_FORMAT_R32G32B32A32_UINT,
307 // R32G32B32A32 SFLOAT
308 BASE_FORMAT_R32G32B32A32_UINT,
309
310 // R64 UINT
311 BASE_FORMAT_R32_UINT, // fallback to 32 bit channel
312 // R64 SINT
313 BASE_FORMAT_R64_UINT,
314 // R64 SFLOAT
315 BASE_FORMAT_R64_UINT,
316
317 // R64G64 UINT
318 BASE_FORMAT_R64G64B64A64_UINT, // fallback to 4 channels
319 // R64G64 SINT
320 BASE_FORMAT_R64G64_UINT,
321 // R64G64 SFLOAT
322 BASE_FORMAT_R64G64_UINT,
323
324 // R64G64B64 UINT
325 BASE_FORMAT_R64G64B64A64_UINT, // fallback to 4 channels
326 // R64G64B64 SINT
327 BASE_FORMAT_R64G64B64_UINT,
328 // R64G64B64 SFLOAT
329 BASE_FORMAT_R64G64B64_UINT,
330
331 // R64G64B64A64 UINT
332 BASE_FORMAT_R32G32B32A32_UINT, // fallback to 32 bit channels
333 // R64G64B64A64 SINT
334 BASE_FORMAT_R64G64B64A64_UINT,
335 // R32G32B32A32 SFLOAT
336 BASE_FORMAT_R64G64B64A64_UINT,
337
338 // B10G11R11 UFLOAT PACK32
339 BASE_FORMAT_R16G16B16A16_SFLOAT, // fallback to 4 channel, 16 bit HDR
340
341 // E5B9G9R9 UFLOAT PACK32
342 BASE_FORMAT_R16G16B16A16_SFLOAT, // fallback to 4 channel, 16 bit HDR
343
344 // D16 UNORM
345 BASE_FORMAT_D32_SFLOAT, // fallback to 32 bit depth only
346 // X8 D24 UNORM PACK32
347 BASE_FORMAT_D32_SFLOAT,
348 // D32 SFLOAT
349 BASE_FORMAT_X8_D24_UNORM_PACK32,
350 // S8 UINT
351 BASE_FORMAT_D24_UNORM_S8_UINT,
352 // D16 UNORM S8 UINT
353 BASE_FORMAT_D24_UNORM_S8_UINT,
354 // D24 UNORM S8 UINT
355 BASE_FORMAT_D32_SFLOAT_S8_UINT,
356 // D32 SFLOAT S8 UINT
357 BASE_FORMAT_D24_UNORM_S8_UINT,
358
359 // BC1 RGB UNORM BLOCK
360 BASE_FORMAT_UNDEFINED, // undefined
361 // BC1 RGB SRGB BLOCK
362 BASE_FORMAT_BC1_RGB_UNORM_BLOCK,
363 // BC1 RGBA UNORM BLOCK
364 BASE_FORMAT_UNDEFINED, // undefined
365 // BC1 RGBA SRGB BLOCK
366 BASE_FORMAT_BC1_RGBA_UNORM_BLOCK,
367 // BC2 UNORM BLOCK
368 BASE_FORMAT_UNDEFINED, // undefined
369 // BC2 SRGB BLOCK
370 BASE_FORMAT_BC2_UNORM_BLOCK,
371 // BC3 UNORM BLOCK
372 BASE_FORMAT_UNDEFINED, // undefined
373 // BC3 SRGB BLOCK
374 BASE_FORMAT_BC3_UNORM_BLOCK,
375 // BC4 UNORM BLOCK
376 BASE_FORMAT_UNDEFINED, // undefined
377 // BC4 SNORM BLOCK
378 BASE_FORMAT_BC4_UNORM_BLOCK,
379 // BC5 UNORM BLOCK
380 BASE_FORMAT_UNDEFINED, // undefined
381 // BC5 SNORM BLOCK
382 BASE_FORMAT_BC5_UNORM_BLOCK,
383 // BC6H UFLOAT BLOCK
384 BASE_FORMAT_UNDEFINED, // undefined
385 // BC6H SFLOAT BLOCK
386 BASE_FORMAT_BC6H_UFLOAT_BLOCK,
387 // BC7 UNORM BLOCK
388 BASE_FORMAT_UNDEFINED, // undefined
389 // BC7 SRGB BLOCK
390 BASE_FORMAT_BC7_UNORM_BLOCK,
391
392 // ETC2 R8G8B8 UNORM BLOCK
393 BASE_FORMAT_UNDEFINED, // undefined
394 // ETC2 R8G8B8 SRGB BLOCK
395 BASE_FORMAT_ETC2_R8G8B8_UNORM_BLOCK,
396 // ETC2 R8G8B8A1 UNORM BLOCK
397 BASE_FORMAT_UNDEFINED,
398 // ETC2 R8G8B8A1 SRGB BLOCK
399 BASE_FORMAT_ETC2_R8G8B8A1_UNORM_BLOCK,
400 // ETC2 R8G8B8A8 UNORM BLOCK
401 BASE_FORMAT_UNDEFINED,
402 // ETC2 R8G8B8A8 SRGB BLOCK
403 BASE_FORMAT_ETC2_R8G8B8A8_UNORM_BLOCK,
404
405 // EAC R11 UNORM BLOCK
406 BASE_FORMAT_UNDEFINED, // undefined
407 // EAC R11 SNORM BLOCK
408 BASE_FORMAT_EAC_R11_UNORM_BLOCK,
409 // EAC R11G11 UNORM BLOCK
410 BASE_FORMAT_UNDEFINED, // undefined
411 // EAC R11G11 SNORM BLOCK
412 BASE_FORMAT_EAC_R11G11_UNORM_BLOCK,
413
414 // ASTC 4x4 UNORM BLOCK
415 BASE_FORMAT_UNDEFINED, // undefined
416 // ASTC 4x4 SRGB BLOCK
417 BASE_FORMAT_ASTC_4x4_UNORM_BLOCK,
418 // ASTC 5x4 UNORM BLOCK
419 BASE_FORMAT_UNDEFINED, // undefined
420 // ASTC 5x4 SRGB BLOCK
421 BASE_FORMAT_ASTC_5x4_UNORM_BLOCK,
422 // ASTC 5x5 UNORM BLOCK
423 BASE_FORMAT_UNDEFINED, // undefined
424 // ASTC 5x5 SRGB BLOCK
425 BASE_FORMAT_ASTC_5x5_UNORM_BLOCK,
426 // ASTC 6x5 UNORM BLOCK
427 BASE_FORMAT_UNDEFINED, // undefined
428 // ASTC 6x5 SRGB BLOCK
429 BASE_FORMAT_ASTC_6x5_UNORM_BLOCK,
430 // ASTC 6x6 UNORM BLOCK
431 BASE_FORMAT_UNDEFINED, // undefined
432 // ASTC 6x6 SRGB BLOCK
433 BASE_FORMAT_ASTC_6x6_UNORM_BLOCK,
434 // ASTC 8x5 UNORM BLOCK
435 BASE_FORMAT_UNDEFINED, // undefined
436 // ASTC 8x5 SRGB BLOCK
437 BASE_FORMAT_ASTC_8x5_UNORM_BLOCK,
438 // ASTC 8x6 UNORM BLOCK
439 BASE_FORMAT_UNDEFINED, // undefined
440 // ASTC 8x6 SRGB BLOCK
441 BASE_FORMAT_ASTC_8x6_UNORM_BLOCK,
442 // ASTC 8x8 UNORM BLOCK
443 BASE_FORMAT_UNDEFINED, // undefined
444 // ASTC 8x8 SRGB BLOCK
445 BASE_FORMAT_ASTC_8x8_UNORM_BLOCK,
446 // ASTC 10x5 UNORM BLOCK
447 BASE_FORMAT_UNDEFINED, // undefined
448 // ASTC 10x5 SRGB BLOCK
449 BASE_FORMAT_ASTC_10x5_UNORM_BLOCK,
450 // ASTC 10x6 UNORM BLOCK
451 BASE_FORMAT_UNDEFINED, // undefined
452 // ASTC 10x6 SRGB BLOCK
453 BASE_FORMAT_ASTC_10x6_UNORM_BLOCK,
454 // ASTC 10x8 UNORM BLOCK
455 BASE_FORMAT_UNDEFINED, // undefined
456 // ASTC 10x8 SRGB BLOCK
457 BASE_FORMAT_ASTC_10x8_UNORM_BLOCK,
458 // ASTC 10x10 UNORM BLOCK
459 BASE_FORMAT_UNDEFINED, // undefined
460 // ASTC 10x10 SRGB BLOCK
461 BASE_FORMAT_ASTC_10x10_UNORM_BLOCK,
462 // ASTC 12x10 UNORM BLOCK
463 BASE_FORMAT_UNDEFINED, // undefined
464 // ASTC 12x10 SRGB BLOCK
465 BASE_FORMAT_ASTC_12x10_UNORM_BLOCK,
466 // ASTC 12x12 UNORM BLOCK
467 BASE_FORMAT_UNDEFINED, // undefined
468 // ASTC 12x12 SRGB BLOCK
469 BASE_FORMAT_ASTC_12x12_UNORM_BLOCK,
470 };
471
472 constexpr const auto LINEAR_FORMAT_COUNT = BASE_NS::Format::BASE_FORMAT_ASTC_12x12_SRGB_BLOCK + 1u;
473 PLUGIN_STATIC_ASSERT(BASE_NS::countof(FALLBACK_FORMATS) == LINEAR_FORMAT_COUNT);
474
CreateDepthBuffer(const DeviceBackendType backendType,const Swapchain & swapchain,GpuResourceManager & gpuResourceManager,Device::InternalSwapchainData & swapchainData)475 void CreateDepthBuffer(const DeviceBackendType backendType, const Swapchain& swapchain,
476 GpuResourceManager& gpuResourceManager, Device::InternalSwapchainData& swapchainData)
477 {
478 #if (RENDER_VALIDATION_ENABLED == 1)
479 PLUGIN_LOG_I("RENDER_VALIDATION: Default swapchain depth buffer created.");
480 #endif
481 swapchainData.additionalDepthBufferHandle = gpuResourceManager.Create(
482 DefaultEngineGpuResourceConstants::CORE_DEFAULT_BACKBUFFER_DEPTH, swapchain.GetDescDepthBuffer());
483 }
484 } // namespace
485
Device(RenderContext & renderContext,const DeviceCreateInfo & deviceCreateInfo)486 Device::Device(RenderContext& renderContext, const DeviceCreateInfo& deviceCreateInfo) : renderContext_(renderContext)
487 {
488 if ((deviceConfiguration_.bufferingCount < MIN_BUFFERING_COUNT) ||
489 (deviceConfiguration_.bufferingCount > MAX_BUFFERING_COUNT)) {
490 deviceConfiguration_.bufferingCount =
491 std::clamp(deviceConfiguration_.bufferingCount, MIN_BUFFERING_COUNT, MAX_BUFFERING_COUNT);
492 PLUGIN_LOG_D("buffering count clamped to: %u", deviceConfiguration_.bufferingCount);
493 }
494 }
495
CreateSwapchainImpl(const SwapchainCreateInfo & swapchainCreateInfo,const RenderHandleReference & replacedHandle,const string_view name)496 RenderHandleReference Device::CreateSwapchainImpl(
497 const SwapchainCreateInfo& swapchainCreateInfo, const RenderHandleReference& replacedHandle, const string_view name)
498 {
499 Activate();
500 // NOTE: with optimal implementation shouldn't be needed here
501 WaitForIdle();
502
503 uint32_t swapchainIdx = static_cast<uint32_t>(swapchains_.size());
504 bool replace = false;
505 // check if the handle needs to be replaced
506 RenderHandleReference finalReplaceHandle = replacedHandle;
507 {
508 const RenderHandle rawReplaceHandle = finalReplaceHandle.GetHandle();
509 const bool checkReplaceHandle = RenderHandleUtil::IsValid(rawReplaceHandle);
510 const bool checkReplaceWindow = (swapchainCreateInfo.window.window != 0);
511 const bool checkReplaceSurface = (swapchainCreateInfo.surfaceHandle != 0);
512 for (uint32_t idx = 0; idx < swapchains_.size(); ++idx) {
513 const auto& cmpSwap = swapchains_[idx];
514 // if window is the same, or surface is the same, or handle is the same
515 // -> re-use the old handle
516 replace = replace || (checkReplaceWindow && (cmpSwap.window == swapchainCreateInfo.window.window));
517 replace = replace || (checkReplaceSurface && (cmpSwap.surfaceHandle == swapchainCreateInfo.surfaceHandle));
518 replace = replace ||
519 (checkReplaceHandle && ((cmpSwap.remappableSwapchainImage.GetHandle() == rawReplaceHandle) ||
520 (cmpSwap.remappableAdditionalSwapchainImage == rawReplaceHandle)));
521 if (replace) {
522 #if (RENDER_VALIDATION_ENABLED == 1)
523 {
524 RenderHandle printHandle = cmpSwap.remappableSwapchainImage.GetHandle();
525 if (!RenderHandleUtil::IsValid(printHandle)) {
526 printHandle = cmpSwap.remappableAdditionalSwapchainImage;
527 }
528 PLUGIN_LOG_I("RENDER_VALIDATION: Replacing old swapchain handle %" PRIx64, printHandle.id);
529 }
530 #endif
531 swapchainIdx = idx;
532 finalReplaceHandle = swapchains_[swapchainIdx].remappableSwapchainImage;
533 swapchains_[swapchainIdx] = {};
534 DestroyDeviceSwapchain(); // NOTE: GLES handling
535 break;
536 }
537 }
538 }
539
540 if ((!replace) && (swapchains_.size() == DeviceConstants::MAX_SWAPCHAIN_COUNT)) {
541 PLUGIN_LOG_W("Only (%u) swapchains supported.", DeviceConstants::MAX_SWAPCHAIN_COUNT);
542 Deactivate();
543 return {};
544 }
545
546 if (!replace) {
547 swapchains_.push_back({});
548 }
549 auto& swapchainData = swapchains_[swapchainIdx];
550 swapchainData = {};
551 swapchainData.swapchain = CreateDeviceSwapchain(swapchainCreateInfo);
552 if (!swapchainData.swapchain) {
553 Deactivate();
554 return {};
555 }
556
557 {
558 vector<unique_ptr<GpuImage>> swapchainGpuImages = CreateGpuImageViews(*swapchainData.swapchain);
559 Deactivate();
560
561 // create shallow handle with handle in the name
562 GpuImageDesc shallowDesc = swapchainData.swapchain->GetDesc();
563 shallowDesc.width = 2u;
564 shallowDesc.height = 2u;
565 swapchainData.surfaceHandle = swapchainCreateInfo.surfaceHandle;
566 swapchainData.window = swapchainCreateInfo.window.window;
567 swapchainData.globalName = name;
568 swapchainData.name = DefaultEngineGpuResourceConstants::CORE_DEFAULT_SWAPCHAIN +
569 to_hex(swapchainData.swapchain->GetSurfaceHandle()) + '_';
570 swapchainData.remappableSwapchainImage =
571 gpuResourceMgr_->CreateSwapchainImage(finalReplaceHandle, name, shallowDesc);
572 PLUGIN_ASSERT(SwapchainData::MAX_IMAGE_VIEW_COUNT >= static_cast<uint32_t>(swapchainGpuImages.size()));
573 swapchainData.imageViewCount = static_cast<uint32_t>(swapchainGpuImages.size());
574 for (uint32_t idx = 0; idx < swapchainGpuImages.size(); ++idx) {
575 const auto& ref = swapchainGpuImages[idx];
576 swapchainData.imageViews[idx] = gpuResourceMgr_->CreateView(
577 swapchainData.name + to_string(idx), ref->GetDesc(), ref->GetBasePlatformData());
578 }
579
580 Activate();
581 }
582 {
583 Deactivate();
584 if (swapchainData.imageViewCount > 0U) {
585 const RenderHandle firstSwapchain = swapchainData.imageViews[0U].GetHandle();
586 gpuResourceMgr_->RemapGpuImageHandle(swapchainData.remappableSwapchainImage.GetHandle(), firstSwapchain);
587 // check for default swapchain existance and remap
588 if (!defaultSwapchainHandle_) {
589 const RenderHandle shallowHandle =
590 gpuResourceMgr_->GetImageRawHandle(DefaultEngineGpuResourceConstants::CORE_DEFAULT_BACKBUFFER);
591 gpuResourceMgr_->RemapGpuImageHandle(shallowHandle, firstSwapchain);
592 swapchainData.remappableAdditionalSwapchainImage = shallowHandle;
593 // store, that we use default built-in swapchain for backbuffer
594 defaultSwapchainHandle_ = swapchainData.remappableSwapchainImage;
595 }
596 }
597 }
598
599 // configure automatically backbuffer as swapchain
600 {
601 IRenderDataStoreManager& rdsm = renderContext_.GetRenderDataStoreManager();
602 auto dataStorePod = static_cast<IRenderDataStorePod*>(rdsm.GetRenderDataStore(RenderDataStorePod::TYPE_NAME));
603 if (dataStorePod) {
604 auto const dataView = dataStorePod->Get("NodeGraphBackBufferConfiguration");
605 PLUGIN_ASSERT(dataView.size_bytes() == sizeof(NodeGraphBackBufferConfiguration));
606 NodeGraphBackBufferConfiguration ngbbc = *(const NodeGraphBackBufferConfiguration*)dataView.data();
607 StringUtil::CopyStringToArray(DefaultEngineGpuResourceConstants::CORE_DEFAULT_BACKBUFFER,
608 ngbbc.backBufferName, NodeGraphBackBufferConfiguration::CORE_MAX_BACK_BUFFER_NAME_LENGTH);
609 ngbbc.backBufferType = NodeGraphBackBufferConfiguration::BackBufferType::SWAPCHAIN;
610 ngbbc.present = true;
611 dataStorePod->Set("NodeGraphBackBufferConfiguration", arrayviewU8(ngbbc));
612 }
613 }
614 if ((defaultSwapchainHandle_.GetHandle() == swapchainData.remappableSwapchainImage.GetHandle()) &&
615 (swapchainCreateInfo.swapchainFlags & SwapchainFlagBits::CORE_SWAPCHAIN_DEPTH_BUFFER_BIT)) {
616 CreateDepthBuffer(GetBackendType(), *swapchainData.swapchain, *gpuResourceMgr_, swapchainData);
617 }
618 #if (RENDER_VALIDATION_ENABLED == 1)
619 if ((defaultSwapchainHandle_.GetHandle() != swapchainData.remappableSwapchainImage.GetHandle()) &&
620 (swapchainCreateInfo.swapchainFlags & SwapchainFlagBits::CORE_SWAPCHAIN_DEPTH_BUFFER_BIT)) {
621 PLUGIN_LOG_W("RENDER_VALIDATION: Automatic swapchain depth buffer creation supported for default swapchain.");
622 }
623 #endif
624
625 return swapchainData.remappableSwapchainImage;
626 }
627
CreateSwapchainHandle(const SwapchainCreateInfo & swapchainCreateInfo,const RenderHandleReference & replacedHandle,const string_view name)628 RenderHandleReference Device::CreateSwapchainHandle(
629 const SwapchainCreateInfo& swapchainCreateInfo, const RenderHandleReference& replacedHandle, const string_view name)
630 {
631 if (replacedHandle.GetHandle() == defaultSwapchainHandle_.GetHandle()) {
632 // first safety destroy for legacy default swapchain
633 DestroySwapchainImpl(defaultSwapchainHandle_);
634 }
635 return CreateSwapchainImpl(swapchainCreateInfo, replacedHandle, name);
636 }
637
CreateSwapchainHandle(const SwapchainCreateInfo & swapchainCreateInfo)638 RenderHandleReference Device::CreateSwapchainHandle(const SwapchainCreateInfo& swapchainCreateInfo)
639 {
640 // first safety destroy for legacy default swapchain
641 DestroySwapchainImpl(defaultSwapchainHandle_);
642 return CreateSwapchainImpl(swapchainCreateInfo, {}, {});
643 }
644
CreateSwapchain(const SwapchainCreateInfo & swapchainCreateInfo)645 void Device::CreateSwapchain(const SwapchainCreateInfo& swapchainCreateInfo)
646 {
647 // first safety destroy for legacy default swapchain
648 DestroySwapchainImpl(defaultSwapchainHandle_);
649 CreateSwapchainImpl(swapchainCreateInfo, {}, {});
650 }
651
DestroySwapchainImpl(const RenderHandleReference & handle)652 void Device::DestroySwapchainImpl(const RenderHandleReference& handle)
653 {
654 // NOTE: the destruction should be deferred, but we expect this to be called from rendering thread
655 if (isRenderbackendRunning_) {
656 // NOTE: we are currently only sending error message and not trying to prevent
657 PLUGIN_LOG_E("DestroySwapchain called while RenderFrame is running");
658 }
659
660 if (handle) {
661 const RenderHandle rawHandle = handle.GetHandle();
662 for (auto iter = swapchains_.cbegin(); iter != swapchains_.cend(); ++iter) {
663 if (iter->remappableSwapchainImage.GetHandle() == rawHandle) {
664 Activate();
665 WaitForIdle();
666
667 swapchains_.erase(iter);
668
669 DestroyDeviceSwapchain();
670 // remove swapchain configuration from the backbuffer
671 if ((handle.GetHandle() == defaultSwapchainHandle_.GetHandle()) || (!handle)) {
672 IRenderDataStoreManager& rdsm = renderContext_.GetRenderDataStoreManager();
673 auto dataStorePod =
674 static_cast<IRenderDataStorePod*>(rdsm.GetRenderDataStore(RenderDataStorePod::TYPE_NAME));
675 if (dataStorePod) {
676 auto const dataView = dataStorePod->Get("NodeGraphBackBufferConfiguration");
677 PLUGIN_ASSERT(dataView.size_bytes() == sizeof(NodeGraphBackBufferConfiguration));
678 NodeGraphBackBufferConfiguration ngbbc =
679 *(const NodeGraphBackBufferConfiguration*)dataView.data();
680 if (ngbbc.backBufferType == NodeGraphBackBufferConfiguration::BackBufferType::SWAPCHAIN) {
681 ngbbc.backBufferType = NodeGraphBackBufferConfiguration::BackBufferType::UNDEFINED;
682 ngbbc.present = false;
683 }
684 dataStorePod->Set("NodeGraphBackBufferConfiguration", arrayviewU8(ngbbc));
685 }
686 }
687 Deactivate();
688
689 // destroy default swapchain handle if it was in use
690 if (handle.GetHandle() == defaultSwapchainHandle_.GetHandle()) {
691 defaultSwapchainHandle_ = {};
692 }
693
694 // element erased -> break
695 break;
696 }
697 }
698 }
699 }
700
DestroySwapchain()701 void Device::DestroySwapchain()
702 {
703 DestroySwapchainImpl(defaultSwapchainHandle_);
704 }
705
DestroySwapchain(const RenderHandleReference & handle)706 void Device::DestroySwapchain(const RenderHandleReference& handle)
707 {
708 DestroySwapchainImpl(handle);
709 }
710
GetSurfaceTransformFlags(const RenderHandle & handle) const711 SurfaceTransformFlags Device::GetSurfaceTransformFlags(const RenderHandle& handle) const
712 {
713 // NOTE: we lock data hear to check for the transforms flags
714 // the flags should be stored, and the data should not be locked for every frame access
715 if (RenderHandleUtil::IsSwapchain(handle)) {
716 for (const auto& swapchain : swapchains_) {
717 if (((swapchain.remappableSwapchainImage.GetHandle() == handle) ||
718 (swapchain.remappableAdditionalSwapchainImage == handle)) &&
719 (swapchain.swapchain)) {
720 return swapchain.swapchain->GetSurfaceTransformFlags();
721 }
722 }
723 }
724 return 0u;
725 }
726
FrameStart()727 void Device::FrameStart()
728 {
729 ++frameCount_;
730 }
731
FrameEnd()732 void Device::FrameEnd() {}
733
SetDeviceStatus(const bool status)734 void Device::SetDeviceStatus(const bool status)
735 {
736 deviceStatus_.store(status);
737 }
738
GetDeviceStatus() const739 bool Device::GetDeviceStatus() const
740 {
741 return deviceStatus_.load();
742 };
GetFrameCount() const743 uint64_t Device::GetFrameCount() const
744 {
745 return frameCount_;
746 }
747
GetCommonDeviceProperties() const748 const CommonDeviceProperties& Device::GetCommonDeviceProperties() const
749 {
750 return commonDeviceProperties_;
751 }
752
GetSharedMemoryPropertyFlags() const753 MemoryPropertyFlags Device::GetSharedMemoryPropertyFlags() const
754 {
755 return deviceSharedMemoryPropertyFlags_;
756 }
757
GetDeviceConfiguration() const758 DeviceConfiguration Device::GetDeviceConfiguration() const
759 {
760 return deviceConfiguration_;
761 }
762
GetCommandBufferingCount() const763 uint32_t Device::GetCommandBufferingCount() const
764 {
765 return deviceConfiguration_.bufferingCount;
766 }
767
HasSwapchain() const768 bool Device::HasSwapchain() const
769 {
770 return (!swapchains_.empty());
771 }
772
GetSwapchain(const RenderHandle handle) const773 const Swapchain* Device::GetSwapchain(const RenderHandle handle) const
774 {
775 const RenderHandle cmpHandle = RenderHandleUtil::IsValid(handle) ? handle : defaultSwapchainHandle_.GetHandle();
776 // NOTE: returns a pointer to data which could be destroyed
777 // if the API documentation and restrictions are not applied by the user
778 for (const auto& swapData : swapchains_) {
779 if (((swapData.remappableSwapchainImage.GetHandle() == cmpHandle) ||
780 (swapData.remappableAdditionalSwapchainImage == cmpHandle)) &&
781 (swapData.swapchain)) {
782 return swapData.swapchain.get();
783 }
784 }
785 return nullptr;
786 }
787
GetSwapchainData(const RenderHandle handle) const788 Device::SwapchainData Device::GetSwapchainData(const RenderHandle handle) const
789 {
790 PLUGIN_ASSERT(isRenderbackendRunning_);
791
792 const RenderHandle cmpHandle = RenderHandleUtil::IsValid(handle) ? handle : defaultSwapchainHandle_.GetHandle();
793 for (const auto& swapData : swapchains_) {
794 if (((swapData.remappableSwapchainImage.GetHandle() == cmpHandle) ||
795 (swapData.remappableAdditionalSwapchainImage == cmpHandle)) &&
796 (swapData.swapchain)) {
797 SwapchainData sd;
798 // comparison handle should be a valid handle here and is used in image re-mapping
799 sd.remappableSwapchainImage = cmpHandle;
800 PLUGIN_ASSERT(swapData.imageViewCount <= SwapchainData::MAX_IMAGE_VIEW_COUNT);
801 sd.imageViewCount = swapData.imageViewCount;
802 for (uint32_t idx = 0; idx < swapData.imageViewCount; ++idx) {
803 sd.imageViews[idx] = swapData.imageViews[idx].GetHandle();
804 }
805 return sd;
806 }
807 }
808 return {};
809 }
810
SetLockResourceBackendAccess(const bool value)811 void Device::SetLockResourceBackendAccess(const bool value)
812 {
813 isBackendResourceAccessLocked_ = value;
814 }
815
GetLockResourceBackendAccess() const816 bool Device::GetLockResourceBackendAccess() const
817 {
818 return isBackendResourceAccessLocked_;
819 }
820
SetRenderBackendRunning(const bool value)821 void Device::SetRenderBackendRunning(const bool value)
822 {
823 isRenderbackendRunning_ = value;
824 }
825
SetRenderFrameRunning(const bool value)826 void Device::SetRenderFrameRunning(const bool value)
827 {
828 isRenderFrameRunning_ = value;
829 }
830
GetRenderFrameRunning() const831 bool Device::GetRenderFrameRunning() const
832 {
833 return isRenderFrameRunning_;
834 }
835
GetGpuResourceManager() const836 IGpuResourceManager& Device::GetGpuResourceManager() const
837 {
838 return *gpuResourceMgr_;
839 }
840
GetShaderManager() const841 IShaderManager& Device::GetShaderManager() const
842 {
843 return *shaderMgr_;
844 }
845
SetBackendConfig(const BackendConfig & config)846 void Device::SetBackendConfig(const BackendConfig& config) {}
847
GetFormatOrFallback(const Format inputFormat) const848 Format Device::GetFormatOrFallback(const Format inputFormat) const
849 {
850 Format format = inputFormat;
851 if (static_cast<uint32_t>(format) < LINEAR_FORMAT_COUNT) {
852 auto properties = GetFormatProperties(format);
853 #if (RENDER_VALIDATION_ENABLED == 1)
854 uint32_t fallbackCount = 0U;
855 #endif
856 while (format != Format::BASE_FORMAT_UNDEFINED && !properties.linearTilingFeatures &&
857 !properties.optimalTilingFeatures) {
858 format = FALLBACK_FORMATS[format];
859 properties = GetFormatProperties(format);
860 #if (RENDER_VALIDATION_ENABLED == 1)
861 fallbackCount++;
862 #endif
863 }
864 #if (RENDER_VALIDATION_ENABLED == 1)
865 if (fallbackCount > 0U) {
866 PLUGIN_LOG_I("RENDER_VALIDATION: input format (%u) fallback format (%u)",
867 static_cast<uint32_t>(inputFormat), static_cast<uint32_t>(format));
868 }
869 #endif
870 }
871 return format;
872 }
873 RENDER_END_NAMESPACE()
874