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