diff --git a/src/gallium/drivers/zink/zink_device_info.py b/src/gallium/drivers/zink/zink_device_info.py index 2af16c590e2..0af02cc08e9 100644 --- a/src/gallium/drivers/zink/zink_device_info.py +++ b/src/gallium/drivers/zink/zink_device_info.py @@ -585,7 +585,7 @@ zink_get_physical_device_info(struct zink_screen *screen) %endif %endfor - if (screen->vk_version < VK_MAKE_VERSION(1,2,0) && screen->instance_info.have_KHR_external_memory_capabilities) { + if (screen->vk_version < VK_MAKE_VERSION(1,2,0) && screen->instance_info->have_KHR_external_memory_capabilities) { info->deviceid_props.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ID_PROPERTIES; info->deviceid_props.pNext = props.pNext; props.pNext = &info->deviceid_props; diff --git a/src/gallium/drivers/zink/zink_instance.py b/src/gallium/drivers/zink/zink_instance.py index a3847af2647..00cdc8eeb67 100644 --- a/src/gallium/drivers/zink/zink_instance.py +++ b/src/gallium/drivers/zink/zink_instance.py @@ -97,8 +97,8 @@ struct zink_instance_info { %endfor }; -bool -zink_create_instance(struct zink_screen *screen); +VkInstance +zink_create_instance(struct zink_screen *screen, struct zink_instance_info *instance_info); void zink_verify_instance_extensions(struct zink_screen *screen); @@ -128,11 +128,9 @@ impl_code = """ #include "zink_instance.h" #include "zink_screen.h" -bool -zink_create_instance(struct zink_screen *screen) +VkInstance +zink_create_instance(struct zink_screen *screen, struct zink_instance_info *instance_info) { - struct zink_instance_info *instance_info = &screen->instance_info; - /* reserve one slot for MoltenVK */ const char *layers[${len(layers) + 1}] = {0}; uint32_t num_layers = 0; @@ -266,14 +264,14 @@ zink_create_instance(struct zink_screen *screen) GET_PROC_ADDR_INSTANCE_LOCAL(screen, NULL, CreateInstance); assert(vk_CreateInstance); - VkResult err = vk_CreateInstance(&ici, NULL, &screen->instance); + VkInstance instance; + VkResult err = vk_CreateInstance(&ici, NULL, &instance); if (err != VK_SUCCESS) { if (!screen->driver_name_is_inferred) mesa_loge("ZINK: vkCreateInstance failed (%s)", vk_Result_to_str(err)); - return false; } - return true; + return instance; } void @@ -284,7 +282,7 @@ zink_verify_instance_extensions(struct zink_screen *screen) %if ext.platform_guard: #ifdef ${ext.platform_guard} %endif - if (screen->instance_info.have_${ext.name_with_vendor()}) { + if (screen->instance_info->have_${ext.name_with_vendor()}) { %for cmd in registry.get_registry_entry(ext.name).instance_commands: if (!screen->vk.${cmd.lstrip("vk")}) { #ifndef NDEBUG diff --git a/src/gallium/drivers/zink/zink_resource.c b/src/gallium/drivers/zink/zink_resource.c index 5f2b3342983..0e29737d0ff 100644 --- a/src/gallium/drivers/zink/zink_resource.c +++ b/src/gallium/drivers/zink/zink_resource.c @@ -2440,7 +2440,7 @@ overwrite: // This is a known limitation of MoltenVK. // See https://github.com/KhronosGroup/MoltenVK/blob/master/Docs/MoltenVK_Runtime_UserGuide.md#known-moltenvk-limitations - || screen->instance_info.have_MVK_moltenvk + || screen->instance_info->have_MVK_moltenvk #endif ) { VkDeviceSize size = box->width; @@ -3230,7 +3230,7 @@ zink_screen_resource_init(struct pipe_screen *pscreen) if (screen->info.have_EXT_external_memory_host) { pscreen->resource_from_user_memory = zink_resource_from_user_memory; } - if (screen->instance_info.have_KHR_external_memory_capabilities) { + if (screen->instance_info->have_KHR_external_memory_capabilities) { pscreen->memobj_create_from_handle = zink_memobj_create_from_handle; pscreen->memobj_destroy = zink_memobj_destroy; pscreen->resource_from_memobj = zink_resource_from_memobj; diff --git a/src/gallium/drivers/zink/zink_screen.c b/src/gallium/drivers/zink/zink_screen.c index 94ac775d056..e4e63f7a35c 100644 --- a/src/gallium/drivers/zink/zink_screen.c +++ b/src/gallium/drivers/zink/zink_screen.c @@ -139,6 +139,21 @@ DEBUG_GET_ONCE_FLAGS_OPTION(zink_descriptor_mode, "ZINK_DESCRIPTORS", zink_descr enum zink_descriptor_mode zink_descriptor_mode; +struct zink_device { + unsigned refcount; + VkPhysicalDevice pdev; + VkDevice dev; + struct zink_device_info *info; +}; + +static simple_mtx_t device_lock = SIMPLE_MTX_INITIALIZER; +static struct set device_table; + +static simple_mtx_t instance_lock = SIMPLE_MTX_INITIALIZER; +static struct zink_instance_info instance_info; +static unsigned instance_refcount; +static VkInstance instance; + static const char * zink_get_vendor(struct pipe_screen *pscreen) { @@ -793,14 +808,14 @@ zink_init_screen_caps(struct zink_screen *screen) caps->fbfetch_coherent = screen->info.have_EXT_rasterization_order_attachment_access; caps->memobj = - screen->instance_info.have_KHR_external_memory_capabilities && + screen->instance_info->have_KHR_external_memory_capabilities && (screen->info.have_KHR_external_memory_fd || screen->info.have_KHR_external_memory_win32); caps->fence_signal = screen->info.have_KHR_external_semaphore_fd || screen->info.have_KHR_external_semaphore_win32; caps->native_fence_fd = - screen->instance_info.have_KHR_external_semaphore_capabilities && + screen->instance_info->have_KHR_external_semaphore_capabilities && screen->info.have_KHR_external_semaphore_fd; caps->resource_from_user_memory = screen->info.have_EXT_external_memory_host; @@ -1175,7 +1190,7 @@ zink_init_screen_caps(struct zink_screen *screen) caps->post_depth_coverage = screen->info.have_EXT_post_depth_coverage; - caps->string_marker = screen->instance_info.have_EXT_debug_utils; + caps->string_marker = screen->instance_info->have_EXT_debug_utils; caps->min_line_width = caps->min_line_width_aa = @@ -1550,11 +1565,31 @@ zink_destroy_screen(struct pipe_screen *pscreen) if (screen->bindless_layout) VKSCR(DestroyDescriptorSetLayout)(screen->dev, screen->bindless_layout, NULL); - if (screen->dev) - VKSCR(DestroyDevice)(screen->dev, NULL); + if (screen->dev) { + simple_mtx_lock(&device_lock); + set_foreach(&device_table, entry) { + struct zink_device *zdev = (void*)entry->key; + if (zdev->pdev == screen->pdev) { + zdev->refcount--; + if (!zdev->refcount) { + VKSCR(DestroyDevice)(zdev->dev, NULL); + _mesa_set_remove(&device_table, entry); + free(zdev); + break; + } + } + } + if (!device_table.entries) { + ralloc_free(device_table.table); + device_table.table = NULL; + } + simple_mtx_unlock(&device_lock); + } - if (screen->instance) - VKSCR(DestroyInstance)(screen->instance, NULL); + simple_mtx_lock(&instance_lock); + if (screen->instance && --instance_refcount == 0) + VKSCR(DestroyInstance)(instance, NULL); + simple_mtx_unlock(&instance_lock); util_idalloc_mt_fini(&screen->buffer_ids); @@ -1705,7 +1740,7 @@ choose_pdev(struct zink_screen *screen, int64_t dev_major, int64_t dev_minor, ui screen->info.device_version = screen->info.props.apiVersion; /* runtime version is the lesser of the instance version and device version */ - screen->vk_version = MIN2(screen->info.device_version, screen->instance_info.loader_version); + screen->vk_version = MIN2(screen->info.device_version, screen->instance_info->loader_version); /* calculate SPIR-V version based on VK version */ if (screen->vk_version >= VK_MAKE_VERSION(1, 3, 0)) @@ -2008,7 +2043,7 @@ zink_internal_setup_moltenvk(struct zink_screen *screen) // disable unless we can get MoltenVK to confirm it is supported screen->have_dynamic_state_vertex_input_binding_stride = false; - if (!screen->instance_info.have_MVK_moltenvk) + if (!screen->instance_info->have_MVK_moltenvk) return true; GET_PROC_ADDR_INSTANCE_LOCAL(screen, screen->instance, GetMoltenVKConfigurationMVK); @@ -2648,10 +2683,40 @@ hack_it_up: } static VkDevice -zink_create_logical_device(struct zink_screen *screen) +get_device(struct zink_screen *screen, VkDeviceCreateInfo *dci) { VkDevice dev = VK_NULL_HANDLE; + simple_mtx_lock(&device_lock); + + if (!device_table.table) + _mesa_set_init(&device_table, NULL, _mesa_hash_pointer, _mesa_key_pointer_equal); + + set_foreach(&device_table, entry) { + struct zink_device *zdev = (void*)entry->key; + if (zdev->pdev != screen->pdev) + continue; + zdev->refcount++; + simple_mtx_unlock(&device_lock); + return zdev->dev; + } + + VkResult result = VKSCR(CreateDevice)(screen->pdev, dci, NULL, &dev); + if (result != VK_SUCCESS) + mesa_loge("ZINK: vkCreateDevice failed (%s)", vk_Result_to_str(result)); + + struct zink_device *zdev = malloc(sizeof(struct zink_device)); + zdev->refcount = 1; + zdev->pdev = screen->pdev; + zdev->dev = dev; + _mesa_set_add(&device_table, zdev); + simple_mtx_unlock(&device_lock); + return dev; +} + +static VkDevice +zink_create_logical_device(struct zink_screen *screen) +{ VkDeviceQueueCreateInfo qci[2] = {0}; uint32_t queues[3] = { screen->gfx_queue, @@ -2685,11 +2750,7 @@ zink_create_logical_device(struct zink_screen *screen) dci.ppEnabledExtensionNames = screen->info.extensions; dci.enabledExtensionCount = screen->info.num_extensions; - VkResult result = VKSCR(CreateDevice)(screen->pdev, &dci, NULL, &dev); - if (result != VK_SUCCESS) - mesa_loge("ZINK: vkCreateDevice failed (%s)", vk_Result_to_str(result)); - - return dev; + return get_device(screen, &dci); } static void @@ -3258,7 +3319,6 @@ zink_internal_create_screen(const struct pipe_screen_config *config, int64_t dev goto fail; } - screen->instance_info.loader_version = zink_get_loader_version(screen); if (config) { driParseConfigFiles(config->options, config->options_info, 0, "zink", NULL, NULL, NULL, 0, NULL, 0); @@ -3268,12 +3328,22 @@ zink_internal_create_screen(const struct pipe_screen_config *config, int64_t dev screen->driconf.zink_shader_object_enable = driQueryOptionb(config->options, "zink_shader_object_enable"); } - if (!zink_create_instance(screen)) - goto fail; + simple_mtx_lock(&instance_lock); + if (++instance_refcount == 1) { + instance_info.loader_version = zink_get_loader_version(screen); + instance = zink_create_instance(screen, &instance_info); + if (!instance) + goto fail; + } else { + assert(instance); + } + screen->instance = instance; + screen->instance_info = &instance_info; + simple_mtx_unlock(&instance_lock); if (zink_debug & ZINK_DEBUG_VALIDATION) { - if (!screen->instance_info.have_layer_KHRONOS_validation && - !screen->instance_info.have_layer_LUNARG_standard_validation) { + if (!screen->instance_info->have_layer_KHRONOS_validation && + !screen->instance_info->have_layer_LUNARG_standard_validation) { if (!screen->driver_name_is_inferred) mesa_loge("Failed to load validation layer"); goto fail; @@ -3289,7 +3359,7 @@ zink_internal_create_screen(const struct pipe_screen_config *config, int64_t dev zink_verify_instance_extensions(screen); - if (screen->instance_info.have_EXT_debug_utils && + if (screen->instance_info->have_EXT_debug_utils && (zink_debug & ZINK_DEBUG_VALIDATION) && !create_debug(screen)) { if (!screen->driver_name_is_inferred) debug_printf("ZINK: failed to setup debug utils\n"); @@ -3438,7 +3508,7 @@ zink_internal_create_screen(const struct pipe_screen_config *config, int64_t dev util_live_shader_cache_init(&screen->shaders, zink_create_gfx_shader_state, zink_delete_shader_state); screen->base.get_name = zink_get_name; - if (screen->instance_info.have_KHR_external_memory_capabilities) { + if (screen->instance_info->have_KHR_external_memory_capabilities) { screen->base.get_device_uuid = zink_get_device_uuid; screen->base.get_driver_uuid = zink_get_driver_uuid; } @@ -3650,7 +3720,7 @@ zink_internal_create_screen(const struct pipe_screen_config *config, int64_t dev init_optimal_keys(screen); screen->screen_id = p_atomic_inc_return(&num_screens); - zink_tracing = screen->instance_info.have_EXT_debug_utils && + zink_tracing = screen->instance_info->have_EXT_debug_utils && (u_trace_is_enabled(U_TRACE_TYPE_PERFETTO) || u_trace_is_enabled(U_TRACE_TYPE_MARKERS)); screen->frame_marker_emitted = zink_screen_debug_marker_begin(screen, "frame"); diff --git a/src/gallium/drivers/zink/zink_types.h b/src/gallium/drivers/zink/zink_types.h index 9853a5b9df7..c34b9a222bc 100644 --- a/src/gallium/drivers/zink/zink_types.h +++ b/src/gallium/drivers/zink/zink_types.h @@ -1461,7 +1461,7 @@ struct zink_screen { uint64_t mapped_vram; VkInstance instance; - struct zink_instance_info instance_info; + const struct zink_instance_info *instance_info; struct hash_table *debug_mem_sizes; simple_mtx_t debug_mem_lock;