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