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