18bf80f4bSopenharmony_ci/*
28bf80f4bSopenharmony_ci * Copyright (c) 2024 Huawei Device Co., Ltd.
38bf80f4bSopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License");
48bf80f4bSopenharmony_ci * you may not use this file except in compliance with the License.
58bf80f4bSopenharmony_ci * You may obtain a copy of the License at
68bf80f4bSopenharmony_ci *
78bf80f4bSopenharmony_ci *     http://www.apache.org/licenses/LICENSE-2.0
88bf80f4bSopenharmony_ci *
98bf80f4bSopenharmony_ci * Unless required by applicable law or agreed to in writing, software
108bf80f4bSopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS,
118bf80f4bSopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
128bf80f4bSopenharmony_ci * See the License for the specific language governing permissions and
138bf80f4bSopenharmony_ci * limitations under the License.
148bf80f4bSopenharmony_ci */
158bf80f4bSopenharmony_ci
168bf80f4bSopenharmony_ci#include "device_vk.h"
178bf80f4bSopenharmony_ci
188bf80f4bSopenharmony_ci#include <algorithm>
198bf80f4bSopenharmony_ci#include <cinttypes>
208bf80f4bSopenharmony_ci#include <cstdint>
218bf80f4bSopenharmony_ci#include <vulkan/vulkan_core.h>
228bf80f4bSopenharmony_ci
238bf80f4bSopenharmony_ci#include <base/containers/vector.h>
248bf80f4bSopenharmony_ci#include <base/math/mathf.h>
258bf80f4bSopenharmony_ci#include <core/engine_info.h>
268bf80f4bSopenharmony_ci#include <render/intf_render_context.h>
278bf80f4bSopenharmony_ci#include <render/namespace.h>
288bf80f4bSopenharmony_ci
298bf80f4bSopenharmony_ci#include "device/device.h"
308bf80f4bSopenharmony_ci#include "device/gpu_program_util.h"
318bf80f4bSopenharmony_ci#include "device/gpu_resource_manager.h"
328bf80f4bSopenharmony_ci#include "device/shader_manager.h"
338bf80f4bSopenharmony_ci#include "device/shader_module.h"
348bf80f4bSopenharmony_ci#include "platform_vk.h"
358bf80f4bSopenharmony_ci#include "util/log.h"
368bf80f4bSopenharmony_ci#include "vulkan/create_functions_vk.h"
378bf80f4bSopenharmony_ci#include "vulkan/gpu_buffer_vk.h"
388bf80f4bSopenharmony_ci#include "vulkan/gpu_image_vk.h"
398bf80f4bSopenharmony_ci#include "vulkan/gpu_memory_allocator_vk.h"
408bf80f4bSopenharmony_ci#include "vulkan/gpu_program_vk.h"
418bf80f4bSopenharmony_ci#include "vulkan/gpu_query_vk.h"
428bf80f4bSopenharmony_ci#include "vulkan/gpu_sampler_vk.h"
438bf80f4bSopenharmony_ci#include "vulkan/gpu_semaphore_vk.h"
448bf80f4bSopenharmony_ci#include "vulkan/node_context_descriptor_set_manager_vk.h"
458bf80f4bSopenharmony_ci#include "vulkan/node_context_pool_manager_vk.h"
468bf80f4bSopenharmony_ci#include "vulkan/pipeline_state_object_vk.h"
478bf80f4bSopenharmony_ci#include "vulkan/render_backend_vk.h"
488bf80f4bSopenharmony_ci#include "vulkan/render_frame_sync_vk.h"
498bf80f4bSopenharmony_ci#include "vulkan/shader_module_vk.h"
508bf80f4bSopenharmony_ci#include "vulkan/swapchain_vk.h"
518bf80f4bSopenharmony_ci#include "vulkan/validate_vk.h"
528bf80f4bSopenharmony_ci
538bf80f4bSopenharmony_ciusing namespace BASE_NS;
548bf80f4bSopenharmony_ci
558bf80f4bSopenharmony_ciRENDER_BEGIN_NAMESPACE()
568bf80f4bSopenharmony_cinamespace {
578bf80f4bSopenharmony_cistatic constexpr string_view DEVICE_EXTENSION_SWAPCHAIN { VK_KHR_SWAPCHAIN_EXTENSION_NAME };
588bf80f4bSopenharmony_ci
598bf80f4bSopenharmony_ci// promoted to 1.2, requires VK_KHR_create_renderpass2
608bf80f4bSopenharmony_cistatic constexpr string_view DEVICE_EXTENSION_DEPTH_STENCIL_RESOLVE { VK_KHR_DEPTH_STENCIL_RESOLVE_EXTENSION_NAME };
618bf80f4bSopenharmony_cistatic constexpr string_view DEVICE_EXTENSION_CREATE_RENDERPASS2 { VK_KHR_CREATE_RENDERPASS_2_EXTENSION_NAME };
628bf80f4bSopenharmony_ci
638bf80f4bSopenharmony_cistatic constexpr string_view DEVICE_EXTENSION_EXTERNAL_MEMORY { VK_KHR_EXTERNAL_MEMORY_EXTENSION_NAME };
648bf80f4bSopenharmony_cistatic constexpr string_view DEVICE_EXTENSION_GET_MEMORY_REQUIREMENTS2 {
658bf80f4bSopenharmony_ci    VK_KHR_GET_MEMORY_REQUIREMENTS_2_EXTENSION_NAME
668bf80f4bSopenharmony_ci};
678bf80f4bSopenharmony_cistatic constexpr string_view DEVICE_EXTENSION_SAMPLER_YCBCR_CONVERSION {
688bf80f4bSopenharmony_ci    VK_KHR_SAMPLER_YCBCR_CONVERSION_EXTENSION_NAME
698bf80f4bSopenharmony_ci};
708bf80f4bSopenharmony_cistatic constexpr string_view DEVICE_EXTENSION_QUEUE_FAMILY_FOREIGN { VK_EXT_QUEUE_FAMILY_FOREIGN_EXTENSION_NAME };
718bf80f4bSopenharmony_cistatic constexpr string_view DEVICE_EXTENSION_MULTIVIEW { VK_KHR_MULTIVIEW_EXTENSION_NAME };
728bf80f4bSopenharmony_cistatic constexpr string_view DEVICE_EXTENSION_MAINTENANCE4 = VK_KHR_MAINTENANCE_4_EXTENSION_NAME;
738bf80f4bSopenharmony_cistatic constexpr string_view DEVICE_EXTENSION_DESCRIPTOR_INDEXING = VK_EXT_DESCRIPTOR_INDEXING_EXTENSION_NAME;
748bf80f4bSopenharmony_ci
758bf80f4bSopenharmony_cistruct ChainWrapper {
768bf80f4bSopenharmony_ci    void** ppNextFeatures { nullptr };
778bf80f4bSopenharmony_ci    void** ppNextProperties { nullptr };
788bf80f4bSopenharmony_ci};
798bf80f4bSopenharmony_ci
808bf80f4bSopenharmony_cistruct PhysicalDeviceYcbcrStructsVk {
818bf80f4bSopenharmony_ci    VkPhysicalDeviceSamplerYcbcrConversionFeatures ycbcrConversionFeatures {};
828bf80f4bSopenharmony_ci};
838bf80f4bSopenharmony_ci
848bf80f4bSopenharmony_ci#if (RENDER_VULKAN_FSR_ENABLED == 1)
858bf80f4bSopenharmony_cistruct PhysicalDeviceFragmentShadingRateStructsVk {
868bf80f4bSopenharmony_ci    VkPhysicalDeviceFragmentShadingRateFeaturesKHR physicalDeviceFragmentShadingRateFeatures;
878bf80f4bSopenharmony_ci    VkPhysicalDeviceFragmentShadingRatePropertiesKHR physicalDeviceFragmentShadingRateProperties;
888bf80f4bSopenharmony_ci};
898bf80f4bSopenharmony_ci#endif
908bf80f4bSopenharmony_ci
918bf80f4bSopenharmony_ci#if (RENDER_VULKAN_RT_ENABLED == 1)
928bf80f4bSopenharmony_cistruct PhysicalDeviceRayTracingStructsVk {
938bf80f4bSopenharmony_ci    VkPhysicalDeviceBufferDeviceAddressFeatures physicalDeviceBufferDeviceAddressFeatures;
948bf80f4bSopenharmony_ci    VkPhysicalDeviceRayTracingPipelineFeaturesKHR physicalDeviceRayTracingPipelineFeatures;
958bf80f4bSopenharmony_ci    VkPhysicalDeviceAccelerationStructureFeaturesKHR physicalDeviceAccelerationStructureFeatures;
968bf80f4bSopenharmony_ci    VkPhysicalDeviceRayQueryFeaturesKHR physicalDeviceRayQueryFeatures;
978bf80f4bSopenharmony_ci};
988bf80f4bSopenharmony_ci#endif
998bf80f4bSopenharmony_ci
1008bf80f4bSopenharmony_cistruct PhysicalDeviceMultiviewStructsVk {
1018bf80f4bSopenharmony_ci    VkPhysicalDeviceMultiviewFeaturesKHR physicalDeviceMultiviewFeatures;
1028bf80f4bSopenharmony_ci    VkPhysicalDeviceMultiviewPropertiesKHR physicalDeviceMultiviewProperties;
1038bf80f4bSopenharmony_ci};
1048bf80f4bSopenharmony_ci
1058bf80f4bSopenharmony_cistruct PhysicalDeviceDesciptorIndexingStructsVk {
1068bf80f4bSopenharmony_ci    VkPhysicalDeviceDescriptorIndexingFeatures physicalDeviceDescriptorIndexingFeatures;
1078bf80f4bSopenharmony_ci    VkPhysicalDeviceDescriptorIndexingProperties physicalDeviceDescriptorIndexingProperties;
1088bf80f4bSopenharmony_ci};
1098bf80f4bSopenharmony_ci
1108bf80f4bSopenharmony_cistruct PhysicalDeviceMaintenance4Vk {
1118bf80f4bSopenharmony_ci    VkPhysicalDeviceMaintenance4Features maintenance4Features {};
1128bf80f4bSopenharmony_ci};
1138bf80f4bSopenharmony_ci
1148bf80f4bSopenharmony_cistruct ChainObjects {
1158bf80f4bSopenharmony_ci    unique_ptr<PhysicalDeviceYcbcrStructsVk> ycbcr;
1168bf80f4bSopenharmony_ci#if (RENDER_VULKAN_RT_ENABLED == 1)
1178bf80f4bSopenharmony_ci    unique_ptr<PhysicalDeviceRayTracingStructsVk> rt;
1188bf80f4bSopenharmony_ci#endif
1198bf80f4bSopenharmony_ci#if (RENDER_VULKAN_FSR_ENABLED == 1)
1208bf80f4bSopenharmony_ci    unique_ptr<PhysicalDeviceFragmentShadingRateStructsVk> fsr;
1218bf80f4bSopenharmony_ci#endif
1228bf80f4bSopenharmony_ci    unique_ptr<PhysicalDeviceMultiviewStructsVk> mv;
1238bf80f4bSopenharmony_ci    unique_ptr<PhysicalDeviceDesciptorIndexingStructsVk> di;
1248bf80f4bSopenharmony_ci    unique_ptr<PhysicalDeviceMaintenance4Vk> maintenance4;
1258bf80f4bSopenharmony_ci};
1268bf80f4bSopenharmony_ci
1278bf80f4bSopenharmony_ci// fragment shading rate
1288bf80f4bSopenharmony_ci#if (RENDER_VULKAN_FSR_ENABLED == 1)
1298bf80f4bSopenharmony_ci// VK_KHR_fragment_shading_rate, requires VK_KHR_create_renderpass2, requires VK_KHR_get_physical_device_properties2
1308bf80f4bSopenharmony_cistatic constexpr string_view DEVICE_EXTENSION_FRAGMENT_SHADING_RATE { VK_KHR_FRAGMENT_SHADING_RATE_EXTENSION_NAME };
1318bf80f4bSopenharmony_ci
1328bf80f4bSopenharmony_civoid GetPhysicalDeviceFragmentShadingRateStructs(ChainObjects& co, ChainWrapper& cw)
1338bf80f4bSopenharmony_ci{
1348bf80f4bSopenharmony_ci    co.fsr = make_unique<PhysicalDeviceFragmentShadingRateStructsVk>();
1358bf80f4bSopenharmony_ci    auto& fsr = co.fsr;
1368bf80f4bSopenharmony_ci    fsr->physicalDeviceFragmentShadingRateFeatures = {
1378bf80f4bSopenharmony_ci        VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FRAGMENT_SHADING_RATE_FEATURES_KHR, // sType
1388bf80f4bSopenharmony_ci        nullptr,                                                              // pNext
1398bf80f4bSopenharmony_ci        VK_FALSE,                                                             // pipelineFragmentShadingRate
1408bf80f4bSopenharmony_ci        VK_FALSE,                                                             // primitiveFragmentShadingRate
1418bf80f4bSopenharmony_ci        VK_FALSE,                                                             // attachmentFragmentShadingRate
1428bf80f4bSopenharmony_ci    };
1438bf80f4bSopenharmony_ci    *cw.ppNextFeatures = &fsr->physicalDeviceFragmentShadingRateFeatures;
1448bf80f4bSopenharmony_ci    cw.ppNextFeatures = &fsr->physicalDeviceFragmentShadingRateFeatures.pNext;
1458bf80f4bSopenharmony_ci
1468bf80f4bSopenharmony_ci    fsr->physicalDeviceFragmentShadingRateProperties = {
1478bf80f4bSopenharmony_ci        VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FRAGMENT_SHADING_RATE_PROPERTIES_KHR, // sType
1488bf80f4bSopenharmony_ci        nullptr,                                                                // pNext
1498bf80f4bSopenharmony_ci    };
1508bf80f4bSopenharmony_ci    *cw.ppNextProperties = &fsr->physicalDeviceFragmentShadingRateProperties;
1518bf80f4bSopenharmony_ci    cw.ppNextProperties = &fsr->physicalDeviceFragmentShadingRateProperties.pNext;
1528bf80f4bSopenharmony_ci}
1538bf80f4bSopenharmony_ci#endif
1548bf80f4bSopenharmony_ci
1558bf80f4bSopenharmony_civoid GetPhysicalDeviceMultiviewFeaturesStructs(ChainObjects& co, ChainWrapper& cw)
1568bf80f4bSopenharmony_ci{
1578bf80f4bSopenharmony_ci    co.mv = make_unique<PhysicalDeviceMultiviewStructsVk>();
1588bf80f4bSopenharmony_ci    auto& mv = co.mv;
1598bf80f4bSopenharmony_ci    mv->physicalDeviceMultiviewFeatures = {
1608bf80f4bSopenharmony_ci        VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MULTIVIEW_FEATURES_KHR, // sType
1618bf80f4bSopenharmony_ci        nullptr,                                                  // pNext
1628bf80f4bSopenharmony_ci        VK_FALSE,                                                 // multiview
1638bf80f4bSopenharmony_ci        VK_FALSE,                                                 // multiviewGeometryShader
1648bf80f4bSopenharmony_ci        VK_FALSE,                                                 // multiviewTessellationShader
1658bf80f4bSopenharmony_ci    };
1668bf80f4bSopenharmony_ci    *cw.ppNextFeatures = &mv->physicalDeviceMultiviewFeatures;
1678bf80f4bSopenharmony_ci    cw.ppNextFeatures = &mv->physicalDeviceMultiviewFeatures.pNext;
1688bf80f4bSopenharmony_ci
1698bf80f4bSopenharmony_ci    mv->physicalDeviceMultiviewProperties = {
1708bf80f4bSopenharmony_ci        VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MULTIVIEW_PROPERTIES_KHR, // sType
1718bf80f4bSopenharmony_ci        nullptr,                                                    // pNext
1728bf80f4bSopenharmony_ci        0,                                                          // maxMultiviewViewCount
1738bf80f4bSopenharmony_ci        0,                                                          // maxMultiviewInstanceIndex
1748bf80f4bSopenharmony_ci    };
1758bf80f4bSopenharmony_ci    *cw.ppNextProperties = &mv->physicalDeviceMultiviewProperties;
1768bf80f4bSopenharmony_ci    cw.ppNextProperties = &mv->physicalDeviceMultiviewProperties.pNext;
1778bf80f4bSopenharmony_ci}
1788bf80f4bSopenharmony_ci
1798bf80f4bSopenharmony_civoid GetPhysicalDeviceDescriptorIndexingFeaturesStructs(ChainObjects& co, ChainWrapper& cw)
1808bf80f4bSopenharmony_ci{
1818bf80f4bSopenharmony_ci    co.di = make_unique<PhysicalDeviceDesciptorIndexingStructsVk>();
1828bf80f4bSopenharmony_ci    auto& di = co.di;
1838bf80f4bSopenharmony_ci    di->physicalDeviceDescriptorIndexingFeatures = {
1848bf80f4bSopenharmony_ci        VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DESCRIPTOR_INDEXING_FEATURES, // sType
1858bf80f4bSopenharmony_ci        nullptr,                                                        // pNext
1868bf80f4bSopenharmony_ci        VK_FALSE,                                                       // shaderInputAttachmentArrayDynamicIndexing
1878bf80f4bSopenharmony_ci        VK_FALSE,                                                       // shaderUniformTexelBufferArrayDynamicIndexing
1888bf80f4bSopenharmony_ci        VK_FALSE,                                                       // shaderStorageTexelBufferArrayDynamicIndexing
1898bf80f4bSopenharmony_ci        VK_FALSE,                                                       // shaderUniformBufferArrayNonUniformIndexing
1908bf80f4bSopenharmony_ci        VK_FALSE,                                                       // shaderSampledImageArrayNonUniformIndexing
1918bf80f4bSopenharmony_ci        VK_FALSE,                                                       // shaderStorageBufferArrayNonUniformIndexing
1928bf80f4bSopenharmony_ci        VK_FALSE,                                                       // shaderStorageImageArrayNonUniformIndexing
1938bf80f4bSopenharmony_ci        VK_FALSE,                                                       // shaderInputAttachmentArrayNonUniformIndexing
1948bf80f4bSopenharmony_ci        VK_FALSE, // shaderUniformTexelBufferArrayNonUniformIndexing
1958bf80f4bSopenharmony_ci        VK_FALSE, // shaderStorageTexelBufferArrayNonUniformIndexing
1968bf80f4bSopenharmony_ci        VK_FALSE, // descriptorBindingUniformBufferUpdateAfterBind
1978bf80f4bSopenharmony_ci        VK_FALSE, // descriptorBindingSampledImageUpdateAsfterBind
1988bf80f4bSopenharmony_ci        VK_FALSE, // descriptorBindingStorageImageUpdateAfterBind
1998bf80f4bSopenharmony_ci        VK_FALSE, // descriptorBindingStorageBufferUpdateAfterBind
2008bf80f4bSopenharmony_ci        VK_FALSE, // descriptorBindingUniformTexelBufferUpdateAfterBind
2018bf80f4bSopenharmony_ci        VK_FALSE, // descriptorBindingStorageTexelBufferUpdateAfterBind
2028bf80f4bSopenharmony_ci        VK_FALSE, // descriptorBindingUpdateUnusedWhilePending
2038bf80f4bSopenharmony_ci        VK_FALSE, // descriptorBindingPartiallyBound
2048bf80f4bSopenharmony_ci        VK_FALSE, // descriptorBindingVariableDescriptorCount
2058bf80f4bSopenharmony_ci        VK_FALSE, // runtimeDescriptorArray
2068bf80f4bSopenharmony_ci    };
2078bf80f4bSopenharmony_ci    *cw.ppNextFeatures = &di->physicalDeviceDescriptorIndexingFeatures;
2088bf80f4bSopenharmony_ci    cw.ppNextFeatures = &di->physicalDeviceDescriptorIndexingFeatures.pNext;
2098bf80f4bSopenharmony_ci
2108bf80f4bSopenharmony_ci    di->physicalDeviceDescriptorIndexingProperties = {
2118bf80f4bSopenharmony_ci        VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DESCRIPTOR_INDEXING_PROPERTIES, // sType
2128bf80f4bSopenharmony_ci        nullptr,                                                          // pNext
2138bf80f4bSopenharmony_ci        0U,                                                               // maxUpdateAfterBindDescriptorsInAllPools
2148bf80f4bSopenharmony_ci        VK_FALSE, // shaderUniformBufferArrayNonUniformIndexingNative
2158bf80f4bSopenharmony_ci        VK_FALSE, // shaderSampledImageArrayNonUniformIndexingNative
2168bf80f4bSopenharmony_ci        VK_FALSE, // shaderStorageBufferArrayNonUniformIndexingNative
2178bf80f4bSopenharmony_ci        VK_FALSE, // shaderStorageImageArrayNonUniformIndexingNative
2188bf80f4bSopenharmony_ci        VK_FALSE, // shaderInputAttachmentArrayNonUniformIndexingNative
2198bf80f4bSopenharmony_ci        VK_FALSE, // robustBufferAccessUpdateAfterBind
2208bf80f4bSopenharmony_ci        VK_FALSE, // quadDivergentImplicitLod
2218bf80f4bSopenharmony_ci        0U,       // maxPerStageDescriptorUpdateAfterBindSamplers
2228bf80f4bSopenharmony_ci        0U,       // maxPerStageDescriptorUpdateAfterBindUniformBuffers
2238bf80f4bSopenharmony_ci        0U,       // maxPerStageDescriptorUpdateAfterBindStorageBuffers
2248bf80f4bSopenharmony_ci        0U,       // maxPerStageDescriptorUpdateAfterBindSampledImages
2258bf80f4bSopenharmony_ci        0U,       // maxPerStageDescriptorUpdateAfterBindStorageImages
2268bf80f4bSopenharmony_ci        0U,       // maxPerStageDescriptorUpdateAfterBindInputAttachments
2278bf80f4bSopenharmony_ci        0U,       // maxPerStageUpdateAfterBindResources
2288bf80f4bSopenharmony_ci        0U,       // maxDescriptorSetUpdateAfterBindSamplers
2298bf80f4bSopenharmony_ci        0U,       // maxDescriptorSetUpdateAfterBindUniformBuffers
2308bf80f4bSopenharmony_ci        0U,       // maxDescriptorSetUpdateAfterBindUniformBuffersDynamic
2318bf80f4bSopenharmony_ci        0U,       // maxDescriptorSetUpdateAfterBindStorageBuffers
2328bf80f4bSopenharmony_ci        0U,       // maxDescriptorSetUpdateAfterBindStorageBuffersDynamic
2338bf80f4bSopenharmony_ci        0U,       // maxDescriptorSetUpdateAfterBindSampledImages
2348bf80f4bSopenharmony_ci        0U,       // maxDescriptorSetUpdateAfterBindStorageImages
2358bf80f4bSopenharmony_ci        0U,       // maxDescriptorSetUpdateAfterBindInputAttachments
2368bf80f4bSopenharmony_ci    };
2378bf80f4bSopenharmony_ci    *cw.ppNextProperties = &di->physicalDeviceDescriptorIndexingProperties;
2388bf80f4bSopenharmony_ci    cw.ppNextProperties = &di->physicalDeviceDescriptorIndexingProperties.pNext;
2398bf80f4bSopenharmony_ci}
2408bf80f4bSopenharmony_ci
2418bf80f4bSopenharmony_ci// ray-tracing
2428bf80f4bSopenharmony_ci#if (RENDER_VULKAN_RT_ENABLED == 1)
2438bf80f4bSopenharmony_cistatic constexpr string_view DEVICE_EXTENSION_ACCELERATION_STRUCTURE { "VK_KHR_acceleration_structure" };
2448bf80f4bSopenharmony_cistatic constexpr string_view DEVICE_EXTENSION_RAY_QUERY { "VK_KHR_ray_query" };
2458bf80f4bSopenharmony_cistatic constexpr string_view DEVICE_EXTENSION_DEFERRED_HOST_OPERATIONS { "VK_KHR_deferred_host_operations" };
2468bf80f4bSopenharmony_cistatic constexpr string_view DEVICE_EXTENSION_RAY_TRACING_PIPELINE { "VK_KHR_ray_tracing_pipeline" };
2478bf80f4bSopenharmony_cistatic constexpr string_view DEVICE_EXTENSION_PIPELINE_LIBRARY { "VK_KHR_pipeline_library" };
2488bf80f4bSopenharmony_ci
2498bf80f4bSopenharmony_civoid GetPhysicalDeviceRayTracingStructs(ChainObjects& co, ChainWrapper& cw)
2508bf80f4bSopenharmony_ci{
2518bf80f4bSopenharmony_ci    co.rt = make_unique<PhysicalDeviceRayTracingStructsVk>();
2528bf80f4bSopenharmony_ci    auto& rt = co.rt;
2538bf80f4bSopenharmony_ci    rt->physicalDeviceBufferDeviceAddressFeatures = {
2548bf80f4bSopenharmony_ci        VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_BUFFER_DEVICE_ADDRESS_FEATURES, // sType
2558bf80f4bSopenharmony_ci        nullptr,                                                          // pNext
2568bf80f4bSopenharmony_ci        VK_FALSE,                                                         // bufferDeviceAddress;
2578bf80f4bSopenharmony_ci        VK_FALSE,                                                         // bufferDeviceAddressCaptureReplay
2588bf80f4bSopenharmony_ci        VK_FALSE,                                                         // bufferDeviceAddressMultiDevice
2598bf80f4bSopenharmony_ci    };
2608bf80f4bSopenharmony_ci    rt->physicalDeviceRayTracingPipelineFeatures = {
2618bf80f4bSopenharmony_ci        VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_RAY_TRACING_PIPELINE_FEATURES_KHR, // sType
2628bf80f4bSopenharmony_ci        &rt->physicalDeviceBufferDeviceAddressFeatures,                      // pNext
2638bf80f4bSopenharmony_ci        VK_FALSE,                                                            // rayTracingPipeline;
2648bf80f4bSopenharmony_ci        VK_FALSE, // rayTracingPipelineShaderGroupHandleCaptureReplay;
2658bf80f4bSopenharmony_ci        VK_FALSE, // rayTracingPipelineShaderGroupHandleCaptureReplayMixed;
2668bf80f4bSopenharmony_ci        VK_FALSE, // rayTracingPipelineTraceRaysIndirect;
2678bf80f4bSopenharmony_ci        VK_FALSE, // rayTraversalPrimitiveCulling;
2688bf80f4bSopenharmony_ci    };
2698bf80f4bSopenharmony_ci    rt->physicalDeviceAccelerationStructureFeatures = {
2708bf80f4bSopenharmony_ci        VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ACCELERATION_STRUCTURE_FEATURES_KHR, // sType
2718bf80f4bSopenharmony_ci        &rt->physicalDeviceRayTracingPipelineFeatures,                         // pNext
2728bf80f4bSopenharmony_ci        VK_FALSE,                                                              // accelerationStructure;
2738bf80f4bSopenharmony_ci        VK_FALSE,                                                              // accelerationStructureCaptureReplay
2748bf80f4bSopenharmony_ci        VK_FALSE,                                                              // accelerationStructureIndirectBuild
2758bf80f4bSopenharmony_ci        VK_FALSE,                                                              // accelerationStructureHostCommands
2768bf80f4bSopenharmony_ci        VK_FALSE, // descriptorBindingAccelerationStructureUpdateAfterBind
2778bf80f4bSopenharmony_ci    };
2788bf80f4bSopenharmony_ci    rt->physicalDeviceRayQueryFeatures = {
2798bf80f4bSopenharmony_ci        VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_RAY_QUERY_FEATURES_KHR, // sType
2808bf80f4bSopenharmony_ci        &rt->physicalDeviceAccelerationStructureFeatures,         // pNext
2818bf80f4bSopenharmony_ci        true,                                                     // rayQuery
2828bf80f4bSopenharmony_ci    };
2838bf80f4bSopenharmony_ci
2848bf80f4bSopenharmony_ci    *cw.ppNextFeatures = &rt->physicalDeviceRayQueryFeatures;
2858bf80f4bSopenharmony_ci    cw.ppNextFeatures = &rt->physicalDeviceBufferDeviceAddressFeatures.pNext;
2868bf80f4bSopenharmony_ci}
2878bf80f4bSopenharmony_ci#endif
2888bf80f4bSopenharmony_ci
2898bf80f4bSopenharmony_civoid GetPhysicalDeviceYcbcrStructs(ChainObjects& co, ChainWrapper& cw)
2908bf80f4bSopenharmony_ci{
2918bf80f4bSopenharmony_ci    co.ycbcr = make_unique<PhysicalDeviceYcbcrStructsVk>();
2928bf80f4bSopenharmony_ci    auto& ycbcr = co.ycbcr;
2938bf80f4bSopenharmony_ci    ycbcr->ycbcrConversionFeatures = {
2948bf80f4bSopenharmony_ci        VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SAMPLER_YCBCR_CONVERSION_FEATURES, // sType
2958bf80f4bSopenharmony_ci        nullptr,                                                             // pNext
2968bf80f4bSopenharmony_ci        VK_FALSE,                                                            // samplerYcbcrConversion
2978bf80f4bSopenharmony_ci    };
2988bf80f4bSopenharmony_ci
2998bf80f4bSopenharmony_ci    *cw.ppNextFeatures = &ycbcr->ycbcrConversionFeatures;
3008bf80f4bSopenharmony_ci    cw.ppNextFeatures = &ycbcr->ycbcrConversionFeatures.pNext;
3018bf80f4bSopenharmony_ci}
3028bf80f4bSopenharmony_ci
3038bf80f4bSopenharmony_civoid GetYcbcrExtFunctions(const VkInstance instance, DeviceVk::ExtFunctions& extFunctions)
3048bf80f4bSopenharmony_ci{
3058bf80f4bSopenharmony_ci    extFunctions.vkCreateSamplerYcbcrConversion =
3068bf80f4bSopenharmony_ci        (PFN_vkCreateSamplerYcbcrConversion)(void*)vkGetInstanceProcAddr(instance, "vkCreateSamplerYcbcrConversion");
3078bf80f4bSopenharmony_ci    if (!extFunctions.vkCreateSamplerYcbcrConversion) {
3088bf80f4bSopenharmony_ci        PLUGIN_LOG_E("vkGetInstanceProcAddr failed for vkCreateSamplerYcbcrConversion");
3098bf80f4bSopenharmony_ci    }
3108bf80f4bSopenharmony_ci    extFunctions.vkDestroySamplerYcbcrConversion =
3118bf80f4bSopenharmony_ci        (PFN_vkDestroySamplerYcbcrConversion)vkGetInstanceProcAddr(instance, "vkDestroySamplerYcbcrConversion");
3128bf80f4bSopenharmony_ci    if (!extFunctions.vkDestroySamplerYcbcrConversion) {
3138bf80f4bSopenharmony_ci        PLUGIN_LOG_E("vkGetInstanceProcAddr failed for vkDestroySamplerYcbcrConversion");
3148bf80f4bSopenharmony_ci    }
3158bf80f4bSopenharmony_ci}
3168bf80f4bSopenharmony_ci
3178bf80f4bSopenharmony_civoid GetPhysicalDeviceMaintenance4Structs(ChainObjects& co, ChainWrapper& cw)
3188bf80f4bSopenharmony_ci{
3198bf80f4bSopenharmony_ci    co.maintenance4 = make_unique<PhysicalDeviceMaintenance4Vk>();
3208bf80f4bSopenharmony_ci    auto& m4 = co.maintenance4;
3218bf80f4bSopenharmony_ci    m4->maintenance4Features = {
3228bf80f4bSopenharmony_ci        VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MAINTENANCE_4_FEATURES, // sType
3238bf80f4bSopenharmony_ci        nullptr,                                                  // pNext
3248bf80f4bSopenharmony_ci        true,                                                     // maintenance4
3258bf80f4bSopenharmony_ci    };
3268bf80f4bSopenharmony_ci
3278bf80f4bSopenharmony_ci    *cw.ppNextFeatures = &m4->maintenance4Features;
3288bf80f4bSopenharmony_ci    cw.ppNextFeatures = &m4->maintenance4Features.pNext;
3298bf80f4bSopenharmony_ci}
3308bf80f4bSopenharmony_ci
3318bf80f4bSopenharmony_ciconstexpr uint32_t MIN_ALLOCATION_BLOCK_SIZE { 4u * 1024u * 1024u };
3328bf80f4bSopenharmony_ciconstexpr uint32_t MAX_ALLOCATION_BLOCK_SIZE { 1024u * 1024u * 1024u };
3338bf80f4bSopenharmony_cistatic constexpr const QueueProperties DEFAULT_QUEUE {
3348bf80f4bSopenharmony_ci    VK_QUEUE_GRAPHICS_BIT, // requiredFlags
3358bf80f4bSopenharmony_ci    1,                     // count
3368bf80f4bSopenharmony_ci    1.0f,                  // priority
3378bf80f4bSopenharmony_ci    false,                 // explicitFlags
3388bf80f4bSopenharmony_ci    true,                  // canPresent
3398bf80f4bSopenharmony_ci};
3408bf80f4bSopenharmony_ci
3418bf80f4bSopenharmony_ciPlatformGpuMemoryAllocator::GpuMemoryAllocatorCreateInfo GetAllocatorCreateInfo(const BackendExtraVk* backendExtra)
3428bf80f4bSopenharmony_ci{
3438bf80f4bSopenharmony_ci    // create default pools
3448bf80f4bSopenharmony_ci    PlatformGpuMemoryAllocator::GpuMemoryAllocatorCreateInfo createInfo;
3458bf80f4bSopenharmony_ci    uint32_t dynamicUboByteSize = 16u * 1024u * 1024u;
3468bf80f4bSopenharmony_ci    if (backendExtra) {
3478bf80f4bSopenharmony_ci        const auto& sizes = backendExtra->gpuMemoryAllocatorSizes;
3488bf80f4bSopenharmony_ci        if (sizes.defaultAllocationBlockSize != ~0u) {
3498bf80f4bSopenharmony_ci            createInfo.preferredLargeHeapBlockSize = Math::min(
3508bf80f4bSopenharmony_ci                MAX_ALLOCATION_BLOCK_SIZE, Math::max(sizes.defaultAllocationBlockSize, MIN_ALLOCATION_BLOCK_SIZE));
3518bf80f4bSopenharmony_ci        }
3528bf80f4bSopenharmony_ci        if (sizes.customAllocationDynamicUboBlockSize != ~0u) {
3538bf80f4bSopenharmony_ci            dynamicUboByteSize = Math::min(MAX_ALLOCATION_BLOCK_SIZE,
3548bf80f4bSopenharmony_ci                Math::max(sizes.customAllocationDynamicUboBlockSize, MIN_ALLOCATION_BLOCK_SIZE));
3558bf80f4bSopenharmony_ci        }
3568bf80f4bSopenharmony_ci    }
3578bf80f4bSopenharmony_ci
3588bf80f4bSopenharmony_ci    // staging
3598bf80f4bSopenharmony_ci    {
3608bf80f4bSopenharmony_ci        GpuBufferDesc desc;
3618bf80f4bSopenharmony_ci        desc.engineCreationFlags = EngineBufferCreationFlagBits::CORE_ENGINE_BUFFER_CREATION_SINGLE_SHOT_STAGING;
3628bf80f4bSopenharmony_ci        desc.memoryPropertyFlags = MemoryPropertyFlagBits::CORE_MEMORY_PROPERTY_HOST_COHERENT_BIT |
3638bf80f4bSopenharmony_ci                                   MemoryPropertyFlagBits::CORE_MEMORY_PROPERTY_HOST_VISIBLE_BIT;
3648bf80f4bSopenharmony_ci        desc.usageFlags = BufferUsageFlagBits::CORE_BUFFER_USAGE_TRANSFER_SRC_BIT;
3658bf80f4bSopenharmony_ci        createInfo.customPools.push_back({
3668bf80f4bSopenharmony_ci            "STAGING_GPU_BUFFER",
3678bf80f4bSopenharmony_ci            PlatformGpuMemoryAllocator::MemoryAllocatorResourceType::GPU_BUFFER,
3688bf80f4bSopenharmony_ci            0u,
3698bf80f4bSopenharmony_ci            // if linear allocator is used, depending clients usage pattern, memory can be easily wasted.
3708bf80f4bSopenharmony_ci            false,
3718bf80f4bSopenharmony_ci            { move(desc) },
3728bf80f4bSopenharmony_ci        });
3738bf80f4bSopenharmony_ci    }
3748bf80f4bSopenharmony_ci    // dynamic uniform ring buffers
3758bf80f4bSopenharmony_ci    {
3768bf80f4bSopenharmony_ci        GpuBufferDesc desc;
3778bf80f4bSopenharmony_ci        desc.engineCreationFlags = EngineBufferCreationFlagBits::CORE_ENGINE_BUFFER_CREATION_DYNAMIC_RING_BUFFER;
3788bf80f4bSopenharmony_ci        desc.memoryPropertyFlags = MemoryPropertyFlagBits::CORE_MEMORY_PROPERTY_HOST_COHERENT_BIT |
3798bf80f4bSopenharmony_ci                                   MemoryPropertyFlagBits::CORE_MEMORY_PROPERTY_HOST_VISIBLE_BIT;
3808bf80f4bSopenharmony_ci        desc.usageFlags = BufferUsageFlagBits::CORE_BUFFER_USAGE_UNIFORM_BUFFER_BIT;
3818bf80f4bSopenharmony_ci        createInfo.customPools.push_back({
3828bf80f4bSopenharmony_ci            "DYNAMIC_UNIFORM_GPU_BUFFER",
3838bf80f4bSopenharmony_ci            PlatformGpuMemoryAllocator::MemoryAllocatorResourceType::GPU_BUFFER,
3848bf80f4bSopenharmony_ci            dynamicUboByteSize,
3858bf80f4bSopenharmony_ci            false,
3868bf80f4bSopenharmony_ci            { move(desc) },
3878bf80f4bSopenharmony_ci        });
3888bf80f4bSopenharmony_ci    }
3898bf80f4bSopenharmony_ci
3908bf80f4bSopenharmony_ci    return createInfo;
3918bf80f4bSopenharmony_ci}
3928bf80f4bSopenharmony_ci
3938bf80f4bSopenharmony_ciVkBool32 VKAPI_PTR DebugMessengerCallback(VkDebugUtilsMessageSeverityFlagBitsEXT messageSeverity,
3948bf80f4bSopenharmony_ci    VkDebugUtilsMessageTypeFlagsEXT messageTypes, const VkDebugUtilsMessengerCallbackDataEXT* pCallbackData,
3958bf80f4bSopenharmony_ci    void* pUserData)
3968bf80f4bSopenharmony_ci{
3978bf80f4bSopenharmony_ci    if (pCallbackData && pCallbackData->pMessage) {
3988bf80f4bSopenharmony_ci        if ((VkDebugUtilsMessageSeverityFlagsEXT)messageSeverity & VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT) {
3998bf80f4bSopenharmony_ci            PLUGIN_LOG_E("%s: %s", pCallbackData->pMessageIdName, pCallbackData->pMessage);
4008bf80f4bSopenharmony_ci        } else if ((VkDebugUtilsMessageSeverityFlagsEXT)messageSeverity &
4018bf80f4bSopenharmony_ci                   (VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT)) {
4028bf80f4bSopenharmony_ci            PLUGIN_LOG_W("%s: %s", pCallbackData->pMessageIdName, pCallbackData->pMessage);
4038bf80f4bSopenharmony_ci        } else if ((VkDebugUtilsMessageSeverityFlagsEXT)messageSeverity &
4048bf80f4bSopenharmony_ci                   VK_DEBUG_UTILS_MESSAGE_SEVERITY_INFO_BIT_EXT) {
4058bf80f4bSopenharmony_ci            PLUGIN_LOG_I("%s: %s", pCallbackData->pMessageIdName, pCallbackData->pMessage);
4068bf80f4bSopenharmony_ci        } else if ((VkDebugUtilsMessageSeverityFlagsEXT)messageSeverity &
4078bf80f4bSopenharmony_ci                   VK_DEBUG_UTILS_MESSAGE_SEVERITY_VERBOSE_BIT_EXT) {
4088bf80f4bSopenharmony_ci            PLUGIN_LOG_V("%s: %s", pCallbackData->pMessageIdName, pCallbackData->pMessage);
4098bf80f4bSopenharmony_ci        }
4108bf80f4bSopenharmony_ci    }
4118bf80f4bSopenharmony_ci
4128bf80f4bSopenharmony_ci    // The application should always return VK_FALSE.
4138bf80f4bSopenharmony_ci    return VK_FALSE;
4148bf80f4bSopenharmony_ci}
4158bf80f4bSopenharmony_ci
4168bf80f4bSopenharmony_ciVkBool32 VKAPI_PTR DebugReportCallback(VkDebugReportFlagsEXT flags, VkDebugReportObjectTypeEXT, uint64_t, size_t,
4178bf80f4bSopenharmony_ci    int32_t, const char*, const char* pMessage, void*)
4188bf80f4bSopenharmony_ci{
4198bf80f4bSopenharmony_ci    if (flags & VK_DEBUG_REPORT_ERROR_BIT_EXT) {
4208bf80f4bSopenharmony_ci        PLUGIN_LOG_E("%s", pMessage);
4218bf80f4bSopenharmony_ci    } else if (flags & (VK_DEBUG_REPORT_WARNING_BIT_EXT | VK_DEBUG_REPORT_PERFORMANCE_WARNING_BIT_EXT)) {
4228bf80f4bSopenharmony_ci        PLUGIN_LOG_W("%s", pMessage);
4238bf80f4bSopenharmony_ci    } else if (flags & VK_DEBUG_REPORT_INFORMATION_BIT_EXT) {
4248bf80f4bSopenharmony_ci        PLUGIN_LOG_I("%s", pMessage);
4258bf80f4bSopenharmony_ci    } else if (flags & VK_DEBUG_REPORT_DEBUG_BIT_EXT) {
4268bf80f4bSopenharmony_ci        PLUGIN_LOG_D("%s", pMessage);
4278bf80f4bSopenharmony_ci    }
4288bf80f4bSopenharmony_ci    return VK_FALSE;
4298bf80f4bSopenharmony_ci}
4308bf80f4bSopenharmony_ci
4318bf80f4bSopenharmony_civoid EmplaceDeviceQueue(
4328bf80f4bSopenharmony_ci    const VkDevice device, const LowLevelQueueInfo& aQueueInfo, vector<LowLevelGpuQueueVk>& aLowLevelQueues)
4338bf80f4bSopenharmony_ci{
4348bf80f4bSopenharmony_ci    for (uint32_t idx = 0; idx < aQueueInfo.queueCount; ++idx) {
4358bf80f4bSopenharmony_ci        VkQueue queue = VK_NULL_HANDLE;
4368bf80f4bSopenharmony_ci        vkGetDeviceQueue(device,         // device
4378bf80f4bSopenharmony_ci            aQueueInfo.queueFamilyIndex, // queueFamilyIndex
4388bf80f4bSopenharmony_ci            idx,                         // queueIndex
4398bf80f4bSopenharmony_ci            &queue);                     // pQueue
4408bf80f4bSopenharmony_ci        aLowLevelQueues.push_back(LowLevelGpuQueueVk { queue, aQueueInfo });
4418bf80f4bSopenharmony_ci    }
4428bf80f4bSopenharmony_ci}
4438bf80f4bSopenharmony_ci
4448bf80f4bSopenharmony_civoid CheckValidDepthFormats(const DevicePlatformDataVk& devicePlat, DevicePlatformInternalDataVk& dataInternal)
4458bf80f4bSopenharmony_ci{
4468bf80f4bSopenharmony_ci    constexpr uint32_t DEPTH_FORMAT_COUNT { 4 };
4478bf80f4bSopenharmony_ci    constexpr Format DEPTH_FORMATS[DEPTH_FORMAT_COUNT] = { BASE_FORMAT_D24_UNORM_S8_UINT, BASE_FORMAT_D32_SFLOAT,
4488bf80f4bSopenharmony_ci        BASE_FORMAT_D16_UNORM, BASE_FORMAT_X8_D24_UNORM_PACK32 };
4498bf80f4bSopenharmony_ci    for (uint32_t idx = 0; idx < DEPTH_FORMAT_COUNT; ++idx) {
4508bf80f4bSopenharmony_ci        VkFormatProperties formatProperties;
4518bf80f4bSopenharmony_ci        Format format = DEPTH_FORMATS[idx];
4528bf80f4bSopenharmony_ci        vkGetPhysicalDeviceFormatProperties(devicePlat.physicalDevice, // physicalDevice
4538bf80f4bSopenharmony_ci            (VkFormat)format,                                          // format
4548bf80f4bSopenharmony_ci            &formatProperties);                                        // pFormatProperties
4558bf80f4bSopenharmony_ci        const VkFormatFeatureFlags optimalTilingFeatureFlags = formatProperties.optimalTilingFeatures;
4568bf80f4bSopenharmony_ci        if (optimalTilingFeatureFlags & VkFormatFeatureFlagBits::VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT) {
4578bf80f4bSopenharmony_ci            dataInternal.supportedDepthFormats.push_back(format);
4588bf80f4bSopenharmony_ci        }
4598bf80f4bSopenharmony_ci    }
4608bf80f4bSopenharmony_ci}
4618bf80f4bSopenharmony_ci
4628bf80f4bSopenharmony_civector<string_view> GetPreferredDeviceExtensions(const BackendExtraVk* backendExtra, DevicePlatformDataVk& plat)
4638bf80f4bSopenharmony_ci{
4648bf80f4bSopenharmony_ci    vector<string_view> extensions { DEVICE_EXTENSION_SWAPCHAIN };
4658bf80f4bSopenharmony_ci    extensions.push_back(DEVICE_EXTENSION_CREATE_RENDERPASS2);
4668bf80f4bSopenharmony_ci    extensions.push_back(DEVICE_EXTENSION_DEPTH_STENCIL_RESOLVE);
4678bf80f4bSopenharmony_ci    extensions.push_back(DEVICE_EXTENSION_MAINTENANCE4);
4688bf80f4bSopenharmony_ci    GetPlatformDeviceExtensions(extensions);
4698bf80f4bSopenharmony_ci#if (RENDER_VULKAN_FSR_ENABLED == 1)
4708bf80f4bSopenharmony_ci    extensions.push_back(DEVICE_EXTENSION_FRAGMENT_SHADING_RATE);
4718bf80f4bSopenharmony_ci#endif
4728bf80f4bSopenharmony_ci#if (RENDER_VULKAN_RT_ENABLED == 1)
4738bf80f4bSopenharmony_ci    extensions.push_back(DEVICE_EXTENSION_ACCELERATION_STRUCTURE);
4748bf80f4bSopenharmony_ci    extensions.push_back(DEVICE_EXTENSION_RAY_TRACING_PIPELINE);
4758bf80f4bSopenharmony_ci    extensions.push_back(DEVICE_EXTENSION_RAY_QUERY);
4768bf80f4bSopenharmony_ci    extensions.push_back(DEVICE_EXTENSION_PIPELINE_LIBRARY);
4778bf80f4bSopenharmony_ci    extensions.push_back(DEVICE_EXTENSION_DEFERRED_HOST_OPERATIONS);
4788bf80f4bSopenharmony_ci#endif
4798bf80f4bSopenharmony_ci    if (plat.deviceApiMinor >= 1) { // enable only for 1.1+
4808bf80f4bSopenharmony_ci        extensions.push_back(DEVICE_EXTENSION_MULTIVIEW);
4818bf80f4bSopenharmony_ci    }
4828bf80f4bSopenharmony_ci    if (plat.deviceApiMinor >= 2) { // enable only for 1.2+
4838bf80f4bSopenharmony_ci        extensions.push_back(DEVICE_EXTENSION_DESCRIPTOR_INDEXING);
4848bf80f4bSopenharmony_ci    }
4858bf80f4bSopenharmony_ci    if (backendExtra) {
4868bf80f4bSopenharmony_ci        for (const auto str : backendExtra->extensions.extensionNames) {
4878bf80f4bSopenharmony_ci            extensions.push_back(str);
4888bf80f4bSopenharmony_ci        }
4898bf80f4bSopenharmony_ci    }
4908bf80f4bSopenharmony_ci    return extensions;
4918bf80f4bSopenharmony_ci}
4928bf80f4bSopenharmony_ci
4938bf80f4bSopenharmony_ciDeviceVk::CommonDeviceExtensions GetEnabledCommonDeviceExtensions(
4948bf80f4bSopenharmony_ci    const unordered_map<string, uint32_t>& enabledDeviceExtensions)
4958bf80f4bSopenharmony_ci{
4968bf80f4bSopenharmony_ci    DeviceVk::CommonDeviceExtensions extensions;
4978bf80f4bSopenharmony_ci    extensions.swapchain = enabledDeviceExtensions.contains(DEVICE_EXTENSION_SWAPCHAIN);
4988bf80f4bSopenharmony_ci    // renderpass2 required on 1.2, we only use renderpass 2 when we need depth stencil resolve
4998bf80f4bSopenharmony_ci    extensions.renderPass2 = enabledDeviceExtensions.contains(DEVICE_EXTENSION_DEPTH_STENCIL_RESOLVE) &&
5008bf80f4bSopenharmony_ci                             enabledDeviceExtensions.contains(DEVICE_EXTENSION_CREATE_RENDERPASS2);
5018bf80f4bSopenharmony_ci    extensions.externalMemory = enabledDeviceExtensions.contains(DEVICE_EXTENSION_EXTERNAL_MEMORY);
5028bf80f4bSopenharmony_ci    extensions.getMemoryRequirements2 = enabledDeviceExtensions.contains(DEVICE_EXTENSION_GET_MEMORY_REQUIREMENTS2);
5038bf80f4bSopenharmony_ci    extensions.queueFamilyForeign = enabledDeviceExtensions.contains(DEVICE_EXTENSION_QUEUE_FAMILY_FOREIGN);
5048bf80f4bSopenharmony_ci    extensions.samplerYcbcrConversion = enabledDeviceExtensions.contains(DEVICE_EXTENSION_SAMPLER_YCBCR_CONVERSION);
5058bf80f4bSopenharmony_ci    extensions.multiView = enabledDeviceExtensions.contains(DEVICE_EXTENSION_MULTIVIEW);
5068bf80f4bSopenharmony_ci    extensions.descriptorIndexing = enabledDeviceExtensions.contains(DEVICE_EXTENSION_DESCRIPTOR_INDEXING);
5078bf80f4bSopenharmony_ci#if (RENDER_VULKAN_FSR_ENABLED == 1)
5088bf80f4bSopenharmony_ci    extensions.fragmentShadingRate = enabledDeviceExtensions.contains(DEVICE_EXTENSION_FRAGMENT_SHADING_RATE);
5098bf80f4bSopenharmony_ci#endif
5108bf80f4bSopenharmony_ci
5118bf80f4bSopenharmony_ci    return extensions;
5128bf80f4bSopenharmony_ci}
5138bf80f4bSopenharmony_ci
5148bf80f4bSopenharmony_ciCommonDeviceProperties GetCommonDevicePropertiesFunc(const ChainObjects& co)
5158bf80f4bSopenharmony_ci{
5168bf80f4bSopenharmony_ci    CommonDeviceProperties cdp;
5178bf80f4bSopenharmony_ci#if (RENDER_VULKAN_FSR_ENABLED == 1)
5188bf80f4bSopenharmony_ci    if (co.fsr) {
5198bf80f4bSopenharmony_ci        const auto& fsrVk = co.fsr->physicalDeviceFragmentShadingRateProperties;
5208bf80f4bSopenharmony_ci        cdp.fragmentShadingRateProperties.minFragmentShadingRateAttachmentTexelSize = {
5218bf80f4bSopenharmony_ci            fsrVk.minFragmentShadingRateAttachmentTexelSize.width,
5228bf80f4bSopenharmony_ci            fsrVk.minFragmentShadingRateAttachmentTexelSize.height
5238bf80f4bSopenharmony_ci        };
5248bf80f4bSopenharmony_ci        cdp.fragmentShadingRateProperties.maxFragmentShadingRateAttachmentTexelSize = {
5258bf80f4bSopenharmony_ci            fsrVk.maxFragmentShadingRateAttachmentTexelSize.width,
5268bf80f4bSopenharmony_ci            fsrVk.maxFragmentShadingRateAttachmentTexelSize.height
5278bf80f4bSopenharmony_ci        };
5288bf80f4bSopenharmony_ci        cdp.fragmentShadingRateProperties.maxFragmentSize = { fsrVk.maxFragmentSize.width,
5298bf80f4bSopenharmony_ci            fsrVk.maxFragmentSize.height };
5308bf80f4bSopenharmony_ci    }
5318bf80f4bSopenharmony_ci#endif
5328bf80f4bSopenharmony_ci    return cdp;
5338bf80f4bSopenharmony_ci}
5348bf80f4bSopenharmony_ci
5358bf80f4bSopenharmony_civoid PreparePhysicalDeviceFeaturesForEnabling(const BackendExtraVk* backendExtra, DevicePlatformDataVk& plat)
5368bf80f4bSopenharmony_ci{
5378bf80f4bSopenharmony_ci    // enable all by default and then disable few
5388bf80f4bSopenharmony_ci    plat.enabledPhysicalDeviceFeatures = plat.physicalDeviceProperties.physicalDeviceFeatures;
5398bf80f4bSopenharmony_ci    // prepare feature disable for core engine
5408bf80f4bSopenharmony_ci    plat.enabledPhysicalDeviceFeatures.geometryShader = VK_FALSE;
5418bf80f4bSopenharmony_ci    plat.enabledPhysicalDeviceFeatures.tessellationShader = VK_FALSE;
5428bf80f4bSopenharmony_ci    plat.enabledPhysicalDeviceFeatures.sampleRateShading = VK_FALSE;
5438bf80f4bSopenharmony_ci    plat.enabledPhysicalDeviceFeatures.occlusionQueryPrecise = VK_FALSE;
5448bf80f4bSopenharmony_ci    plat.enabledPhysicalDeviceFeatures.pipelineStatisticsQuery = VK_FALSE;
5458bf80f4bSopenharmony_ci    plat.enabledPhysicalDeviceFeatures.shaderTessellationAndGeometryPointSize = VK_FALSE;
5468bf80f4bSopenharmony_ci    plat.enabledPhysicalDeviceFeatures.inheritedQueries = VK_FALSE;
5478bf80f4bSopenharmony_ci    if (backendExtra) {
5488bf80f4bSopenharmony_ci        // check for support and prepare enabling
5498bf80f4bSopenharmony_ci        if (backendExtra->extensions.physicalDeviceFeaturesToEnable) {
5508bf80f4bSopenharmony_ci            const size_t valueCount = sizeof(VkPhysicalDeviceFeatures) / sizeof(VkBool32);
5518bf80f4bSopenharmony_ci            const array_view<const VkBool32> supported(
5528bf80f4bSopenharmony_ci                reinterpret_cast<VkBool32*>(&plat.physicalDeviceProperties.physicalDeviceFeatures), valueCount);
5538bf80f4bSopenharmony_ci            VkPhysicalDeviceFeatures* wantedFeatures =
5548bf80f4bSopenharmony_ci                (&backendExtra->extensions.physicalDeviceFeaturesToEnable->features);
5558bf80f4bSopenharmony_ci            const array_view<const VkBool32> wanted(reinterpret_cast<VkBool32*>(wantedFeatures), valueCount);
5568bf80f4bSopenharmony_ci
5578bf80f4bSopenharmony_ci            array_view<VkBool32> enabledPhysicalDeviceFeatures(
5588bf80f4bSopenharmony_ci                reinterpret_cast<VkBool32*>(&plat.enabledPhysicalDeviceFeatures), valueCount);
5598bf80f4bSopenharmony_ci            for (size_t idx = 0; idx < valueCount; ++idx) {
5608bf80f4bSopenharmony_ci                if (supported[idx] && wanted[idx]) {
5618bf80f4bSopenharmony_ci                    enabledPhysicalDeviceFeatures[idx] = VK_TRUE;
5628bf80f4bSopenharmony_ci                } else if (wanted[idx]) {
5638bf80f4bSopenharmony_ci                    PLUGIN_LOG_W(
5648bf80f4bSopenharmony_ci                        "physical device feature not supported/enabled from idx: %u", static_cast<uint32_t>(idx));
5658bf80f4bSopenharmony_ci                }
5668bf80f4bSopenharmony_ci            }
5678bf80f4bSopenharmony_ci        }
5688bf80f4bSopenharmony_ci    }
5698bf80f4bSopenharmony_ci}
5708bf80f4bSopenharmony_ci
5718bf80f4bSopenharmony_ciFormatProperties FillDeviceFormatSupport(VkPhysicalDevice physicalDevice, const Format format)
5728bf80f4bSopenharmony_ci{
5738bf80f4bSopenharmony_ci    VkFormatProperties formatProperties;
5748bf80f4bSopenharmony_ci    vkGetPhysicalDeviceFormatProperties(physicalDevice, // physicalDevice
5758bf80f4bSopenharmony_ci        (VkFormat)format,                               // format
5768bf80f4bSopenharmony_ci        &formatProperties);                             // pFormatProperties
5778bf80f4bSopenharmony_ci    return FormatProperties {
5788bf80f4bSopenharmony_ci        (FormatFeatureFlags)formatProperties.linearTilingFeatures,
5798bf80f4bSopenharmony_ci        (FormatFeatureFlags)formatProperties.optimalTilingFeatures,
5808bf80f4bSopenharmony_ci        (FormatFeatureFlags)formatProperties.bufferFeatures,
5818bf80f4bSopenharmony_ci        GpuProgramUtil::FormatByteSize(format),
5828bf80f4bSopenharmony_ci    };
5838bf80f4bSopenharmony_ci}
5848bf80f4bSopenharmony_ci
5858bf80f4bSopenharmony_civoid FillFormatSupport(VkPhysicalDevice physicalDevice, vector<FormatProperties>& formats)
5868bf80f4bSopenharmony_ci{
5878bf80f4bSopenharmony_ci    const uint32_t fullSize = DeviceFormatSupportConstants::LINEAR_FORMAT_MAX_COUNT +
5888bf80f4bSopenharmony_ci                              DeviceFormatSupportConstants::ADDITIONAL_FORMAT_MAX_COUNT;
5898bf80f4bSopenharmony_ci    formats.resize(fullSize);
5908bf80f4bSopenharmony_ci    for (uint32_t idx = 0; idx < DeviceFormatSupportConstants::LINEAR_FORMAT_MAX_COUNT; ++idx) {
5918bf80f4bSopenharmony_ci        formats[idx] = FillDeviceFormatSupport(physicalDevice, static_cast<Format>(idx));
5928bf80f4bSopenharmony_ci    }
5938bf80f4bSopenharmony_ci    // pre-build additional formats
5948bf80f4bSopenharmony_ci    for (uint32_t idx = 0; idx < DeviceFormatSupportConstants::ADDITIONAL_FORMAT_MAX_COUNT; ++idx) {
5958bf80f4bSopenharmony_ci        const uint32_t currIdx = idx + DeviceFormatSupportConstants::ADDITIONAL_FORMAT_BASE_IDX;
5968bf80f4bSopenharmony_ci        PLUGIN_ASSERT(currIdx < static_cast<uint32_t>(formats.size()));
5978bf80f4bSopenharmony_ci        const uint32_t formatIdx = idx + DeviceFormatSupportConstants::ADDITIONAL_FORMAT_START_NUMBER;
5988bf80f4bSopenharmony_ci        formats[currIdx] = FillDeviceFormatSupport(physicalDevice, static_cast<Format>(formatIdx));
5998bf80f4bSopenharmony_ci    }
6008bf80f4bSopenharmony_ci}
6018bf80f4bSopenharmony_ci} // namespace
6028bf80f4bSopenharmony_ci
6038bf80f4bSopenharmony_ciDeviceVk::DeviceVk(RenderContext& renderContext, DeviceCreateInfo const& createInfo) : Device(renderContext, createInfo)
6048bf80f4bSopenharmony_ci{
6058bf80f4bSopenharmony_ci    // assume instance and device will be created internally
6068bf80f4bSopenharmony_ci    ownInstanceAndDevice_ = true;
6078bf80f4bSopenharmony_ci
6088bf80f4bSopenharmony_ci    const BackendExtraVk* backendExtra = static_cast<const BackendExtraVk*>(createInfo.backendConfiguration);
6098bf80f4bSopenharmony_ci    // update internal state based the optional backend configuration given by the client. the size of queuProperties
6108bf80f4bSopenharmony_ci    // will depend on the enableMultiQueue setting.
6118bf80f4bSopenharmony_ci    const auto queueProperties = CheckExternalConfig(backendExtra);
6128bf80f4bSopenharmony_ci
6138bf80f4bSopenharmony_ci    // these check internally ownInstanceAndDevice_ and skip creation if provided by user
6148bf80f4bSopenharmony_ci    CreateInstance();
6158bf80f4bSopenharmony_ci    CreatePhysicalDevice();
6168bf80f4bSopenharmony_ci
6178bf80f4bSopenharmony_ci    const auto availableQueues = CreateFunctionsVk::GetAvailableQueues(plat_.physicalDevice, queueProperties);
6188bf80f4bSopenharmony_ci
6198bf80f4bSopenharmony_ci    // own device creation does a lot of work for figuring out what to create, but for external device
6208bf80f4bSopenharmony_ci    // CheckExternalConfig stored the enabled extensions and features, and we just need to check what is available
6218bf80f4bSopenharmony_ci    if (ownInstanceAndDevice_) {
6228bf80f4bSopenharmony_ci        CreateDevice(backendExtra, availableQueues);
6238bf80f4bSopenharmony_ci    } else {
6248bf80f4bSopenharmony_ci        commonDeviceExtensions_ = GetEnabledCommonDeviceExtensions(extensions_);
6258bf80f4bSopenharmony_ci        platformDeviceExtensions_ = GetEnabledPlatformDeviceExtensions(extensions_);
6268bf80f4bSopenharmony_ci        // filling commonDeviceProperties_ isn't done, but at the moment that only contains fragment rate shading
6278bf80f4bSopenharmony_ci        // should walk through BackendExtraVk::extensions::physicalDeviceFeaturesToEnable::pNext and see what's
6288bf80f4bSopenharmony_ci        // available.
6298bf80f4bSopenharmony_ci    }
6308bf80f4bSopenharmony_ci
6318bf80f4bSopenharmony_ci    CreateDebugFunctions();
6328bf80f4bSopenharmony_ci    CreateExtFunctions();
6338bf80f4bSopenharmony_ci    CreatePlatformExtFunctions();
6348bf80f4bSopenharmony_ci    SortAvailableQueues(availableQueues);
6358bf80f4bSopenharmony_ci
6368bf80f4bSopenharmony_ci    CheckValidDepthFormats(plat_, platInternal_);
6378bf80f4bSopenharmony_ci    FillFormatSupport(plat_.physicalDevice, formatProperties_);
6388bf80f4bSopenharmony_ci
6398bf80f4bSopenharmony_ci    PLUGIN_ASSERT_MSG(!lowLevelGpuQueues_.graphicsQueues.empty(), "default queue not initialized");
6408bf80f4bSopenharmony_ci    if (!lowLevelGpuQueues_.graphicsQueues.empty()) {
6418bf80f4bSopenharmony_ci        lowLevelGpuQueues_.defaultQueue = lowLevelGpuQueues_.graphicsQueues[0];
6428bf80f4bSopenharmony_ci    } else {
6438bf80f4bSopenharmony_ci        PLUGIN_LOG_E("default vulkan queue not initialized");
6448bf80f4bSopenharmony_ci    }
6458bf80f4bSopenharmony_ci
6468bf80f4bSopenharmony_ci    gpuQueueCount_ =
6478bf80f4bSopenharmony_ci        static_cast<uint32_t>(lowLevelGpuQueues_.computeQueues.size() + lowLevelGpuQueues_.graphicsQueues.size() +
6488bf80f4bSopenharmony_ci                              lowLevelGpuQueues_.transferQueues.size());
6498bf80f4bSopenharmony_ci
6508bf80f4bSopenharmony_ci    const PlatformGpuMemoryAllocator::GpuMemoryAllocatorCreateInfo allocatorCreateInfo =
6518bf80f4bSopenharmony_ci        GetAllocatorCreateInfo(backendExtra);
6528bf80f4bSopenharmony_ci    platformGpuMemoryAllocator_ = make_unique<PlatformGpuMemoryAllocator>(
6538bf80f4bSopenharmony_ci        plat_.instance, plat_.physicalDevice, plat_.device, allocatorCreateInfo);
6548bf80f4bSopenharmony_ci
6558bf80f4bSopenharmony_ci    if (queueProperties.size() > 1) {
6568bf80f4bSopenharmony_ci        PLUGIN_LOG_I("gpu queue count: %u", gpuQueueCount_);
6578bf80f4bSopenharmony_ci    }
6588bf80f4bSopenharmony_ci
6598bf80f4bSopenharmony_ci    SetDeviceStatus(true);
6608bf80f4bSopenharmony_ci
6618bf80f4bSopenharmony_ci    const GpuResourceManager::CreateInfo grmCreateInfo {
6628bf80f4bSopenharmony_ci        GpuResourceManager::GPU_RESOURCE_MANAGER_OPTIMIZE_STAGING_MEMORY,
6638bf80f4bSopenharmony_ci    };
6648bf80f4bSopenharmony_ci    gpuResourceMgr_ = make_unique<GpuResourceManager>(*this, grmCreateInfo);
6658bf80f4bSopenharmony_ci    shaderMgr_ = make_unique<ShaderManager>(*this);
6668bf80f4bSopenharmony_ci
6678bf80f4bSopenharmony_ci    lowLevelDevice_ = make_unique<LowLevelDeviceVk>(*this);
6688bf80f4bSopenharmony_ci}
6698bf80f4bSopenharmony_ci
6708bf80f4bSopenharmony_ciDeviceVk::~DeviceVk()
6718bf80f4bSopenharmony_ci{
6728bf80f4bSopenharmony_ci    WaitForIdle();
6738bf80f4bSopenharmony_ci
6748bf80f4bSopenharmony_ci    // must release handles before taking down gpu resource manager.
6758bf80f4bSopenharmony_ci    swapchains_.clear();
6768bf80f4bSopenharmony_ci
6778bf80f4bSopenharmony_ci    gpuResourceMgr_.reset();
6788bf80f4bSopenharmony_ci    shaderMgr_.reset();
6798bf80f4bSopenharmony_ci
6808bf80f4bSopenharmony_ci    platformGpuMemoryAllocator_.reset();
6818bf80f4bSopenharmony_ci
6828bf80f4bSopenharmony_ci    if (plat_.pipelineCache) {
6838bf80f4bSopenharmony_ci        CreateFunctionsVk::DestroyPipelineCache(plat_.device, plat_.pipelineCache);
6848bf80f4bSopenharmony_ci    }
6858bf80f4bSopenharmony_ci
6868bf80f4bSopenharmony_ci    if (ownInstanceAndDevice_) {
6878bf80f4bSopenharmony_ci        CreateFunctionsVk::DestroyDevice(plat_.device);
6888bf80f4bSopenharmony_ci        CreateFunctionsVk::DestroyDebugMessenger(plat_.instance, debugFunctionUtilities_.debugMessenger);
6898bf80f4bSopenharmony_ci        CreateFunctionsVk::DestroyDebugCallback(plat_.instance, debugFunctionUtilities_.debugCallback);
6908bf80f4bSopenharmony_ci        CreateFunctionsVk::DestroyInstance(plat_.instance);
6918bf80f4bSopenharmony_ci    }
6928bf80f4bSopenharmony_ci}
6938bf80f4bSopenharmony_ci
6948bf80f4bSopenharmony_civoid DeviceVk::CreateInstance()
6958bf80f4bSopenharmony_ci{
6968bf80f4bSopenharmony_ci    const auto instanceWrapper = (plat_.instance == VK_NULL_HANDLE) ?
6978bf80f4bSopenharmony_ci        CreateFunctionsVk::CreateInstance(VersionInfo { "core_renderer", 0, 1, 0},
6988bf80f4bSopenharmony_ci        VersionInfo { "core_renderer_app", 0, 1, 0 }) : CreateFunctionsVk::GetWrapper(plat_.instance);
6998bf80f4bSopenharmony_ci
7008bf80f4bSopenharmony_ci    plat_.instance = instanceWrapper.instance;
7018bf80f4bSopenharmony_ci    // update with physical device creation
7028bf80f4bSopenharmony_ci    plat_.deviceApiMajor = instanceWrapper.apiMajor;
7038bf80f4bSopenharmony_ci    plat_.deviceApiMinor = instanceWrapper.apiMinor;
7048bf80f4bSopenharmony_ci    if (instanceWrapper.debugUtilsSupported) {
7058bf80f4bSopenharmony_ci        debugFunctionUtilities_.debugMessenger =
7068bf80f4bSopenharmony_ci            CreateFunctionsVk::CreateDebugMessenger(plat_.instance, DebugMessengerCallback);
7078bf80f4bSopenharmony_ci    }
7088bf80f4bSopenharmony_ci    if (!debugFunctionUtilities_.debugMessenger && instanceWrapper.debugReportSupported) {
7098bf80f4bSopenharmony_ci        debugFunctionUtilities_.debugCallback =
7108bf80f4bSopenharmony_ci            CreateFunctionsVk::CreateDebugCallback(plat_.instance, DebugReportCallback);
7118bf80f4bSopenharmony_ci    }
7128bf80f4bSopenharmony_ci
7138bf80f4bSopenharmony_ci    extFunctions_.vkAcquireNextImageKHR =
7148bf80f4bSopenharmony_ci        (PFN_vkAcquireNextImageKHR)(void*)vkGetInstanceProcAddr(plat_.instance, "vkAcquireNextImageKHR");
7158bf80f4bSopenharmony_ci    if ((plat_.deviceApiMajor >= 1) && (plat_.deviceApiMinor >= 1)) {
7168bf80f4bSopenharmony_ci        extFunctions_.vkGetPhysicalDeviceFeatures2 =
7178bf80f4bSopenharmony_ci            (PFN_vkGetPhysicalDeviceFeatures2)vkGetInstanceProcAddr(plat_.instance, "vkGetPhysicalDeviceFeatures2");
7188bf80f4bSopenharmony_ci        extFunctions_.vkGetPhysicalDeviceProperties2 =
7198bf80f4bSopenharmony_ci            (PFN_vkGetPhysicalDeviceProperties2)vkGetInstanceProcAddr(plat_.instance, "vkGetPhysicalDeviceProperties2");
7208bf80f4bSopenharmony_ci    }
7218bf80f4bSopenharmony_ci}
7228bf80f4bSopenharmony_ci
7238bf80f4bSopenharmony_civoid DeviceVk::CreatePhysicalDevice()
7248bf80f4bSopenharmony_ci{
7258bf80f4bSopenharmony_ci    auto physicalDeviceWrapper = (plat_.physicalDevice == VK_NULL_HANDLE) ?
7268bf80f4bSopenharmony_ci        CreateFunctionsVk::CreatePhysicalDevice(plat_.instance, DEFAULT_QUEUE ) :
7278bf80f4bSopenharmony_ci        CreateFunctionsVk::GetWrapper(plat_.physicalDevice);
7288bf80f4bSopenharmony_ci    const uint32_t physicalDeviceApiMajor =
7298bf80f4bSopenharmony_ci        VK_VERSION_MAJOR(physicalDeviceWrapper.physicalDeviceProperties.physicalDeviceProperties.apiVersion);
7308bf80f4bSopenharmony_ci    const uint32_t physicalDeviceApiMinor =
7318bf80f4bSopenharmony_ci        VK_VERSION_MINOR(physicalDeviceWrapper.physicalDeviceProperties.physicalDeviceProperties.apiVersion);
7328bf80f4bSopenharmony_ci    plat_.deviceApiMajor = Math::min(plat_.deviceApiMajor, physicalDeviceApiMajor);
7338bf80f4bSopenharmony_ci    plat_.deviceApiMinor = Math::min(plat_.deviceApiMinor, physicalDeviceApiMinor);
7348bf80f4bSopenharmony_ci    PLUGIN_LOG_D("device api version %u.%u", plat_.deviceApiMajor, plat_.deviceApiMinor);
7358bf80f4bSopenharmony_ci
7368bf80f4bSopenharmony_ci    plat_.physicalDevice = physicalDeviceWrapper.physicalDevice;
7378bf80f4bSopenharmony_ci    plat_.physicalDeviceProperties = move(physicalDeviceWrapper.physicalDeviceProperties);
7388bf80f4bSopenharmony_ci    plat_.physicalDeviceExtensions = move(physicalDeviceWrapper.physicalDeviceExtensions);
7398bf80f4bSopenharmony_ci    const auto& memoryProperties = plat_.physicalDeviceProperties.physicalDeviceMemoryProperties;
7408bf80f4bSopenharmony_ci    deviceSharedMemoryPropertyFlags_ =
7418bf80f4bSopenharmony_ci        (memoryProperties.memoryTypeCount > 0) ? (MemoryPropertyFlags)memoryProperties.memoryTypes[0].propertyFlags : 0;
7428bf80f4bSopenharmony_ci    for (uint32_t idx = 1; idx < memoryProperties.memoryTypeCount; ++idx) {
7438bf80f4bSopenharmony_ci        const MemoryPropertyFlags memoryPropertyFlags =
7448bf80f4bSopenharmony_ci            (MemoryPropertyFlags)memoryProperties.memoryTypes[idx].propertyFlags;
7458bf80f4bSopenharmony_ci        // do not compare lazily allocated or protected memory blocks
7468bf80f4bSopenharmony_ci        if ((memoryPropertyFlags & (CORE_MEMORY_PROPERTY_LAZILY_ALLOCATED_BIT | CORE_MEMORY_PROPERTY_PROTECTED_BIT)) ==
7478bf80f4bSopenharmony_ci            0) {
7488bf80f4bSopenharmony_ci            deviceSharedMemoryPropertyFlags_ &= memoryPropertyFlags;
7498bf80f4bSopenharmony_ci        }
7508bf80f4bSopenharmony_ci    }
7518bf80f4bSopenharmony_ci}
7528bf80f4bSopenharmony_ci
7538bf80f4bSopenharmony_civoid DeviceVk::CreateDevice(const BackendExtraVk* backendExtra, const vector<LowLevelQueueInfo>& availableQueues)
7548bf80f4bSopenharmony_ci{
7558bf80f4bSopenharmony_ci    vector<string_view> preferredExtensions = GetPreferredDeviceExtensions(backendExtra, plat_);
7568bf80f4bSopenharmony_ci    PreparePhysicalDeviceFeaturesForEnabling(backendExtra, plat_);
7578bf80f4bSopenharmony_ci
7588bf80f4bSopenharmony_ci    ChainWrapper chainWrapper;
7598bf80f4bSopenharmony_ci    ChainObjects chainObjects;
7608bf80f4bSopenharmony_ci
7618bf80f4bSopenharmony_ci    VkPhysicalDeviceFeatures2* physicalDeviceFeatures2Ptr = nullptr;
7628bf80f4bSopenharmony_ci    VkPhysicalDeviceFeatures2 physicalDeviceFeatures2 {
7638bf80f4bSopenharmony_ci        VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2, // sType
7648bf80f4bSopenharmony_ci        nullptr,                                      // pNext
7658bf80f4bSopenharmony_ci        {},                                           // features
7668bf80f4bSopenharmony_ci    };
7678bf80f4bSopenharmony_ci    chainWrapper.ppNextFeatures = &physicalDeviceFeatures2.pNext;
7688bf80f4bSopenharmony_ci
7698bf80f4bSopenharmony_ci    VkPhysicalDeviceProperties2 physicalDeviceProperties2 {
7708bf80f4bSopenharmony_ci        VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2, // sType
7718bf80f4bSopenharmony_ci        nullptr,                                        // pNext
7728bf80f4bSopenharmony_ci        {},                                             // properties
7738bf80f4bSopenharmony_ci    };
7748bf80f4bSopenharmony_ci    chainWrapper.ppNextProperties = &physicalDeviceProperties2.pNext;
7758bf80f4bSopenharmony_ci
7768bf80f4bSopenharmony_ci    GetPhysicalDeviceYcbcrStructs(chainObjects, chainWrapper);
7778bf80f4bSopenharmony_ci#if (RENDER_VULKAN_RT_ENABLED == 1)
7788bf80f4bSopenharmony_ci    GetPhysicalDeviceRayTracingStructs(chainObjects, chainWrapper);
7798bf80f4bSopenharmony_ci#endif
7808bf80f4bSopenharmony_ci#if (RENDER_VULKAN_FSR_ENABLED == 1)
7818bf80f4bSopenharmony_ci    if (CreateFunctionsVk::HasExtension(plat_.physicalDeviceExtensions, DEVICE_EXTENSION_FRAGMENT_SHADING_RATE)) {
7828bf80f4bSopenharmony_ci        GetPhysicalDeviceFragmentShadingRateStructs(chainObjects, chainWrapper);
7838bf80f4bSopenharmony_ci    }
7848bf80f4bSopenharmony_ci#endif
7858bf80f4bSopenharmony_ci    if (plat_.deviceApiMinor >= 1) { // enable only for 1.1 + for now
7868bf80f4bSopenharmony_ci        GetPhysicalDeviceMultiviewFeaturesStructs(chainObjects, chainWrapper);
7878bf80f4bSopenharmony_ci    }
7888bf80f4bSopenharmony_ci    if (plat_.deviceApiMinor >= 2) { // enable only for 1.2 + for now
7898bf80f4bSopenharmony_ci        GetPhysicalDeviceDescriptorIndexingFeaturesStructs(chainObjects, chainWrapper);
7908bf80f4bSopenharmony_ci    }
7918bf80f4bSopenharmony_ci    if (CreateFunctionsVk::HasExtension(plat_.physicalDeviceExtensions, DEVICE_EXTENSION_MAINTENANCE4)) {
7928bf80f4bSopenharmony_ci        GetPhysicalDeviceMaintenance4Structs(chainObjects, chainWrapper);
7938bf80f4bSopenharmony_ci    }
7948bf80f4bSopenharmony_ci    if ((plat_.deviceApiMajor >= 1) && (plat_.deviceApiMinor >= 1)) {
7958bf80f4bSopenharmony_ci        // pipe user extension physical device features
7968bf80f4bSopenharmony_ci        if (backendExtra) {
7978bf80f4bSopenharmony_ci            if (backendExtra->extensions.physicalDeviceFeaturesToEnable) {
7988bf80f4bSopenharmony_ci                *chainWrapper.ppNextFeatures = backendExtra->extensions.physicalDeviceFeaturesToEnable->pNext;
7998bf80f4bSopenharmony_ci            }
8008bf80f4bSopenharmony_ci        }
8018bf80f4bSopenharmony_ci        if (extFunctions_.vkGetPhysicalDeviceFeatures2) {
8028bf80f4bSopenharmony_ci            extFunctions_.vkGetPhysicalDeviceFeatures2(plat_.physicalDevice, &physicalDeviceFeatures2);
8038bf80f4bSopenharmony_ci        }
8048bf80f4bSopenharmony_ci        if (extFunctions_.vkGetPhysicalDeviceProperties2) {
8058bf80f4bSopenharmony_ci            extFunctions_.vkGetPhysicalDeviceProperties2(plat_.physicalDevice, &physicalDeviceProperties2);
8068bf80f4bSopenharmony_ci        }
8078bf80f4bSopenharmony_ci
8088bf80f4bSopenharmony_ci        // vkGetPhysicalDeviceFeatures has already filled this and PreparePhysicalDeviceFeaturesForEnabling
8098bf80f4bSopenharmony_ci        // disabled/ enabled some features.
8108bf80f4bSopenharmony_ci        physicalDeviceFeatures2.features = plat_.enabledPhysicalDeviceFeatures;
8118bf80f4bSopenharmony_ci        physicalDeviceFeatures2Ptr = &physicalDeviceFeatures2;
8128bf80f4bSopenharmony_ci    }
8138bf80f4bSopenharmony_ci    const DeviceWrapper deviceWrapper =
8148bf80f4bSopenharmony_ci        CreateFunctionsVk::CreateDevice(plat_.instance, plat_.physicalDevice, plat_.physicalDeviceExtensions,
8158bf80f4bSopenharmony_ci            plat_.enabledPhysicalDeviceFeatures, physicalDeviceFeatures2Ptr, availableQueues, preferredExtensions);
8168bf80f4bSopenharmony_ci    plat_.device = deviceWrapper.device;
8178bf80f4bSopenharmony_ci    for (const auto& ref : deviceWrapper.extensions) {
8188bf80f4bSopenharmony_ci        extensions_[ref] = 1u;
8198bf80f4bSopenharmony_ci    }
8208bf80f4bSopenharmony_ci    commonDeviceExtensions_ = GetEnabledCommonDeviceExtensions(extensions_);
8218bf80f4bSopenharmony_ci    platformDeviceExtensions_ = GetEnabledPlatformDeviceExtensions(extensions_);
8228bf80f4bSopenharmony_ci    commonDeviceProperties_ = GetCommonDevicePropertiesFunc(chainObjects);
8238bf80f4bSopenharmony_ci}
8248bf80f4bSopenharmony_ci
8258bf80f4bSopenharmony_civector<QueueProperties> DeviceVk::CheckExternalConfig(const BackendExtraVk* backendConfiguration)
8268bf80f4bSopenharmony_ci{
8278bf80f4bSopenharmony_ci    vector<QueueProperties> queueProperties;
8288bf80f4bSopenharmony_ci    queueProperties.push_back(DEFAULT_QUEUE);
8298bf80f4bSopenharmony_ci
8308bf80f4bSopenharmony_ci    if (!backendConfiguration) {
8318bf80f4bSopenharmony_ci        return queueProperties;
8328bf80f4bSopenharmony_ci    }
8338bf80f4bSopenharmony_ci
8348bf80f4bSopenharmony_ci    const auto& extra = *backendConfiguration;
8358bf80f4bSopenharmony_ci    if (extra.enableMultiQueue) {
8368bf80f4bSopenharmony_ci        queueProperties.push_back(QueueProperties {
8378bf80f4bSopenharmony_ci            VK_QUEUE_COMPUTE_BIT, // requiredFlags
8388bf80f4bSopenharmony_ci            1,                    // count
8398bf80f4bSopenharmony_ci            1.0f,                 // priority
8408bf80f4bSopenharmony_ci            true,                 // explicitFlags
8418bf80f4bSopenharmony_ci            false,                // canPresent
8428bf80f4bSopenharmony_ci        });
8438bf80f4bSopenharmony_ci        PLUGIN_LOG_I("trying to enable gpu multi-queue, with queue count: %u", (uint32_t)queueProperties.size());
8448bf80f4bSopenharmony_ci    }
8458bf80f4bSopenharmony_ci
8468bf80f4bSopenharmony_ci    if (extra.instance != VK_NULL_HANDLE) {
8478bf80f4bSopenharmony_ci        PLUGIN_LOG_D("trying to use application given vulkan instance, device, and physical device");
8488bf80f4bSopenharmony_ci        PLUGIN_ASSERT((extra.instance && extra.physicalDevice && extra.device));
8498bf80f4bSopenharmony_ci        plat_.instance = extra.instance;
8508bf80f4bSopenharmony_ci        plat_.physicalDevice = extra.physicalDevice;
8518bf80f4bSopenharmony_ci        plat_.device = extra.device;
8528bf80f4bSopenharmony_ci        if (extra.extensions.physicalDeviceFeaturesToEnable) {
8538bf80f4bSopenharmony_ci            plat_.enabledPhysicalDeviceFeatures = extra.extensions.physicalDeviceFeaturesToEnable->features;
8548bf80f4bSopenharmony_ci        }
8558bf80f4bSopenharmony_ci        ownInstanceAndDevice_ = false; // everything given from the application
8568bf80f4bSopenharmony_ci
8578bf80f4bSopenharmony_ci        const auto myDevice = plat_.physicalDevice;
8588bf80f4bSopenharmony_ci        auto& myProperties = plat_.physicalDeviceProperties;
8598bf80f4bSopenharmony_ci        vkGetPhysicalDeviceProperties(myDevice, &myProperties.physicalDeviceProperties);
8608bf80f4bSopenharmony_ci        vkGetPhysicalDeviceFeatures(myDevice, &myProperties.physicalDeviceFeatures);
8618bf80f4bSopenharmony_ci        vkGetPhysicalDeviceMemoryProperties(myDevice, &myProperties.physicalDeviceMemoryProperties);
8628bf80f4bSopenharmony_ci
8638bf80f4bSopenharmony_ci        for (const auto& extension : extra.extensions.extensionNames) {
8648bf80f4bSopenharmony_ci            extensions_[extension] = 1u;
8658bf80f4bSopenharmony_ci        }
8668bf80f4bSopenharmony_ci    }
8678bf80f4bSopenharmony_ci    return queueProperties;
8688bf80f4bSopenharmony_ci}
8698bf80f4bSopenharmony_ci
8708bf80f4bSopenharmony_civoid DeviceVk::SortAvailableQueues(const vector<LowLevelQueueInfo>& availableQueues)
8718bf80f4bSopenharmony_ci{
8728bf80f4bSopenharmony_ci    for (const auto& ref : availableQueues) {
8738bf80f4bSopenharmony_ci        if (ref.queueFlags == VkQueueFlagBits::VK_QUEUE_COMPUTE_BIT) {
8748bf80f4bSopenharmony_ci            EmplaceDeviceQueue(plat_.device, ref, lowLevelGpuQueues_.computeQueues);
8758bf80f4bSopenharmony_ci        } else if (ref.queueFlags == VkQueueFlagBits::VK_QUEUE_GRAPHICS_BIT) {
8768bf80f4bSopenharmony_ci            EmplaceDeviceQueue(plat_.device, ref, lowLevelGpuQueues_.graphicsQueues);
8778bf80f4bSopenharmony_ci        } else if (ref.queueFlags == VkQueueFlagBits::VK_QUEUE_TRANSFER_BIT) {
8788bf80f4bSopenharmony_ci            EmplaceDeviceQueue(plat_.device, ref, lowLevelGpuQueues_.transferQueues);
8798bf80f4bSopenharmony_ci        }
8808bf80f4bSopenharmony_ci    }
8818bf80f4bSopenharmony_ci}
8828bf80f4bSopenharmony_ci
8838bf80f4bSopenharmony_ciDeviceBackendType DeviceVk::GetBackendType() const
8848bf80f4bSopenharmony_ci{
8858bf80f4bSopenharmony_ci    return DeviceBackendType::VULKAN;
8868bf80f4bSopenharmony_ci}
8878bf80f4bSopenharmony_ci
8888bf80f4bSopenharmony_ciconst DevicePlatformData& DeviceVk::GetPlatformData() const
8898bf80f4bSopenharmony_ci{
8908bf80f4bSopenharmony_ci    return plat_;
8918bf80f4bSopenharmony_ci}
8928bf80f4bSopenharmony_ci
8938bf80f4bSopenharmony_ciconst DevicePlatformDataVk& DeviceVk::GetPlatformDataVk() const
8948bf80f4bSopenharmony_ci{
8958bf80f4bSopenharmony_ci    return plat_;
8968bf80f4bSopenharmony_ci}
8978bf80f4bSopenharmony_ci
8988bf80f4bSopenharmony_ciconst DevicePlatformInternalDataVk& DeviceVk::GetPlatformInternalDataVk() const
8998bf80f4bSopenharmony_ci{
9008bf80f4bSopenharmony_ci    return platInternal_;
9018bf80f4bSopenharmony_ci}
9028bf80f4bSopenharmony_ci
9038bf80f4bSopenharmony_ciILowLevelDevice& DeviceVk::GetLowLevelDevice() const
9048bf80f4bSopenharmony_ci{
9058bf80f4bSopenharmony_ci    return *lowLevelDevice_;
9068bf80f4bSopenharmony_ci}
9078bf80f4bSopenharmony_ci
9088bf80f4bSopenharmony_ciFormatProperties DeviceVk::GetFormatProperties(const Format format) const
9098bf80f4bSopenharmony_ci{
9108bf80f4bSopenharmony_ci    const uint32_t formatSupportSize = static_cast<uint32_t>(formatProperties_.size());
9118bf80f4bSopenharmony_ci    const uint32_t formatIdx = static_cast<uint32_t>(format);
9128bf80f4bSopenharmony_ci    if (formatIdx < formatSupportSize) {
9138bf80f4bSopenharmony_ci        return formatProperties_[formatIdx];
9148bf80f4bSopenharmony_ci    } else if ((formatIdx >= DeviceFormatSupportConstants::ADDITIONAL_FORMAT_START_NUMBER) &&
9158bf80f4bSopenharmony_ci               (formatIdx <= DeviceFormatSupportConstants::ADDITIONAL_FORMAT_END_NUMBER)) {
9168bf80f4bSopenharmony_ci        const uint32_t currIdx = formatIdx - DeviceFormatSupportConstants::ADDITIONAL_FORMAT_START_NUMBER;
9178bf80f4bSopenharmony_ci        PLUGIN_UNUSED(currIdx);
9188bf80f4bSopenharmony_ci        PLUGIN_ASSERT(currIdx < formatSupportSize);
9198bf80f4bSopenharmony_ci        return formatProperties_[currIdx];
9208bf80f4bSopenharmony_ci    }
9218bf80f4bSopenharmony_ci    return {};
9228bf80f4bSopenharmony_ci}
9238bf80f4bSopenharmony_ci
9248bf80f4bSopenharmony_ciAccelerationStructureBuildSizes DeviceVk::GetAccelerationStructureBuildSizes(
9258bf80f4bSopenharmony_ci    const AccelerationStructureBuildGeometryInfo& geometry,
9268bf80f4bSopenharmony_ci    BASE_NS::array_view<const AccelerationStructureGeometryTrianglesInfo> triangles,
9278bf80f4bSopenharmony_ci    BASE_NS::array_view<const AccelerationStructureGeometryAabbsInfo> aabbs,
9288bf80f4bSopenharmony_ci    BASE_NS::array_view<const AccelerationStructureGeometryInstancesInfo> instances) const
9298bf80f4bSopenharmony_ci{
9308bf80f4bSopenharmony_ci#if (RENDER_VULKAN_RT_ENABLED == 1)
9318bf80f4bSopenharmony_ci    const VkDevice device = plat_.device;
9328bf80f4bSopenharmony_ci
9338bf80f4bSopenharmony_ci    const size_t arraySize = triangles.size() + aabbs.size() + instances.size();
9348bf80f4bSopenharmony_ci    vector<VkAccelerationStructureGeometryKHR> geometryData(arraySize);
9358bf80f4bSopenharmony_ci    vector<uint32_t> maxPrimitiveCounts(arraySize);
9368bf80f4bSopenharmony_ci    uint32_t arrayIndex = 0;
9378bf80f4bSopenharmony_ci    for (const auto& trianglesRef : triangles) {
9388bf80f4bSopenharmony_ci        geometryData[arrayIndex] = VkAccelerationStructureGeometryKHR {
9398bf80f4bSopenharmony_ci            VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_GEOMETRY_KHR, // sType
9408bf80f4bSopenharmony_ci            nullptr,                                               // pNext
9418bf80f4bSopenharmony_ci            VkGeometryTypeKHR::VK_GEOMETRY_TYPE_TRIANGLES_KHR,     // geometryType
9428bf80f4bSopenharmony_ci            {},                                                    // geometry;
9438bf80f4bSopenharmony_ci            VkGeometryFlagsKHR(trianglesRef.geometryFlags),        // flags
9448bf80f4bSopenharmony_ci        };
9458bf80f4bSopenharmony_ci        geometryData[arrayIndex].geometry.triangles = VkAccelerationStructureGeometryTrianglesDataKHR {
9468bf80f4bSopenharmony_ci            VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_GEOMETRY_TRIANGLES_DATA_KHR, // sType
9478bf80f4bSopenharmony_ci            nullptr,                                                              // pNext
9488bf80f4bSopenharmony_ci            VkFormat(trianglesRef.vertexFormat),                                  // vertexFormat
9498bf80f4bSopenharmony_ci            {},                                                                   // vertexData
9508bf80f4bSopenharmony_ci            VkDeviceSize(trianglesRef.vertexStride),                              // vertexStride
9518bf80f4bSopenharmony_ci            trianglesRef.maxVertex,                                               // maxVertex
9528bf80f4bSopenharmony_ci            VkIndexType(trianglesRef.indexType),                                  // indexType
9538bf80f4bSopenharmony_ci            {},                                                                   // indexData
9548bf80f4bSopenharmony_ci            {},                                                                   // transformData
9558bf80f4bSopenharmony_ci        };
9568bf80f4bSopenharmony_ci        maxPrimitiveCounts[arrayIndex] = trianglesRef.indexCount / 3u; // triangles;
9578bf80f4bSopenharmony_ci        arrayIndex++;
9588bf80f4bSopenharmony_ci    }
9598bf80f4bSopenharmony_ci    for (const auto& aabbsRef : aabbs) {
9608bf80f4bSopenharmony_ci        geometryData[arrayIndex] = VkAccelerationStructureGeometryKHR {
9618bf80f4bSopenharmony_ci            VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_GEOMETRY_KHR, // sType
9628bf80f4bSopenharmony_ci            nullptr,                                               // pNext
9638bf80f4bSopenharmony_ci            VkGeometryTypeKHR::VK_GEOMETRY_TYPE_AABBS_KHR,         // geometryType
9648bf80f4bSopenharmony_ci            {},                                                    // geometry;
9658bf80f4bSopenharmony_ci            0,                                                     // flags
9668bf80f4bSopenharmony_ci        };
9678bf80f4bSopenharmony_ci        geometryData[arrayIndex].geometry.aabbs = VkAccelerationStructureGeometryAabbsDataKHR {
9688bf80f4bSopenharmony_ci            VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_GEOMETRY_AABBS_DATA_KHR, // sType
9698bf80f4bSopenharmony_ci            nullptr,                                                          // pNext
9708bf80f4bSopenharmony_ci            {},                                                               // data
9718bf80f4bSopenharmony_ci            aabbsRef.stride,                                                  // stride
9728bf80f4bSopenharmony_ci        };
9738bf80f4bSopenharmony_ci        maxPrimitiveCounts[arrayIndex] = 1u;
9748bf80f4bSopenharmony_ci        arrayIndex++;
9758bf80f4bSopenharmony_ci    }
9768bf80f4bSopenharmony_ci    for (const auto& instancesRef : instances) {
9778bf80f4bSopenharmony_ci        geometryData[arrayIndex] = VkAccelerationStructureGeometryKHR {
9788bf80f4bSopenharmony_ci            VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_GEOMETRY_KHR, // sType
9798bf80f4bSopenharmony_ci            nullptr,                                               // pNext
9808bf80f4bSopenharmony_ci            VkGeometryTypeKHR::VK_GEOMETRY_TYPE_INSTANCES_KHR,     // geometryType
9818bf80f4bSopenharmony_ci            {},                                                    // geometry;
9828bf80f4bSopenharmony_ci            0,                                                     // flags
9838bf80f4bSopenharmony_ci        };
9848bf80f4bSopenharmony_ci        geometryData[arrayIndex].geometry.instances = VkAccelerationStructureGeometryInstancesDataKHR {
9858bf80f4bSopenharmony_ci            VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_GEOMETRY_INSTANCES_DATA_KHR, // sType
9868bf80f4bSopenharmony_ci            nullptr,                                                              // pNext
9878bf80f4bSopenharmony_ci            instancesRef.arrayOfPointers,                                         // arrayOfPointers
9888bf80f4bSopenharmony_ci            {},                                                                   // data
9898bf80f4bSopenharmony_ci        };
9908bf80f4bSopenharmony_ci        maxPrimitiveCounts[arrayIndex] = 1u;
9918bf80f4bSopenharmony_ci        arrayIndex++;
9928bf80f4bSopenharmony_ci    }
9938bf80f4bSopenharmony_ci
9948bf80f4bSopenharmony_ci    const VkAccelerationStructureBuildGeometryInfoKHR geometryInfoVk {
9958bf80f4bSopenharmony_ci        VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_BUILD_GEOMETRY_INFO_KHR, // sType
9968bf80f4bSopenharmony_ci        nullptr,                                                          // pNext
9978bf80f4bSopenharmony_ci        VkAccelerationStructureTypeKHR(geometry.type),                    // type
9988bf80f4bSopenharmony_ci        VkBuildAccelerationStructureFlagsKHR(geometry.flags),             // flags
9998bf80f4bSopenharmony_ci        VkBuildAccelerationStructureModeKHR(geometry.mode),               // mode
10008bf80f4bSopenharmony_ci        VK_NULL_HANDLE,                                                   // srcAccelerationStructure
10018bf80f4bSopenharmony_ci        VK_NULL_HANDLE,                                                   // dstAccelerationStructure
10028bf80f4bSopenharmony_ci        arrayIndex,                                                       // geometryCount
10038bf80f4bSopenharmony_ci        geometryData.data(),                                              // pGeometries
10048bf80f4bSopenharmony_ci        nullptr,                                                          // ppGeometries
10058bf80f4bSopenharmony_ci        {},                                                               // scratchData
10068bf80f4bSopenharmony_ci    };
10078bf80f4bSopenharmony_ci
10088bf80f4bSopenharmony_ci    VkAccelerationStructureBuildSizesInfoKHR buildSizesInfo {
10098bf80f4bSopenharmony_ci        VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_BUILD_SIZES_INFO_KHR, // sType
10108bf80f4bSopenharmony_ci        nullptr,                                                       // pNext
10118bf80f4bSopenharmony_ci        0,                                                             // accelerationStructureSize
10128bf80f4bSopenharmony_ci        0,                                                             // updateScratchSize
10138bf80f4bSopenharmony_ci        0,                                                             // buildScratchSize
10148bf80f4bSopenharmony_ci    };
10158bf80f4bSopenharmony_ci    if ((arrayIndex > 0) && extFunctions_.vkGetAccelerationStructureBuildSizesKHR) {
10168bf80f4bSopenharmony_ci        extFunctions_.vkGetAccelerationStructureBuildSizesKHR(device, // device
10178bf80f4bSopenharmony_ci            VK_ACCELERATION_STRUCTURE_BUILD_TYPE_DEVICE_KHR,          // buildType,
10188bf80f4bSopenharmony_ci            &geometryInfoVk,                                          // pBuildInfo
10198bf80f4bSopenharmony_ci            maxPrimitiveCounts.data(),                                // pMaxPrimitiveCounts
10208bf80f4bSopenharmony_ci            &buildSizesInfo);                                         // pSizeInfo
10218bf80f4bSopenharmony_ci    }
10228bf80f4bSopenharmony_ci
10238bf80f4bSopenharmony_ci    return AccelerationStructureBuildSizes {
10248bf80f4bSopenharmony_ci        static_cast<uint32_t>(buildSizesInfo.accelerationStructureSize),
10258bf80f4bSopenharmony_ci        static_cast<uint32_t>(buildSizesInfo.updateScratchSize),
10268bf80f4bSopenharmony_ci        static_cast<uint32_t>(buildSizesInfo.buildScratchSize),
10278bf80f4bSopenharmony_ci    };
10288bf80f4bSopenharmony_ci#else
10298bf80f4bSopenharmony_ci    return AccelerationStructureBuildSizes { 0, 0, 0 };
10308bf80f4bSopenharmony_ci#endif
10318bf80f4bSopenharmony_ci}
10328bf80f4bSopenharmony_ci
10338bf80f4bSopenharmony_ciunique_ptr<Swapchain> DeviceVk::CreateDeviceSwapchain(const SwapchainCreateInfo& swapchainCreateInfo)
10348bf80f4bSopenharmony_ci{
10358bf80f4bSopenharmony_ci    return make_unique<SwapchainVk>(*this, swapchainCreateInfo);
10368bf80f4bSopenharmony_ci}
10378bf80f4bSopenharmony_ci
10388bf80f4bSopenharmony_civoid DeviceVk::DestroyDeviceSwapchain() {}
10398bf80f4bSopenharmony_ci
10408bf80f4bSopenharmony_ciPlatformGpuMemoryAllocator* DeviceVk::GetPlatformGpuMemoryAllocator()
10418bf80f4bSopenharmony_ci{
10428bf80f4bSopenharmony_ci    return platformGpuMemoryAllocator_.get();
10438bf80f4bSopenharmony_ci}
10448bf80f4bSopenharmony_ci
10458bf80f4bSopenharmony_ciGpuQueue DeviceVk::GetValidGpuQueue(const GpuQueue& gpuQueue) const
10468bf80f4bSopenharmony_ci{
10478bf80f4bSopenharmony_ci    const auto getSpecificQueue = [](const uint32_t queueIndex, const GpuQueue::QueueType queueType,
10488bf80f4bSopenharmony_ci                                      const vector<LowLevelGpuQueueVk>& specificQueues, const GpuQueue& defaultQueue) {
10498bf80f4bSopenharmony_ci        const uint32_t queueCount = (uint32_t)specificQueues.size();
10508bf80f4bSopenharmony_ci        if (queueIndex < queueCount) {
10518bf80f4bSopenharmony_ci            return GpuQueue { queueType, queueIndex };
10528bf80f4bSopenharmony_ci        } else if (queueCount > 0) {
10538bf80f4bSopenharmony_ci            return GpuQueue { queueType, 0 };
10548bf80f4bSopenharmony_ci        }
10558bf80f4bSopenharmony_ci        return defaultQueue;
10568bf80f4bSopenharmony_ci    };
10578bf80f4bSopenharmony_ci
10588bf80f4bSopenharmony_ci    GpuQueue defaultQueue { GpuQueue::QueueType::GRAPHICS, 0 };
10598bf80f4bSopenharmony_ci    if (gpuQueue.type == GpuQueue::QueueType::COMPUTE) {
10608bf80f4bSopenharmony_ci        return getSpecificQueue(
10618bf80f4bSopenharmony_ci            gpuQueue.index, GpuQueue::QueueType::COMPUTE, lowLevelGpuQueues_.computeQueues, defaultQueue);
10628bf80f4bSopenharmony_ci    } else if (gpuQueue.type == GpuQueue::QueueType::GRAPHICS) {
10638bf80f4bSopenharmony_ci        return getSpecificQueue(
10648bf80f4bSopenharmony_ci            gpuQueue.index, GpuQueue::QueueType::GRAPHICS, lowLevelGpuQueues_.graphicsQueues, defaultQueue);
10658bf80f4bSopenharmony_ci    } else if (gpuQueue.type == GpuQueue::QueueType::TRANSFER) {
10668bf80f4bSopenharmony_ci        return getSpecificQueue(
10678bf80f4bSopenharmony_ci            gpuQueue.index, GpuQueue::QueueType::TRANSFER, lowLevelGpuQueues_.transferQueues, defaultQueue);
10688bf80f4bSopenharmony_ci    } else {
10698bf80f4bSopenharmony_ci        return defaultQueue;
10708bf80f4bSopenharmony_ci    }
10718bf80f4bSopenharmony_ci}
10728bf80f4bSopenharmony_ci
10738bf80f4bSopenharmony_ciuint32_t DeviceVk::GetGpuQueueCount() const
10748bf80f4bSopenharmony_ci{
10758bf80f4bSopenharmony_ci    return gpuQueueCount_;
10768bf80f4bSopenharmony_ci}
10778bf80f4bSopenharmony_ci
10788bf80f4bSopenharmony_civoid DeviceVk::InitializePipelineCache(array_view<const uint8_t> initialData)
10798bf80f4bSopenharmony_ci{
10808bf80f4bSopenharmony_ci    if (plat_.pipelineCache) {
10818bf80f4bSopenharmony_ci        CreateFunctionsVk::DestroyPipelineCache(plat_.device, plat_.pipelineCache);
10828bf80f4bSopenharmony_ci    }
10838bf80f4bSopenharmony_ci    struct CacheHeader {
10848bf80f4bSopenharmony_ci        uint32_t bytes;
10858bf80f4bSopenharmony_ci        uint32_t version;
10868bf80f4bSopenharmony_ci        uint32_t vendorId;
10878bf80f4bSopenharmony_ci        uint32_t deviceId;
10888bf80f4bSopenharmony_ci        uint8_t pipelineCacheUUID[VK_UUID_SIZE];
10898bf80f4bSopenharmony_ci    };
10908bf80f4bSopenharmony_ci    if (initialData.size() > sizeof(CacheHeader)) {
10918bf80f4bSopenharmony_ci        CacheHeader header;
10928bf80f4bSopenharmony_ci        CloneData(&header, sizeof(header), initialData.data(), sizeof(header));
10938bf80f4bSopenharmony_ci        const auto& props = plat_.physicalDeviceProperties.physicalDeviceProperties;
10948bf80f4bSopenharmony_ci        if (header.version != VkPipelineCacheHeaderVersion::VK_PIPELINE_CACHE_HEADER_VERSION_ONE ||
10958bf80f4bSopenharmony_ci            header.vendorId != props.vendorID || header.deviceId != props.deviceID ||
10968bf80f4bSopenharmony_ci            memcmp(header.pipelineCacheUUID, props.pipelineCacheUUID, VK_UUID_SIZE)) {
10978bf80f4bSopenharmony_ci            initialData = {};
10988bf80f4bSopenharmony_ci        }
10998bf80f4bSopenharmony_ci    }
11008bf80f4bSopenharmony_ci
11018bf80f4bSopenharmony_ci    plat_.pipelineCache = CreateFunctionsVk::CreatePipelineCache(plat_.device, initialData);
11028bf80f4bSopenharmony_ci}
11038bf80f4bSopenharmony_ci
11048bf80f4bSopenharmony_civector<uint8_t> DeviceVk::GetPipelineCache() const
11058bf80f4bSopenharmony_ci{
11068bf80f4bSopenharmony_ci    vector<uint8_t> deviceData;
11078bf80f4bSopenharmony_ci    if (plat_.pipelineCache) {
11088bf80f4bSopenharmony_ci        size_t dataSize = 0u;
11098bf80f4bSopenharmony_ci        if (auto result = vkGetPipelineCacheData(plat_.device, plat_.pipelineCache, &dataSize, nullptr);
11108bf80f4bSopenharmony_ci            result == VK_SUCCESS && dataSize) {
11118bf80f4bSopenharmony_ci            deviceData.resize(dataSize);
11128bf80f4bSopenharmony_ci            dataSize = deviceData.size();
11138bf80f4bSopenharmony_ci            result = vkGetPipelineCacheData(plat_.device, plat_.pipelineCache, &dataSize, deviceData.data());
11148bf80f4bSopenharmony_ci            if (result == VK_SUCCESS) {
11158bf80f4bSopenharmony_ci                deviceData.resize(dataSize);
11168bf80f4bSopenharmony_ci            } else {
11178bf80f4bSopenharmony_ci                deviceData.clear();
11188bf80f4bSopenharmony_ci            }
11198bf80f4bSopenharmony_ci        }
11208bf80f4bSopenharmony_ci    }
11218bf80f4bSopenharmony_ci    return deviceData;
11228bf80f4bSopenharmony_ci}
11238bf80f4bSopenharmony_ci
11248bf80f4bSopenharmony_ciLowLevelGpuQueueVk DeviceVk::GetGpuQueue(const GpuQueue& gpuQueue) const
11258bf80f4bSopenharmony_ci{
11268bf80f4bSopenharmony_ci    // 1. tries to return the typed queue with given index
11278bf80f4bSopenharmony_ci    // 2. tries to return the typed queue with an index 0
11288bf80f4bSopenharmony_ci    // 3. returns the default queue
11298bf80f4bSopenharmony_ci    const auto getSpecificQueue = [](const uint32_t queueIndex, const vector<LowLevelGpuQueueVk>& specificQueues,
11308bf80f4bSopenharmony_ci                                      const LowLevelGpuQueueVk& defaultQueue) {
11318bf80f4bSopenharmony_ci        const uint32_t queueCount = (uint32_t)specificQueues.size();
11328bf80f4bSopenharmony_ci        if (queueIndex < queueCount) {
11338bf80f4bSopenharmony_ci            return specificQueues[queueIndex];
11348bf80f4bSopenharmony_ci        } else if (queueCount > 0) {
11358bf80f4bSopenharmony_ci            return specificQueues[0];
11368bf80f4bSopenharmony_ci        }
11378bf80f4bSopenharmony_ci        return defaultQueue;
11388bf80f4bSopenharmony_ci    };
11398bf80f4bSopenharmony_ci
11408bf80f4bSopenharmony_ci    if (gpuQueue.type == GpuQueue::QueueType::COMPUTE) {
11418bf80f4bSopenharmony_ci        return getSpecificQueue(gpuQueue.index, lowLevelGpuQueues_.computeQueues, lowLevelGpuQueues_.defaultQueue);
11428bf80f4bSopenharmony_ci    } else if (gpuQueue.type == GpuQueue::QueueType::GRAPHICS) {
11438bf80f4bSopenharmony_ci        return getSpecificQueue(gpuQueue.index, lowLevelGpuQueues_.graphicsQueues, lowLevelGpuQueues_.defaultQueue);
11448bf80f4bSopenharmony_ci    } else if (gpuQueue.type == GpuQueue::QueueType::TRANSFER) {
11458bf80f4bSopenharmony_ci        return getSpecificQueue(gpuQueue.index, lowLevelGpuQueues_.transferQueues, lowLevelGpuQueues_.defaultQueue);
11468bf80f4bSopenharmony_ci    } else {
11478bf80f4bSopenharmony_ci        return lowLevelGpuQueues_.defaultQueue;
11488bf80f4bSopenharmony_ci    }
11498bf80f4bSopenharmony_ci}
11508bf80f4bSopenharmony_ci
11518bf80f4bSopenharmony_ciLowLevelGpuQueueVk DeviceVk::GetPresentationGpuQueue() const
11528bf80f4bSopenharmony_ci{
11538bf80f4bSopenharmony_ci    // NOTE: expected presentation
11548bf80f4bSopenharmony_ci    return GetGpuQueue(GpuQueue { GpuQueue::QueueType::GRAPHICS, 0 });
11558bf80f4bSopenharmony_ci}
11568bf80f4bSopenharmony_ci
11578bf80f4bSopenharmony_civector<LowLevelGpuQueueVk> DeviceVk::GetLowLevelGpuQueues() const
11588bf80f4bSopenharmony_ci{
11598bf80f4bSopenharmony_ci    vector<LowLevelGpuQueueVk> gpuQueues;
11608bf80f4bSopenharmony_ci    gpuQueues.reserve(gpuQueueCount_);
11618bf80f4bSopenharmony_ci    gpuQueues.insert(gpuQueues.end(), lowLevelGpuQueues_.computeQueues.begin(), lowLevelGpuQueues_.computeQueues.end());
11628bf80f4bSopenharmony_ci    gpuQueues.insert(
11638bf80f4bSopenharmony_ci        gpuQueues.end(), lowLevelGpuQueues_.graphicsQueues.begin(), lowLevelGpuQueues_.graphicsQueues.end());
11648bf80f4bSopenharmony_ci    gpuQueues.insert(
11658bf80f4bSopenharmony_ci        gpuQueues.end(), lowLevelGpuQueues_.transferQueues.begin(), lowLevelGpuQueues_.transferQueues.end());
11668bf80f4bSopenharmony_ci    return gpuQueues;
11678bf80f4bSopenharmony_ci}
11688bf80f4bSopenharmony_ci
11698bf80f4bSopenharmony_civoid DeviceVk::WaitForIdle()
11708bf80f4bSopenharmony_ci{
11718bf80f4bSopenharmony_ci    if (plat_.device) {
11728bf80f4bSopenharmony_ci        if (!isRenderbackendRunning_) {
11738bf80f4bSopenharmony_ci            PLUGIN_LOG_D("Device - WaitForIdle");
11748bf80f4bSopenharmony_ci            vkDeviceWaitIdle(plat_.device); // device
11758bf80f4bSopenharmony_ci        } else {
11768bf80f4bSopenharmony_ci            PLUGIN_LOG_E("Device WaitForIdle can only called when render backend is not running");
11778bf80f4bSopenharmony_ci        }
11788bf80f4bSopenharmony_ci    }
11798bf80f4bSopenharmony_ci}
11808bf80f4bSopenharmony_ci
11818bf80f4bSopenharmony_civoid DeviceVk::Activate() {}
11828bf80f4bSopenharmony_ci
11838bf80f4bSopenharmony_civoid DeviceVk::Deactivate() {}
11848bf80f4bSopenharmony_ci
11858bf80f4bSopenharmony_cibool DeviceVk::AllowThreadedProcessing() const
11868bf80f4bSopenharmony_ci{
11878bf80f4bSopenharmony_ci    return true;
11888bf80f4bSopenharmony_ci}
11898bf80f4bSopenharmony_ci
11908bf80f4bSopenharmony_ciconst DeviceVk::FeatureConfigurations& DeviceVk::GetFeatureConfigurations() const
11918bf80f4bSopenharmony_ci{
11928bf80f4bSopenharmony_ci    return featureConfigurations_;
11938bf80f4bSopenharmony_ci}
11948bf80f4bSopenharmony_ci
11958bf80f4bSopenharmony_ciconst DeviceVk::CommonDeviceExtensions& DeviceVk::GetCommonDeviceExtensions() const
11968bf80f4bSopenharmony_ci{
11978bf80f4bSopenharmony_ci    return commonDeviceExtensions_;
11988bf80f4bSopenharmony_ci}
11998bf80f4bSopenharmony_ci
12008bf80f4bSopenharmony_ciconst PlatformDeviceExtensions& DeviceVk::GetPlatformDeviceExtensions() const
12018bf80f4bSopenharmony_ci{
12028bf80f4bSopenharmony_ci    return platformDeviceExtensions_;
12038bf80f4bSopenharmony_ci}
12048bf80f4bSopenharmony_ci
12058bf80f4bSopenharmony_cibool DeviceVk::HasDeviceExtension(const string_view extensionName) const
12068bf80f4bSopenharmony_ci{
12078bf80f4bSopenharmony_ci    return extensions_.contains(extensionName);
12088bf80f4bSopenharmony_ci}
12098bf80f4bSopenharmony_ci
12108bf80f4bSopenharmony_ciunique_ptr<Device> CreateDeviceVk(RenderContext& renderContext, DeviceCreateInfo const& createInfo)
12118bf80f4bSopenharmony_ci{
12128bf80f4bSopenharmony_ci    return make_unique<DeviceVk>(renderContext, createInfo);
12138bf80f4bSopenharmony_ci}
12148bf80f4bSopenharmony_ci
12158bf80f4bSopenharmony_ciunique_ptr<GpuBuffer> DeviceVk::CreateGpuBuffer(const GpuBufferDesc& desc)
12168bf80f4bSopenharmony_ci{
12178bf80f4bSopenharmony_ci    return make_unique<GpuBufferVk>(*this, desc);
12188bf80f4bSopenharmony_ci}
12198bf80f4bSopenharmony_ci
12208bf80f4bSopenharmony_ciunique_ptr<GpuBuffer> DeviceVk::CreateGpuBuffer(const GpuAccelerationStructureDesc& descAccel)
12218bf80f4bSopenharmony_ci{
12228bf80f4bSopenharmony_ci    return make_unique<GpuBufferVk>(*this, descAccel);
12238bf80f4bSopenharmony_ci}
12248bf80f4bSopenharmony_ci
12258bf80f4bSopenharmony_ciunique_ptr<GpuImage> DeviceVk::CreateGpuImage(const GpuImageDesc& desc)
12268bf80f4bSopenharmony_ci{
12278bf80f4bSopenharmony_ci    return make_unique<GpuImageVk>(*this, desc);
12288bf80f4bSopenharmony_ci}
12298bf80f4bSopenharmony_ci
12308bf80f4bSopenharmony_ciunique_ptr<GpuImage> DeviceVk::CreateGpuImageView(
12318bf80f4bSopenharmony_ci    const GpuImageDesc& desc, const GpuImagePlatformData& platformData, const uintptr_t hwBuffer)
12328bf80f4bSopenharmony_ci{
12338bf80f4bSopenharmony_ci    return make_unique<GpuImageVk>(*this, desc, platformData, hwBuffer);
12348bf80f4bSopenharmony_ci}
12358bf80f4bSopenharmony_ci
12368bf80f4bSopenharmony_ciunique_ptr<GpuImage> DeviceVk::CreateGpuImageView(const GpuImageDesc& desc, const GpuImagePlatformData& platformData)
12378bf80f4bSopenharmony_ci{
12388bf80f4bSopenharmony_ci    return CreateGpuImageView(desc, platformData, 0);
12398bf80f4bSopenharmony_ci}
12408bf80f4bSopenharmony_ci
12418bf80f4bSopenharmony_civector<unique_ptr<GpuImage>> DeviceVk::CreateGpuImageViews(const Swapchain& swapchain)
12428bf80f4bSopenharmony_ci{
12438bf80f4bSopenharmony_ci    const GpuImageDesc& desc = swapchain.GetDesc();
12448bf80f4bSopenharmony_ci    const auto& swapchainPlat = static_cast<const SwapchainVk&>(swapchain).GetPlatformData();
12458bf80f4bSopenharmony_ci
12468bf80f4bSopenharmony_ci    vector<unique_ptr<GpuImage>> gpuImages(swapchainPlat.swapchainImages.images.size());
12478bf80f4bSopenharmony_ci    for (size_t idx = 0; idx < gpuImages.size(); ++idx) {
12488bf80f4bSopenharmony_ci        GpuImagePlatformDataVk gpuImagePlat;
12498bf80f4bSopenharmony_ci        gpuImagePlat.image = swapchainPlat.swapchainImages.images[idx];
12508bf80f4bSopenharmony_ci        gpuImagePlat.imageView = swapchainPlat.swapchainImages.imageViews[idx];
12518bf80f4bSopenharmony_ci        gpuImages[idx] = this->CreateGpuImageView(desc, gpuImagePlat);
12528bf80f4bSopenharmony_ci    }
12538bf80f4bSopenharmony_ci    return gpuImages;
12548bf80f4bSopenharmony_ci}
12558bf80f4bSopenharmony_ci
12568bf80f4bSopenharmony_ciunique_ptr<GpuImage> DeviceVk::CreateGpuImageView(
12578bf80f4bSopenharmony_ci    const GpuImageDesc& desc, const BackendSpecificImageDesc& platformData)
12588bf80f4bSopenharmony_ci{
12598bf80f4bSopenharmony_ci    const ImageDescVk& imageDesc = (const ImageDescVk&)platformData;
12608bf80f4bSopenharmony_ci    GpuImagePlatformDataVk platData;
12618bf80f4bSopenharmony_ci    platData.image = imageDesc.image;
12628bf80f4bSopenharmony_ci    platData.imageView = imageDesc.imageView;
12638bf80f4bSopenharmony_ci    return CreateGpuImageView(desc, platData, imageDesc.platformHwBuffer);
12648bf80f4bSopenharmony_ci}
12658bf80f4bSopenharmony_ci
12668bf80f4bSopenharmony_ciunique_ptr<GpuSampler> DeviceVk::CreateGpuSampler(const GpuSamplerDesc& desc)
12678bf80f4bSopenharmony_ci{
12688bf80f4bSopenharmony_ci    return make_unique<GpuSamplerVk>(*this, desc);
12698bf80f4bSopenharmony_ci}
12708bf80f4bSopenharmony_ci
12718bf80f4bSopenharmony_ciunique_ptr<RenderFrameSync> DeviceVk::CreateRenderFrameSync()
12728bf80f4bSopenharmony_ci{
12738bf80f4bSopenharmony_ci    return make_unique<RenderFrameSyncVk>(*this);
12748bf80f4bSopenharmony_ci}
12758bf80f4bSopenharmony_ci
12768bf80f4bSopenharmony_ciunique_ptr<RenderBackend> DeviceVk::CreateRenderBackend(
12778bf80f4bSopenharmony_ci    GpuResourceManager& gpuResourceMgr, const CORE_NS::IParallelTaskQueue::Ptr& queue)
12788bf80f4bSopenharmony_ci{
12798bf80f4bSopenharmony_ci    return make_unique<RenderBackendVk>(*this, gpuResourceMgr, queue);
12808bf80f4bSopenharmony_ci}
12818bf80f4bSopenharmony_ci
12828bf80f4bSopenharmony_ciunique_ptr<ShaderModule> DeviceVk::CreateShaderModule(const ShaderModuleCreateInfo& data)
12838bf80f4bSopenharmony_ci{
12848bf80f4bSopenharmony_ci    return make_unique<ShaderModuleVk>(*this, data);
12858bf80f4bSopenharmony_ci}
12868bf80f4bSopenharmony_ci
12878bf80f4bSopenharmony_ciunique_ptr<ShaderModule> DeviceVk::CreateComputeShaderModule(const ShaderModuleCreateInfo& data)
12888bf80f4bSopenharmony_ci{
12898bf80f4bSopenharmony_ci    return make_unique<ShaderModuleVk>(*this, data);
12908bf80f4bSopenharmony_ci}
12918bf80f4bSopenharmony_ci
12928bf80f4bSopenharmony_ciunique_ptr<GpuShaderProgram> DeviceVk::CreateGpuShaderProgram(const GpuShaderProgramCreateData& data)
12938bf80f4bSopenharmony_ci{
12948bf80f4bSopenharmony_ci    return make_unique<GpuShaderProgramVk>(*this, data);
12958bf80f4bSopenharmony_ci}
12968bf80f4bSopenharmony_ci
12978bf80f4bSopenharmony_ciunique_ptr<GpuComputeProgram> DeviceVk::CreateGpuComputeProgram(const GpuComputeProgramCreateData& data)
12988bf80f4bSopenharmony_ci{
12998bf80f4bSopenharmony_ci    return make_unique<GpuComputeProgramVk>(*this, data);
13008bf80f4bSopenharmony_ci}
13018bf80f4bSopenharmony_ci
13028bf80f4bSopenharmony_ciunique_ptr<NodeContextDescriptorSetManager> DeviceVk::CreateNodeContextDescriptorSetManager()
13038bf80f4bSopenharmony_ci{
13048bf80f4bSopenharmony_ci    return make_unique<NodeContextDescriptorSetManagerVk>(*this);
13058bf80f4bSopenharmony_ci}
13068bf80f4bSopenharmony_ci
13078bf80f4bSopenharmony_ciunique_ptr<NodeContextPoolManager> DeviceVk::CreateNodeContextPoolManager(
13088bf80f4bSopenharmony_ci    GpuResourceManager& gpuResourceMgr, const GpuQueue& gpuQueue)
13098bf80f4bSopenharmony_ci{
13108bf80f4bSopenharmony_ci    return make_unique<NodeContextPoolManagerVk>(*this, gpuResourceMgr, gpuQueue);
13118bf80f4bSopenharmony_ci}
13128bf80f4bSopenharmony_ci
13138bf80f4bSopenharmony_ciunique_ptr<GraphicsPipelineStateObject> DeviceVk::CreateGraphicsPipelineStateObject(const GpuShaderProgram& gpuProgram,
13148bf80f4bSopenharmony_ci    const GraphicsState& graphicsState, const PipelineLayout& pipelineLayout,
13158bf80f4bSopenharmony_ci    const VertexInputDeclarationView& vertexInputDeclaration,
13168bf80f4bSopenharmony_ci    const ShaderSpecializationConstantDataView& specializationConstants,
13178bf80f4bSopenharmony_ci    const array_view<const DynamicStateEnum> dynamicStates, const RenderPassDesc& renderPassDesc,
13188bf80f4bSopenharmony_ci    const array_view<const RenderPassSubpassDesc>& renderPassSubpassDescs, const uint32_t subpassIndex,
13198bf80f4bSopenharmony_ci    const LowLevelRenderPassData* renderPassData, const LowLevelPipelineLayoutData* pipelineLayoutData)
13208bf80f4bSopenharmony_ci{
13218bf80f4bSopenharmony_ci    PLUGIN_ASSERT(renderPassData);
13228bf80f4bSopenharmony_ci    PLUGIN_ASSERT(pipelineLayoutData);
13238bf80f4bSopenharmony_ci    return make_unique<GraphicsPipelineStateObjectVk>(*this, gpuProgram, graphicsState, pipelineLayout,
13248bf80f4bSopenharmony_ci        vertexInputDeclaration, specializationConstants, dynamicStates, renderPassDesc, renderPassSubpassDescs,
13258bf80f4bSopenharmony_ci        subpassIndex, *renderPassData, *pipelineLayoutData);
13268bf80f4bSopenharmony_ci}
13278bf80f4bSopenharmony_ci
13288bf80f4bSopenharmony_ciunique_ptr<ComputePipelineStateObject> DeviceVk::CreateComputePipelineStateObject(const GpuComputeProgram& gpuProgram,
13298bf80f4bSopenharmony_ci    const PipelineLayout& pipelineLayout, const ShaderSpecializationConstantDataView& specializationConstants,
13308bf80f4bSopenharmony_ci    const LowLevelPipelineLayoutData* pipelineLayoutData)
13318bf80f4bSopenharmony_ci{
13328bf80f4bSopenharmony_ci    PLUGIN_ASSERT(pipelineLayoutData);
13338bf80f4bSopenharmony_ci    return make_unique<ComputePipelineStateObjectVk>(
13348bf80f4bSopenharmony_ci        *this, gpuProgram, pipelineLayout, specializationConstants, *pipelineLayoutData);
13358bf80f4bSopenharmony_ci}
13368bf80f4bSopenharmony_ci
13378bf80f4bSopenharmony_ciunique_ptr<GpuSemaphore> DeviceVk::CreateGpuSemaphore()
13388bf80f4bSopenharmony_ci{
13398bf80f4bSopenharmony_ci    return make_unique<GpuSemaphoreVk>(*this);
13408bf80f4bSopenharmony_ci}
13418bf80f4bSopenharmony_ci
13428bf80f4bSopenharmony_ciunique_ptr<GpuSemaphore> DeviceVk::CreateGpuSemaphoreView(const uint64_t handle)
13438bf80f4bSopenharmony_ci{
13448bf80f4bSopenharmony_ci    return make_unique<GpuSemaphoreVk>(*this, handle);
13458bf80f4bSopenharmony_ci}
13468bf80f4bSopenharmony_ci
13478bf80f4bSopenharmony_ciconst DebugFunctionUtilitiesVk& DeviceVk::GetDebugFunctionUtilities() const
13488bf80f4bSopenharmony_ci{
13498bf80f4bSopenharmony_ci    return debugFunctionUtilities_;
13508bf80f4bSopenharmony_ci}
13518bf80f4bSopenharmony_ci
13528bf80f4bSopenharmony_civoid DeviceVk::CreateDebugFunctions()
13538bf80f4bSopenharmony_ci{
13548bf80f4bSopenharmony_ci#if (RENDER_VULKAN_VALIDATION_ENABLED == 1)
13558bf80f4bSopenharmony_ci    debugFunctionUtilities_.vkSetDebugUtilsObjectNameEXT =
13568bf80f4bSopenharmony_ci        (PFN_vkSetDebugUtilsObjectNameEXT)(void*)vkGetDeviceProcAddr(plat_.device, "vkSetDebugUtilsObjectNameEXT");
13578bf80f4bSopenharmony_ci#endif
13588bf80f4bSopenharmony_ci#if (RENDER_DEBUG_MARKERS_ENABLED == 1) || (RENDER_DEBUG_COMMAND_MARKERS_ENABLED == 1)
13598bf80f4bSopenharmony_ci    debugFunctionUtilities_.vkCmdBeginDebugUtilsLabelEXT =
13608bf80f4bSopenharmony_ci        (PFN_vkCmdBeginDebugUtilsLabelEXT)vkGetInstanceProcAddr(plat_.instance, "vkCmdBeginDebugUtilsLabelEXT");
13618bf80f4bSopenharmony_ci    debugFunctionUtilities_.vkCmdEndDebugUtilsLabelEXT =
13628bf80f4bSopenharmony_ci        (PFN_vkCmdEndDebugUtilsLabelEXT)vkGetInstanceProcAddr(plat_.instance, "vkCmdEndDebugUtilsLabelEXT");
13638bf80f4bSopenharmony_ci#endif
13648bf80f4bSopenharmony_ci}
13658bf80f4bSopenharmony_ci
13668bf80f4bSopenharmony_ciconst DeviceVk::ExtFunctions& DeviceVk::GetExtFunctions() const
13678bf80f4bSopenharmony_ci{
13688bf80f4bSopenharmony_ci    return extFunctions_;
13698bf80f4bSopenharmony_ci}
13708bf80f4bSopenharmony_ci
13718bf80f4bSopenharmony_ciconst PlatformExtFunctions& DeviceVk::GetPlatformExtFunctions() const
13728bf80f4bSopenharmony_ci{
13738bf80f4bSopenharmony_ci    return platformExtFunctions_;
13748bf80f4bSopenharmony_ci}
13758bf80f4bSopenharmony_ci
13768bf80f4bSopenharmony_civoid DeviceVk::CreateExtFunctions()
13778bf80f4bSopenharmony_ci{
13788bf80f4bSopenharmony_ci    if (commonDeviceExtensions_.renderPass2) {
13798bf80f4bSopenharmony_ci        extFunctions_.vkCreateRenderPass2KHR =
13808bf80f4bSopenharmony_ci            (PFN_vkCreateRenderPass2KHR)(void*)vkGetInstanceProcAddr(plat_.instance, "vkCreateRenderPass2KHR");
13818bf80f4bSopenharmony_ci        if (!extFunctions_.vkCreateRenderPass2KHR) {
13828bf80f4bSopenharmony_ci            commonDeviceExtensions_.renderPass2 = false;
13838bf80f4bSopenharmony_ci            PLUGIN_LOG_E("vkGetInstanceProcAddr failed for vkCreateRenderPass2KHR");
13848bf80f4bSopenharmony_ci        }
13858bf80f4bSopenharmony_ci    }
13868bf80f4bSopenharmony_ci    if (commonDeviceExtensions_.getMemoryRequirements2) {
13878bf80f4bSopenharmony_ci        extFunctions_.vkGetImageMemoryRequirements2 = (PFN_vkGetImageMemoryRequirements2)vkGetInstanceProcAddr(
13888bf80f4bSopenharmony_ci            plat_.instance, "vkGetImageMemoryRequirements2KHR");
13898bf80f4bSopenharmony_ci        if (!extFunctions_.vkGetImageMemoryRequirements2) {
13908bf80f4bSopenharmony_ci            PLUGIN_LOG_E("vkGetInstanceProcAddr failed for vkGetImageMemoryRequirements2");
13918bf80f4bSopenharmony_ci        }
13928bf80f4bSopenharmony_ci    }
13938bf80f4bSopenharmony_ci    if (commonDeviceExtensions_.samplerYcbcrConversion) {
13948bf80f4bSopenharmony_ci        GetYcbcrExtFunctions(plat_.instance, extFunctions_);
13958bf80f4bSopenharmony_ci    }
13968bf80f4bSopenharmony_ci#if (RENDER_VULKAN_FSR_ENABLED == 1)
13978bf80f4bSopenharmony_ci    if (commonDeviceExtensions_.fragmentShadingRate) {
13988bf80f4bSopenharmony_ci        extFunctions_.vkCmdSetFragmentShadingRateKHR =
13998bf80f4bSopenharmony_ci            (PFN_vkCmdSetFragmentShadingRateKHR)vkGetInstanceProcAddr(plat_.instance, "vkCmdSetFragmentShadingRateKHR");
14008bf80f4bSopenharmony_ci    }
14018bf80f4bSopenharmony_ci#endif
14028bf80f4bSopenharmony_ci
14038bf80f4bSopenharmony_ci#if (RENDER_VULKAN_RT_ENABLED == 1)
14048bf80f4bSopenharmony_ci    extFunctions_.vkGetAccelerationStructureBuildSizesKHR =
14058bf80f4bSopenharmony_ci        (PFN_vkGetAccelerationStructureBuildSizesKHR)vkGetInstanceProcAddr(
14068bf80f4bSopenharmony_ci            plat_.instance, "vkGetAccelerationStructureBuildSizesKHR");
14078bf80f4bSopenharmony_ci    if (!extFunctions_.vkGetAccelerationStructureBuildSizesKHR) {
14088bf80f4bSopenharmony_ci        PLUGIN_LOG_E("vkGetInstanceProcAddr failed for vkGetAccelerationStructureBuildSizesKHR");
14098bf80f4bSopenharmony_ci    }
14108bf80f4bSopenharmony_ci    extFunctions_.vkCmdBuildAccelerationStructuresKHR = (PFN_vkCmdBuildAccelerationStructuresKHR)vkGetInstanceProcAddr(
14118bf80f4bSopenharmony_ci        plat_.instance, "vkCmdBuildAccelerationStructuresKHR");
14128bf80f4bSopenharmony_ci    if (!extFunctions_.vkCmdBuildAccelerationStructuresKHR) {
14138bf80f4bSopenharmony_ci        PLUGIN_LOG_E("vkGetInstanceProcAddr failed for vkCmdBuildAccelerationStructuresKHR");
14148bf80f4bSopenharmony_ci    }
14158bf80f4bSopenharmony_ci    extFunctions_.vkCreateAccelerationStructureKHR =
14168bf80f4bSopenharmony_ci        (PFN_vkCreateAccelerationStructureKHR)vkGetInstanceProcAddr(plat_.instance, "vkCreateAccelerationStructureKHR");
14178bf80f4bSopenharmony_ci    if (!extFunctions_.vkCreateAccelerationStructureKHR) {
14188bf80f4bSopenharmony_ci        PLUGIN_LOG_E("vkGetInstanceProcAddr failed for vkCreateAccelerationStructureKHR");
14198bf80f4bSopenharmony_ci    }
14208bf80f4bSopenharmony_ci    extFunctions_.vkDestroyAccelerationStructureKHR = (PFN_vkDestroyAccelerationStructureKHR)vkGetInstanceProcAddr(
14218bf80f4bSopenharmony_ci        plat_.instance, "vkDestroyAccelerationStructureKHR");
14228bf80f4bSopenharmony_ci    if (!extFunctions_.vkDestroyAccelerationStructureKHR) {
14238bf80f4bSopenharmony_ci        PLUGIN_LOG_E("vkGetInstanceProcAddr failed for vkDestroyAccelerationStructureKHR");
14248bf80f4bSopenharmony_ci    }
14258bf80f4bSopenharmony_ci    extFunctions_.vkGetAccelerationStructureDeviceAddressKHR =
14268bf80f4bSopenharmony_ci        (PFN_vkGetAccelerationStructureDeviceAddressKHR)vkGetInstanceProcAddr(
14278bf80f4bSopenharmony_ci            plat_.instance, "vkGetAccelerationStructureDeviceAddressKHR");
14288bf80f4bSopenharmony_ci    if (!extFunctions_.vkGetAccelerationStructureDeviceAddressKHR) {
14298bf80f4bSopenharmony_ci        PLUGIN_LOG_E("vkGetInstanceProcAddr failed for vkGetAccelerationStructureDeviceAddressKHR");
14308bf80f4bSopenharmony_ci    }
14318bf80f4bSopenharmony_ci#endif
14328bf80f4bSopenharmony_ci}
14338bf80f4bSopenharmony_ci
14348bf80f4bSopenharmony_ciLowLevelDeviceVk::LowLevelDeviceVk(DeviceVk& deviceVk)
14358bf80f4bSopenharmony_ci    : deviceVk_(deviceVk), gpuResourceMgr_(static_cast<GpuResourceManager&>(deviceVk_.GetGpuResourceManager()))
14368bf80f4bSopenharmony_ci{}
14378bf80f4bSopenharmony_ci
14388bf80f4bSopenharmony_ciDeviceBackendType LowLevelDeviceVk::GetBackendType() const
14398bf80f4bSopenharmony_ci{
14408bf80f4bSopenharmony_ci    return DeviceBackendType::VULKAN;
14418bf80f4bSopenharmony_ci}
14428bf80f4bSopenharmony_ci
14438bf80f4bSopenharmony_ciconst DevicePlatformDataVk& LowLevelDeviceVk::GetPlatformDataVk() const
14448bf80f4bSopenharmony_ci{
14458bf80f4bSopenharmony_ci    return deviceVk_.GetPlatformDataVk();
14468bf80f4bSopenharmony_ci}
14478bf80f4bSopenharmony_ci
14488bf80f4bSopenharmony_ciGpuBufferPlatformDataVk LowLevelDeviceVk::GetBuffer(RenderHandle handle) const
14498bf80f4bSopenharmony_ci{
14508bf80f4bSopenharmony_ci    if (deviceVk_.GetLockResourceBackendAccess()) {
14518bf80f4bSopenharmony_ci        GpuBufferVk* buffer = gpuResourceMgr_.GetBuffer<GpuBufferVk>(handle);
14528bf80f4bSopenharmony_ci        if (buffer) {
14538bf80f4bSopenharmony_ci            return buffer->GetPlatformData();
14548bf80f4bSopenharmony_ci        }
14558bf80f4bSopenharmony_ci    } else {
14568bf80f4bSopenharmony_ci        PLUGIN_LOG_E("low level device methods can only be used within specific methods");
14578bf80f4bSopenharmony_ci    }
14588bf80f4bSopenharmony_ci    return {};
14598bf80f4bSopenharmony_ci}
14608bf80f4bSopenharmony_ci
14618bf80f4bSopenharmony_ciGpuImagePlatformDataVk LowLevelDeviceVk::GetImage(RenderHandle handle) const
14628bf80f4bSopenharmony_ci{
14638bf80f4bSopenharmony_ci    if (deviceVk_.GetLockResourceBackendAccess()) {
14648bf80f4bSopenharmony_ci        GpuImageVk* image = gpuResourceMgr_.GetImage<GpuImageVk>(handle);
14658bf80f4bSopenharmony_ci        if (image) {
14668bf80f4bSopenharmony_ci            return image->GetPlatformData();
14678bf80f4bSopenharmony_ci        }
14688bf80f4bSopenharmony_ci    } else {
14698bf80f4bSopenharmony_ci        PLUGIN_LOG_E("low level device methods can only be used within specific methods");
14708bf80f4bSopenharmony_ci    }
14718bf80f4bSopenharmony_ci    return {};
14728bf80f4bSopenharmony_ci}
14738bf80f4bSopenharmony_ci
14748bf80f4bSopenharmony_ciGpuSamplerPlatformDataVk LowLevelDeviceVk::GetSampler(RenderHandle handle) const
14758bf80f4bSopenharmony_ci{
14768bf80f4bSopenharmony_ci    if (deviceVk_.GetLockResourceBackendAccess()) {
14778bf80f4bSopenharmony_ci        GpuSamplerVk* sampler = gpuResourceMgr_.GetSampler<GpuSamplerVk>(handle);
14788bf80f4bSopenharmony_ci        if (sampler) {
14798bf80f4bSopenharmony_ci            return sampler->GetPlatformData();
14808bf80f4bSopenharmony_ci        }
14818bf80f4bSopenharmony_ci    } else {
14828bf80f4bSopenharmony_ci        PLUGIN_LOG_E("low level device methods can be only used within specific methods");
14838bf80f4bSopenharmony_ci    }
14848bf80f4bSopenharmony_ci    return {};
14858bf80f4bSopenharmony_ci}
14868bf80f4bSopenharmony_ciRENDER_END_NAMESPACE()
1487