17ec681f3Smrg/* 27ec681f3Smrg * Copyright 2019 Google LLC 37ec681f3Smrg * SPDX-License-Identifier: MIT 47ec681f3Smrg * 57ec681f3Smrg * based in part on anv and radv which are: 67ec681f3Smrg * Copyright © 2015 Intel Corporation 77ec681f3Smrg * Copyright © 2016 Red Hat. 87ec681f3Smrg * Copyright © 2016 Bas Nieuwenhuizen 97ec681f3Smrg */ 107ec681f3Smrg 117ec681f3Smrg#include "vn_instance.h" 127ec681f3Smrg 137ec681f3Smrg#include "util/driconf.h" 147ec681f3Smrg#include "venus-protocol/vn_protocol_driver_info.h" 157ec681f3Smrg#include "venus-protocol/vn_protocol_driver_instance.h" 167ec681f3Smrg#include "venus-protocol/vn_protocol_driver_transport.h" 177ec681f3Smrg 187ec681f3Smrg#include "vn_icd.h" 197ec681f3Smrg#include "vn_physical_device.h" 207ec681f3Smrg#include "vn_renderer.h" 217ec681f3Smrg 227ec681f3Smrg#define VN_INSTANCE_LARGE_RING_SIZE (64 * 1024) 237ec681f3Smrg#define VN_INSTANCE_LARGE_RING_DIRECT_THRESHOLD \ 247ec681f3Smrg (VN_INSTANCE_LARGE_RING_SIZE / 16) 257ec681f3Smrg 267ec681f3Smrg/* this must not exceed 2KiB for the ring to fit in a 4K page */ 277ec681f3Smrg#define VN_INSTANCE_RING_SIZE (2 * 1024) 287ec681f3Smrg#define VN_INSTANCE_RING_DIRECT_THRESHOLD (VN_INSTANCE_RING_SIZE / 8) 297ec681f3Smrg 307ec681f3Smrg/* 317ec681f3Smrg * Instance extensions add instance-level or physical-device-level 327ec681f3Smrg * functionalities. It seems renderer support is either unnecessary or 337ec681f3Smrg * optional. We should be able to advertise them or lie about them locally. 347ec681f3Smrg */ 357ec681f3Smrgstatic const struct vk_instance_extension_table 367ec681f3Smrg vn_instance_supported_extensions = { 377ec681f3Smrg /* promoted to VK_VERSION_1_1 */ 387ec681f3Smrg .KHR_device_group_creation = true, 397ec681f3Smrg .KHR_external_fence_capabilities = true, 407ec681f3Smrg .KHR_external_memory_capabilities = true, 417ec681f3Smrg .KHR_external_semaphore_capabilities = true, 427ec681f3Smrg .KHR_get_physical_device_properties2 = true, 437ec681f3Smrg 447ec681f3Smrg#ifdef VN_USE_WSI_PLATFORM 457ec681f3Smrg .KHR_get_surface_capabilities2 = true, 467ec681f3Smrg .KHR_surface = true, 477ec681f3Smrg .KHR_surface_protected_capabilities = true, 487ec681f3Smrg#endif 497ec681f3Smrg#ifdef VK_USE_PLATFORM_WAYLAND_KHR 507ec681f3Smrg .KHR_wayland_surface = true, 517ec681f3Smrg#endif 527ec681f3Smrg#ifdef VK_USE_PLATFORM_XCB_KHR 537ec681f3Smrg .KHR_xcb_surface = true, 547ec681f3Smrg#endif 557ec681f3Smrg#ifdef VK_USE_PLATFORM_XLIB_KHR 567ec681f3Smrg .KHR_xlib_surface = true, 577ec681f3Smrg#endif 587ec681f3Smrg }; 597ec681f3Smrg 607ec681f3Smrgstatic const driOptionDescription vn_dri_options[] = { 617ec681f3Smrg /* clang-format off */ 627ec681f3Smrg DRI_CONF_SECTION_PERFORMANCE 637ec681f3Smrg DRI_CONF_VK_X11_ENSURE_MIN_IMAGE_COUNT(false) 647ec681f3Smrg DRI_CONF_VK_X11_OVERRIDE_MIN_IMAGE_COUNT(0) 657ec681f3Smrg DRI_CONF_VK_X11_STRICT_IMAGE_COUNT(false) 667ec681f3Smrg DRI_CONF_SECTION_END 677ec681f3Smrg DRI_CONF_SECTION_DEBUG 687ec681f3Smrg DRI_CONF_VK_WSI_FORCE_BGRA8_UNORM_FIRST(false) 697ec681f3Smrg DRI_CONF_SECTION_END 707ec681f3Smrg /* clang-format on */ 717ec681f3Smrg}; 727ec681f3Smrg 737ec681f3Smrgstatic VkResult 747ec681f3Smrgvn_instance_init_renderer_versions(struct vn_instance *instance) 757ec681f3Smrg{ 767ec681f3Smrg uint32_t instance_version = 0; 777ec681f3Smrg VkResult result = 787ec681f3Smrg vn_call_vkEnumerateInstanceVersion(instance, &instance_version); 797ec681f3Smrg if (result != VK_SUCCESS) { 807ec681f3Smrg if (VN_DEBUG(INIT)) 817ec681f3Smrg vn_log(instance, "failed to enumerate renderer instance version"); 827ec681f3Smrg return result; 837ec681f3Smrg } 847ec681f3Smrg 857ec681f3Smrg if (instance_version < VN_MIN_RENDERER_VERSION) { 867ec681f3Smrg if (VN_DEBUG(INIT)) { 877ec681f3Smrg vn_log(instance, "unsupported renderer instance version %d.%d", 887ec681f3Smrg VK_VERSION_MAJOR(instance_version), 897ec681f3Smrg VK_VERSION_MINOR(instance_version)); 907ec681f3Smrg } 917ec681f3Smrg return VK_ERROR_INITIALIZATION_FAILED; 927ec681f3Smrg } 937ec681f3Smrg 947ec681f3Smrg if (VN_DEBUG(INIT)) { 957ec681f3Smrg vn_log(instance, "renderer instance version %d.%d.%d", 967ec681f3Smrg VK_VERSION_MAJOR(instance_version), 977ec681f3Smrg VK_VERSION_MINOR(instance_version), 987ec681f3Smrg VK_VERSION_PATCH(instance_version)); 997ec681f3Smrg } 1007ec681f3Smrg 1017ec681f3Smrg /* request at least VN_MIN_RENDERER_VERSION internally */ 1027ec681f3Smrg instance->renderer_api_version = 1037ec681f3Smrg MAX2(instance->base.base.app_info.api_version, VN_MIN_RENDERER_VERSION); 1047ec681f3Smrg 1057ec681f3Smrg /* instance version for internal use is capped */ 1067ec681f3Smrg instance_version = MIN3(instance_version, instance->renderer_api_version, 1077ec681f3Smrg instance->renderer_info.vk_xml_version); 1087ec681f3Smrg assert(instance_version >= VN_MIN_RENDERER_VERSION); 1097ec681f3Smrg 1107ec681f3Smrg instance->renderer_version = instance_version; 1117ec681f3Smrg 1127ec681f3Smrg return VK_SUCCESS; 1137ec681f3Smrg} 1147ec681f3Smrg 1157ec681f3Smrgstatic VkResult 1167ec681f3Smrgvn_instance_init_ring(struct vn_instance *instance) 1177ec681f3Smrg{ 1187ec681f3Smrg const size_t buf_size = instance->experimental.largeRing 1197ec681f3Smrg ? VN_INSTANCE_LARGE_RING_SIZE 1207ec681f3Smrg : VN_INSTANCE_RING_SIZE; 1217ec681f3Smrg /* 32-bit seqno for renderer roundtrips */ 1227ec681f3Smrg const size_t extra_size = sizeof(uint32_t); 1237ec681f3Smrg struct vn_ring_layout layout; 1247ec681f3Smrg vn_ring_get_layout(buf_size, extra_size, &layout); 1257ec681f3Smrg 1267ec681f3Smrg instance->ring.shmem = 1277ec681f3Smrg vn_renderer_shmem_create(instance->renderer, layout.shmem_size); 1287ec681f3Smrg if (!instance->ring.shmem) { 1297ec681f3Smrg if (VN_DEBUG(INIT)) 1307ec681f3Smrg vn_log(instance, "failed to allocate/map ring shmem"); 1317ec681f3Smrg return VK_ERROR_OUT_OF_HOST_MEMORY; 1327ec681f3Smrg } 1337ec681f3Smrg 1347ec681f3Smrg mtx_init(&instance->ring.mutex, mtx_plain); 1357ec681f3Smrg 1367ec681f3Smrg struct vn_ring *ring = &instance->ring.ring; 1377ec681f3Smrg vn_ring_init(ring, instance->renderer, &layout, 1387ec681f3Smrg instance->ring.shmem->mmap_ptr); 1397ec681f3Smrg 1407ec681f3Smrg instance->ring.id = (uintptr_t)ring; 1417ec681f3Smrg 1427ec681f3Smrg const struct VkRingCreateInfoMESA info = { 1437ec681f3Smrg .sType = VK_STRUCTURE_TYPE_RING_CREATE_INFO_MESA, 1447ec681f3Smrg .resourceId = instance->ring.shmem->res_id, 1457ec681f3Smrg .size = layout.shmem_size, 1467ec681f3Smrg .idleTimeout = 50ull * 1000 * 1000, 1477ec681f3Smrg .headOffset = layout.head_offset, 1487ec681f3Smrg .tailOffset = layout.tail_offset, 1497ec681f3Smrg .statusOffset = layout.status_offset, 1507ec681f3Smrg .bufferOffset = layout.buffer_offset, 1517ec681f3Smrg .bufferSize = layout.buffer_size, 1527ec681f3Smrg .extraOffset = layout.extra_offset, 1537ec681f3Smrg .extraSize = layout.extra_size, 1547ec681f3Smrg }; 1557ec681f3Smrg 1567ec681f3Smrg uint32_t create_ring_data[64]; 1577ec681f3Smrg struct vn_cs_encoder local_enc = VN_CS_ENCODER_INITIALIZER_LOCAL( 1587ec681f3Smrg create_ring_data, sizeof(create_ring_data)); 1597ec681f3Smrg vn_encode_vkCreateRingMESA(&local_enc, 0, instance->ring.id, &info); 1607ec681f3Smrg vn_renderer_submit_simple(instance->renderer, create_ring_data, 1617ec681f3Smrg vn_cs_encoder_get_len(&local_enc)); 1627ec681f3Smrg 1637ec681f3Smrg vn_cs_encoder_init_indirect(&instance->ring.upload, instance, 1647ec681f3Smrg 1 * 1024 * 1024); 1657ec681f3Smrg 1667ec681f3Smrg mtx_init(&instance->ring.roundtrip_mutex, mtx_plain); 1677ec681f3Smrg instance->ring.roundtrip_next = 1; 1687ec681f3Smrg 1697ec681f3Smrg return VK_SUCCESS; 1707ec681f3Smrg} 1717ec681f3Smrg 1727ec681f3Smrgstatic struct vn_renderer_shmem * 1737ec681f3Smrgvn_instance_get_reply_shmem_locked(struct vn_instance *instance, 1747ec681f3Smrg size_t size, 1757ec681f3Smrg void **ptr); 1767ec681f3Smrg 1777ec681f3Smrgstatic VkResult 1787ec681f3Smrgvn_instance_init_experimental_features(struct vn_instance *instance) 1797ec681f3Smrg{ 1807ec681f3Smrg if (instance->renderer_info.vk_mesa_venus_protocol_spec_version != 1817ec681f3Smrg 100000) { 1827ec681f3Smrg if (VN_DEBUG(INIT)) 1837ec681f3Smrg vn_log(instance, "renderer supports no experimental features"); 1847ec681f3Smrg return VK_SUCCESS; 1857ec681f3Smrg } 1867ec681f3Smrg 1877ec681f3Smrg size_t struct_size = sizeof(instance->experimental); 1887ec681f3Smrg 1897ec681f3Smrg /* prepare the reply shmem */ 1907ec681f3Smrg const size_t reply_size = 1917ec681f3Smrg vn_sizeof_vkGetVenusExperimentalFeatureData100000MESA_reply( 1927ec681f3Smrg &struct_size, &instance->experimental); 1937ec681f3Smrg void *reply_ptr; 1947ec681f3Smrg struct vn_renderer_shmem *reply_shmem = 1957ec681f3Smrg vn_instance_get_reply_shmem_locked(instance, reply_size, &reply_ptr); 1967ec681f3Smrg if (!reply_shmem) 1977ec681f3Smrg return VK_ERROR_OUT_OF_HOST_MEMORY; 1987ec681f3Smrg 1997ec681f3Smrg /* encode the command */ 2007ec681f3Smrg uint32_t local_data[16]; 2017ec681f3Smrg struct vn_cs_encoder local_enc = 2027ec681f3Smrg VN_CS_ENCODER_INITIALIZER_LOCAL(local_data, sizeof(local_data)); 2037ec681f3Smrg vn_encode_vkGetVenusExperimentalFeatureData100000MESA( 2047ec681f3Smrg &local_enc, VK_COMMAND_GENERATE_REPLY_BIT_EXT, &struct_size, 2057ec681f3Smrg &instance->experimental); 2067ec681f3Smrg 2077ec681f3Smrg VkResult result = vn_renderer_submit_simple_sync( 2087ec681f3Smrg instance->renderer, local_data, vn_cs_encoder_get_len(&local_enc)); 2097ec681f3Smrg if (result != VK_SUCCESS) { 2107ec681f3Smrg vn_renderer_shmem_unref(instance->renderer, reply_shmem); 2117ec681f3Smrg return result; 2127ec681f3Smrg } 2137ec681f3Smrg 2147ec681f3Smrg struct vn_cs_decoder reply_dec = 2157ec681f3Smrg VN_CS_DECODER_INITIALIZER(reply_ptr, reply_size); 2167ec681f3Smrg vn_decode_vkGetVenusExperimentalFeatureData100000MESA_reply( 2177ec681f3Smrg &reply_dec, &struct_size, &instance->experimental); 2187ec681f3Smrg vn_renderer_shmem_unref(instance->renderer, reply_shmem); 2197ec681f3Smrg 2207ec681f3Smrg if (VN_DEBUG(INIT)) { 2217ec681f3Smrg vn_log(instance, 2227ec681f3Smrg "VkVenusExperimentalFeatures100000MESA is as below:" 2237ec681f3Smrg "\n\tmemoryResourceAllocationSize = %u" 2247ec681f3Smrg "\n\tglobalFencing = %u" 2257ec681f3Smrg "\n\tlargeRing = %u", 2267ec681f3Smrg instance->experimental.memoryResourceAllocationSize, 2277ec681f3Smrg instance->experimental.globalFencing, 2287ec681f3Smrg instance->experimental.largeRing); 2297ec681f3Smrg } 2307ec681f3Smrg 2317ec681f3Smrg return VK_SUCCESS; 2327ec681f3Smrg} 2337ec681f3Smrg 2347ec681f3Smrgstatic VkResult 2357ec681f3Smrgvn_instance_init_renderer(struct vn_instance *instance) 2367ec681f3Smrg{ 2377ec681f3Smrg const VkAllocationCallbacks *alloc = &instance->base.base.alloc; 2387ec681f3Smrg 2397ec681f3Smrg VkResult result = vn_renderer_create(instance, alloc, &instance->renderer); 2407ec681f3Smrg if (result != VK_SUCCESS) 2417ec681f3Smrg return result; 2427ec681f3Smrg 2437ec681f3Smrg vn_renderer_get_info(instance->renderer, &instance->renderer_info); 2447ec681f3Smrg 2457ec681f3Smrg uint32_t version = vn_info_wire_format_version(); 2467ec681f3Smrg if (instance->renderer_info.wire_format_version != version) { 2477ec681f3Smrg if (VN_DEBUG(INIT)) { 2487ec681f3Smrg vn_log(instance, "wire format version %d != %d", 2497ec681f3Smrg instance->renderer_info.wire_format_version, version); 2507ec681f3Smrg } 2517ec681f3Smrg return VK_ERROR_INITIALIZATION_FAILED; 2527ec681f3Smrg } 2537ec681f3Smrg 2547ec681f3Smrg version = vn_info_vk_xml_version(); 2557ec681f3Smrg if (instance->renderer_info.vk_xml_version > version) 2567ec681f3Smrg instance->renderer_info.vk_xml_version = version; 2577ec681f3Smrg if (instance->renderer_info.vk_xml_version < VN_MIN_RENDERER_VERSION) { 2587ec681f3Smrg if (VN_DEBUG(INIT)) { 2597ec681f3Smrg vn_log(instance, "vk xml version %d.%d.%d < %d.%d.%d", 2607ec681f3Smrg VK_VERSION_MAJOR(instance->renderer_info.vk_xml_version), 2617ec681f3Smrg VK_VERSION_MINOR(instance->renderer_info.vk_xml_version), 2627ec681f3Smrg VK_VERSION_PATCH(instance->renderer_info.vk_xml_version), 2637ec681f3Smrg VK_VERSION_MAJOR(VN_MIN_RENDERER_VERSION), 2647ec681f3Smrg VK_VERSION_MINOR(VN_MIN_RENDERER_VERSION), 2657ec681f3Smrg VK_VERSION_PATCH(VN_MIN_RENDERER_VERSION)); 2667ec681f3Smrg } 2677ec681f3Smrg return VK_ERROR_INITIALIZATION_FAILED; 2687ec681f3Smrg } 2697ec681f3Smrg 2707ec681f3Smrg version = vn_info_extension_spec_version("VK_EXT_command_serialization"); 2717ec681f3Smrg if (instance->renderer_info.vk_ext_command_serialization_spec_version > 2727ec681f3Smrg version) { 2737ec681f3Smrg instance->renderer_info.vk_ext_command_serialization_spec_version = 2747ec681f3Smrg version; 2757ec681f3Smrg } 2767ec681f3Smrg 2777ec681f3Smrg version = vn_info_extension_spec_version("VK_MESA_venus_protocol"); 2787ec681f3Smrg if (instance->renderer_info.vk_mesa_venus_protocol_spec_version > 2797ec681f3Smrg version) { 2807ec681f3Smrg instance->renderer_info.vk_mesa_venus_protocol_spec_version = version; 2817ec681f3Smrg } 2827ec681f3Smrg 2837ec681f3Smrg if (VN_DEBUG(INIT)) { 2847ec681f3Smrg vn_log(instance, "connected to renderer"); 2857ec681f3Smrg vn_log(instance, "wire format version %d", 2867ec681f3Smrg instance->renderer_info.wire_format_version); 2877ec681f3Smrg vn_log(instance, "vk xml version %d.%d.%d", 2887ec681f3Smrg VK_VERSION_MAJOR(instance->renderer_info.vk_xml_version), 2897ec681f3Smrg VK_VERSION_MINOR(instance->renderer_info.vk_xml_version), 2907ec681f3Smrg VK_VERSION_PATCH(instance->renderer_info.vk_xml_version)); 2917ec681f3Smrg vn_log( 2927ec681f3Smrg instance, "VK_EXT_command_serialization spec version %d", 2937ec681f3Smrg instance->renderer_info.vk_ext_command_serialization_spec_version); 2947ec681f3Smrg vn_log(instance, "VK_MESA_venus_protocol spec version %d", 2957ec681f3Smrg instance->renderer_info.vk_mesa_venus_protocol_spec_version); 2967ec681f3Smrg } 2977ec681f3Smrg 2987ec681f3Smrg return VK_SUCCESS; 2997ec681f3Smrg} 3007ec681f3Smrg 3017ec681f3SmrgVkResult 3027ec681f3Smrgvn_instance_submit_roundtrip(struct vn_instance *instance, 3037ec681f3Smrg uint32_t *roundtrip_seqno) 3047ec681f3Smrg{ 3057ec681f3Smrg uint32_t write_ring_extra_data[8]; 3067ec681f3Smrg struct vn_cs_encoder local_enc = VN_CS_ENCODER_INITIALIZER_LOCAL( 3077ec681f3Smrg write_ring_extra_data, sizeof(write_ring_extra_data)); 3087ec681f3Smrg 3097ec681f3Smrg /* submit a vkWriteRingExtraMESA through the renderer */ 3107ec681f3Smrg mtx_lock(&instance->ring.roundtrip_mutex); 3117ec681f3Smrg const uint32_t seqno = instance->ring.roundtrip_next++; 3127ec681f3Smrg vn_encode_vkWriteRingExtraMESA(&local_enc, 0, instance->ring.id, 0, seqno); 3137ec681f3Smrg VkResult result = 3147ec681f3Smrg vn_renderer_submit_simple(instance->renderer, write_ring_extra_data, 3157ec681f3Smrg vn_cs_encoder_get_len(&local_enc)); 3167ec681f3Smrg mtx_unlock(&instance->ring.roundtrip_mutex); 3177ec681f3Smrg 3187ec681f3Smrg *roundtrip_seqno = seqno; 3197ec681f3Smrg return result; 3207ec681f3Smrg} 3217ec681f3Smrg 3227ec681f3Smrgvoid 3237ec681f3Smrgvn_instance_wait_roundtrip(struct vn_instance *instance, 3247ec681f3Smrg uint32_t roundtrip_seqno) 3257ec681f3Smrg{ 3267ec681f3Smrg const struct vn_ring *ring = &instance->ring.ring; 3277ec681f3Smrg const volatile atomic_uint *ptr = ring->shared.extra; 3287ec681f3Smrg uint32_t iter = 0; 3297ec681f3Smrg do { 3307ec681f3Smrg const uint32_t cur = atomic_load_explicit(ptr, memory_order_acquire); 3317ec681f3Smrg if (cur >= roundtrip_seqno || roundtrip_seqno - cur >= INT32_MAX) 3327ec681f3Smrg break; 3337ec681f3Smrg vn_relax(&iter, "roundtrip"); 3347ec681f3Smrg } while (true); 3357ec681f3Smrg} 3367ec681f3Smrg 3377ec681f3Smrgstruct vn_instance_submission { 3387ec681f3Smrg const struct vn_cs_encoder *cs; 3397ec681f3Smrg struct vn_ring_submit *submit; 3407ec681f3Smrg 3417ec681f3Smrg struct { 3427ec681f3Smrg struct vn_cs_encoder cs; 3437ec681f3Smrg struct vn_cs_encoder_buffer buffer; 3447ec681f3Smrg uint32_t data[64]; 3457ec681f3Smrg } indirect; 3467ec681f3Smrg}; 3477ec681f3Smrg 3487ec681f3Smrgstatic const struct vn_cs_encoder * 3497ec681f3Smrgvn_instance_submission_get_cs(struct vn_instance_submission *submit, 3507ec681f3Smrg const struct vn_cs_encoder *cs, 3517ec681f3Smrg bool direct) 3527ec681f3Smrg{ 3537ec681f3Smrg if (direct) 3547ec681f3Smrg return cs; 3557ec681f3Smrg 3567ec681f3Smrg VkCommandStreamDescriptionMESA local_descs[8]; 3577ec681f3Smrg VkCommandStreamDescriptionMESA *descs = local_descs; 3587ec681f3Smrg if (cs->buffer_count > ARRAY_SIZE(local_descs)) { 3597ec681f3Smrg descs = 3607ec681f3Smrg malloc(sizeof(VkCommandStreamDescriptionMESA) * cs->buffer_count); 3617ec681f3Smrg if (!descs) 3627ec681f3Smrg return NULL; 3637ec681f3Smrg } 3647ec681f3Smrg 3657ec681f3Smrg uint32_t desc_count = 0; 3667ec681f3Smrg for (uint32_t i = 0; i < cs->buffer_count; i++) { 3677ec681f3Smrg const struct vn_cs_encoder_buffer *buf = &cs->buffers[i]; 3687ec681f3Smrg if (buf->committed_size) { 3697ec681f3Smrg descs[desc_count++] = (VkCommandStreamDescriptionMESA){ 3707ec681f3Smrg .resourceId = buf->shmem->res_id, 3717ec681f3Smrg .offset = buf->offset, 3727ec681f3Smrg .size = buf->committed_size, 3737ec681f3Smrg }; 3747ec681f3Smrg } 3757ec681f3Smrg } 3767ec681f3Smrg 3777ec681f3Smrg const size_t exec_size = vn_sizeof_vkExecuteCommandStreamsMESA( 3787ec681f3Smrg desc_count, descs, NULL, 0, NULL, 0); 3797ec681f3Smrg void *exec_data = submit->indirect.data; 3807ec681f3Smrg if (exec_size > sizeof(submit->indirect.data)) { 3817ec681f3Smrg exec_data = malloc(exec_size); 3827ec681f3Smrg if (!exec_data) { 3837ec681f3Smrg if (descs != local_descs) 3847ec681f3Smrg free(descs); 3857ec681f3Smrg return NULL; 3867ec681f3Smrg } 3877ec681f3Smrg } 3887ec681f3Smrg 3897ec681f3Smrg submit->indirect.buffer = VN_CS_ENCODER_BUFFER_INITIALIZER(exec_data); 3907ec681f3Smrg submit->indirect.cs = 3917ec681f3Smrg VN_CS_ENCODER_INITIALIZER(&submit->indirect.buffer, exec_size); 3927ec681f3Smrg vn_encode_vkExecuteCommandStreamsMESA(&submit->indirect.cs, 0, desc_count, 3937ec681f3Smrg descs, NULL, 0, NULL, 0); 3947ec681f3Smrg vn_cs_encoder_commit(&submit->indirect.cs); 3957ec681f3Smrg 3967ec681f3Smrg if (descs != local_descs) 3977ec681f3Smrg free(descs); 3987ec681f3Smrg 3997ec681f3Smrg return &submit->indirect.cs; 4007ec681f3Smrg} 4017ec681f3Smrg 4027ec681f3Smrgstatic struct vn_ring_submit * 4037ec681f3Smrgvn_instance_submission_get_ring_submit(struct vn_ring *ring, 4047ec681f3Smrg const struct vn_cs_encoder *cs, 4057ec681f3Smrg struct vn_renderer_shmem *extra_shmem, 4067ec681f3Smrg bool direct) 4077ec681f3Smrg{ 4087ec681f3Smrg const uint32_t shmem_count = 4097ec681f3Smrg (direct ? 0 : cs->buffer_count) + (extra_shmem ? 1 : 0); 4107ec681f3Smrg struct vn_ring_submit *submit = vn_ring_get_submit(ring, shmem_count); 4117ec681f3Smrg if (!submit) 4127ec681f3Smrg return NULL; 4137ec681f3Smrg 4147ec681f3Smrg submit->shmem_count = shmem_count; 4157ec681f3Smrg if (!direct) { 4167ec681f3Smrg for (uint32_t i = 0; i < cs->buffer_count; i++) { 4177ec681f3Smrg submit->shmems[i] = 4187ec681f3Smrg vn_renderer_shmem_ref(ring->renderer, cs->buffers[i].shmem); 4197ec681f3Smrg } 4207ec681f3Smrg } 4217ec681f3Smrg if (extra_shmem) { 4227ec681f3Smrg submit->shmems[shmem_count - 1] = 4237ec681f3Smrg vn_renderer_shmem_ref(ring->renderer, extra_shmem); 4247ec681f3Smrg } 4257ec681f3Smrg 4267ec681f3Smrg return submit; 4277ec681f3Smrg} 4287ec681f3Smrg 4297ec681f3Smrgstatic void 4307ec681f3Smrgvn_instance_submission_cleanup(struct vn_instance_submission *submit) 4317ec681f3Smrg{ 4327ec681f3Smrg if (submit->cs == &submit->indirect.cs && 4337ec681f3Smrg submit->indirect.buffer.base != submit->indirect.data) 4347ec681f3Smrg free(submit->indirect.buffer.base); 4357ec681f3Smrg} 4367ec681f3Smrg 4377ec681f3Smrgstatic VkResult 4387ec681f3Smrgvn_instance_submission_prepare(struct vn_instance_submission *submit, 4397ec681f3Smrg const struct vn_cs_encoder *cs, 4407ec681f3Smrg struct vn_ring *ring, 4417ec681f3Smrg struct vn_renderer_shmem *extra_shmem, 4427ec681f3Smrg bool direct) 4437ec681f3Smrg{ 4447ec681f3Smrg submit->cs = vn_instance_submission_get_cs(submit, cs, direct); 4457ec681f3Smrg if (!submit->cs) 4467ec681f3Smrg return VK_ERROR_OUT_OF_HOST_MEMORY; 4477ec681f3Smrg 4487ec681f3Smrg submit->submit = 4497ec681f3Smrg vn_instance_submission_get_ring_submit(ring, cs, extra_shmem, direct); 4507ec681f3Smrg if (!submit->submit) { 4517ec681f3Smrg vn_instance_submission_cleanup(submit); 4527ec681f3Smrg return VK_ERROR_OUT_OF_HOST_MEMORY; 4537ec681f3Smrg } 4547ec681f3Smrg 4557ec681f3Smrg return VK_SUCCESS; 4567ec681f3Smrg} 4577ec681f3Smrg 4587ec681f3Smrgstatic bool 4597ec681f3Smrgvn_instance_submission_can_direct(const struct vn_instance *instance, 4607ec681f3Smrg const struct vn_cs_encoder *cs) 4617ec681f3Smrg{ 4627ec681f3Smrg const size_t threshold = instance->experimental.largeRing 4637ec681f3Smrg ? VN_INSTANCE_LARGE_RING_DIRECT_THRESHOLD 4647ec681f3Smrg : VN_INSTANCE_RING_DIRECT_THRESHOLD; 4657ec681f3Smrg return vn_cs_encoder_get_len(cs) <= threshold; 4667ec681f3Smrg} 4677ec681f3Smrg 4687ec681f3Smrgstatic struct vn_cs_encoder * 4697ec681f3Smrgvn_instance_ring_cs_upload_locked(struct vn_instance *instance, 4707ec681f3Smrg const struct vn_cs_encoder *cs) 4717ec681f3Smrg{ 4727ec681f3Smrg assert(!cs->indirect && cs->buffer_count == 1); 4737ec681f3Smrg const void *cs_data = cs->buffers[0].base; 4747ec681f3Smrg const size_t cs_size = cs->total_committed_size; 4757ec681f3Smrg assert(cs_size == vn_cs_encoder_get_len(cs)); 4767ec681f3Smrg 4777ec681f3Smrg struct vn_cs_encoder *upload = &instance->ring.upload; 4787ec681f3Smrg vn_cs_encoder_reset(upload); 4797ec681f3Smrg 4807ec681f3Smrg if (!vn_cs_encoder_reserve(upload, cs_size)) 4817ec681f3Smrg return NULL; 4827ec681f3Smrg 4837ec681f3Smrg vn_cs_encoder_write(upload, cs_size, cs_data, cs_size); 4847ec681f3Smrg vn_cs_encoder_commit(upload); 4857ec681f3Smrg vn_instance_wait_roundtrip(instance, upload->current_buffer_roundtrip); 4867ec681f3Smrg 4877ec681f3Smrg return upload; 4887ec681f3Smrg} 4897ec681f3Smrg 4907ec681f3Smrgstatic VkResult 4917ec681f3Smrgvn_instance_ring_submit_locked(struct vn_instance *instance, 4927ec681f3Smrg const struct vn_cs_encoder *cs, 4937ec681f3Smrg struct vn_renderer_shmem *extra_shmem, 4947ec681f3Smrg uint32_t *ring_seqno) 4957ec681f3Smrg{ 4967ec681f3Smrg struct vn_ring *ring = &instance->ring.ring; 4977ec681f3Smrg 4987ec681f3Smrg const bool direct = vn_instance_submission_can_direct(instance, cs); 4997ec681f3Smrg if (!direct && !cs->indirect) { 5007ec681f3Smrg cs = vn_instance_ring_cs_upload_locked(instance, cs); 5017ec681f3Smrg if (!cs) 5027ec681f3Smrg return VK_ERROR_OUT_OF_HOST_MEMORY; 5037ec681f3Smrg assert(cs->indirect); 5047ec681f3Smrg } 5057ec681f3Smrg 5067ec681f3Smrg struct vn_instance_submission submit; 5077ec681f3Smrg VkResult result = 5087ec681f3Smrg vn_instance_submission_prepare(&submit, cs, ring, extra_shmem, direct); 5097ec681f3Smrg if (result != VK_SUCCESS) 5107ec681f3Smrg return result; 5117ec681f3Smrg 5127ec681f3Smrg uint32_t seqno; 5137ec681f3Smrg const bool notify = vn_ring_submit(ring, submit.submit, submit.cs, &seqno); 5147ec681f3Smrg if (notify) { 5157ec681f3Smrg uint32_t notify_ring_data[8]; 5167ec681f3Smrg struct vn_cs_encoder local_enc = VN_CS_ENCODER_INITIALIZER_LOCAL( 5177ec681f3Smrg notify_ring_data, sizeof(notify_ring_data)); 5187ec681f3Smrg vn_encode_vkNotifyRingMESA(&local_enc, 0, instance->ring.id, seqno, 0); 5197ec681f3Smrg vn_renderer_submit_simple(instance->renderer, notify_ring_data, 5207ec681f3Smrg vn_cs_encoder_get_len(&local_enc)); 5217ec681f3Smrg } 5227ec681f3Smrg 5237ec681f3Smrg vn_instance_submission_cleanup(&submit); 5247ec681f3Smrg 5257ec681f3Smrg if (ring_seqno) 5267ec681f3Smrg *ring_seqno = seqno; 5277ec681f3Smrg 5287ec681f3Smrg return VK_SUCCESS; 5297ec681f3Smrg} 5307ec681f3Smrg 5317ec681f3SmrgVkResult 5327ec681f3Smrgvn_instance_ring_submit(struct vn_instance *instance, 5337ec681f3Smrg const struct vn_cs_encoder *cs) 5347ec681f3Smrg{ 5357ec681f3Smrg mtx_lock(&instance->ring.mutex); 5367ec681f3Smrg VkResult result = vn_instance_ring_submit_locked(instance, cs, NULL, NULL); 5377ec681f3Smrg mtx_unlock(&instance->ring.mutex); 5387ec681f3Smrg 5397ec681f3Smrg return result; 5407ec681f3Smrg} 5417ec681f3Smrg 5427ec681f3Smrgstatic bool 5437ec681f3Smrgvn_instance_grow_reply_shmem_locked(struct vn_instance *instance, size_t size) 5447ec681f3Smrg{ 5457ec681f3Smrg const size_t min_shmem_size = 1 << 20; 5467ec681f3Smrg 5477ec681f3Smrg size_t shmem_size = 5487ec681f3Smrg instance->reply.size ? instance->reply.size : min_shmem_size; 5497ec681f3Smrg while (shmem_size < size) { 5507ec681f3Smrg shmem_size <<= 1; 5517ec681f3Smrg if (!shmem_size) 5527ec681f3Smrg return false; 5537ec681f3Smrg } 5547ec681f3Smrg 5557ec681f3Smrg struct vn_renderer_shmem *shmem = 5567ec681f3Smrg vn_renderer_shmem_create(instance->renderer, shmem_size); 5577ec681f3Smrg if (!shmem) 5587ec681f3Smrg return false; 5597ec681f3Smrg 5607ec681f3Smrg if (instance->reply.shmem) 5617ec681f3Smrg vn_renderer_shmem_unref(instance->renderer, instance->reply.shmem); 5627ec681f3Smrg instance->reply.shmem = shmem; 5637ec681f3Smrg instance->reply.size = shmem_size; 5647ec681f3Smrg instance->reply.used = 0; 5657ec681f3Smrg instance->reply.ptr = shmem->mmap_ptr; 5667ec681f3Smrg 5677ec681f3Smrg return true; 5687ec681f3Smrg} 5697ec681f3Smrg 5707ec681f3Smrgstatic struct vn_renderer_shmem * 5717ec681f3Smrgvn_instance_get_reply_shmem_locked(struct vn_instance *instance, 5727ec681f3Smrg size_t size, 5737ec681f3Smrg void **ptr) 5747ec681f3Smrg{ 5757ec681f3Smrg if (unlikely(instance->reply.used + size > instance->reply.size)) { 5767ec681f3Smrg if (!vn_instance_grow_reply_shmem_locked(instance, size)) 5777ec681f3Smrg return NULL; 5787ec681f3Smrg 5797ec681f3Smrg uint32_t set_reply_command_stream_data[16]; 5807ec681f3Smrg struct vn_cs_encoder local_enc = VN_CS_ENCODER_INITIALIZER_LOCAL( 5817ec681f3Smrg set_reply_command_stream_data, 5827ec681f3Smrg sizeof(set_reply_command_stream_data)); 5837ec681f3Smrg const struct VkCommandStreamDescriptionMESA stream = { 5847ec681f3Smrg .resourceId = instance->reply.shmem->res_id, 5857ec681f3Smrg .size = instance->reply.size, 5867ec681f3Smrg }; 5877ec681f3Smrg vn_encode_vkSetReplyCommandStreamMESA(&local_enc, 0, &stream); 5887ec681f3Smrg vn_cs_encoder_commit(&local_enc); 5897ec681f3Smrg 5907ec681f3Smrg if (likely(instance->ring.id)) { 5917ec681f3Smrg vn_instance_roundtrip(instance); 5927ec681f3Smrg vn_instance_ring_submit_locked(instance, &local_enc, NULL, NULL); 5937ec681f3Smrg } else { 5947ec681f3Smrg vn_renderer_submit_simple(instance->renderer, 5957ec681f3Smrg set_reply_command_stream_data, 5967ec681f3Smrg vn_cs_encoder_get_len(&local_enc)); 5977ec681f3Smrg } 5987ec681f3Smrg } 5997ec681f3Smrg 6007ec681f3Smrg /* TODO avoid this seek command and go lock-free? */ 6017ec681f3Smrg uint32_t seek_reply_command_stream_data[8]; 6027ec681f3Smrg struct vn_cs_encoder local_enc = VN_CS_ENCODER_INITIALIZER_LOCAL( 6037ec681f3Smrg seek_reply_command_stream_data, sizeof(seek_reply_command_stream_data)); 6047ec681f3Smrg const size_t offset = instance->reply.used; 6057ec681f3Smrg vn_encode_vkSeekReplyCommandStreamMESA(&local_enc, 0, offset); 6067ec681f3Smrg vn_cs_encoder_commit(&local_enc); 6077ec681f3Smrg 6087ec681f3Smrg if (likely(instance->ring.id)) { 6097ec681f3Smrg vn_instance_ring_submit_locked(instance, &local_enc, NULL, NULL); 6107ec681f3Smrg } else { 6117ec681f3Smrg vn_renderer_submit_simple(instance->renderer, 6127ec681f3Smrg seek_reply_command_stream_data, 6137ec681f3Smrg vn_cs_encoder_get_len(&local_enc)); 6147ec681f3Smrg } 6157ec681f3Smrg 6167ec681f3Smrg *ptr = instance->reply.ptr + offset; 6177ec681f3Smrg instance->reply.used += size; 6187ec681f3Smrg 6197ec681f3Smrg return vn_renderer_shmem_ref(instance->renderer, instance->reply.shmem); 6207ec681f3Smrg} 6217ec681f3Smrg 6227ec681f3Smrgvoid 6237ec681f3Smrgvn_instance_submit_command(struct vn_instance *instance, 6247ec681f3Smrg struct vn_instance_submit_command *submit) 6257ec681f3Smrg{ 6267ec681f3Smrg void *reply_ptr = NULL; 6277ec681f3Smrg submit->reply_shmem = NULL; 6287ec681f3Smrg 6297ec681f3Smrg mtx_lock(&instance->ring.mutex); 6307ec681f3Smrg 6317ec681f3Smrg if (vn_cs_encoder_is_empty(&submit->command)) 6327ec681f3Smrg goto fail; 6337ec681f3Smrg vn_cs_encoder_commit(&submit->command); 6347ec681f3Smrg 6357ec681f3Smrg if (submit->reply_size) { 6367ec681f3Smrg submit->reply_shmem = vn_instance_get_reply_shmem_locked( 6377ec681f3Smrg instance, submit->reply_size, &reply_ptr); 6387ec681f3Smrg if (!submit->reply_shmem) 6397ec681f3Smrg goto fail; 6407ec681f3Smrg } 6417ec681f3Smrg 6427ec681f3Smrg uint32_t ring_seqno; 6437ec681f3Smrg VkResult result = vn_instance_ring_submit_locked( 6447ec681f3Smrg instance, &submit->command, submit->reply_shmem, &ring_seqno); 6457ec681f3Smrg 6467ec681f3Smrg mtx_unlock(&instance->ring.mutex); 6477ec681f3Smrg 6487ec681f3Smrg submit->reply = VN_CS_DECODER_INITIALIZER(reply_ptr, submit->reply_size); 6497ec681f3Smrg 6507ec681f3Smrg if (submit->reply_size && result == VK_SUCCESS) 6517ec681f3Smrg vn_ring_wait(&instance->ring.ring, ring_seqno); 6527ec681f3Smrg 6537ec681f3Smrg return; 6547ec681f3Smrg 6557ec681f3Smrgfail: 6567ec681f3Smrg instance->ring.command_dropped++; 6577ec681f3Smrg mtx_unlock(&instance->ring.mutex); 6587ec681f3Smrg} 6597ec681f3Smrg 6607ec681f3Smrg/* instance commands */ 6617ec681f3Smrg 6627ec681f3SmrgVkResult 6637ec681f3Smrgvn_EnumerateInstanceVersion(uint32_t *pApiVersion) 6647ec681f3Smrg{ 6657ec681f3Smrg *pApiVersion = VN_MAX_API_VERSION; 6667ec681f3Smrg return VK_SUCCESS; 6677ec681f3Smrg} 6687ec681f3Smrg 6697ec681f3SmrgVkResult 6707ec681f3Smrgvn_EnumerateInstanceExtensionProperties(const char *pLayerName, 6717ec681f3Smrg uint32_t *pPropertyCount, 6727ec681f3Smrg VkExtensionProperties *pProperties) 6737ec681f3Smrg{ 6747ec681f3Smrg if (pLayerName) 6757ec681f3Smrg return vn_error(NULL, VK_ERROR_LAYER_NOT_PRESENT); 6767ec681f3Smrg 6777ec681f3Smrg return vk_enumerate_instance_extension_properties( 6787ec681f3Smrg &vn_instance_supported_extensions, pPropertyCount, pProperties); 6797ec681f3Smrg} 6807ec681f3Smrg 6817ec681f3SmrgVkResult 6827ec681f3Smrgvn_EnumerateInstanceLayerProperties(uint32_t *pPropertyCount, 6837ec681f3Smrg VkLayerProperties *pProperties) 6847ec681f3Smrg{ 6857ec681f3Smrg *pPropertyCount = 0; 6867ec681f3Smrg return VK_SUCCESS; 6877ec681f3Smrg} 6887ec681f3Smrg 6897ec681f3SmrgVkResult 6907ec681f3Smrgvn_CreateInstance(const VkInstanceCreateInfo *pCreateInfo, 6917ec681f3Smrg const VkAllocationCallbacks *pAllocator, 6927ec681f3Smrg VkInstance *pInstance) 6937ec681f3Smrg{ 6947ec681f3Smrg const VkAllocationCallbacks *alloc = 6957ec681f3Smrg pAllocator ? pAllocator : vk_default_allocator(); 6967ec681f3Smrg struct vn_instance *instance; 6977ec681f3Smrg VkResult result; 6987ec681f3Smrg 6997ec681f3Smrg vn_debug_init(); 7007ec681f3Smrg vn_trace_init(); 7017ec681f3Smrg 7027ec681f3Smrg instance = vk_zalloc(alloc, sizeof(*instance), VN_DEFAULT_ALIGN, 7037ec681f3Smrg VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE); 7047ec681f3Smrg if (!instance) 7057ec681f3Smrg return vn_error(NULL, VK_ERROR_OUT_OF_HOST_MEMORY); 7067ec681f3Smrg 7077ec681f3Smrg struct vk_instance_dispatch_table dispatch_table; 7087ec681f3Smrg vk_instance_dispatch_table_from_entrypoints( 7097ec681f3Smrg &dispatch_table, &vn_instance_entrypoints, true); 7107ec681f3Smrg vk_instance_dispatch_table_from_entrypoints( 7117ec681f3Smrg &dispatch_table, &wsi_instance_entrypoints, false); 7127ec681f3Smrg result = vn_instance_base_init(&instance->base, 7137ec681f3Smrg &vn_instance_supported_extensions, 7147ec681f3Smrg &dispatch_table, pCreateInfo, alloc); 7157ec681f3Smrg if (result != VK_SUCCESS) { 7167ec681f3Smrg vk_free(alloc, instance); 7177ec681f3Smrg return vn_error(NULL, result); 7187ec681f3Smrg } 7197ec681f3Smrg 7207ec681f3Smrg mtx_init(&instance->physical_device.mutex, mtx_plain); 7217ec681f3Smrg 7227ec681f3Smrg if (!vn_icd_supports_api_version( 7237ec681f3Smrg instance->base.base.app_info.api_version)) { 7247ec681f3Smrg result = VK_ERROR_INCOMPATIBLE_DRIVER; 7257ec681f3Smrg goto fail; 7267ec681f3Smrg } 7277ec681f3Smrg 7287ec681f3Smrg if (pCreateInfo->enabledLayerCount) { 7297ec681f3Smrg result = VK_ERROR_LAYER_NOT_PRESENT; 7307ec681f3Smrg goto fail; 7317ec681f3Smrg } 7327ec681f3Smrg 7337ec681f3Smrg result = vn_instance_init_renderer(instance); 7347ec681f3Smrg if (result != VK_SUCCESS) 7357ec681f3Smrg goto fail; 7367ec681f3Smrg 7377ec681f3Smrg result = vn_instance_init_experimental_features(instance); 7387ec681f3Smrg if (result != VK_SUCCESS) 7397ec681f3Smrg goto fail; 7407ec681f3Smrg 7417ec681f3Smrg result = vn_instance_init_ring(instance); 7427ec681f3Smrg if (result != VK_SUCCESS) 7437ec681f3Smrg goto fail; 7447ec681f3Smrg 7457ec681f3Smrg result = vn_instance_init_renderer_versions(instance); 7467ec681f3Smrg if (result != VK_SUCCESS) 7477ec681f3Smrg goto fail; 7487ec681f3Smrg 7497ec681f3Smrg VkInstanceCreateInfo local_create_info = *pCreateInfo; 7507ec681f3Smrg local_create_info.ppEnabledExtensionNames = NULL; 7517ec681f3Smrg local_create_info.enabledExtensionCount = 0; 7527ec681f3Smrg pCreateInfo = &local_create_info; 7537ec681f3Smrg 7547ec681f3Smrg VkApplicationInfo local_app_info; 7557ec681f3Smrg if (instance->base.base.app_info.api_version < 7567ec681f3Smrg instance->renderer_api_version) { 7577ec681f3Smrg if (pCreateInfo->pApplicationInfo) { 7587ec681f3Smrg local_app_info = *pCreateInfo->pApplicationInfo; 7597ec681f3Smrg local_app_info.apiVersion = instance->renderer_api_version; 7607ec681f3Smrg } else { 7617ec681f3Smrg local_app_info = (const VkApplicationInfo){ 7627ec681f3Smrg .sType = VK_STRUCTURE_TYPE_APPLICATION_INFO, 7637ec681f3Smrg .apiVersion = instance->renderer_api_version, 7647ec681f3Smrg }; 7657ec681f3Smrg } 7667ec681f3Smrg local_create_info.pApplicationInfo = &local_app_info; 7677ec681f3Smrg } 7687ec681f3Smrg 7697ec681f3Smrg VkInstance instance_handle = vn_instance_to_handle(instance); 7707ec681f3Smrg result = 7717ec681f3Smrg vn_call_vkCreateInstance(instance, pCreateInfo, NULL, &instance_handle); 7727ec681f3Smrg if (result != VK_SUCCESS) 7737ec681f3Smrg goto fail; 7747ec681f3Smrg 7757ec681f3Smrg driParseOptionInfo(&instance->available_dri_options, vn_dri_options, 7767ec681f3Smrg ARRAY_SIZE(vn_dri_options)); 7777ec681f3Smrg driParseConfigFiles(&instance->dri_options, 7787ec681f3Smrg &instance->available_dri_options, 0, "venus", NULL, NULL, 7797ec681f3Smrg instance->base.base.app_info.app_name, 7807ec681f3Smrg instance->base.base.app_info.app_version, 7817ec681f3Smrg instance->base.base.app_info.engine_name, 7827ec681f3Smrg instance->base.base.app_info.engine_version); 7837ec681f3Smrg 7847ec681f3Smrg *pInstance = instance_handle; 7857ec681f3Smrg 7867ec681f3Smrg return VK_SUCCESS; 7877ec681f3Smrg 7887ec681f3Smrgfail: 7897ec681f3Smrg if (instance->reply.shmem) 7907ec681f3Smrg vn_renderer_shmem_unref(instance->renderer, instance->reply.shmem); 7917ec681f3Smrg 7927ec681f3Smrg if (instance->ring.shmem) { 7937ec681f3Smrg uint32_t destroy_ring_data[4]; 7947ec681f3Smrg struct vn_cs_encoder local_enc = VN_CS_ENCODER_INITIALIZER_LOCAL( 7957ec681f3Smrg destroy_ring_data, sizeof(destroy_ring_data)); 7967ec681f3Smrg vn_encode_vkDestroyRingMESA(&local_enc, 0, instance->ring.id); 7977ec681f3Smrg vn_renderer_submit_simple(instance->renderer, destroy_ring_data, 7987ec681f3Smrg vn_cs_encoder_get_len(&local_enc)); 7997ec681f3Smrg 8007ec681f3Smrg mtx_destroy(&instance->ring.roundtrip_mutex); 8017ec681f3Smrg vn_cs_encoder_fini(&instance->ring.upload); 8027ec681f3Smrg vn_renderer_shmem_unref(instance->renderer, instance->ring.shmem); 8037ec681f3Smrg vn_ring_fini(&instance->ring.ring); 8047ec681f3Smrg mtx_destroy(&instance->ring.mutex); 8057ec681f3Smrg } 8067ec681f3Smrg 8077ec681f3Smrg if (instance->renderer) 8087ec681f3Smrg vn_renderer_destroy(instance->renderer, alloc); 8097ec681f3Smrg 8107ec681f3Smrg mtx_destroy(&instance->physical_device.mutex); 8117ec681f3Smrg 8127ec681f3Smrg vn_instance_base_fini(&instance->base); 8137ec681f3Smrg vk_free(alloc, instance); 8147ec681f3Smrg 8157ec681f3Smrg return vn_error(NULL, result); 8167ec681f3Smrg} 8177ec681f3Smrg 8187ec681f3Smrgvoid 8197ec681f3Smrgvn_DestroyInstance(VkInstance _instance, 8207ec681f3Smrg const VkAllocationCallbacks *pAllocator) 8217ec681f3Smrg{ 8227ec681f3Smrg struct vn_instance *instance = vn_instance_from_handle(_instance); 8237ec681f3Smrg const VkAllocationCallbacks *alloc = 8247ec681f3Smrg pAllocator ? pAllocator : &instance->base.base.alloc; 8257ec681f3Smrg 8267ec681f3Smrg if (!instance) 8277ec681f3Smrg return; 8287ec681f3Smrg 8297ec681f3Smrg if (instance->physical_device.initialized) { 8307ec681f3Smrg for (uint32_t i = 0; i < instance->physical_device.device_count; i++) 8317ec681f3Smrg vn_physical_device_fini(&instance->physical_device.devices[i]); 8327ec681f3Smrg vk_free(alloc, instance->physical_device.devices); 8337ec681f3Smrg vk_free(alloc, instance->physical_device.groups); 8347ec681f3Smrg } 8357ec681f3Smrg mtx_destroy(&instance->physical_device.mutex); 8367ec681f3Smrg 8377ec681f3Smrg vn_call_vkDestroyInstance(instance, _instance, NULL); 8387ec681f3Smrg 8397ec681f3Smrg vn_renderer_shmem_unref(instance->renderer, instance->reply.shmem); 8407ec681f3Smrg 8417ec681f3Smrg uint32_t destroy_ring_data[4]; 8427ec681f3Smrg struct vn_cs_encoder local_enc = VN_CS_ENCODER_INITIALIZER_LOCAL( 8437ec681f3Smrg destroy_ring_data, sizeof(destroy_ring_data)); 8447ec681f3Smrg vn_encode_vkDestroyRingMESA(&local_enc, 0, instance->ring.id); 8457ec681f3Smrg vn_renderer_submit_simple(instance->renderer, destroy_ring_data, 8467ec681f3Smrg vn_cs_encoder_get_len(&local_enc)); 8477ec681f3Smrg 8487ec681f3Smrg mtx_destroy(&instance->ring.roundtrip_mutex); 8497ec681f3Smrg vn_cs_encoder_fini(&instance->ring.upload); 8507ec681f3Smrg vn_ring_fini(&instance->ring.ring); 8517ec681f3Smrg mtx_destroy(&instance->ring.mutex); 8527ec681f3Smrg vn_renderer_shmem_unref(instance->renderer, instance->ring.shmem); 8537ec681f3Smrg 8547ec681f3Smrg vn_renderer_destroy(instance->renderer, alloc); 8557ec681f3Smrg 8567ec681f3Smrg driDestroyOptionCache(&instance->dri_options); 8577ec681f3Smrg driDestroyOptionInfo(&instance->available_dri_options); 8587ec681f3Smrg 8597ec681f3Smrg vn_instance_base_fini(&instance->base); 8607ec681f3Smrg vk_free(alloc, instance); 8617ec681f3Smrg} 8627ec681f3Smrg 8637ec681f3SmrgPFN_vkVoidFunction 8647ec681f3Smrgvn_GetInstanceProcAddr(VkInstance _instance, const char *pName) 8657ec681f3Smrg{ 8667ec681f3Smrg struct vn_instance *instance = vn_instance_from_handle(_instance); 8677ec681f3Smrg return vk_instance_get_proc_addr(&instance->base.base, 8687ec681f3Smrg &vn_instance_entrypoints, pName); 8697ec681f3Smrg} 870