diff --git a/src/virtio/vulkan/vn_device.c b/src/virtio/vulkan/vn_device.c index dcd916da984..e6a4e0dea0b 100644 --- a/src/virtio/vulkan/vn_device.c +++ b/src/virtio/vulkan/vn_device.c @@ -10,7 +10,11 @@ #include "vn_device.h" +#include + +#include "git_sha1.h" #include "util/driconf.h" +#include "util/mesa-sha1.h" #include "venus-protocol/vn_protocol_driver.h" #include "vn_icd.h" @@ -555,6 +559,1084 @@ fail: mtx_unlock(&instance->ring.mutex); } +static struct vn_physical_device * +vn_instance_find_physical_device(struct vn_instance *instance, + vn_object_id id) +{ + for (uint32_t i = 0; i < instance->physical_device_count; i++) { + if (instance->physical_devices[i].base.id == id) + return &instance->physical_devices[i]; + } + return NULL; +} + +static void +vn_physical_device_init_features(struct vn_physical_device *physical_dev) +{ + struct vn_instance *instance = physical_dev->instance; + 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; + + physical_dev->features.sType = + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2; + if (physical_dev->renderer_version >= VK_API_VERSION_1_2) { + physical_dev->features.pNext = &physical_dev->vulkan_1_1_features; + + physical_dev->vulkan_1_1_features.sType = + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_1_FEATURES; + physical_dev->vulkan_1_1_features.pNext = + &physical_dev->vulkan_1_2_features; + physical_dev->vulkan_1_2_features.sType = + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_2_FEATURES; + physical_dev->vulkan_1_2_features.pNext = NULL; + } else { + physical_dev->features.pNext = &local_feats.sixteen_bit_storage; + + local_feats.sixteen_bit_storage.sType = + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_16BIT_STORAGE_FEATURES; + local_feats.sixteen_bit_storage.pNext = &local_feats.multiview; + local_feats.multiview.sType = + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MULTIVIEW_FEATURES; + local_feats.multiview.pNext = &local_feats.variable_pointers; + local_feats.variable_pointers.sType = + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VARIABLE_POINTERS_FEATURES; + local_feats.variable_pointers.pNext = &local_feats.protected_memory; + local_feats.protected_memory.sType = + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROTECTED_MEMORY_FEATURES; + local_feats.protected_memory.pNext = + &local_feats.sampler_ycbcr_conversion; + local_feats.sampler_ycbcr_conversion.sType = + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SAMPLER_YCBCR_CONVERSION_FEATURES; + local_feats.sampler_ycbcr_conversion.pNext = + &local_feats.shader_draw_parameters; + local_feats.shader_draw_parameters.sType = + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_DRAW_PARAMETERS_FEATURES; + local_feats.shader_draw_parameters.pNext = + &local_feats.eight_bit_storage; + + local_feats.eight_bit_storage.sType = + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_8BIT_STORAGE_FEATURES; + local_feats.eight_bit_storage.pNext = &local_feats.shader_atomic_int64; + local_feats.shader_atomic_int64.sType = + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_ATOMIC_INT64_FEATURES; + local_feats.shader_atomic_int64.pNext = + &local_feats.shader_float16_int8; + local_feats.shader_float16_int8.sType = + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_FLOAT16_INT8_FEATURES; + local_feats.shader_float16_int8.pNext = + &local_feats.descriptor_indexing; + local_feats.descriptor_indexing.sType = + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DESCRIPTOR_INDEXING_FEATURES; + local_feats.descriptor_indexing.pNext = + &local_feats.scalar_block_layout; + local_feats.scalar_block_layout.sType = + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SCALAR_BLOCK_LAYOUT_FEATURES; + local_feats.scalar_block_layout.pNext = + &local_feats.imageless_framebuffer; + local_feats.imageless_framebuffer.sType = + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGELESS_FRAMEBUFFER_FEATURES; + local_feats.imageless_framebuffer.pNext = + &local_feats.uniform_buffer_standard_layout; + local_feats.uniform_buffer_standard_layout.sType = + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_UNIFORM_BUFFER_STANDARD_LAYOUT_FEATURES; + local_feats.uniform_buffer_standard_layout.pNext = + &local_feats.shader_subgroup_extended_types; + local_feats.shader_subgroup_extended_types.sType = + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_SUBGROUP_EXTENDED_TYPES_FEATURES; + local_feats.shader_subgroup_extended_types.pNext = + &local_feats.separate_depth_stencil_layouts; + local_feats.separate_depth_stencil_layouts.sType = + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SEPARATE_DEPTH_STENCIL_LAYOUTS_FEATURES; + local_feats.separate_depth_stencil_layouts.pNext = + &local_feats.host_query_reset; + local_feats.host_query_reset.sType = + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_HOST_QUERY_RESET_FEATURES; + local_feats.host_query_reset.pNext = &local_feats.timeline_semaphore; + local_feats.timeline_semaphore.sType = + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_TIMELINE_SEMAPHORE_FEATURES; + local_feats.timeline_semaphore.pNext = + &local_feats.buffer_device_address; + local_feats.buffer_device_address.sType = + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_BUFFER_DEVICE_ADDRESS_FEATURES; + local_feats.buffer_device_address.pNext = + &local_feats.vulkan_memory_model; + local_feats.vulkan_memory_model.sType = + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_MEMORY_MODEL_FEATURES; + local_feats.vulkan_memory_model.pNext = NULL; + } + + vn_call_vkGetPhysicalDeviceFeatures2( + instance, vn_physical_device_to_handle(physical_dev), + &physical_dev->features); + + const struct vk_device_extension_table *exts = + &physical_dev->renderer_extensions; + struct VkPhysicalDeviceVulkan11Features *vk11_feats = + &physical_dev->vulkan_1_1_features; + struct VkPhysicalDeviceVulkan12Features *vk12_feats = + &physical_dev->vulkan_1_2_features; + + 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 VkPhysicalDeviceProperties *props = + &physical_dev->properties.properties; + struct VkPhysicalDeviceVulkan11Properties *vk11_props = + &physical_dev->vulkan_1_1_properties; + struct VkPhysicalDeviceVulkan12Properties *vk12_props = + &physical_dev->vulkan_1_2_properties; + struct mesa_sha1 sha1_ctx; + uint8_t sha1[SHA1_DIGEST_LENGTH]; + + static_assert(VK_UUID_SIZE <= SHA1_DIGEST_LENGTH, ""); + + /* keep props->pipelineCacheUUID? */ + + _mesa_sha1_init(&sha1_ctx); + _mesa_sha1_update(&sha1_ctx, &props->vendorID, sizeof(props->vendorID)); + _mesa_sha1_update(&sha1_ctx, &props->deviceID, sizeof(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_instance *instance = physical_dev->instance; + 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; + + physical_dev->properties.sType = + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2; + if (physical_dev->renderer_version >= VK_API_VERSION_1_2) { + physical_dev->properties.pNext = &physical_dev->vulkan_1_1_properties; + + physical_dev->vulkan_1_1_properties.sType = + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_1_PROPERTIES; + physical_dev->vulkan_1_1_properties.pNext = + &physical_dev->vulkan_1_2_properties; + physical_dev->vulkan_1_2_properties.sType = + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_2_PROPERTIES; + physical_dev->vulkan_1_2_properties.pNext = NULL; + } else { + physical_dev->properties.pNext = &local_props.id; + + local_props.id.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ID_PROPERTIES; + local_props.id.pNext = &local_props.subgroup; + local_props.subgroup.sType = + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SUBGROUP_PROPERTIES; + local_props.subgroup.pNext = &local_props.point_clipping; + local_props.point_clipping.sType = + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_POINT_CLIPPING_PROPERTIES; + local_props.point_clipping.pNext = &local_props.multiview; + local_props.multiview.sType = + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MULTIVIEW_PROPERTIES; + local_props.multiview.pNext = &local_props.protected_memory; + local_props.protected_memory.sType = + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROTECTED_MEMORY_PROPERTIES; + local_props.protected_memory.pNext = &local_props.maintenance_3; + local_props.maintenance_3.sType = + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MAINTENANCE_3_PROPERTIES; + local_props.maintenance_3.pNext = &local_props.driver; + + local_props.driver.sType = + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DRIVER_PROPERTIES; + local_props.driver.pNext = &local_props.float_controls; + local_props.float_controls.sType = + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FLOAT_CONTROLS_PROPERTIES; + local_props.float_controls.pNext = &local_props.descriptor_indexing; + local_props.descriptor_indexing.sType = + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DESCRIPTOR_INDEXING_PROPERTIES; + local_props.descriptor_indexing.pNext = + &local_props.depth_stencil_resolve; + local_props.depth_stencil_resolve.sType = + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DEPTH_STENCIL_RESOLVE_PROPERTIES; + local_props.depth_stencil_resolve.pNext = + &local_props.sampler_filter_minmax; + local_props.sampler_filter_minmax.sType = + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SAMPLER_FILTER_MINMAX_PROPERTIES; + local_props.sampler_filter_minmax.pNext = + &local_props.timeline_semaphore; + local_props.timeline_semaphore.sType = + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_TIMELINE_SEMAPHORE_PROPERTIES; + local_props.timeline_semaphore.pNext = NULL; + } + + vn_call_vkGetPhysicalDeviceProperties2( + instance, vn_physical_device_to_handle(physical_dev), + &physical_dev->properties); + + const struct vk_device_extension_table *exts = + &physical_dev->renderer_extensions; + struct VkPhysicalDeviceProperties *props = + &physical_dev->properties.properties; + struct VkPhysicalDeviceVulkan11Properties *vk11_props = + &physical_dev->vulkan_1_1_properties; + struct VkPhysicalDeviceVulkan12Properties *vk12_props = + &physical_dev->vulkan_1_2_properties; + + 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) { + props->apiVersion = version_override; + } else { + if (props->apiVersion > VK_HEADER_VERSION_COMPLETE) + props->apiVersion = VK_HEADER_VERSION_COMPLETE; + if (props->apiVersion > vn_info_vk_xml_version()) + props->apiVersion = vn_info_vk_xml_version(); + if (!instance->renderer_info.has_timeline_sync && + props->apiVersion >= VK_API_VERSION_1_2) + props->apiVersion = VK_MAKE_VERSION(1, 1, 130); + } + + props->driverVersion = vk_get_driver_version(); + props->vendorID = instance->renderer_info.pci.vendor_id; + props->deviceID = instance->renderer_info.pci.device_id; + /* some apps don't like VK_PHYSICAL_DEVICE_TYPE_VIRTUAL_GPU */ + props->deviceType = VK_PHYSICAL_DEVICE_TYPE_INTEGRATED_GPU; + snprintf(props->deviceName, sizeof(props->deviceName), "Virtio GPU"); + + vk12_props->driverID = 0; + 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 = (VkConformanceVersionKHR){ + .major = 0, + .minor = 0, + .subminor = 0, + .patch = 0, + }; + + 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); + + uint32_t *sync_queue_bases; + VkQueueFamilyProperties2 *props = + vk_alloc(alloc, (sizeof(*props) + sizeof(*sync_queue_bases)) * count, + VN_DEFAULT_ALIGN, VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE); + if (!props) + return VK_ERROR_OUT_OF_HOST_MEMORY; + sync_queue_bases = (uint32_t *)&props[count]; + + for (uint32_t i = 0; i < count; i++) { + props[i].sType = VK_STRUCTURE_TYPE_QUEUE_FAMILY_PROPERTIES_2; + /* define an extension to query sync queue base? */ + props[i].pNext = NULL; + } + vn_call_vkGetPhysicalDeviceQueueFamilyProperties2( + instance, vn_physical_device_to_handle(physical_dev), &count, props); + + physical_dev->queue_family_properties = props; + /* sync_queue_bases will be initialized later */ + physical_dev->queue_family_sync_queue_bases = sync_queue_bases; + 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_handles( + struct vn_physical_device *physical_dev) +{ + if (!physical_dev->instance->renderer_info.has_dmabuf_import) + return; + + /* We have export support but we don't advertise it. It is for WSI only at + * the moment. For import support, we need to be able to serialize + * vkGetMemoryFdPropertiesKHR and VkImportMemoryFdInfoKHR. We can + * serialize fd to bo->res_id, but we probably want to add new + * commands/structs first (using VK_MESA_venus_protocol). + * + * We also create a BO when a vn_device_memory is mappable. We don't know + * which handle type the renderer uses. That seems fine though. + */ +} + +static void +vn_physical_device_init_external_fence_handles( + struct vn_physical_device *physical_dev) +{ + if (!physical_dev->instance->renderer_info.has_external_sync) + return; + + /* In the current model, a vn_fence can be implemented entirely on top of + * vn_renderer_sync. All operations can go through the renderer sync. + * + * The current code still creates a host-side VkFence, which can be + * eliminated. The renderer also lacks proper external sync (i.e., + * drm_syncobj) support and we can only support handle types with copy + * transference (i.e., sync fds). + * + * We are considering creating a vn_renderer_sync from a host-side VkFence + * instead, similar to how a vn_renderer_bo is created from a host-side + * VkDeviceMemory. That will require tons of works on the host side, but + * should allow us to get rid of ring<->renderer syncs in vkQueueSubmit. + */ + physical_dev->external_fence_handles = + VK_EXTERNAL_FENCE_HANDLE_TYPE_SYNC_FD_BIT; +} + +static void +vn_physical_device_init_external_semaphore_handles( + struct vn_physical_device *physical_dev) +{ + /* In the current model, it is not possible to support external semaphores. + * At least an external semaphore cannot be waited on GPU in the host but + * can only be waited on CPU in the guest. + * + * A binary vn_semaphore is implemented solely on top of a host-side binary + * VkSemaphore. There is no CPU operation against binary semaphroes and + * there is no need for vn_renderer_sync. + * + * A timeline vn_semaphore is implemented on top of both a host-side + * timeline VkSemaphore and a vn_renderer_sync. Whenever a timeline + * vn_semaphore is updated, we make sure both the host-side timeline + * VkSemaphore and the vn_renderer_sync are updated. This allows us to use + * whichever is more convenient depending on the operations: the host-side + * timeline VkSemaphore for GPU waits and the vn_renderer_sync for CPU + * waits/gets. + * + * To support external semaphores, we should create a vn_renderer_sync from + * a host-side VkSemaphore instead, similar to how a vn_renderer_bo is + * created from a host-side VkDeviceMemory. The reasons to make a similar + * move for fences apply to timeline semaphores as well. Besides, the + * external handle (drm_syncobj or sync file) needs to carry the necessary + * information to identify the host-side semaphore. + */ +} + +static void +vn_physical_device_get_supported_extensions( + const struct vn_physical_device *device, + struct vk_device_extension_table *supported, + struct vk_device_extension_table *recognized) +{ + memset(supported, 0, sizeof(*supported)); + memset(recognized, 0, sizeof(*recognized)); +} + +static VkResult +vn_physical_device_init_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; + } + } + + struct vk_device_extension_table supported; + struct vk_device_extension_table recognized; + vn_physical_device_get_supported_extensions(physical_dev, &supported, + &recognized); + if (!instance->renderer_info.has_timeline_sync) + recognized.KHR_timeline_semaphore = false; + + 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]; + const VkExtensionProperties *renderer_props = NULL; + + for (uint32_t j = 0; j < count; j++) { + if (!strcmp(props->extensionName, exts[j].extensionName)) { + physical_dev->renderer_extensions.extensions[i] = true; + renderer_props = &exts[j]; + break; + } + } + + /* does not depend on renderer (e.g., WSI) */ + if (supported.extensions[i]) { + physical_dev->base.base.supported_extensions.extensions[i] = true; + physical_dev->extension_spec_versions[i] = props->specVersion; + continue; + } + + /* no driver support */ + if (!recognized.extensions[i]) + continue; + + /* check renderer support */ + if (!renderer_props) + continue; + + /* check encoder support */ + const uint32_t spec_version = + vn_info_extension_spec_version(props->extensionName); + if (!spec_version) + continue; + + physical_dev->base.base.supported_extensions.extensions[i] = true; + physical_dev->extension_spec_versions[i] = + MIN2(renderer_props->specVersion, spec_version); + } + + vk_free(alloc, exts); + + return VK_SUCCESS; +} + +static VkResult +vn_physical_device_init_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, "unsupported renderer device version %d.%d", + VK_VERSION_MAJOR(props.apiVersion), + VK_VERSION_MINOR(props.apiVersion)); + } + return VK_ERROR_INITIALIZATION_FAILED; + } + + physical_dev->renderer_version = props.apiVersion; + if (physical_dev->renderer_version > instance->renderer_version) + physical_dev->renderer_version = instance->renderer_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 = vn_physical_device_init_version(physical_dev); + if (result != VK_SUCCESS) + return result; + + result = vn_physical_device_init_extensions(physical_dev); + if (result != VK_SUCCESS) + return result; + + /* 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_handles(physical_dev); + vn_physical_device_init_external_fence_handles(physical_dev); + vn_physical_device_init_external_semaphore_handles(physical_dev); + + return VK_SUCCESS; + +fail: + vk_free(alloc, physical_dev->extension_spec_versions); + vk_free(alloc, physical_dev->queue_family_properties); + return result; +} + +static 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; + + 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 VkResult +vn_instance_enumerate_physical_devices(struct vn_instance *instance) +{ + const VkAllocationCallbacks *alloc = &instance->base.base.alloc; + struct vn_physical_device *physical_devs = NULL; + VkResult result; + + mtx_lock(&instance->physical_device_mutex); + + if (instance->physical_devices) { + result = VK_SUCCESS; + goto out; + } + + uint32_t count; + result = vn_call_vkEnumeratePhysicalDevices( + instance, vn_instance_to_handle(instance), &count, NULL); + if (result != VK_SUCCESS || !count) + goto out; + + physical_devs = + vk_zalloc(alloc, sizeof(*physical_devs) * count, VN_DEFAULT_ALIGN, + VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE); + if (!physical_devs) { + result = VK_ERROR_OUT_OF_HOST_MEMORY; + goto out; + } + + VkPhysicalDevice *handles = + vk_alloc(alloc, sizeof(*handles) * count, VN_DEFAULT_ALIGN, + VK_SYSTEM_ALLOCATION_SCOPE_COMMAND); + if (!handles) { + result = VK_ERROR_OUT_OF_HOST_MEMORY; + goto out; + } + + 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); + result = vn_physical_device_base_init( + &physical_dev->base, &instance->base, NULL, &dispatch_table); + if (result != VK_SUCCESS) { + count = i; + goto out; + } + + 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); + vk_free(alloc, handles); + + if (result != VK_SUCCESS) + goto out; + + uint32_t sync_queue_base = 0; + uint32_t i = 0; + while (i < count) { + struct vn_physical_device *physical_dev = &physical_devs[i]; + + result = vn_physical_device_init(physical_dev); + if (result == VK_SUCCESS) { + /* TODO assign sync queues more fairly */ + for (uint32_t j = 0; j < physical_dev->queue_family_count; j++) { + const VkQueueFamilyProperties *props = + &physical_dev->queue_family_properties[j].queueFamilyProperties; + + if (sync_queue_base + props->queueCount > + instance->renderer_info.max_sync_queue_count) { + if (VN_DEBUG(INIT)) { + vn_log(instance, "not enough sync queues (max %d)", + instance->renderer_info.max_sync_queue_count); + } + result = VK_ERROR_INITIALIZATION_FAILED; + break; + } + + physical_dev->queue_family_sync_queue_bases[j] = sync_queue_base; + sync_queue_base += props->queueCount; + } + } + + if (result != VK_SUCCESS) { + vn_physical_device_base_fini(&physical_devs[i].base); + memmove(&physical_devs[i], &physical_devs[i + 1], + sizeof(*physical_devs) * (count - i - 1)); + count--; + continue; + } + + i++; + } + + if (count) { + instance->physical_devices = physical_devs; + instance->physical_device_count = count; + result = VK_SUCCESS; + } + +out: + if (result != VK_SUCCESS && physical_devs) { + for (uint32_t i = 0; i < count; i++) + vn_physical_device_base_fini(&physical_devs[i].base); + vk_free(alloc, physical_devs); + } + + mtx_unlock(&instance->physical_device_mutex); + return result; +} + /* instance commands */ VkResult @@ -612,6 +1694,8 @@ vn_CreateInstance(const VkInstanceCreateInfo *pCreateInfo, return vn_error(NULL, result); } + mtx_init(&instance->physical_device_mutex, mtx_plain); + if (!vn_icd_supports_api_version( instance->base.base.app_info.api_version)) { result = VK_ERROR_INCOMPATIBLE_DRIVER; @@ -697,6 +1781,8 @@ fail: vn_renderer_destroy(instance->renderer, alloc); } + mtx_destroy(&instance->physical_device_mutex); + vn_instance_base_fini(&instance->base); vk_free(alloc, instance); @@ -714,6 +1800,12 @@ vn_DestroyInstance(VkInstance _instance, if (!instance) return; + if (instance->physical_devices) { + for (uint32_t i = 0; i < instance->physical_device_count; i++) + vn_physical_device_fini(&instance->physical_devices[i]); + vk_free(alloc, instance->physical_devices); + } + vn_call_vkDestroyInstance(instance, _instance, NULL); vn_renderer_bo_unref(instance->reply.bo); @@ -733,6 +1825,8 @@ vn_DestroyInstance(VkInstance _instance, mtx_destroy(&instance->roundtrip_mutex); vn_renderer_destroy(instance->renderer, alloc); + mtx_destroy(&instance->physical_device_mutex); + driDestroyOptionCache(&instance->dri_options); driDestroyOptionInfo(&instance->available_dri_options); @@ -757,19 +1851,109 @@ vn_EnumeratePhysicalDevices(VkInstance _instance, { struct vn_instance *instance = vn_instance_from_handle(_instance); - return vn_error(instance, VK_ERROR_INCOMPATIBLE_DRIVER); + VkResult result = vn_instance_enumerate_physical_devices(instance); + if (result != VK_SUCCESS) + return vn_error(instance, result); + + VK_OUTARRAY_MAKE(out, pPhysicalDevices, pPhysicalDeviceCount); + for (uint32_t i = 0; i < instance->physical_device_count; i++) { + vk_outarray_append (&out, physical_dev) { + *physical_dev = + vn_physical_device_to_handle(&instance->physical_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); + const VkAllocationCallbacks *alloc = &instance->base.base.alloc; + struct vn_physical_device_base *dummy = NULL; + VkResult result; + + result = vn_instance_enumerate_physical_devices(instance); + if (result != VK_SUCCESS) + return vn_error(instance, result); + + /* make sure VkPhysicalDevice point to objects, as they are considered + * inputs by the encoder + */ + if (pPhysicalDeviceGroupProperties) { + const uint32_t count = *pPhysicalDeviceGroupCount; + const size_t size = sizeof(*dummy) * VK_MAX_DEVICE_GROUP_SIZE * count; + + dummy = vk_zalloc(alloc, size, VN_DEFAULT_ALIGN, + VK_SYSTEM_ALLOCATION_SCOPE_COMMAND); + if (!dummy) + return vn_error(instance, VK_ERROR_OUT_OF_HOST_MEMORY); + + for (uint32_t i = 0; i < count; i++) { + VkPhysicalDeviceGroupProperties *props = + &pPhysicalDeviceGroupProperties[i]; + + for (uint32_t j = 0; j < VK_MAX_DEVICE_GROUP_SIZE; j++) { + struct vn_physical_device_base *obj = + &dummy[VK_MAX_DEVICE_GROUP_SIZE * i + j]; + obj->base.base.type = VK_OBJECT_TYPE_PHYSICAL_DEVICE; + props->physicalDevices[j] = (VkPhysicalDevice)obj; + } + } + } + + result = vn_call_vkEnumeratePhysicalDeviceGroups( + instance, vn_instance_to_handle(instance), pPhysicalDeviceGroupCount, + pPhysicalDeviceGroupProperties); + if (result != VK_SUCCESS) { + if (dummy) + vk_free(alloc, dummy); + return vn_error(instance, result); + } + + if (pPhysicalDeviceGroupProperties) { + for (uint32_t i = 0; i < *pPhysicalDeviceGroupCount; i++) { + VkPhysicalDeviceGroupProperties *props = + &pPhysicalDeviceGroupProperties[i]; + for (uint32_t j = 0; j < props->physicalDeviceCount; j++) { + const vn_object_id id = + dummy[VK_MAX_DEVICE_GROUP_SIZE * i + j].id; + struct vn_physical_device *physical_dev = + vn_instance_find_physical_device(instance, id); + props->physicalDevices[j] = + vn_physical_device_to_handle(physical_dev); + } + } + } + + if (dummy) + vk_free(alloc, dummy); + + return VK_SUCCESS; } void vn_GetPhysicalDeviceFeatures(VkPhysicalDevice physicalDevice, VkPhysicalDeviceFeatures *pFeatures) { + struct vn_physical_device *physical_dev = + vn_physical_device_from_handle(physicalDevice); + + *pFeatures = physical_dev->features.features; } void vn_GetPhysicalDeviceProperties(VkPhysicalDevice physicalDevice, VkPhysicalDeviceProperties *pProperties) { + struct vn_physical_device *physical_dev = + vn_physical_device_from_handle(physicalDevice); + + *pProperties = physical_dev->properties.properties; } void @@ -778,6 +1962,16 @@ vn_GetPhysicalDeviceQueueFamilyProperties( uint32_t *pQueueFamilyPropertyCount, VkQueueFamilyProperties *pQueueFamilyProperties) { + struct vn_physical_device *physical_dev = + vn_physical_device_from_handle(physicalDevice); + + VK_OUTARRAY_MAKE(out, pQueueFamilyProperties, pQueueFamilyPropertyCount); + for (uint32_t i = 0; i < physical_dev->queue_family_count; i++) { + vk_outarray_append (&out, props) { + *props = + physical_dev->queue_family_properties[i].queueFamilyProperties; + } + } } void @@ -785,6 +1979,10 @@ vn_GetPhysicalDeviceMemoryProperties( VkPhysicalDevice physicalDevice, VkPhysicalDeviceMemoryProperties *pMemoryProperties) { + struct vn_physical_device *physical_dev = + vn_physical_device_from_handle(physicalDevice); + + *pMemoryProperties = physical_dev->memory_properties.memoryProperties; } void @@ -792,6 +1990,12 @@ vn_GetPhysicalDeviceFormatProperties(VkPhysicalDevice physicalDevice, VkFormat format, VkFormatProperties *pFormatProperties) { + struct vn_physical_device *physical_dev = + vn_physical_device_from_handle(physicalDevice); + + /* TODO query all formats during init */ + vn_call_vkGetPhysicalDeviceFormatProperties( + physical_dev->instance, physicalDevice, format, pFormatProperties); } VkResult @@ -804,7 +2008,15 @@ vn_GetPhysicalDeviceImageFormatProperties( VkImageCreateFlags flags, VkImageFormatProperties *pImageFormatProperties) { - return vn_error(NULL, VK_ERROR_OUT_OF_HOST_MEMORY); + struct vn_physical_device *physical_dev = + vn_physical_device_from_handle(physicalDevice); + + /* TODO per-device cache */ + VkResult result = vn_call_vkGetPhysicalDeviceImageFormatProperties( + physical_dev->instance, physicalDevice, format, type, tiling, usage, + flags, pImageFormatProperties); + + return vn_result(physical_dev->instance, result); } void @@ -818,6 +2030,631 @@ vn_GetPhysicalDeviceSparseImageFormatProperties( uint32_t *pPropertyCount, VkSparseImageFormatProperties *pProperties) { + struct vn_physical_device *physical_dev = + vn_physical_device_from_handle(physicalDevice); + + /* TODO per-device cache */ + vn_call_vkGetPhysicalDeviceSparseImageFormatProperties( + physical_dev->instance, physicalDevice, format, type, samples, usage, + tiling, pPropertyCount, pProperties); +} + +void +vn_GetPhysicalDeviceFeatures2(VkPhysicalDevice physicalDevice, + VkPhysicalDeviceFeatures2 *pFeatures) +{ + struct vn_physical_device *physical_dev = + vn_physical_device_from_handle(physicalDevice); + const struct VkPhysicalDeviceVulkan11Features *vk11_feats = + &physical_dev->vulkan_1_1_features; + const struct VkPhysicalDeviceVulkan12Features *vk12_feats = + &physical_dev->vulkan_1_2_features; + union { + VkBaseOutStructure *pnext; + + /* 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; + } 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: + memcpy(u.pnext, &physical_dev->features, + sizeof(physical_dev->features)); + break; + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_1_FEATURES: + memcpy(u.pnext, vk11_feats, sizeof(*vk11_feats)); + break; + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_2_FEATURES: + memcpy(u.pnext, vk12_feats, sizeof(*vk12_feats)); + break; + 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; + 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; + 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 VkPhysicalDeviceVulkan11Properties *vk11_props = + &physical_dev->vulkan_1_1_properties; + const struct VkPhysicalDeviceVulkan12Properties *vk12_props = + &physical_dev->vulkan_1_2_properties; + union { + VkBaseOutStructure *pnext; + + /* 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; + + VkPhysicalDevicePCIBusInfoPropertiesEXT *pci_bus_info; + } u; + + u.pnext = (VkBaseOutStructure *)pProperties; + while (u.pnext) { + void *saved = u.pnext->pNext; + switch (u.pnext->sType) { + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2: + memcpy(u.pnext, &physical_dev->properties, + sizeof(physical_dev->properties)); + break; + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_1_PROPERTIES: + memcpy(u.pnext, vk11_props, sizeof(*vk11_props)); + break; + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_2_PROPERTIES: + memcpy(u.pnext, vk12_props, sizeof(*vk12_props)); + break; + 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; + 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; + 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; + 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(out, pQueueFamilyProperties, pQueueFamilyPropertyCount); + for (uint32_t i = 0; i < physical_dev->queue_family_count; i++) { + vk_outarray_append (&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); + + /* TODO query all formats during init */ + vn_call_vkGetPhysicalDeviceFormatProperties2( + physical_dev->instance, physicalDevice, format, pFormatProperties); +} + +VkResult +vn_GetPhysicalDeviceImageFormatProperties2( + VkPhysicalDevice physicalDevice, + const VkPhysicalDeviceImageFormatInfo2 *pImageFormatInfo, + VkImageFormatProperties2 *pImageFormatProperties) +{ + struct vn_physical_device *physical_dev = + vn_physical_device_from_handle(physicalDevice); + + 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; + + if (external_info && + !(external_info->handleType & physical_dev->external_memory_handles)) + 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) { + VkExternalImageFormatProperties *img_props = vk_find_struct( + pImageFormatProperties->pNext, EXTERNAL_IMAGE_FORMAT_PROPERTIES); + VkExternalMemoryProperties *mem_props = + &img_props->externalMemoryProperties; + + mem_props->compatibleHandleTypes &= + physical_dev->external_memory_handles; + mem_props->exportFromImportedHandleTypes &= + physical_dev->external_memory_handles; + } + + return vn_result(physical_dev->instance, result); +} + +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 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); + VkExternalMemoryProperties *props = + &pExternalBufferProperties->externalMemoryProperties; + + if (!(pExternalBufferInfo->handleType & + physical_dev->external_memory_handles)) { + props->compatibleHandleTypes = pExternalBufferInfo->handleType; + props->exportFromImportedHandleTypes = 0; + props->externalMemoryFeatures = 0; + return; + } + + /* TODO per-device cache */ + vn_call_vkGetPhysicalDeviceExternalBufferProperties( + physical_dev->instance, physicalDevice, pExternalBufferInfo, + pExternalBufferProperties); + + props->compatibleHandleTypes &= physical_dev->external_memory_handles; + props->exportFromImportedHandleTypes &= + physical_dev->external_memory_handles; +} + +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 = + pExternalFenceInfo->handleType; + 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 VkSemaphoreTypeCreateInfoKHR *type_info = vk_find_struct_const( + pExternalSemaphoreInfo->pNext, SEMAPHORE_TYPE_CREATE_INFO_KHR); + 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 = + pExternalSemaphoreInfo->handleType; + pExternalSemaphoreProperties->exportFromImportedHandleTypes = 0; + pExternalSemaphoreProperties->externalSemaphoreFeatures = 0; + } } /* device commands */ diff --git a/src/virtio/vulkan/vn_device.h b/src/virtio/vulkan/vn_device.h index 950d628a5d2..3a1f8fc7f59 100644 --- a/src/virtio/vulkan/vn_device.h +++ b/src/virtio/vulkan/vn_device.h @@ -47,6 +47,10 @@ struct vn_instance { size_t used; void *ptr; } reply; + + mtx_t physical_device_mutex; + struct vn_physical_device *physical_devices; + uint32_t physical_device_count; }; VK_DEFINE_HANDLE_CASTS(vn_instance, base.base.base, @@ -57,6 +61,30 @@ struct vn_physical_device { struct vn_physical_device_base base; struct vn_instance *instance; + + uint32_t renderer_version; + struct vk_device_extension_table renderer_extensions; + + uint32_t *extension_spec_versions; + + VkPhysicalDeviceFeatures2 features; + VkPhysicalDeviceVulkan11Features vulkan_1_1_features; + VkPhysicalDeviceVulkan12Features vulkan_1_2_features; + + VkPhysicalDeviceProperties2 properties; + VkPhysicalDeviceVulkan11Properties vulkan_1_1_properties; + VkPhysicalDeviceVulkan12Properties vulkan_1_2_properties; + + VkQueueFamilyProperties2 *queue_family_properties; + uint32_t *queue_family_sync_queue_bases; + uint32_t queue_family_count; + + VkPhysicalDeviceMemoryProperties2 memory_properties; + + VkExternalMemoryHandleTypeFlags external_memory_handles; + VkExternalFenceHandleTypeFlags external_fence_handles; + VkExternalSemaphoreHandleTypeFlags external_binary_semaphore_handles; + VkExternalSemaphoreHandleTypeFlags external_timeline_semaphore_handles; }; VK_DEFINE_HANDLE_CASTS(vn_physical_device, base.base.base,