/* * Copyright 2019 Google LLC * SPDX-License-Identifier: MIT * * based in part on anv and radv which are: * Copyright © 2015 Intel Corporation * Copyright © 2016 Red Hat. * Copyright © 2016 Bas Nieuwenhuizen */ #include "vn_physical_device.h" #include #include "git_sha1.h" #include "util/mesa-sha1.h" #include "venus-protocol/vn_protocol_driver_device.h" #include "vn_android.h" #include "vn_instance.h" #define VN_EXTENSION_TABLE_INDEX(tbl, ext) \ ((const bool *)((const void *)(&(tbl)) + \ offsetof(__typeof__(tbl), ext)) - \ (tbl).extensions) #define VN_PREFIX_STYPE(stype) (VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_##stype) #define VN_ADD_TO_PNEXT(elem, s_type, head) \ do { \ (elem).sType = VN_PREFIX_STYPE(s_type); \ (elem).pNext = (head).pNext; \ (head).pNext = &(elem); \ } while (0) #define VN_ADD_EXT_TO_PNEXT(ext, elem, s_type, head) \ if (ext) VN_ADD_TO_PNEXT(elem, s_type, head) static void vn_physical_device_init_features(struct vn_physical_device *physical_dev) { struct vn_physical_device_features *feats = &physical_dev->features; struct vn_instance *instance = physical_dev->instance; const struct vk_device_extension_table *exts = &physical_dev->renderer_extensions; VkPhysicalDeviceFeatures2 features2 = { .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2, }; struct { /* Vulkan 1.1 */ VkPhysicalDevice16BitStorageFeatures sixteen_bit_storage; VkPhysicalDeviceMultiviewFeatures multiview; VkPhysicalDeviceVariablePointersFeatures variable_pointers; VkPhysicalDeviceProtectedMemoryFeatures protected_memory; VkPhysicalDeviceSamplerYcbcrConversionFeatures sampler_ycbcr_conversion; VkPhysicalDeviceShaderDrawParametersFeatures shader_draw_parameters; /* Vulkan 1.2 */ VkPhysicalDevice8BitStorageFeatures eight_bit_storage; VkPhysicalDeviceShaderAtomicInt64Features shader_atomic_int64; VkPhysicalDeviceShaderFloat16Int8Features shader_float16_int8; VkPhysicalDeviceDescriptorIndexingFeatures descriptor_indexing; VkPhysicalDeviceScalarBlockLayoutFeatures scalar_block_layout; VkPhysicalDeviceImagelessFramebufferFeatures imageless_framebuffer; VkPhysicalDeviceUniformBufferStandardLayoutFeatures uniform_buffer_standard_layout; VkPhysicalDeviceShaderSubgroupExtendedTypesFeatures shader_subgroup_extended_types; VkPhysicalDeviceSeparateDepthStencilLayoutsFeatures separate_depth_stencil_layouts; VkPhysicalDeviceHostQueryResetFeatures host_query_reset; VkPhysicalDeviceTimelineSemaphoreFeatures timeline_semaphore; VkPhysicalDeviceBufferDeviceAddressFeatures buffer_device_address; VkPhysicalDeviceVulkanMemoryModelFeatures vulkan_memory_model; } local_feats; if (physical_dev->renderer_version >= VK_API_VERSION_1_2) { VN_ADD_TO_PNEXT(feats->vulkan_1_1, VULKAN_1_1_FEATURES, features2); VN_ADD_TO_PNEXT(feats->vulkan_1_2, VULKAN_1_2_FEATURES, features2); } else { /* Vulkan 1.1 */ VN_ADD_TO_PNEXT(local_feats.sixteen_bit_storage, 16BIT_STORAGE_FEATURES, features2); VN_ADD_TO_PNEXT(local_feats.multiview, MULTIVIEW_FEATURES, features2); VN_ADD_TO_PNEXT(local_feats.variable_pointers, VARIABLE_POINTERS_FEATURES, features2); VN_ADD_TO_PNEXT(local_feats.protected_memory, PROTECTED_MEMORY_FEATURES, features2); VN_ADD_TO_PNEXT(local_feats.sampler_ycbcr_conversion, SAMPLER_YCBCR_CONVERSION_FEATURES, features2); VN_ADD_TO_PNEXT(local_feats.shader_draw_parameters, SHADER_DRAW_PARAMETERS_FEATURES, features2); /* Vulkan 1.2 */ VN_ADD_TO_PNEXT(local_feats.eight_bit_storage, 8BIT_STORAGE_FEATURES, features2); VN_ADD_TO_PNEXT(local_feats.shader_atomic_int64, SHADER_ATOMIC_INT64_FEATURES, features2); VN_ADD_TO_PNEXT(local_feats.shader_float16_int8, SHADER_FLOAT16_INT8_FEATURES, features2); VN_ADD_TO_PNEXT(local_feats.descriptor_indexing, DESCRIPTOR_INDEXING_FEATURES, features2); VN_ADD_TO_PNEXT(local_feats.scalar_block_layout, SCALAR_BLOCK_LAYOUT_FEATURES, features2); VN_ADD_TO_PNEXT(local_feats.imageless_framebuffer, IMAGELESS_FRAMEBUFFER_FEATURES, features2); VN_ADD_TO_PNEXT(local_feats.uniform_buffer_standard_layout, UNIFORM_BUFFER_STANDARD_LAYOUT_FEATURES, features2); VN_ADD_TO_PNEXT(local_feats.shader_subgroup_extended_types, SHADER_SUBGROUP_EXTENDED_TYPES_FEATURES, features2); VN_ADD_TO_PNEXT(local_feats.separate_depth_stencil_layouts, SEPARATE_DEPTH_STENCIL_LAYOUTS_FEATURES, features2); VN_ADD_TO_PNEXT(local_feats.host_query_reset, HOST_QUERY_RESET_FEATURES, features2); VN_ADD_TO_PNEXT(local_feats.timeline_semaphore, TIMELINE_SEMAPHORE_FEATURES, features2); VN_ADD_TO_PNEXT(local_feats.buffer_device_address, BUFFER_DEVICE_ADDRESS_FEATURES, features2); VN_ADD_TO_PNEXT(local_feats.vulkan_memory_model, VULKAN_MEMORY_MODEL_FEATURES, features2); } /* Vulkan 1.3 */ VN_ADD_EXT_TO_PNEXT(exts->EXT_4444_formats, feats->argb_4444_formats, 4444_FORMATS_FEATURES_EXT, features2); VN_ADD_EXT_TO_PNEXT(exts->EXT_extended_dynamic_state, feats->extended_dynamic_state, EXTENDED_DYNAMIC_STATE_FEATURES_EXT, features2); VN_ADD_EXT_TO_PNEXT(exts->EXT_extended_dynamic_state2, feats->extended_dynamic_state_2, EXTENDED_DYNAMIC_STATE_2_FEATURES_EXT, features2); VN_ADD_EXT_TO_PNEXT(exts->EXT_image_robustness, feats->image_robustness, IMAGE_ROBUSTNESS_FEATURES_EXT, features2); VN_ADD_EXT_TO_PNEXT(exts->EXT_inline_uniform_block, feats->inline_uniform_block, INLINE_UNIFORM_BLOCK_FEATURES, features2); VN_ADD_EXT_TO_PNEXT(exts->KHR_dynamic_rendering, feats->dynamic_rendering, DYNAMIC_RENDERING_FEATURES, features2); VN_ADD_EXT_TO_PNEXT(exts->KHR_maintenance4, feats->maintenance4, MAINTENANCE_4_FEATURES, features2); VN_ADD_EXT_TO_PNEXT(exts->EXT_shader_demote_to_helper_invocation, feats->shader_demote_to_helper_invocation, SHADER_DEMOTE_TO_HELPER_INVOCATION_FEATURES, features2); /* EXT */ VN_ADD_EXT_TO_PNEXT(exts->EXT_conditional_rendering, feats->conditional_rendering, CONDITIONAL_RENDERING_FEATURES_EXT, features2); VN_ADD_EXT_TO_PNEXT(exts->EXT_custom_border_color, feats->custom_border_color, CUSTOM_BORDER_COLOR_FEATURES_EXT, features2); VN_ADD_EXT_TO_PNEXT(exts->EXT_depth_clip_enable, feats->depth_clip_enable, DEPTH_CLIP_ENABLE_FEATURES_EXT, features2); VN_ADD_EXT_TO_PNEXT(exts->EXT_image_view_min_lod, feats->image_view_min_lod, IMAGE_VIEW_MIN_LOD_FEATURES_EXT, features2); VN_ADD_EXT_TO_PNEXT(exts->EXT_index_type_uint8, feats->index_type_uint8, INDEX_TYPE_UINT8_FEATURES_EXT, features2); VN_ADD_EXT_TO_PNEXT(exts->EXT_line_rasterization, feats->line_rasterization, LINE_RASTERIZATION_FEATURES_EXT, features2); VN_ADD_EXT_TO_PNEXT(exts->EXT_provoking_vertex, feats->provoking_vertex, PROVOKING_VERTEX_FEATURES_EXT, features2); VN_ADD_EXT_TO_PNEXT(exts->EXT_robustness2, feats->robustness_2, ROBUSTNESS_2_FEATURES_EXT, features2); VN_ADD_EXT_TO_PNEXT(exts->EXT_transform_feedback, feats->transform_feedback, TRANSFORM_FEEDBACK_FEATURES_EXT, features2); VN_ADD_EXT_TO_PNEXT(exts->EXT_vertex_attribute_divisor, feats->vertex_attribute_divisor, VERTEX_ATTRIBUTE_DIVISOR_FEATURES_EXT, features2); vn_call_vkGetPhysicalDeviceFeatures2( instance, vn_physical_device_to_handle(physical_dev), &features2); feats->vulkan_1_0 = features2.features; /* TODO allow sparse resource along with sync feedback * * vkQueueBindSparse relies on explicit sync primitives. To intercept the * timeline semaphores within each bind info to write the feedback buffer, * we have to split the call into bindInfoCount number of calls while * inserting vkQueueSubmit to wait on the signal timeline semaphores before * filling the feedback buffer. To intercept the fence to be signaled, we * have to relocate the fence to another vkQueueSubmit call and potentially * have to use an internal timeline semaphore to synchronize between them. * Those would make the code overly complex, so we disable sparse binding * for simplicity. */ if (!VN_PERF(NO_FENCE_FEEDBACK)) { feats->vulkan_1_0.sparseBinding = false; feats->vulkan_1_0.sparseResidencyBuffer = false; feats->vulkan_1_0.sparseResidencyImage2D = false; feats->vulkan_1_0.sparseResidencyImage3D = false; feats->vulkan_1_0.sparseResidency2Samples = false; feats->vulkan_1_0.sparseResidency4Samples = false; feats->vulkan_1_0.sparseResidency8Samples = false; feats->vulkan_1_0.sparseResidency16Samples = false; feats->vulkan_1_0.sparseResidencyAliased = false; } struct VkPhysicalDeviceVulkan11Features *vk11_feats = &feats->vulkan_1_1; struct VkPhysicalDeviceVulkan12Features *vk12_feats = &feats->vulkan_1_2; if (physical_dev->renderer_version < VK_API_VERSION_1_2) { vk11_feats->storageBuffer16BitAccess = local_feats.sixteen_bit_storage.storageBuffer16BitAccess; vk11_feats->uniformAndStorageBuffer16BitAccess = local_feats.sixteen_bit_storage.uniformAndStorageBuffer16BitAccess; vk11_feats->storagePushConstant16 = local_feats.sixteen_bit_storage.storagePushConstant16; vk11_feats->storageInputOutput16 = local_feats.sixteen_bit_storage.storageInputOutput16; vk11_feats->multiview = local_feats.multiview.multiview; vk11_feats->multiviewGeometryShader = local_feats.multiview.multiviewGeometryShader; vk11_feats->multiviewTessellationShader = local_feats.multiview.multiviewTessellationShader; vk11_feats->variablePointersStorageBuffer = local_feats.variable_pointers.variablePointersStorageBuffer; vk11_feats->variablePointers = local_feats.variable_pointers.variablePointers; vk11_feats->protectedMemory = local_feats.protected_memory.protectedMemory; vk11_feats->samplerYcbcrConversion = local_feats.sampler_ycbcr_conversion.samplerYcbcrConversion; vk11_feats->shaderDrawParameters = local_feats.shader_draw_parameters.shaderDrawParameters; vk12_feats->samplerMirrorClampToEdge = exts->KHR_sampler_mirror_clamp_to_edge; vk12_feats->drawIndirectCount = exts->KHR_draw_indirect_count; if (exts->KHR_8bit_storage) { vk12_feats->storageBuffer8BitAccess = local_feats.eight_bit_storage.storageBuffer8BitAccess; vk12_feats->uniformAndStorageBuffer8BitAccess = local_feats.eight_bit_storage.uniformAndStorageBuffer8BitAccess; vk12_feats->storagePushConstant8 = local_feats.eight_bit_storage.storagePushConstant8; } if (exts->KHR_shader_atomic_int64) { vk12_feats->shaderBufferInt64Atomics = local_feats.shader_atomic_int64.shaderBufferInt64Atomics; vk12_feats->shaderSharedInt64Atomics = local_feats.shader_atomic_int64.shaderSharedInt64Atomics; } if (exts->KHR_shader_float16_int8) { vk12_feats->shaderFloat16 = local_feats.shader_float16_int8.shaderFloat16; vk12_feats->shaderInt8 = local_feats.shader_float16_int8.shaderInt8; } if (exts->EXT_descriptor_indexing) { vk12_feats->descriptorIndexing = true; vk12_feats->shaderInputAttachmentArrayDynamicIndexing = local_feats.descriptor_indexing .shaderInputAttachmentArrayDynamicIndexing; vk12_feats->shaderUniformTexelBufferArrayDynamicIndexing = local_feats.descriptor_indexing .shaderUniformTexelBufferArrayDynamicIndexing; vk12_feats->shaderStorageTexelBufferArrayDynamicIndexing = local_feats.descriptor_indexing .shaderStorageTexelBufferArrayDynamicIndexing; vk12_feats->shaderUniformBufferArrayNonUniformIndexing = local_feats.descriptor_indexing .shaderUniformBufferArrayNonUniformIndexing; vk12_feats->shaderSampledImageArrayNonUniformIndexing = local_feats.descriptor_indexing .shaderSampledImageArrayNonUniformIndexing; vk12_feats->shaderStorageBufferArrayNonUniformIndexing = local_feats.descriptor_indexing .shaderStorageBufferArrayNonUniformIndexing; vk12_feats->shaderStorageImageArrayNonUniformIndexing = local_feats.descriptor_indexing .shaderStorageImageArrayNonUniformIndexing; vk12_feats->shaderInputAttachmentArrayNonUniformIndexing = local_feats.descriptor_indexing .shaderInputAttachmentArrayNonUniformIndexing; vk12_feats->shaderUniformTexelBufferArrayNonUniformIndexing = local_feats.descriptor_indexing .shaderUniformTexelBufferArrayNonUniformIndexing; vk12_feats->shaderStorageTexelBufferArrayNonUniformIndexing = local_feats.descriptor_indexing .shaderStorageTexelBufferArrayNonUniformIndexing; vk12_feats->descriptorBindingUniformBufferUpdateAfterBind = local_feats.descriptor_indexing .descriptorBindingUniformBufferUpdateAfterBind; vk12_feats->descriptorBindingSampledImageUpdateAfterBind = local_feats.descriptor_indexing .descriptorBindingSampledImageUpdateAfterBind; vk12_feats->descriptorBindingStorageImageUpdateAfterBind = local_feats.descriptor_indexing .descriptorBindingStorageImageUpdateAfterBind; vk12_feats->descriptorBindingStorageBufferUpdateAfterBind = local_feats.descriptor_indexing .descriptorBindingStorageBufferUpdateAfterBind; vk12_feats->descriptorBindingUniformTexelBufferUpdateAfterBind = local_feats.descriptor_indexing .descriptorBindingUniformTexelBufferUpdateAfterBind; vk12_feats->descriptorBindingStorageTexelBufferUpdateAfterBind = local_feats.descriptor_indexing .descriptorBindingStorageTexelBufferUpdateAfterBind; vk12_feats->descriptorBindingUpdateUnusedWhilePending = local_feats.descriptor_indexing .descriptorBindingUpdateUnusedWhilePending; vk12_feats->descriptorBindingPartiallyBound = local_feats.descriptor_indexing.descriptorBindingPartiallyBound; vk12_feats->descriptorBindingVariableDescriptorCount = local_feats.descriptor_indexing .descriptorBindingVariableDescriptorCount; vk12_feats->runtimeDescriptorArray = local_feats.descriptor_indexing.runtimeDescriptorArray; } vk12_feats->samplerFilterMinmax = exts->EXT_sampler_filter_minmax; if (exts->EXT_scalar_block_layout) { vk12_feats->scalarBlockLayout = local_feats.scalar_block_layout.scalarBlockLayout; } if (exts->KHR_imageless_framebuffer) { vk12_feats->imagelessFramebuffer = local_feats.imageless_framebuffer.imagelessFramebuffer; } if (exts->KHR_uniform_buffer_standard_layout) { vk12_feats->uniformBufferStandardLayout = local_feats.uniform_buffer_standard_layout .uniformBufferStandardLayout; } if (exts->KHR_shader_subgroup_extended_types) { vk12_feats->shaderSubgroupExtendedTypes = local_feats.shader_subgroup_extended_types .shaderSubgroupExtendedTypes; } if (exts->KHR_separate_depth_stencil_layouts) { vk12_feats->separateDepthStencilLayouts = local_feats.separate_depth_stencil_layouts .separateDepthStencilLayouts; } if (exts->EXT_host_query_reset) { vk12_feats->hostQueryReset = local_feats.host_query_reset.hostQueryReset; } if (exts->KHR_timeline_semaphore) { vk12_feats->timelineSemaphore = local_feats.timeline_semaphore.timelineSemaphore; } if (exts->KHR_buffer_device_address) { vk12_feats->bufferDeviceAddress = local_feats.buffer_device_address.bufferDeviceAddress; vk12_feats->bufferDeviceAddressCaptureReplay = local_feats.buffer_device_address.bufferDeviceAddressCaptureReplay; vk12_feats->bufferDeviceAddressMultiDevice = local_feats.buffer_device_address.bufferDeviceAddressMultiDevice; } if (exts->KHR_vulkan_memory_model) { vk12_feats->vulkanMemoryModel = local_feats.vulkan_memory_model.vulkanMemoryModel; vk12_feats->vulkanMemoryModelDeviceScope = local_feats.vulkan_memory_model.vulkanMemoryModelDeviceScope; vk12_feats->vulkanMemoryModelAvailabilityVisibilityChains = local_feats.vulkan_memory_model .vulkanMemoryModelAvailabilityVisibilityChains; } vk12_feats->shaderOutputViewportIndex = exts->EXT_shader_viewport_index_layer; vk12_feats->shaderOutputLayer = exts->EXT_shader_viewport_index_layer; vk12_feats->subgroupBroadcastDynamicId = false; } } static void vn_physical_device_init_uuids(struct vn_physical_device *physical_dev) { struct vn_physical_device_properties *props = &physical_dev->properties; struct VkPhysicalDeviceProperties *vk10_props = &props->vulkan_1_0; struct VkPhysicalDeviceVulkan11Properties *vk11_props = &props->vulkan_1_1; struct VkPhysicalDeviceVulkan12Properties *vk12_props = &props->vulkan_1_2; struct mesa_sha1 sha1_ctx; uint8_t sha1[SHA1_DIGEST_LENGTH]; static_assert(VK_UUID_SIZE <= SHA1_DIGEST_LENGTH, ""); _mesa_sha1_init(&sha1_ctx); _mesa_sha1_update(&sha1_ctx, &vk10_props->pipelineCacheUUID, sizeof(vk10_props->pipelineCacheUUID)); _mesa_sha1_final(&sha1_ctx, sha1); memcpy(vk10_props->pipelineCacheUUID, sha1, VK_UUID_SIZE); _mesa_sha1_init(&sha1_ctx); _mesa_sha1_update(&sha1_ctx, &vk10_props->vendorID, sizeof(vk10_props->vendorID)); _mesa_sha1_update(&sha1_ctx, &vk10_props->deviceID, sizeof(vk10_props->deviceID)); _mesa_sha1_final(&sha1_ctx, sha1); memcpy(vk11_props->deviceUUID, sha1, VK_UUID_SIZE); _mesa_sha1_init(&sha1_ctx); _mesa_sha1_update(&sha1_ctx, vk12_props->driverName, strlen(vk12_props->driverName)); _mesa_sha1_update(&sha1_ctx, vk12_props->driverInfo, strlen(vk12_props->driverInfo)); _mesa_sha1_final(&sha1_ctx, sha1); memcpy(vk11_props->driverUUID, sha1, VK_UUID_SIZE); memset(vk11_props->deviceLUID, 0, VK_LUID_SIZE); vk11_props->deviceNodeMask = 0; vk11_props->deviceLUIDValid = false; } static void vn_physical_device_init_properties(struct vn_physical_device *physical_dev) { struct vn_physical_device_properties *props = &physical_dev->properties; struct vn_instance *instance = physical_dev->instance; const struct vk_device_extension_table *exts = &physical_dev->renderer_extensions; VkPhysicalDeviceProperties2 properties2 = { .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2, }; struct { /* Vulkan 1.1 */ VkPhysicalDeviceIDProperties id; VkPhysicalDeviceSubgroupProperties subgroup; VkPhysicalDevicePointClippingProperties point_clipping; VkPhysicalDeviceMultiviewProperties multiview; VkPhysicalDeviceProtectedMemoryProperties protected_memory; VkPhysicalDeviceMaintenance3Properties maintenance_3; /* Vulkan 1.2 */ VkPhysicalDeviceDriverProperties driver; VkPhysicalDeviceFloatControlsProperties float_controls; VkPhysicalDeviceDescriptorIndexingProperties descriptor_indexing; VkPhysicalDeviceDepthStencilResolveProperties depth_stencil_resolve; VkPhysicalDeviceSamplerFilterMinmaxProperties sampler_filter_minmax; VkPhysicalDeviceTimelineSemaphoreProperties timeline_semaphore; } local_props; if (physical_dev->renderer_version >= VK_API_VERSION_1_2) { VN_ADD_TO_PNEXT(props->vulkan_1_1, VULKAN_1_1_PROPERTIES, properties2); VN_ADD_TO_PNEXT(props->vulkan_1_2, VULKAN_1_2_PROPERTIES, properties2); } else { /* Vulkan 1.1 */ VN_ADD_TO_PNEXT(local_props.id, ID_PROPERTIES, properties2); VN_ADD_TO_PNEXT(local_props.subgroup, SUBGROUP_PROPERTIES, properties2); VN_ADD_TO_PNEXT(local_props.point_clipping, POINT_CLIPPING_PROPERTIES, properties2); VN_ADD_TO_PNEXT(local_props.multiview, MULTIVIEW_PROPERTIES, properties2); VN_ADD_TO_PNEXT(local_props.protected_memory, PROTECTED_MEMORY_PROPERTIES, properties2); VN_ADD_TO_PNEXT(local_props.maintenance_3, MAINTENANCE_3_PROPERTIES, properties2); /* Vulkan 1.2 */ VN_ADD_TO_PNEXT(local_props.driver, DRIVER_PROPERTIES, properties2); VN_ADD_TO_PNEXT(local_props.float_controls, FLOAT_CONTROLS_PROPERTIES, properties2); VN_ADD_TO_PNEXT(local_props.descriptor_indexing, DESCRIPTOR_INDEXING_PROPERTIES, properties2); VN_ADD_TO_PNEXT(local_props.depth_stencil_resolve, DEPTH_STENCIL_RESOLVE_PROPERTIES, properties2); VN_ADD_TO_PNEXT(local_props.sampler_filter_minmax, SAMPLER_FILTER_MINMAX_PROPERTIES, properties2); VN_ADD_TO_PNEXT(local_props.timeline_semaphore, TIMELINE_SEMAPHORE_PROPERTIES, properties2); } /* Vulkan 1.3 */ VN_ADD_EXT_TO_PNEXT(exts->EXT_inline_uniform_block, props->inline_uniform_block, INLINE_UNIFORM_BLOCK_PROPERTIES, properties2); /* EXT */ VN_ADD_EXT_TO_PNEXT( exts->EXT_conservative_rasterization, props->conservative_rasterization, CONSERVATIVE_RASTERIZATION_PROPERTIES_EXT, properties2); VN_ADD_EXT_TO_PNEXT(exts->EXT_custom_border_color, props->custom_border_color, CUSTOM_BORDER_COLOR_PROPERTIES_EXT, properties2); VN_ADD_EXT_TO_PNEXT(exts->EXT_line_rasterization, props->line_rasterization, LINE_RASTERIZATION_PROPERTIES_EXT, properties2); VN_ADD_EXT_TO_PNEXT(exts->EXT_provoking_vertex, props->provoking_vertex, PROVOKING_VERTEX_PROPERTIES_EXT, properties2); VN_ADD_EXT_TO_PNEXT(exts->EXT_robustness2, props->robustness_2, ROBUSTNESS_2_PROPERTIES_EXT, properties2); VN_ADD_EXT_TO_PNEXT(exts->EXT_transform_feedback, props->transform_feedback, TRANSFORM_FEEDBACK_PROPERTIES_EXT, properties2); VN_ADD_EXT_TO_PNEXT(exts->KHR_maintenance4, props->maintenance4, MAINTENANCE_4_PROPERTIES, properties2); VN_ADD_EXT_TO_PNEXT(exts->EXT_vertex_attribute_divisor, props->vertex_attribute_divisor, VERTEX_ATTRIBUTE_DIVISOR_PROPERTIES_EXT, properties2); vn_call_vkGetPhysicalDeviceProperties2( instance, vn_physical_device_to_handle(physical_dev), &properties2); props->vulkan_1_0 = properties2.properties; /* TODO allow sparse resource along with sync feedback */ if (!VN_PERF(NO_FENCE_FEEDBACK)) { props->vulkan_1_0.limits.sparseAddressSpaceSize = 0; props->vulkan_1_0.sparseProperties = (VkPhysicalDeviceSparseProperties){ 0 }; } struct VkPhysicalDeviceProperties *vk10_props = &props->vulkan_1_0; struct VkPhysicalDeviceVulkan11Properties *vk11_props = &props->vulkan_1_1; struct VkPhysicalDeviceVulkan12Properties *vk12_props = &props->vulkan_1_2; if (physical_dev->renderer_version < VK_API_VERSION_1_2) { memcpy(vk11_props->deviceUUID, local_props.id.deviceUUID, sizeof(vk11_props->deviceUUID)); memcpy(vk11_props->driverUUID, local_props.id.driverUUID, sizeof(vk11_props->driverUUID)); memcpy(vk11_props->deviceLUID, local_props.id.deviceLUID, sizeof(vk11_props->deviceLUID)); vk11_props->deviceNodeMask = local_props.id.deviceNodeMask; vk11_props->deviceLUIDValid = local_props.id.deviceLUIDValid; vk11_props->subgroupSize = local_props.subgroup.subgroupSize; vk11_props->subgroupSupportedStages = local_props.subgroup.supportedStages; vk11_props->subgroupSupportedOperations = local_props.subgroup.supportedOperations; vk11_props->subgroupQuadOperationsInAllStages = local_props.subgroup.quadOperationsInAllStages; vk11_props->pointClippingBehavior = local_props.point_clipping.pointClippingBehavior; vk11_props->maxMultiviewViewCount = local_props.multiview.maxMultiviewViewCount; vk11_props->maxMultiviewInstanceIndex = local_props.multiview.maxMultiviewInstanceIndex; vk11_props->protectedNoFault = local_props.protected_memory.protectedNoFault; vk11_props->maxPerSetDescriptors = local_props.maintenance_3.maxPerSetDescriptors; vk11_props->maxMemoryAllocationSize = local_props.maintenance_3.maxMemoryAllocationSize; if (exts->KHR_driver_properties) { vk12_props->driverID = local_props.driver.driverID; memcpy(vk12_props->driverName, local_props.driver.driverName, VK_MAX_DRIVER_NAME_SIZE); memcpy(vk12_props->driverInfo, local_props.driver.driverInfo, VK_MAX_DRIVER_INFO_SIZE); vk12_props->conformanceVersion = local_props.driver.conformanceVersion; } if (exts->KHR_shader_float_controls) { vk12_props->denormBehaviorIndependence = local_props.float_controls.denormBehaviorIndependence; vk12_props->roundingModeIndependence = local_props.float_controls.roundingModeIndependence; vk12_props->shaderSignedZeroInfNanPreserveFloat16 = local_props.float_controls.shaderSignedZeroInfNanPreserveFloat16; vk12_props->shaderSignedZeroInfNanPreserveFloat32 = local_props.float_controls.shaderSignedZeroInfNanPreserveFloat32; vk12_props->shaderSignedZeroInfNanPreserveFloat64 = local_props.float_controls.shaderSignedZeroInfNanPreserveFloat64; vk12_props->shaderDenormPreserveFloat16 = local_props.float_controls.shaderDenormPreserveFloat16; vk12_props->shaderDenormPreserveFloat32 = local_props.float_controls.shaderDenormPreserveFloat32; vk12_props->shaderDenormPreserveFloat64 = local_props.float_controls.shaderDenormPreserveFloat64; vk12_props->shaderDenormFlushToZeroFloat16 = local_props.float_controls.shaderDenormFlushToZeroFloat16; vk12_props->shaderDenormFlushToZeroFloat32 = local_props.float_controls.shaderDenormFlushToZeroFloat32; vk12_props->shaderDenormFlushToZeroFloat64 = local_props.float_controls.shaderDenormFlushToZeroFloat64; vk12_props->shaderRoundingModeRTEFloat16 = local_props.float_controls.shaderRoundingModeRTEFloat16; vk12_props->shaderRoundingModeRTEFloat32 = local_props.float_controls.shaderRoundingModeRTEFloat32; vk12_props->shaderRoundingModeRTEFloat64 = local_props.float_controls.shaderRoundingModeRTEFloat64; vk12_props->shaderRoundingModeRTZFloat16 = local_props.float_controls.shaderRoundingModeRTZFloat16; vk12_props->shaderRoundingModeRTZFloat32 = local_props.float_controls.shaderRoundingModeRTZFloat32; vk12_props->shaderRoundingModeRTZFloat64 = local_props.float_controls.shaderRoundingModeRTZFloat64; } if (exts->EXT_descriptor_indexing) { vk12_props->maxUpdateAfterBindDescriptorsInAllPools = local_props.descriptor_indexing .maxUpdateAfterBindDescriptorsInAllPools; vk12_props->shaderUniformBufferArrayNonUniformIndexingNative = local_props.descriptor_indexing .shaderUniformBufferArrayNonUniformIndexingNative; vk12_props->shaderSampledImageArrayNonUniformIndexingNative = local_props.descriptor_indexing .shaderSampledImageArrayNonUniformIndexingNative; vk12_props->shaderStorageBufferArrayNonUniformIndexingNative = local_props.descriptor_indexing .shaderStorageBufferArrayNonUniformIndexingNative; vk12_props->shaderStorageImageArrayNonUniformIndexingNative = local_props.descriptor_indexing .shaderStorageImageArrayNonUniformIndexingNative; vk12_props->shaderInputAttachmentArrayNonUniformIndexingNative = local_props.descriptor_indexing .shaderInputAttachmentArrayNonUniformIndexingNative; vk12_props->robustBufferAccessUpdateAfterBind = local_props.descriptor_indexing.robustBufferAccessUpdateAfterBind; vk12_props->quadDivergentImplicitLod = local_props.descriptor_indexing.quadDivergentImplicitLod; vk12_props->maxPerStageDescriptorUpdateAfterBindSamplers = local_props.descriptor_indexing .maxPerStageDescriptorUpdateAfterBindSamplers; vk12_props->maxPerStageDescriptorUpdateAfterBindUniformBuffers = local_props.descriptor_indexing .maxPerStageDescriptorUpdateAfterBindUniformBuffers; vk12_props->maxPerStageDescriptorUpdateAfterBindStorageBuffers = local_props.descriptor_indexing .maxPerStageDescriptorUpdateAfterBindStorageBuffers; vk12_props->maxPerStageDescriptorUpdateAfterBindSampledImages = local_props.descriptor_indexing .maxPerStageDescriptorUpdateAfterBindSampledImages; vk12_props->maxPerStageDescriptorUpdateAfterBindStorageImages = local_props.descriptor_indexing .maxPerStageDescriptorUpdateAfterBindStorageImages; vk12_props->maxPerStageDescriptorUpdateAfterBindInputAttachments = local_props.descriptor_indexing .maxPerStageDescriptorUpdateAfterBindInputAttachments; vk12_props->maxPerStageUpdateAfterBindResources = local_props.descriptor_indexing .maxPerStageUpdateAfterBindResources; vk12_props->maxDescriptorSetUpdateAfterBindSamplers = local_props.descriptor_indexing .maxDescriptorSetUpdateAfterBindSamplers; vk12_props->maxDescriptorSetUpdateAfterBindUniformBuffers = local_props.descriptor_indexing .maxDescriptorSetUpdateAfterBindUniformBuffers; vk12_props->maxDescriptorSetUpdateAfterBindUniformBuffersDynamic = local_props.descriptor_indexing .maxDescriptorSetUpdateAfterBindUniformBuffersDynamic; vk12_props->maxDescriptorSetUpdateAfterBindStorageBuffers = local_props.descriptor_indexing .maxDescriptorSetUpdateAfterBindStorageBuffers; vk12_props->maxDescriptorSetUpdateAfterBindStorageBuffersDynamic = local_props.descriptor_indexing .maxDescriptorSetUpdateAfterBindStorageBuffersDynamic; vk12_props->maxDescriptorSetUpdateAfterBindSampledImages = local_props.descriptor_indexing .maxDescriptorSetUpdateAfterBindSampledImages; vk12_props->maxDescriptorSetUpdateAfterBindStorageImages = local_props.descriptor_indexing .maxDescriptorSetUpdateAfterBindStorageImages; vk12_props->maxDescriptorSetUpdateAfterBindInputAttachments = local_props.descriptor_indexing .maxDescriptorSetUpdateAfterBindInputAttachments; } if (exts->KHR_depth_stencil_resolve) { vk12_props->supportedDepthResolveModes = local_props.depth_stencil_resolve.supportedDepthResolveModes; vk12_props->supportedStencilResolveModes = local_props.depth_stencil_resolve.supportedStencilResolveModes; vk12_props->independentResolveNone = local_props.depth_stencil_resolve.independentResolveNone; vk12_props->independentResolve = local_props.depth_stencil_resolve.independentResolve; } if (exts->EXT_sampler_filter_minmax) { vk12_props->filterMinmaxSingleComponentFormats = local_props.sampler_filter_minmax .filterMinmaxSingleComponentFormats; vk12_props->filterMinmaxImageComponentMapping = local_props.sampler_filter_minmax .filterMinmaxImageComponentMapping; } if (exts->KHR_timeline_semaphore) { vk12_props->maxTimelineSemaphoreValueDifference = local_props.timeline_semaphore.maxTimelineSemaphoreValueDifference; } vk12_props->framebufferIntegerColorSampleCounts = VK_SAMPLE_COUNT_1_BIT; } const uint32_t version_override = vk_get_version_override(); if (version_override) { vk10_props->apiVersion = version_override; } else { /* cap the advertised api version */ uint32_t ver = MIN3(vk10_props->apiVersion, VN_MAX_API_VERSION, instance->renderer->info.vk_xml_version); if (VK_VERSION_PATCH(ver) > VK_VERSION_PATCH(vk10_props->apiVersion)) { ver = ver - VK_VERSION_PATCH(ver) + VK_VERSION_PATCH(vk10_props->apiVersion); } vk10_props->apiVersion = ver; } vk10_props->driverVersion = vk_get_driver_version(); char device_name[VK_MAX_PHYSICAL_DEVICE_NAME_SIZE]; int device_name_len = snprintf(device_name, sizeof(device_name), "Virtio-GPU Venus (%s)", vk10_props->deviceName); if (device_name_len >= VK_MAX_PHYSICAL_DEVICE_NAME_SIZE) { memcpy(device_name + VK_MAX_PHYSICAL_DEVICE_NAME_SIZE - 5, "...)", 4); device_name_len = VK_MAX_PHYSICAL_DEVICE_NAME_SIZE - 1; } memcpy(vk10_props->deviceName, device_name, device_name_len + 1); vk12_props->driverID = VK_DRIVER_ID_MESA_VENUS; snprintf(vk12_props->driverName, sizeof(vk12_props->driverName), "venus"); snprintf(vk12_props->driverInfo, sizeof(vk12_props->driverInfo), "Mesa " PACKAGE_VERSION MESA_GIT_SHA1); vk12_props->conformanceVersion = (VkConformanceVersion){ .major = 1, .minor = 2, .subminor = 7, .patch = 1, }; vn_physical_device_init_uuids(physical_dev); } static VkResult vn_physical_device_init_queue_family_properties( struct vn_physical_device *physical_dev) { struct vn_instance *instance = physical_dev->instance; const VkAllocationCallbacks *alloc = &instance->base.base.alloc; uint32_t count; vn_call_vkGetPhysicalDeviceQueueFamilyProperties2( instance, vn_physical_device_to_handle(physical_dev), &count, NULL); VkQueueFamilyProperties2 *props = vk_alloc(alloc, sizeof(*props) * count, VN_DEFAULT_ALIGN, VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE); if (!props) return VK_ERROR_OUT_OF_HOST_MEMORY; for (uint32_t i = 0; i < count; i++) { props[i].sType = VK_STRUCTURE_TYPE_QUEUE_FAMILY_PROPERTIES_2; props[i].pNext = NULL; } vn_call_vkGetPhysicalDeviceQueueFamilyProperties2( instance, vn_physical_device_to_handle(physical_dev), &count, props); physical_dev->queue_family_properties = props; physical_dev->queue_family_count = count; return VK_SUCCESS; } static void vn_physical_device_init_memory_properties( struct vn_physical_device *physical_dev) { struct vn_instance *instance = physical_dev->instance; physical_dev->memory_properties.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MEMORY_PROPERTIES_2; vn_call_vkGetPhysicalDeviceMemoryProperties2( instance, vn_physical_device_to_handle(physical_dev), &physical_dev->memory_properties); if (!instance->renderer->info.has_cache_management) { VkPhysicalDeviceMemoryProperties *props = &physical_dev->memory_properties.memoryProperties; const uint32_t host_flags = VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT | VK_MEMORY_PROPERTY_HOST_CACHED_BIT; for (uint32_t i = 0; i < props->memoryTypeCount; i++) { const bool coherent = props->memoryTypes[i].propertyFlags & VK_MEMORY_PROPERTY_HOST_COHERENT_BIT; if (!coherent) props->memoryTypes[i].propertyFlags &= ~host_flags; } } } static void vn_physical_device_init_external_memory( struct vn_physical_device *physical_dev) { /* When a renderer VkDeviceMemory is exportable, we can create a * vn_renderer_bo from it. The vn_renderer_bo can be freely exported as an * opaque fd or a dma-buf. * * However, to know if a rendender VkDeviceMemory is exportable, we have to * start from VkPhysicalDeviceExternalImageFormatInfo (or * vkGetPhysicalDeviceExternalBufferProperties). That means we need to * know the handle type that the renderer will use to make those queries. * * XXX We also assume that a vn_renderer_bo can be created as long as the * renderer VkDeviceMemory has a mappable memory type. That is plain * wrong. It is impossible to fix though until some new extension is * created and supported by the driver, and that the renderer switches to * the extension. */ if (!physical_dev->instance->renderer->info.has_dma_buf_import) return; /* TODO We assume the renderer uses dma-bufs here. This should be * negotiated by adding a new function to VK_MESA_venus_protocol. */ if (physical_dev->renderer_extensions.EXT_external_memory_dma_buf) { physical_dev->external_memory.renderer_handle_type = VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT; #ifdef ANDROID physical_dev->external_memory.supported_handle_types = VK_EXTERNAL_MEMORY_HANDLE_TYPE_ANDROID_HARDWARE_BUFFER_BIT_ANDROID; #else physical_dev->external_memory.supported_handle_types = VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT | VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT; #endif } } static void vn_physical_device_init_external_fence_handles( struct vn_physical_device *physical_dev) { /* The current code manipulates the host-side VkFence directly. * vkWaitForFences is translated to repeated vkGetFenceStatus. * * External fence is not possible currently. At best, we could cheat by * translating vkGetFenceFdKHR to vkWaitForFences and returning -1, when * the handle type is sync file. * * We would like to create a vn_renderer_sync from a host-side VkFence, * similar to how a vn_renderer_bo is created from a host-side * VkDeviceMemory. That would require kernel support and tons of works on * the host side. If we had that, and we kept both the vn_renderer_sync * and the host-side VkFence in sync, we would have the freedom to use * either of them depending on the occasions, and support external fences * and idle waiting. */ physical_dev->external_fence_handles = 0; #ifdef ANDROID if (physical_dev->instance->experimental.globalFencing) { physical_dev->external_fence_handles = VK_EXTERNAL_FENCE_HANDLE_TYPE_SYNC_FD_BIT; } #endif } static void vn_physical_device_init_external_semaphore_handles( struct vn_physical_device *physical_dev) { /* The current code manipulates the host-side VkSemaphore directly. It * works very well for binary semaphores because there is no CPU operation. * But for timeline semaphores, the situation is similar to that of fences. * vkWaitSemaphores is translated to repeated vkGetSemaphoreCounterValue. * * External semaphore is not possible currently. We could cheat when the * semaphore is binary and the handle type is sync file, but that would * require associating a fence with the semaphore and doing vkWaitForFences * in vkGetSemaphoreFdKHR. * * We would like to create a vn_renderer_sync from a host-side VkSemaphore, * similar to how a vn_renderer_bo is created from a host-side * VkDeviceMemory. The reasoning is the same as that for fences. * Additionally, we would like the sync file exported from the * vn_renderer_sync to carry the necessary information to identify the * host-side VkSemaphore. That would allow the consumers to wait on the * host side rather than the guest side. */ physical_dev->external_binary_semaphore_handles = 0; physical_dev->external_timeline_semaphore_handles = 0; #ifdef ANDROID if (physical_dev->instance->experimental.globalFencing) { physical_dev->external_binary_semaphore_handles = VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_SYNC_FD_BIT; } #endif } static void vn_physical_device_get_native_extensions( const struct vn_physical_device *physical_dev, struct vk_device_extension_table *exts) { const struct vn_instance *instance = physical_dev->instance; const struct vk_device_extension_table *renderer_exts = &physical_dev->renderer_extensions; memset(exts, 0, sizeof(*exts)); /* see vn_physical_device_init_external_memory */ const bool can_external_mem = renderer_exts->EXT_external_memory_dma_buf && instance->renderer->info.has_dma_buf_import; #ifdef ANDROID if (can_external_mem && renderer_exts->EXT_image_drm_format_modifier && renderer_exts->EXT_queue_family_foreign && instance->experimental.memoryResourceAllocationSize == VK_TRUE) { exts->ANDROID_external_memory_android_hardware_buffer = true; exts->ANDROID_native_buffer = true; } /* we have a very poor implementation */ if (instance->experimental.globalFencing) { exts->KHR_external_fence_fd = true; exts->KHR_external_semaphore_fd = true; } #else /* ANDROID */ if (can_external_mem) { exts->KHR_external_memory_fd = true; exts->EXT_external_memory_dma_buf = true; } #ifdef VN_USE_WSI_PLATFORM /* XXX we should check for EXT_queue_family_foreign */ exts->KHR_incremental_present = true; exts->KHR_swapchain = true; exts->KHR_swapchain_mutable_format = true; #endif #endif /* ANDROID */ exts->EXT_physical_device_drm = true; } static void vn_physical_device_get_passthrough_extensions( const struct vn_physical_device *physical_dev, struct vk_device_extension_table *exts) { *exts = (struct vk_device_extension_table){ /* promoted to VK_VERSION_1_1 */ .KHR_16bit_storage = true, .KHR_bind_memory2 = true, .KHR_dedicated_allocation = true, .KHR_descriptor_update_template = true, .KHR_device_group = true, .KHR_external_fence = true, .KHR_external_memory = true, .KHR_external_semaphore = true, .KHR_get_memory_requirements2 = true, .KHR_maintenance1 = true, .KHR_maintenance2 = true, .KHR_maintenance3 = true, .KHR_multiview = true, .KHR_relaxed_block_layout = true, .KHR_sampler_ycbcr_conversion = true, .KHR_shader_draw_parameters = true, .KHR_storage_buffer_storage_class = true, .KHR_variable_pointers = true, /* promoted to VK_VERSION_1_2 */ .KHR_8bit_storage = true, .KHR_buffer_device_address = true, .KHR_create_renderpass2 = true, .KHR_depth_stencil_resolve = true, .KHR_draw_indirect_count = true, #ifndef ANDROID /* xxx remove the #ifndef after venus has a driver id */ .KHR_driver_properties = true, #endif .KHR_image_format_list = true, .KHR_imageless_framebuffer = true, .KHR_sampler_mirror_clamp_to_edge = true, .KHR_separate_depth_stencil_layouts = true, .KHR_shader_atomic_int64 = true, .KHR_shader_float16_int8 = true, .KHR_shader_float_controls = true, .KHR_shader_subgroup_extended_types = true, .KHR_spirv_1_4 = true, .KHR_timeline_semaphore = true, .KHR_uniform_buffer_standard_layout = true, .KHR_vulkan_memory_model = true, .EXT_descriptor_indexing = true, .EXT_host_query_reset = true, .EXT_sampler_filter_minmax = true, .EXT_scalar_block_layout = true, .EXT_separate_stencil_usage = true, .EXT_shader_viewport_index_layer = true, /* promoted to VK_VERSION_1_3 */ .EXT_4444_formats = true, .EXT_extended_dynamic_state = true, .EXT_extended_dynamic_state2 = true, .EXT_image_robustness = true, .EXT_inline_uniform_block = true, .EXT_shader_demote_to_helper_invocation = true, .KHR_copy_commands2 = true, .KHR_dynamic_rendering = true, .KHR_maintenance4 = true, /* EXT */ .EXT_calibrated_timestamps = true, .EXT_conditional_rendering = true, .EXT_conservative_rasterization = true, .EXT_custom_border_color = true, .EXT_depth_clip_enable = true, #ifndef ANDROID .EXT_image_drm_format_modifier = true, #endif .EXT_image_view_min_lod = true, .EXT_index_type_uint8 = true, .EXT_line_rasterization = true, .EXT_provoking_vertex = true, .EXT_queue_family_foreign = true, .EXT_robustness2 = true, .EXT_shader_stencil_export = true, .EXT_transform_feedback = true, .EXT_vertex_attribute_divisor = true, }; } static void vn_physical_device_init_supported_extensions( struct vn_physical_device *physical_dev) { struct vk_device_extension_table native; struct vk_device_extension_table passthrough; vn_physical_device_get_native_extensions(physical_dev, &native); vn_physical_device_get_passthrough_extensions(physical_dev, &passthrough); for (uint32_t i = 0; i < VK_DEVICE_EXTENSION_COUNT; i++) { const VkExtensionProperties *props = &vk_device_extensions[i]; #ifdef ANDROID if (!vk_android_allowed_device_extensions.extensions[i]) continue; #endif if (native.extensions[i]) { physical_dev->base.base.supported_extensions.extensions[i] = true; physical_dev->extension_spec_versions[i] = props->specVersion; } else if (passthrough.extensions[i] && physical_dev->renderer_extensions.extensions[i]) { physical_dev->base.base.supported_extensions.extensions[i] = true; physical_dev->extension_spec_versions[i] = MIN2( physical_dev->extension_spec_versions[i], props->specVersion); } } /* override VK_ANDROID_native_buffer spec version */ if (native.ANDROID_native_buffer) { const uint32_t index = VN_EXTENSION_TABLE_INDEX(native, ANDROID_native_buffer); physical_dev->extension_spec_versions[index] = VN_ANDROID_NATIVE_BUFFER_SPEC_VERSION; } } static VkResult vn_physical_device_init_renderer_extensions( struct vn_physical_device *physical_dev) { struct vn_instance *instance = physical_dev->instance; const VkAllocationCallbacks *alloc = &instance->base.base.alloc; /* get renderer extensions */ uint32_t count; VkResult result = vn_call_vkEnumerateDeviceExtensionProperties( instance, vn_physical_device_to_handle(physical_dev), NULL, &count, NULL); if (result != VK_SUCCESS) return result; VkExtensionProperties *exts = NULL; if (count) { exts = vk_alloc(alloc, sizeof(*exts) * count, VN_DEFAULT_ALIGN, VK_SYSTEM_ALLOCATION_SCOPE_COMMAND); if (!exts) return VK_ERROR_OUT_OF_HOST_MEMORY; result = vn_call_vkEnumerateDeviceExtensionProperties( instance, vn_physical_device_to_handle(physical_dev), NULL, &count, exts); if (result < VK_SUCCESS) { vk_free(alloc, exts); return result; } } physical_dev->extension_spec_versions = vk_zalloc(alloc, sizeof(*physical_dev->extension_spec_versions) * VK_DEVICE_EXTENSION_COUNT, VN_DEFAULT_ALIGN, VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE); if (!physical_dev->extension_spec_versions) { vk_free(alloc, exts); return VK_ERROR_OUT_OF_HOST_MEMORY; } for (uint32_t i = 0; i < VK_DEVICE_EXTENSION_COUNT; i++) { const VkExtensionProperties *props = &vk_device_extensions[i]; for (uint32_t j = 0; j < count; j++) { if (strcmp(props->extensionName, exts[j].extensionName)) continue; /* check encoder support */ const uint32_t enc_ext_spec_version = vn_extension_get_spec_version(props->extensionName); if (!enc_ext_spec_version) continue; physical_dev->renderer_extensions.extensions[i] = true; physical_dev->extension_spec_versions[i] = MIN2(exts[j].specVersion, enc_ext_spec_version); break; } } vk_free(alloc, exts); return VK_SUCCESS; } static VkResult vn_physical_device_init_renderer_version( struct vn_physical_device *physical_dev) { struct vn_instance *instance = physical_dev->instance; /* * We either check and enable VK_KHR_get_physical_device_properties2, or we * must use vkGetPhysicalDeviceProperties to get the device-level version. */ VkPhysicalDeviceProperties props; vn_call_vkGetPhysicalDeviceProperties( instance, vn_physical_device_to_handle(physical_dev), &props); if (props.apiVersion < VN_MIN_RENDERER_VERSION) { if (VN_DEBUG(INIT)) { vn_log(instance, "%s has unsupported renderer device version %d.%d", props.deviceName, VK_VERSION_MAJOR(props.apiVersion), VK_VERSION_MINOR(props.apiVersion)); } return VK_ERROR_INITIALIZATION_FAILED; } /* device version for internal use is capped */ physical_dev->renderer_version = MIN3(props.apiVersion, instance->renderer_api_version, instance->renderer->info.vk_xml_version); return VK_SUCCESS; } static VkResult vn_physical_device_init(struct vn_physical_device *physical_dev) { struct vn_instance *instance = physical_dev->instance; const VkAllocationCallbacks *alloc = &instance->base.base.alloc; VkResult result; result = vn_physical_device_init_renderer_extensions(physical_dev); if (result != VK_SUCCESS) return result; vn_physical_device_init_supported_extensions(physical_dev); /* TODO query all caps with minimal round trips */ vn_physical_device_init_features(physical_dev); vn_physical_device_init_properties(physical_dev); result = vn_physical_device_init_queue_family_properties(physical_dev); if (result != VK_SUCCESS) goto fail; vn_physical_device_init_memory_properties(physical_dev); vn_physical_device_init_external_memory(physical_dev); vn_physical_device_init_external_fence_handles(physical_dev); vn_physical_device_init_external_semaphore_handles(physical_dev); result = vn_wsi_init(physical_dev); if (result != VK_SUCCESS) goto fail; simple_mtx_init(&physical_dev->format_update_mutex, mtx_plain); util_sparse_array_init(&physical_dev->format_properties, sizeof(struct vn_format_properties_entry), 64); return VK_SUCCESS; fail: vk_free(alloc, physical_dev->extension_spec_versions); vk_free(alloc, physical_dev->queue_family_properties); return result; } void vn_physical_device_fini(struct vn_physical_device *physical_dev) { struct vn_instance *instance = physical_dev->instance; const VkAllocationCallbacks *alloc = &instance->base.base.alloc; simple_mtx_destroy(&physical_dev->format_update_mutex); util_sparse_array_finish(&physical_dev->format_properties); vn_wsi_fini(physical_dev); vk_free(alloc, physical_dev->extension_spec_versions); vk_free(alloc, physical_dev->queue_family_properties); vn_physical_device_base_fini(&physical_dev->base); } static struct vn_physical_device * find_physical_device(struct vn_physical_device *physical_devs, uint32_t count, vn_object_id id) { for (uint32_t i = 0; i < count; i++) { if (physical_devs[i].base.id == id) return &physical_devs[i]; } return NULL; } static VkResult vn_instance_enumerate_physical_device_groups_locked( struct vn_instance *instance, struct vn_physical_device *physical_devs, uint32_t physical_dev_count) { VkInstance instance_handle = vn_instance_to_handle(instance); const VkAllocationCallbacks *alloc = &instance->base.base.alloc; VkResult result; uint32_t count; result = vn_call_vkEnumeratePhysicalDeviceGroups(instance, instance_handle, &count, NULL); if (result != VK_SUCCESS) return result; VkPhysicalDeviceGroupProperties *groups = vk_alloc(alloc, sizeof(*groups) * count, VN_DEFAULT_ALIGN, VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE); if (!groups) return VK_ERROR_OUT_OF_HOST_MEMORY; /* VkPhysicalDeviceGroupProperties::physicalDevices is treated as an input * by the encoder. Each VkPhysicalDevice must point to a valid object. * Each object must have id 0 as well, which is interpreted as a query by * the renderer. */ struct vn_physical_device_base *temp_objs = vk_zalloc(alloc, sizeof(*temp_objs) * VK_MAX_DEVICE_GROUP_SIZE * count, VN_DEFAULT_ALIGN, VK_SYSTEM_ALLOCATION_SCOPE_COMMAND); if (!temp_objs) { vk_free(alloc, groups); return VK_ERROR_OUT_OF_HOST_MEMORY; } for (uint32_t i = 0; i < count; i++) { VkPhysicalDeviceGroupProperties *group = &groups[i]; group->sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_GROUP_PROPERTIES; group->pNext = NULL; for (uint32_t j = 0; j < VK_MAX_DEVICE_GROUP_SIZE; j++) { struct vn_physical_device_base *temp_obj = &temp_objs[VK_MAX_DEVICE_GROUP_SIZE * i + j]; temp_obj->base.base.type = VK_OBJECT_TYPE_PHYSICAL_DEVICE; group->physicalDevices[j] = (VkPhysicalDevice)temp_obj; } } result = vn_call_vkEnumeratePhysicalDeviceGroups(instance, instance_handle, &count, groups); if (result != VK_SUCCESS) { vk_free(alloc, groups); vk_free(alloc, temp_objs); return result; } /* fix VkPhysicalDeviceGroupProperties::physicalDevices to point to * physical_devs and discard unsupported ones */ uint32_t supported_count = 0; for (uint32_t i = 0; i < count; i++) { VkPhysicalDeviceGroupProperties *group = &groups[i]; uint32_t group_physical_dev_count = 0; for (uint32_t j = 0; j < group->physicalDeviceCount; j++) { struct vn_physical_device_base *temp_obj = (struct vn_physical_device_base *)group->physicalDevices[j]; struct vn_physical_device *physical_dev = find_physical_device( physical_devs, physical_dev_count, temp_obj->id); if (!physical_dev) continue; group->physicalDevices[group_physical_dev_count++] = vn_physical_device_to_handle(physical_dev); } group->physicalDeviceCount = group_physical_dev_count; if (!group->physicalDeviceCount) continue; if (supported_count < i) groups[supported_count] = *group; supported_count++; } count = supported_count; assert(count); vk_free(alloc, temp_objs); instance->physical_device.groups = groups; instance->physical_device.group_count = count; return VK_SUCCESS; } static VkResult enumerate_physical_devices(struct vn_instance *instance, struct vn_physical_device **out_physical_devs, uint32_t *out_count) { const VkAllocationCallbacks *alloc = &instance->base.base.alloc; struct vn_physical_device *physical_devs = NULL; VkPhysicalDevice *handles = NULL; VkResult result; uint32_t count; result = vn_call_vkEnumeratePhysicalDevices( instance, vn_instance_to_handle(instance), &count, NULL); if (result != VK_SUCCESS || !count) return result; physical_devs = vk_zalloc(alloc, sizeof(*physical_devs) * count, VN_DEFAULT_ALIGN, VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE); if (!physical_devs) return VK_ERROR_OUT_OF_HOST_MEMORY; handles = vk_alloc(alloc, sizeof(*handles) * count, VN_DEFAULT_ALIGN, VK_SYSTEM_ALLOCATION_SCOPE_COMMAND); if (!handles) { vk_free(alloc, physical_devs); return VK_ERROR_OUT_OF_HOST_MEMORY; } for (uint32_t i = 0; i < count; i++) { struct vn_physical_device *physical_dev = &physical_devs[i]; struct vk_physical_device_dispatch_table dispatch_table; vk_physical_device_dispatch_table_from_entrypoints( &dispatch_table, &vn_physical_device_entrypoints, true); vk_physical_device_dispatch_table_from_entrypoints( &dispatch_table, &wsi_physical_device_entrypoints, false); result = vn_physical_device_base_init( &physical_dev->base, &instance->base, NULL, &dispatch_table); if (result != VK_SUCCESS) { count = i; goto fail; } physical_dev->instance = instance; handles[i] = vn_physical_device_to_handle(physical_dev); } result = vn_call_vkEnumeratePhysicalDevices( instance, vn_instance_to_handle(instance), &count, handles); if (result != VK_SUCCESS) goto fail; vk_free(alloc, handles); *out_physical_devs = physical_devs; *out_count = count; return VK_SUCCESS; fail: for (uint32_t i = 0; i < count; i++) vn_physical_device_base_fini(&physical_devs[i].base); vk_free(alloc, physical_devs); vk_free(alloc, handles); return result; } static uint32_t filter_physical_devices(struct vn_physical_device *physical_devs, uint32_t count) { uint32_t supported_count = 0; for (uint32_t i = 0; i < count; i++) { struct vn_physical_device *physical_dev = &physical_devs[i]; /* init renderer version and discard unsupported devices */ VkResult result = vn_physical_device_init_renderer_version(physical_dev); if (result != VK_SUCCESS) { vn_physical_device_base_fini(&physical_dev->base); continue; } if (supported_count < i) physical_devs[supported_count] = *physical_dev; supported_count++; } return supported_count; } static VkResult vn_instance_enumerate_physical_devices_and_groups(struct vn_instance *instance) { const VkAllocationCallbacks *alloc = &instance->base.base.alloc; struct vn_physical_device *physical_devs = NULL; uint32_t count = 0; VkResult result = VK_SUCCESS; mtx_lock(&instance->physical_device.mutex); if (instance->physical_device.initialized) goto unlock; instance->physical_device.initialized = true; result = enumerate_physical_devices(instance, &physical_devs, &count); if (result != VK_SUCCESS) goto unlock; count = filter_physical_devices(physical_devs, count); if (!count) { vk_free(alloc, physical_devs); goto unlock; } /* fully initialize physical devices */ for (uint32_t i = 0; i < count; i++) { struct vn_physical_device *physical_dev = &physical_devs[i]; result = vn_physical_device_init(physical_dev); if (result != VK_SUCCESS) { for (uint32_t j = 0; j < i; j++) vn_physical_device_fini(&physical_devs[j]); for (uint32_t j = i; j < count; j++) vn_physical_device_base_fini(&physical_devs[j].base); vk_free(alloc, physical_devs); goto unlock; } } result = vn_instance_enumerate_physical_device_groups_locked( instance, physical_devs, count); if (result != VK_SUCCESS) { for (uint32_t i = 0; i < count; i++) vn_physical_device_fini(&physical_devs[i]); vk_free(alloc, physical_devs); goto unlock; } instance->physical_device.devices = physical_devs; instance->physical_device.device_count = count; unlock: mtx_unlock(&instance->physical_device.mutex); return result; } /* physical device commands */ VkResult vn_EnumeratePhysicalDevices(VkInstance _instance, uint32_t *pPhysicalDeviceCount, VkPhysicalDevice *pPhysicalDevices) { struct vn_instance *instance = vn_instance_from_handle(_instance); VkResult result = vn_instance_enumerate_physical_devices_and_groups(instance); if (result != VK_SUCCESS) return vn_error(instance, result); VK_OUTARRAY_MAKE_TYPED(VkPhysicalDevice, out, pPhysicalDevices, pPhysicalDeviceCount); for (uint32_t i = 0; i < instance->physical_device.device_count; i++) { vk_outarray_append_typed(VkPhysicalDevice, &out, physical_dev) { *physical_dev = vn_physical_device_to_handle( &instance->physical_device.devices[i]); } } return vk_outarray_status(&out); } VkResult vn_EnumeratePhysicalDeviceGroups( VkInstance _instance, uint32_t *pPhysicalDeviceGroupCount, VkPhysicalDeviceGroupProperties *pPhysicalDeviceGroupProperties) { struct vn_instance *instance = vn_instance_from_handle(_instance); VkResult result = vn_instance_enumerate_physical_devices_and_groups(instance); if (result != VK_SUCCESS) return vn_error(instance, result); VK_OUTARRAY_MAKE_TYPED(VkPhysicalDeviceGroupProperties, out, pPhysicalDeviceGroupProperties, pPhysicalDeviceGroupCount); for (uint32_t i = 0; i < instance->physical_device.group_count; i++) { vk_outarray_append_typed(VkPhysicalDeviceGroupProperties, &out, props) { *props = instance->physical_device.groups[i]; } } return vk_outarray_status(&out); } VkResult vn_EnumerateDeviceExtensionProperties(VkPhysicalDevice physicalDevice, const char *pLayerName, uint32_t *pPropertyCount, VkExtensionProperties *pProperties) { struct vn_physical_device *physical_dev = vn_physical_device_from_handle(physicalDevice); if (pLayerName) return vn_error(physical_dev->instance, VK_ERROR_LAYER_NOT_PRESENT); VK_OUTARRAY_MAKE_TYPED(VkExtensionProperties, out, pProperties, pPropertyCount); for (uint32_t i = 0; i < VK_DEVICE_EXTENSION_COUNT; i++) { if (physical_dev->base.base.supported_extensions.extensions[i]) { vk_outarray_append_typed(VkExtensionProperties, &out, prop) { *prop = vk_device_extensions[i]; prop->specVersion = physical_dev->extension_spec_versions[i]; } } } return vk_outarray_status(&out); } VkResult vn_EnumerateDeviceLayerProperties(VkPhysicalDevice physicalDevice, uint32_t *pPropertyCount, VkLayerProperties *pProperties) { *pPropertyCount = 0; return VK_SUCCESS; } static struct vn_format_properties_entry * vn_physical_device_get_format_properties( struct vn_physical_device *physical_dev, VkFormat format) { return util_sparse_array_get(&physical_dev->format_properties, format); } static void vn_physical_device_add_format_properties( struct vn_physical_device *physical_dev, struct vn_format_properties_entry *entry, const VkFormatProperties *props) { simple_mtx_lock(&physical_dev->format_update_mutex); if (!entry->valid) { entry->properties = *props; entry->valid = true; } simple_mtx_unlock(&physical_dev->format_update_mutex); } void vn_GetPhysicalDeviceFeatures2(VkPhysicalDevice physicalDevice, VkPhysicalDeviceFeatures2 *pFeatures) { struct vn_physical_device *physical_dev = vn_physical_device_from_handle(physicalDevice); const struct vn_physical_device_features *feats = &physical_dev->features; const struct VkPhysicalDeviceVulkan11Features *vk11_feats = &feats->vulkan_1_1; const struct VkPhysicalDeviceVulkan12Features *vk12_feats = &feats->vulkan_1_2; union { VkBaseOutStructure *pnext; VkPhysicalDeviceFeatures2 *features2; VkPhysicalDeviceVulkan11Features *vulkan_1_1; VkPhysicalDeviceVulkan12Features *vulkan_1_2; /* Vulkan 1.1 */ VkPhysicalDevice16BitStorageFeatures *sixteen_bit_storage; VkPhysicalDeviceMultiviewFeatures *multiview; VkPhysicalDeviceVariablePointersFeatures *variable_pointers; VkPhysicalDeviceProtectedMemoryFeatures *protected_memory; VkPhysicalDeviceSamplerYcbcrConversionFeatures *sampler_ycbcr_conversion; VkPhysicalDeviceShaderDrawParametersFeatures *shader_draw_parameters; /* Vulkan 1.2 */ VkPhysicalDevice8BitStorageFeatures *eight_bit_storage; VkPhysicalDeviceShaderAtomicInt64Features *shader_atomic_int64; VkPhysicalDeviceShaderFloat16Int8Features *shader_float16_int8; VkPhysicalDeviceDescriptorIndexingFeatures *descriptor_indexing; VkPhysicalDeviceScalarBlockLayoutFeatures *scalar_block_layout; VkPhysicalDeviceImagelessFramebufferFeatures *imageless_framebuffer; VkPhysicalDeviceUniformBufferStandardLayoutFeatures *uniform_buffer_standard_layout; VkPhysicalDeviceShaderSubgroupExtendedTypesFeatures *shader_subgroup_extended_types; VkPhysicalDeviceSeparateDepthStencilLayoutsFeatures *separate_depth_stencil_layouts; VkPhysicalDeviceHostQueryResetFeatures *host_query_reset; VkPhysicalDeviceTimelineSemaphoreFeatures *timeline_semaphore; VkPhysicalDeviceBufferDeviceAddressFeatures *buffer_device_address; VkPhysicalDeviceVulkanMemoryModelFeatures *vulkan_memory_model; /* Vulkan 1.3 */ VkPhysicalDevice4444FormatsFeaturesEXT *argb_4444_formats; VkPhysicalDeviceDynamicRenderingFeatures *dynamic_rendering; VkPhysicalDeviceExtendedDynamicStateFeaturesEXT *extended_dynamic_state; VkPhysicalDeviceExtendedDynamicState2FeaturesEXT *extended_dynamic_state2; VkPhysicalDeviceImageRobustnessFeatures *image_robustness; VkPhysicalDeviceInlineUniformBlockFeatures *inline_uniform_block; VkPhysicalDeviceMaintenance4Features *maintenance4; VkPhysicalDeviceShaderDemoteToHelperInvocationFeatures *shader_demote_to_helper_invocation; /* EXT */ VkPhysicalDeviceConditionalRenderingFeaturesEXT *conditional_rendering; VkPhysicalDeviceCustomBorderColorFeaturesEXT *custom_border_color; VkPhysicalDeviceDepthClipEnableFeaturesEXT *depth_clip_enable; VkPhysicalDeviceIndexTypeUint8FeaturesEXT *index_type_uint8; VkPhysicalDeviceLineRasterizationFeaturesEXT *line_rasterization; VkPhysicalDeviceProvokingVertexFeaturesEXT *provoking_vertex; VkPhysicalDeviceRobustness2FeaturesEXT *robustness_2; VkPhysicalDeviceTransformFeedbackFeaturesEXT *transform_feedback; VkPhysicalDeviceVertexAttributeDivisorFeaturesEXT *vertex_attribute_divisor; } u; u.pnext = (VkBaseOutStructure *)pFeatures; while (u.pnext) { void *saved = u.pnext->pNext; switch (u.pnext->sType) { case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2: u.features2->features = feats->vulkan_1_0; break; case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_1_FEATURES: *u.vulkan_1_1 = *vk11_feats; break; case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_2_FEATURES: *u.vulkan_1_2 = *vk12_feats; break; /* Vulkan 1.1 */ case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_16BIT_STORAGE_FEATURES: u.sixteen_bit_storage->storageBuffer16BitAccess = vk11_feats->storageBuffer16BitAccess; u.sixteen_bit_storage->uniformAndStorageBuffer16BitAccess = vk11_feats->uniformAndStorageBuffer16BitAccess; u.sixteen_bit_storage->storagePushConstant16 = vk11_feats->storagePushConstant16; u.sixteen_bit_storage->storageInputOutput16 = vk11_feats->storageInputOutput16; break; case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MULTIVIEW_FEATURES: u.multiview->multiview = vk11_feats->multiview; u.multiview->multiviewGeometryShader = vk11_feats->multiviewGeometryShader; u.multiview->multiviewTessellationShader = vk11_feats->multiviewTessellationShader; break; case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VARIABLE_POINTERS_FEATURES: u.variable_pointers->variablePointersStorageBuffer = vk11_feats->variablePointersStorageBuffer; u.variable_pointers->variablePointers = vk11_feats->variablePointers; break; case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROTECTED_MEMORY_FEATURES: u.protected_memory->protectedMemory = vk11_feats->protectedMemory; break; case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SAMPLER_YCBCR_CONVERSION_FEATURES: u.sampler_ycbcr_conversion->samplerYcbcrConversion = vk11_feats->samplerYcbcrConversion; break; case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_DRAW_PARAMETERS_FEATURES: u.shader_draw_parameters->shaderDrawParameters = vk11_feats->shaderDrawParameters; break; /* Vulkan 1.2 */ case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_8BIT_STORAGE_FEATURES: u.eight_bit_storage->storageBuffer8BitAccess = vk12_feats->storageBuffer8BitAccess; u.eight_bit_storage->uniformAndStorageBuffer8BitAccess = vk12_feats->uniformAndStorageBuffer8BitAccess; u.eight_bit_storage->storagePushConstant8 = vk12_feats->storagePushConstant8; break; case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_ATOMIC_INT64_FEATURES: u.shader_atomic_int64->shaderBufferInt64Atomics = vk12_feats->shaderBufferInt64Atomics; u.shader_atomic_int64->shaderSharedInt64Atomics = vk12_feats->shaderSharedInt64Atomics; break; case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_FLOAT16_INT8_FEATURES: u.shader_float16_int8->shaderFloat16 = vk12_feats->shaderFloat16; u.shader_float16_int8->shaderInt8 = vk12_feats->shaderInt8; break; case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DESCRIPTOR_INDEXING_FEATURES: u.descriptor_indexing->shaderInputAttachmentArrayDynamicIndexing = vk12_feats->shaderInputAttachmentArrayDynamicIndexing; u.descriptor_indexing->shaderUniformTexelBufferArrayDynamicIndexing = vk12_feats->shaderUniformTexelBufferArrayDynamicIndexing; u.descriptor_indexing->shaderStorageTexelBufferArrayDynamicIndexing = vk12_feats->shaderStorageTexelBufferArrayDynamicIndexing; u.descriptor_indexing->shaderUniformBufferArrayNonUniformIndexing = vk12_feats->shaderUniformBufferArrayNonUniformIndexing; u.descriptor_indexing->shaderSampledImageArrayNonUniformIndexing = vk12_feats->shaderSampledImageArrayNonUniformIndexing; u.descriptor_indexing->shaderStorageBufferArrayNonUniformIndexing = vk12_feats->shaderStorageBufferArrayNonUniformIndexing; u.descriptor_indexing->shaderStorageImageArrayNonUniformIndexing = vk12_feats->shaderStorageImageArrayNonUniformIndexing; u.descriptor_indexing->shaderInputAttachmentArrayNonUniformIndexing = vk12_feats->shaderInputAttachmentArrayNonUniformIndexing; u.descriptor_indexing ->shaderUniformTexelBufferArrayNonUniformIndexing = vk12_feats->shaderUniformTexelBufferArrayNonUniformIndexing; u.descriptor_indexing ->shaderStorageTexelBufferArrayNonUniformIndexing = vk12_feats->shaderStorageTexelBufferArrayNonUniformIndexing; u.descriptor_indexing->descriptorBindingUniformBufferUpdateAfterBind = vk12_feats->descriptorBindingUniformBufferUpdateAfterBind; u.descriptor_indexing->descriptorBindingSampledImageUpdateAfterBind = vk12_feats->descriptorBindingSampledImageUpdateAfterBind; u.descriptor_indexing->descriptorBindingStorageImageUpdateAfterBind = vk12_feats->descriptorBindingStorageImageUpdateAfterBind; u.descriptor_indexing->descriptorBindingStorageBufferUpdateAfterBind = vk12_feats->descriptorBindingStorageBufferUpdateAfterBind; u.descriptor_indexing ->descriptorBindingUniformTexelBufferUpdateAfterBind = vk12_feats->descriptorBindingUniformTexelBufferUpdateAfterBind; u.descriptor_indexing ->descriptorBindingStorageTexelBufferUpdateAfterBind = vk12_feats->descriptorBindingStorageTexelBufferUpdateAfterBind; u.descriptor_indexing->descriptorBindingUpdateUnusedWhilePending = vk12_feats->descriptorBindingUpdateUnusedWhilePending; u.descriptor_indexing->descriptorBindingPartiallyBound = vk12_feats->descriptorBindingPartiallyBound; u.descriptor_indexing->descriptorBindingVariableDescriptorCount = vk12_feats->descriptorBindingVariableDescriptorCount; u.descriptor_indexing->runtimeDescriptorArray = vk12_feats->runtimeDescriptorArray; break; case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SCALAR_BLOCK_LAYOUT_FEATURES: u.scalar_block_layout->scalarBlockLayout = vk12_feats->scalarBlockLayout; break; case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGELESS_FRAMEBUFFER_FEATURES: u.imageless_framebuffer->imagelessFramebuffer = vk12_feats->imagelessFramebuffer; break; case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_UNIFORM_BUFFER_STANDARD_LAYOUT_FEATURES: u.uniform_buffer_standard_layout->uniformBufferStandardLayout = vk12_feats->uniformBufferStandardLayout; break; case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_SUBGROUP_EXTENDED_TYPES_FEATURES: u.shader_subgroup_extended_types->shaderSubgroupExtendedTypes = vk12_feats->shaderSubgroupExtendedTypes; break; case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SEPARATE_DEPTH_STENCIL_LAYOUTS_FEATURES: u.separate_depth_stencil_layouts->separateDepthStencilLayouts = vk12_feats->separateDepthStencilLayouts; break; case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_HOST_QUERY_RESET_FEATURES: u.host_query_reset->hostQueryReset = vk12_feats->hostQueryReset; break; case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_TIMELINE_SEMAPHORE_FEATURES: u.timeline_semaphore->timelineSemaphore = vk12_feats->timelineSemaphore; break; case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_BUFFER_DEVICE_ADDRESS_FEATURES: u.buffer_device_address->bufferDeviceAddress = vk12_feats->bufferDeviceAddress; u.buffer_device_address->bufferDeviceAddressCaptureReplay = vk12_feats->bufferDeviceAddressCaptureReplay; u.buffer_device_address->bufferDeviceAddressMultiDevice = vk12_feats->bufferDeviceAddressMultiDevice; break; case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_MEMORY_MODEL_FEATURES: u.vulkan_memory_model->vulkanMemoryModel = vk12_feats->vulkanMemoryModel; u.vulkan_memory_model->vulkanMemoryModelDeviceScope = vk12_feats->vulkanMemoryModelDeviceScope; u.vulkan_memory_model->vulkanMemoryModelAvailabilityVisibilityChains = vk12_feats->vulkanMemoryModelAvailabilityVisibilityChains; break; /* Vulkan 1.3 */ case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_4444_FORMATS_FEATURES_EXT: *u.argb_4444_formats = feats->argb_4444_formats; break; case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DYNAMIC_RENDERING_FEATURES: *u.dynamic_rendering = feats->dynamic_rendering; break; case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTENDED_DYNAMIC_STATE_FEATURES_EXT: *u.extended_dynamic_state = feats->extended_dynamic_state; break; case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTENDED_DYNAMIC_STATE_2_FEATURES_EXT: *u.extended_dynamic_state2 = feats->extended_dynamic_state_2; break; case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_ROBUSTNESS_FEATURES: *u.image_robustness = feats->image_robustness; break; case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_INLINE_UNIFORM_BLOCK_FEATURES: *u.inline_uniform_block = feats->inline_uniform_block; break; case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_DEMOTE_TO_HELPER_INVOCATION_FEATURES: *u.shader_demote_to_helper_invocation = feats->shader_demote_to_helper_invocation; break; /* EXT */ case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_CONDITIONAL_RENDERING_FEATURES_EXT: *u.conditional_rendering = feats->conditional_rendering; break; case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_CUSTOM_BORDER_COLOR_FEATURES_EXT: *u.custom_border_color = feats->custom_border_color; break; case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DEPTH_CLIP_ENABLE_FEATURES_EXT: *u.depth_clip_enable = feats->depth_clip_enable; break; case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_INDEX_TYPE_UINT8_FEATURES_EXT: *u.index_type_uint8 = feats->index_type_uint8; break; case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_LINE_RASTERIZATION_FEATURES_EXT: *u.line_rasterization = feats->line_rasterization; break; case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROVOKING_VERTEX_FEATURES_EXT: *u.provoking_vertex = feats->provoking_vertex; break; case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ROBUSTNESS_2_FEATURES_EXT: *u.robustness_2 = feats->robustness_2; break; case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_TRANSFORM_FEEDBACK_FEATURES_EXT: *u.transform_feedback = feats->transform_feedback; break; case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VERTEX_ATTRIBUTE_DIVISOR_FEATURES_EXT: *u.vertex_attribute_divisor = feats->vertex_attribute_divisor; break; case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MAINTENANCE_4_FEATURES: *u.maintenance4 = feats->maintenance4; break; default: break; } u.pnext->pNext = saved; u.pnext = u.pnext->pNext; } } void vn_GetPhysicalDeviceProperties2(VkPhysicalDevice physicalDevice, VkPhysicalDeviceProperties2 *pProperties) { struct vn_physical_device *physical_dev = vn_physical_device_from_handle(physicalDevice); const struct vn_physical_device_properties *props = &physical_dev->properties; const struct VkPhysicalDeviceVulkan11Properties *vk11_props = &props->vulkan_1_1; const struct VkPhysicalDeviceVulkan12Properties *vk12_props = &props->vulkan_1_2; union { VkBaseOutStructure *pnext; VkPhysicalDeviceProperties2 *properties2; VkPhysicalDeviceVulkan11Properties *vulkan_1_1; VkPhysicalDeviceVulkan12Properties *vulkan_1_2; /* Vulkan 1.1 */ VkPhysicalDeviceIDProperties *id; VkPhysicalDeviceSubgroupProperties *subgroup; VkPhysicalDevicePointClippingProperties *point_clipping; VkPhysicalDeviceMultiviewProperties *multiview; VkPhysicalDeviceProtectedMemoryProperties *protected_memory; VkPhysicalDeviceMaintenance3Properties *maintenance_3; /* Vulkan 1.2 */ VkPhysicalDeviceDriverProperties *driver; VkPhysicalDeviceFloatControlsProperties *float_controls; VkPhysicalDeviceDescriptorIndexingProperties *descriptor_indexing; VkPhysicalDeviceDepthStencilResolveProperties *depth_stencil_resolve; VkPhysicalDeviceSamplerFilterMinmaxProperties *sampler_filter_minmax; VkPhysicalDeviceTimelineSemaphoreProperties *timeline_semaphore; /* Vulkan 1.3 */ VkPhysicalDeviceInlineUniformBlockProperties *inline_uniform_block; /* EXT */ VkPhysicalDeviceConservativeRasterizationPropertiesEXT *conservative_rasterization; VkPhysicalDeviceCustomBorderColorPropertiesEXT *custom_border_color; VkPhysicalDeviceDrmPropertiesEXT *drm; VkPhysicalDeviceLineRasterizationPropertiesEXT *line_rasterization; VkPhysicalDevicePCIBusInfoPropertiesEXT *pci_bus_info; VkPhysicalDevicePresentationPropertiesANDROID *presentation_properties; VkPhysicalDeviceProvokingVertexPropertiesEXT *provoking_vertex; VkPhysicalDeviceRobustness2PropertiesEXT *robustness_2; VkPhysicalDeviceMaintenance4Properties *maintenance4; VkPhysicalDeviceTransformFeedbackPropertiesEXT *transform_feedback; VkPhysicalDeviceVertexAttributeDivisorPropertiesEXT *vertex_attribute_divisor; } u; u.pnext = (VkBaseOutStructure *)pProperties; while (u.pnext) { void *saved = u.pnext->pNext; switch ((int32_t)u.pnext->sType) { case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2: u.properties2->properties = props->vulkan_1_0; break; case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_1_PROPERTIES: *u.vulkan_1_1 = *vk11_props; break; case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_2_PROPERTIES: *u.vulkan_1_2 = *vk12_props; break; /* Vulkan 1.1 */ case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ID_PROPERTIES: memcpy(u.id->deviceUUID, vk11_props->deviceUUID, sizeof(vk11_props->deviceUUID)); memcpy(u.id->driverUUID, vk11_props->driverUUID, sizeof(vk11_props->driverUUID)); memcpy(u.id->deviceLUID, vk11_props->deviceLUID, sizeof(vk11_props->deviceLUID)); u.id->deviceNodeMask = vk11_props->deviceNodeMask; u.id->deviceLUIDValid = vk11_props->deviceLUIDValid; break; case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SUBGROUP_PROPERTIES: u.subgroup->subgroupSize = vk11_props->subgroupSize; u.subgroup->supportedStages = vk11_props->subgroupSupportedStages; u.subgroup->supportedOperations = vk11_props->subgroupSupportedOperations; u.subgroup->quadOperationsInAllStages = vk11_props->subgroupQuadOperationsInAllStages; break; case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_POINT_CLIPPING_PROPERTIES: u.point_clipping->pointClippingBehavior = vk11_props->pointClippingBehavior; break; case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MULTIVIEW_PROPERTIES: u.multiview->maxMultiviewViewCount = vk11_props->maxMultiviewViewCount; u.multiview->maxMultiviewInstanceIndex = vk11_props->maxMultiviewInstanceIndex; break; case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROTECTED_MEMORY_PROPERTIES: u.protected_memory->protectedNoFault = vk11_props->protectedNoFault; break; case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MAINTENANCE_3_PROPERTIES: u.maintenance_3->maxPerSetDescriptors = vk11_props->maxPerSetDescriptors; u.maintenance_3->maxMemoryAllocationSize = vk11_props->maxMemoryAllocationSize; break; /* Vulkan 1.2 */ case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DRIVER_PROPERTIES: u.driver->driverID = vk12_props->driverID; memcpy(u.driver->driverName, vk12_props->driverName, sizeof(vk12_props->driverName)); memcpy(u.driver->driverInfo, vk12_props->driverInfo, sizeof(vk12_props->driverInfo)); u.driver->conformanceVersion = vk12_props->conformanceVersion; break; case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FLOAT_CONTROLS_PROPERTIES: u.float_controls->denormBehaviorIndependence = vk12_props->denormBehaviorIndependence; u.float_controls->roundingModeIndependence = vk12_props->roundingModeIndependence; u.float_controls->shaderSignedZeroInfNanPreserveFloat16 = vk12_props->shaderSignedZeroInfNanPreserveFloat16; u.float_controls->shaderSignedZeroInfNanPreserveFloat32 = vk12_props->shaderSignedZeroInfNanPreserveFloat32; u.float_controls->shaderSignedZeroInfNanPreserveFloat64 = vk12_props->shaderSignedZeroInfNanPreserveFloat64; u.float_controls->shaderDenormPreserveFloat16 = vk12_props->shaderDenormPreserveFloat16; u.float_controls->shaderDenormPreserveFloat32 = vk12_props->shaderDenormPreserveFloat32; u.float_controls->shaderDenormPreserveFloat64 = vk12_props->shaderDenormPreserveFloat64; u.float_controls->shaderDenormFlushToZeroFloat16 = vk12_props->shaderDenormFlushToZeroFloat16; u.float_controls->shaderDenormFlushToZeroFloat32 = vk12_props->shaderDenormFlushToZeroFloat32; u.float_controls->shaderDenormFlushToZeroFloat64 = vk12_props->shaderDenormFlushToZeroFloat64; u.float_controls->shaderRoundingModeRTEFloat16 = vk12_props->shaderRoundingModeRTEFloat16; u.float_controls->shaderRoundingModeRTEFloat32 = vk12_props->shaderRoundingModeRTEFloat32; u.float_controls->shaderRoundingModeRTEFloat64 = vk12_props->shaderRoundingModeRTEFloat64; u.float_controls->shaderRoundingModeRTZFloat16 = vk12_props->shaderRoundingModeRTZFloat16; u.float_controls->shaderRoundingModeRTZFloat32 = vk12_props->shaderRoundingModeRTZFloat32; u.float_controls->shaderRoundingModeRTZFloat64 = vk12_props->shaderRoundingModeRTZFloat64; break; case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DESCRIPTOR_INDEXING_PROPERTIES: u.descriptor_indexing->maxUpdateAfterBindDescriptorsInAllPools = vk12_props->maxUpdateAfterBindDescriptorsInAllPools; u.descriptor_indexing ->shaderUniformBufferArrayNonUniformIndexingNative = vk12_props->shaderUniformBufferArrayNonUniformIndexingNative; u.descriptor_indexing ->shaderSampledImageArrayNonUniformIndexingNative = vk12_props->shaderSampledImageArrayNonUniformIndexingNative; u.descriptor_indexing ->shaderStorageBufferArrayNonUniformIndexingNative = vk12_props->shaderStorageBufferArrayNonUniformIndexingNative; u.descriptor_indexing ->shaderStorageImageArrayNonUniformIndexingNative = vk12_props->shaderStorageImageArrayNonUniformIndexingNative; u.descriptor_indexing ->shaderInputAttachmentArrayNonUniformIndexingNative = vk12_props->shaderInputAttachmentArrayNonUniformIndexingNative; u.descriptor_indexing->robustBufferAccessUpdateAfterBind = vk12_props->robustBufferAccessUpdateAfterBind; u.descriptor_indexing->quadDivergentImplicitLod = vk12_props->quadDivergentImplicitLod; u.descriptor_indexing->maxPerStageDescriptorUpdateAfterBindSamplers = vk12_props->maxPerStageDescriptorUpdateAfterBindSamplers; u.descriptor_indexing ->maxPerStageDescriptorUpdateAfterBindUniformBuffers = vk12_props->maxPerStageDescriptorUpdateAfterBindUniformBuffers; u.descriptor_indexing ->maxPerStageDescriptorUpdateAfterBindStorageBuffers = vk12_props->maxPerStageDescriptorUpdateAfterBindStorageBuffers; u.descriptor_indexing ->maxPerStageDescriptorUpdateAfterBindSampledImages = vk12_props->maxPerStageDescriptorUpdateAfterBindSampledImages; u.descriptor_indexing ->maxPerStageDescriptorUpdateAfterBindStorageImages = vk12_props->maxPerStageDescriptorUpdateAfterBindStorageImages; u.descriptor_indexing ->maxPerStageDescriptorUpdateAfterBindInputAttachments = vk12_props->maxPerStageDescriptorUpdateAfterBindInputAttachments; u.descriptor_indexing->maxPerStageUpdateAfterBindResources = vk12_props->maxPerStageUpdateAfterBindResources; u.descriptor_indexing->maxDescriptorSetUpdateAfterBindSamplers = vk12_props->maxDescriptorSetUpdateAfterBindSamplers; u.descriptor_indexing->maxDescriptorSetUpdateAfterBindUniformBuffers = vk12_props->maxDescriptorSetUpdateAfterBindUniformBuffers; u.descriptor_indexing ->maxDescriptorSetUpdateAfterBindUniformBuffersDynamic = vk12_props->maxDescriptorSetUpdateAfterBindUniformBuffersDynamic; u.descriptor_indexing->maxDescriptorSetUpdateAfterBindStorageBuffers = vk12_props->maxDescriptorSetUpdateAfterBindStorageBuffers; u.descriptor_indexing ->maxDescriptorSetUpdateAfterBindStorageBuffersDynamic = vk12_props->maxDescriptorSetUpdateAfterBindStorageBuffersDynamic; u.descriptor_indexing->maxDescriptorSetUpdateAfterBindSampledImages = vk12_props->maxDescriptorSetUpdateAfterBindSampledImages; u.descriptor_indexing->maxDescriptorSetUpdateAfterBindStorageImages = vk12_props->maxDescriptorSetUpdateAfterBindStorageImages; u.descriptor_indexing ->maxDescriptorSetUpdateAfterBindInputAttachments = vk12_props->maxDescriptorSetUpdateAfterBindInputAttachments; break; case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DEPTH_STENCIL_RESOLVE_PROPERTIES: u.depth_stencil_resolve->supportedDepthResolveModes = vk12_props->supportedDepthResolveModes; u.depth_stencil_resolve->supportedStencilResolveModes = vk12_props->supportedStencilResolveModes; u.depth_stencil_resolve->independentResolveNone = vk12_props->independentResolveNone; u.depth_stencil_resolve->independentResolve = vk12_props->independentResolve; break; case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SAMPLER_FILTER_MINMAX_PROPERTIES: u.sampler_filter_minmax->filterMinmaxSingleComponentFormats = vk12_props->filterMinmaxSingleComponentFormats; u.sampler_filter_minmax->filterMinmaxImageComponentMapping = vk12_props->filterMinmaxImageComponentMapping; break; case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_TIMELINE_SEMAPHORE_PROPERTIES: u.timeline_semaphore->maxTimelineSemaphoreValueDifference = vk12_props->maxTimelineSemaphoreValueDifference; break; /* Vulkan 1.3 */ case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_INLINE_UNIFORM_BLOCK_PROPERTIES: *u.inline_uniform_block = props->inline_uniform_block; break; /* EXT */ case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_CONSERVATIVE_RASTERIZATION_PROPERTIES_EXT: *u.conservative_rasterization = props->conservative_rasterization; break; case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_CUSTOM_BORDER_COLOR_PROPERTIES_EXT: *u.custom_border_color = props->custom_border_color; break; case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DRM_PROPERTIES_EXT: u.drm->hasPrimary = physical_dev->instance->renderer->info.drm.has_primary; u.drm->primaryMajor = physical_dev->instance->renderer->info.drm.primary_major; u.drm->primaryMinor = physical_dev->instance->renderer->info.drm.primary_minor; u.drm->hasRender = physical_dev->instance->renderer->info.drm.has_render; u.drm->renderMajor = physical_dev->instance->renderer->info.drm.render_major; u.drm->renderMinor = physical_dev->instance->renderer->info.drm.render_minor; break; case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_LINE_RASTERIZATION_PROPERTIES_EXT: *u.line_rasterization = props->line_rasterization; break; case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PCI_BUS_INFO_PROPERTIES_EXT: /* this is used by WSI */ if (physical_dev->instance->renderer->info.pci.has_bus_info) { u.pci_bus_info->pciDomain = physical_dev->instance->renderer->info.pci.domain; u.pci_bus_info->pciBus = physical_dev->instance->renderer->info.pci.bus; u.pci_bus_info->pciDevice = physical_dev->instance->renderer->info.pci.device; u.pci_bus_info->pciFunction = physical_dev->instance->renderer->info.pci.function; } break; case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PRESENTATION_PROPERTIES_ANDROID: u.presentation_properties->sharedImage = vn_android_gralloc_get_shared_present_usage() ? VK_TRUE : VK_FALSE; break; case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROVOKING_VERTEX_PROPERTIES_EXT: *u.provoking_vertex = props->provoking_vertex; break; case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ROBUSTNESS_2_PROPERTIES_EXT: *u.robustness_2 = props->robustness_2; break; case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_TRANSFORM_FEEDBACK_PROPERTIES_EXT: *u.transform_feedback = props->transform_feedback; break; case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VERTEX_ATTRIBUTE_DIVISOR_PROPERTIES_EXT: *u.vertex_attribute_divisor = props->vertex_attribute_divisor; break; case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MAINTENANCE_4_PROPERTIES: *u.maintenance4 = props->maintenance4; break; default: break; } u.pnext->pNext = saved; u.pnext = u.pnext->pNext; } } void vn_GetPhysicalDeviceQueueFamilyProperties2( VkPhysicalDevice physicalDevice, uint32_t *pQueueFamilyPropertyCount, VkQueueFamilyProperties2 *pQueueFamilyProperties) { struct vn_physical_device *physical_dev = vn_physical_device_from_handle(physicalDevice); VK_OUTARRAY_MAKE_TYPED(VkQueueFamilyProperties2, out, pQueueFamilyProperties, pQueueFamilyPropertyCount); for (uint32_t i = 0; i < physical_dev->queue_family_count; i++) { vk_outarray_append_typed(VkQueueFamilyProperties2, &out, props) { *props = physical_dev->queue_family_properties[i]; } } } void vn_GetPhysicalDeviceMemoryProperties2( VkPhysicalDevice physicalDevice, VkPhysicalDeviceMemoryProperties2 *pMemoryProperties) { struct vn_physical_device *physical_dev = vn_physical_device_from_handle(physicalDevice); pMemoryProperties->memoryProperties = physical_dev->memory_properties.memoryProperties; } void vn_GetPhysicalDeviceFormatProperties2(VkPhysicalDevice physicalDevice, VkFormat format, VkFormatProperties2 *pFormatProperties) { struct vn_physical_device *physical_dev = vn_physical_device_from_handle(physicalDevice); struct vn_format_properties_entry *entry = NULL; if (!pFormatProperties->pNext) { entry = vn_physical_device_get_format_properties(physical_dev, format); if (entry->valid) { pFormatProperties->formatProperties = entry->properties; return; } } vn_call_vkGetPhysicalDeviceFormatProperties2( physical_dev->instance, physicalDevice, format, pFormatProperties); if (entry) { vn_physical_device_add_format_properties( physical_dev, entry, &pFormatProperties->formatProperties); } } struct vn_physical_device_image_format_info { VkPhysicalDeviceImageFormatInfo2 format; VkPhysicalDeviceExternalImageFormatInfo external; VkImageFormatListCreateInfo list; VkImageStencilUsageCreateInfo stencil_usage; VkPhysicalDeviceImageDrmFormatModifierInfoEXT modifier; }; static const VkPhysicalDeviceImageFormatInfo2 * vn_physical_device_fix_image_format_info( struct vn_physical_device *physical_dev, const VkPhysicalDeviceImageFormatInfo2 *info, struct vn_physical_device_image_format_info *local_info) { local_info->format = *info; VkBaseOutStructure *dst = (void *)&local_info->format; bool is_ahb = false; bool has_format_list = false; /* we should generate deep copy functions... */ vk_foreach_struct_const(src, info->pNext) { void *pnext = NULL; switch (src->sType) { case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_IMAGE_FORMAT_INFO: memcpy(&local_info->external, src, sizeof(local_info->external)); is_ahb = local_info->external.handleType == VK_EXTERNAL_MEMORY_HANDLE_TYPE_ANDROID_HARDWARE_BUFFER_BIT_ANDROID; local_info->external.handleType = physical_dev->external_memory.renderer_handle_type; pnext = &local_info->external; break; case VK_STRUCTURE_TYPE_IMAGE_FORMAT_LIST_CREATE_INFO: has_format_list = true; memcpy(&local_info->list, src, sizeof(local_info->list)); pnext = &local_info->list; break; case VK_STRUCTURE_TYPE_IMAGE_STENCIL_USAGE_CREATE_INFO: memcpy(&local_info->stencil_usage, src, sizeof(local_info->stencil_usage)); pnext = &local_info->stencil_usage; break; case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_DRM_FORMAT_MODIFIER_INFO_EXT: memcpy(&local_info->modifier, src, sizeof(local_info->modifier)); pnext = &local_info->modifier; break; default: break; } if (pnext) { dst->pNext = pnext; dst = pnext; } } if (is_ahb) { assert(local_info->format.tiling != VK_IMAGE_TILING_DRM_FORMAT_MODIFIER_EXT); local_info->format.tiling = VK_IMAGE_TILING_DRM_FORMAT_MODIFIER_EXT; if (!vn_android_get_drm_format_modifier_info(&local_info->format, &local_info->modifier)) return NULL; dst->pNext = (void *)&local_info->modifier; dst = dst->pNext; if ((info->flags & VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT) && !local_info->list.viewFormatCount) { /* 12.3. Images * * If tiling is VK_IMAGE_TILING_DRM_FORMAT_MODIFIER_EXT and flags * contains VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT, then the pNext chain * must include a VkImageFormatListCreateInfo structure with non-zero * viewFormatCount. */ VkImageFormatListCreateInfo *list = &local_info->list; uint32_t vcount = 0; const VkFormat *vformats = vn_android_format_to_view_formats(info->format, &vcount); if (!vformats) { /* local_info persists through the image format query call */ vformats = &local_info->format.format; vcount = 1; } list->sType = VK_STRUCTURE_TYPE_IMAGE_FORMAT_LIST_CREATE_INFO; list->viewFormatCount = vcount; list->pViewFormats = vformats; if (!has_format_list) { dst->pNext = (void *)list; dst = dst->pNext; } } } dst->pNext = NULL; return &local_info->format; } VkResult vn_GetPhysicalDeviceImageFormatProperties2( VkPhysicalDevice physicalDevice, const VkPhysicalDeviceImageFormatInfo2 *pImageFormatInfo, VkImageFormatProperties2 *pImageFormatProperties) { struct vn_physical_device *physical_dev = vn_physical_device_from_handle(physicalDevice); const VkExternalMemoryHandleTypeFlagBits renderer_handle_type = physical_dev->external_memory.renderer_handle_type; const VkExternalMemoryHandleTypeFlags supported_handle_types = physical_dev->external_memory.supported_handle_types; const VkPhysicalDeviceExternalImageFormatInfo *external_info = vk_find_struct_const(pImageFormatInfo->pNext, PHYSICAL_DEVICE_EXTERNAL_IMAGE_FORMAT_INFO); if (external_info && !external_info->handleType) external_info = NULL; struct vn_physical_device_image_format_info local_info; if (external_info) { if (!(external_info->handleType & supported_handle_types)) { return vn_error(physical_dev->instance, VK_ERROR_FORMAT_NOT_SUPPORTED); } if (external_info->handleType != renderer_handle_type) { pImageFormatInfo = vn_physical_device_fix_image_format_info( physical_dev, pImageFormatInfo, &local_info); if (!pImageFormatInfo) { return vn_error(physical_dev->instance, VK_ERROR_FORMAT_NOT_SUPPORTED); } } } VkResult result; /* TODO per-device cache */ result = vn_call_vkGetPhysicalDeviceImageFormatProperties2( physical_dev->instance, physicalDevice, pImageFormatInfo, pImageFormatProperties); if (result != VK_SUCCESS || !external_info) return vn_result(physical_dev->instance, result); if (external_info->handleType == VK_EXTERNAL_MEMORY_HANDLE_TYPE_ANDROID_HARDWARE_BUFFER_BIT_ANDROID) { VkAndroidHardwareBufferUsageANDROID *ahb_usage = vk_find_struct(pImageFormatProperties->pNext, ANDROID_HARDWARE_BUFFER_USAGE_ANDROID); if (ahb_usage) { ahb_usage->androidHardwareBufferUsage = vn_android_get_ahb_usage( pImageFormatInfo->usage, pImageFormatInfo->flags); } /* AHBs with mipmap usage will ignore this property */ pImageFormatProperties->imageFormatProperties.maxMipLevels = 1; } VkExternalImageFormatProperties *img_props = vk_find_struct( pImageFormatProperties->pNext, EXTERNAL_IMAGE_FORMAT_PROPERTIES); if (!img_props) return VK_SUCCESS; VkExternalMemoryProperties *mem_props = &img_props->externalMemoryProperties; if (external_info->handleType == VK_EXTERNAL_MEMORY_HANDLE_TYPE_ANDROID_HARDWARE_BUFFER_BIT_ANDROID) { /* AHB backed image requires renderer to support import bit */ if (!(mem_props->externalMemoryFeatures & VK_EXTERNAL_MEMORY_FEATURE_IMPORTABLE_BIT)) return vn_error(physical_dev->instance, VK_ERROR_FORMAT_NOT_SUPPORTED); mem_props->externalMemoryFeatures = VK_EXTERNAL_MEMORY_FEATURE_DEDICATED_ONLY_BIT | VK_EXTERNAL_MEMORY_FEATURE_EXPORTABLE_BIT | VK_EXTERNAL_MEMORY_FEATURE_IMPORTABLE_BIT; mem_props->exportFromImportedHandleTypes = VK_EXTERNAL_MEMORY_HANDLE_TYPE_ANDROID_HARDWARE_BUFFER_BIT_ANDROID; mem_props->compatibleHandleTypes = VK_EXTERNAL_MEMORY_HANDLE_TYPE_ANDROID_HARDWARE_BUFFER_BIT_ANDROID; } else { mem_props->compatibleHandleTypes = supported_handle_types; mem_props->exportFromImportedHandleTypes = (mem_props->exportFromImportedHandleTypes & renderer_handle_type) ? supported_handle_types : 0; } return VK_SUCCESS; } void vn_GetPhysicalDeviceSparseImageFormatProperties2( VkPhysicalDevice physicalDevice, const VkPhysicalDeviceSparseImageFormatInfo2 *pFormatInfo, uint32_t *pPropertyCount, VkSparseImageFormatProperties2 *pProperties) { struct vn_physical_device *physical_dev = vn_physical_device_from_handle(physicalDevice); /* TODO allow sparse resource along with sync feedback * * If VK_IMAGE_CREATE_SPARSE_RESIDENCY_BIT is not supported for the given * arguments, pPropertyCount will be set to zero upon return, and no data * will be written to pProperties. */ if (!VN_PERF(NO_FENCE_FEEDBACK)) { *pPropertyCount = 0; return; } /* TODO per-device cache */ vn_call_vkGetPhysicalDeviceSparseImageFormatProperties2( physical_dev->instance, physicalDevice, pFormatInfo, pPropertyCount, pProperties); } void vn_GetPhysicalDeviceExternalBufferProperties( VkPhysicalDevice physicalDevice, const VkPhysicalDeviceExternalBufferInfo *pExternalBufferInfo, VkExternalBufferProperties *pExternalBufferProperties) { struct vn_physical_device *physical_dev = vn_physical_device_from_handle(physicalDevice); const VkExternalMemoryHandleTypeFlagBits renderer_handle_type = physical_dev->external_memory.renderer_handle_type; const VkExternalMemoryHandleTypeFlags supported_handle_types = physical_dev->external_memory.supported_handle_types; const bool is_ahb = pExternalBufferInfo->handleType == VK_EXTERNAL_MEMORY_HANDLE_TYPE_ANDROID_HARDWARE_BUFFER_BIT_ANDROID; VkExternalMemoryProperties *props = &pExternalBufferProperties->externalMemoryProperties; if (!(pExternalBufferInfo->handleType & supported_handle_types)) { props->compatibleHandleTypes = pExternalBufferInfo->handleType; props->exportFromImportedHandleTypes = 0; props->externalMemoryFeatures = 0; return; } VkPhysicalDeviceExternalBufferInfo local_info; if (pExternalBufferInfo->handleType != renderer_handle_type) { local_info = *pExternalBufferInfo; local_info.handleType = renderer_handle_type; pExternalBufferInfo = &local_info; } /* TODO per-device cache */ vn_call_vkGetPhysicalDeviceExternalBufferProperties( physical_dev->instance, physicalDevice, pExternalBufferInfo, pExternalBufferProperties); if (is_ahb) { props->compatibleHandleTypes = VK_EXTERNAL_MEMORY_HANDLE_TYPE_ANDROID_HARDWARE_BUFFER_BIT_ANDROID; /* AHB backed buffer requires renderer to support import bit while it * also requires the renderer to must not advertise dedicated only bit */ if (!(props->externalMemoryFeatures & VK_EXTERNAL_MEMORY_FEATURE_IMPORTABLE_BIT) || (props->externalMemoryFeatures & VK_EXTERNAL_MEMORY_FEATURE_DEDICATED_ONLY_BIT)) { props->externalMemoryFeatures = 0; props->exportFromImportedHandleTypes = 0; return; } props->externalMemoryFeatures = VK_EXTERNAL_MEMORY_FEATURE_EXPORTABLE_BIT | VK_EXTERNAL_MEMORY_FEATURE_IMPORTABLE_BIT; props->exportFromImportedHandleTypes = VK_EXTERNAL_MEMORY_HANDLE_TYPE_ANDROID_HARDWARE_BUFFER_BIT_ANDROID; } else { props->compatibleHandleTypes = supported_handle_types; props->exportFromImportedHandleTypes = (props->exportFromImportedHandleTypes & renderer_handle_type) ? supported_handle_types : 0; } } void vn_GetPhysicalDeviceExternalFenceProperties( VkPhysicalDevice physicalDevice, const VkPhysicalDeviceExternalFenceInfo *pExternalFenceInfo, VkExternalFenceProperties *pExternalFenceProperties) { struct vn_physical_device *physical_dev = vn_physical_device_from_handle(physicalDevice); if (pExternalFenceInfo->handleType & physical_dev->external_fence_handles) { pExternalFenceProperties->compatibleHandleTypes = physical_dev->external_fence_handles; pExternalFenceProperties->exportFromImportedHandleTypes = physical_dev->external_fence_handles; pExternalFenceProperties->externalFenceFeatures = VK_EXTERNAL_FENCE_FEATURE_EXPORTABLE_BIT | VK_EXTERNAL_FENCE_FEATURE_IMPORTABLE_BIT; } else { pExternalFenceProperties->compatibleHandleTypes = 0; pExternalFenceProperties->exportFromImportedHandleTypes = 0; pExternalFenceProperties->externalFenceFeatures = 0; } } void vn_GetPhysicalDeviceExternalSemaphoreProperties( VkPhysicalDevice physicalDevice, const VkPhysicalDeviceExternalSemaphoreInfo *pExternalSemaphoreInfo, VkExternalSemaphoreProperties *pExternalSemaphoreProperties) { struct vn_physical_device *physical_dev = vn_physical_device_from_handle(physicalDevice); const VkSemaphoreTypeCreateInfo *type_info = vk_find_struct_const( pExternalSemaphoreInfo->pNext, SEMAPHORE_TYPE_CREATE_INFO); const VkSemaphoreType sem_type = type_info ? type_info->semaphoreType : VK_SEMAPHORE_TYPE_BINARY; const VkExternalSemaphoreHandleTypeFlags valid_handles = sem_type == VK_SEMAPHORE_TYPE_BINARY ? physical_dev->external_binary_semaphore_handles : physical_dev->external_timeline_semaphore_handles; if (pExternalSemaphoreInfo->handleType & valid_handles) { pExternalSemaphoreProperties->compatibleHandleTypes = valid_handles; pExternalSemaphoreProperties->exportFromImportedHandleTypes = valid_handles; pExternalSemaphoreProperties->externalSemaphoreFeatures = VK_EXTERNAL_SEMAPHORE_FEATURE_EXPORTABLE_BIT | VK_EXTERNAL_SEMAPHORE_FEATURE_IMPORTABLE_BIT; } else { pExternalSemaphoreProperties->compatibleHandleTypes = 0; pExternalSemaphoreProperties->exportFromImportedHandleTypes = 0; pExternalSemaphoreProperties->externalSemaphoreFeatures = 0; } } VkResult vn_GetPhysicalDeviceCalibrateableTimeDomainsEXT( VkPhysicalDevice physicalDevice, uint32_t *pTimeDomainCount, VkTimeDomainEXT *pTimeDomains) { struct vn_physical_device *physical_dev = vn_physical_device_from_handle(physicalDevice); return vn_call_vkGetPhysicalDeviceCalibrateableTimeDomainsEXT( physical_dev->instance, physicalDevice, pTimeDomainCount, pTimeDomains); }