1bf215546Sopenharmony_ci/*
2bf215546Sopenharmony_ci * Copyright 2019 Google LLC
3bf215546Sopenharmony_ci * SPDX-License-Identifier: MIT
4bf215546Sopenharmony_ci *
5bf215546Sopenharmony_ci * based in part on anv and radv which are:
6bf215546Sopenharmony_ci * Copyright © 2015 Intel Corporation
7bf215546Sopenharmony_ci * Copyright © 2016 Red Hat.
8bf215546Sopenharmony_ci * Copyright © 2016 Bas Nieuwenhuizen
9bf215546Sopenharmony_ci */
10bf215546Sopenharmony_ci
11bf215546Sopenharmony_ci#include "vn_instance.h"
12bf215546Sopenharmony_ci
13bf215546Sopenharmony_ci#include "util/driconf.h"
14bf215546Sopenharmony_ci#include "venus-protocol/vn_protocol_driver_info.h"
15bf215546Sopenharmony_ci#include "venus-protocol/vn_protocol_driver_instance.h"
16bf215546Sopenharmony_ci#include "venus-protocol/vn_protocol_driver_transport.h"
17bf215546Sopenharmony_ci
18bf215546Sopenharmony_ci#include "vn_icd.h"
19bf215546Sopenharmony_ci#include "vn_physical_device.h"
20bf215546Sopenharmony_ci#include "vn_renderer.h"
21bf215546Sopenharmony_ci
22bf215546Sopenharmony_ci#define VN_INSTANCE_LARGE_RING_SIZE (64 * 1024)
23bf215546Sopenharmony_ci#define VN_INSTANCE_LARGE_RING_DIRECT_THRESHOLD                              \
24bf215546Sopenharmony_ci   (VN_INSTANCE_LARGE_RING_SIZE / 16)
25bf215546Sopenharmony_ci
26bf215546Sopenharmony_ci/* this must not exceed 2KiB for the ring to fit in a 4K page */
27bf215546Sopenharmony_ci#define VN_INSTANCE_RING_SIZE (2 * 1024)
28bf215546Sopenharmony_ci#define VN_INSTANCE_RING_DIRECT_THRESHOLD (VN_INSTANCE_RING_SIZE / 8)
29bf215546Sopenharmony_ci
30bf215546Sopenharmony_ci/*
31bf215546Sopenharmony_ci * Instance extensions add instance-level or physical-device-level
32bf215546Sopenharmony_ci * functionalities.  It seems renderer support is either unnecessary or
33bf215546Sopenharmony_ci * optional.  We should be able to advertise them or lie about them locally.
34bf215546Sopenharmony_ci */
35bf215546Sopenharmony_cistatic const struct vk_instance_extension_table
36bf215546Sopenharmony_ci   vn_instance_supported_extensions = {
37bf215546Sopenharmony_ci      /* promoted to VK_VERSION_1_1 */
38bf215546Sopenharmony_ci      .KHR_device_group_creation = true,
39bf215546Sopenharmony_ci      .KHR_external_fence_capabilities = true,
40bf215546Sopenharmony_ci      .KHR_external_memory_capabilities = true,
41bf215546Sopenharmony_ci      .KHR_external_semaphore_capabilities = true,
42bf215546Sopenharmony_ci      .KHR_get_physical_device_properties2 = true,
43bf215546Sopenharmony_ci
44bf215546Sopenharmony_ci#ifdef VN_USE_WSI_PLATFORM
45bf215546Sopenharmony_ci      .KHR_get_surface_capabilities2 = true,
46bf215546Sopenharmony_ci      .KHR_surface = true,
47bf215546Sopenharmony_ci      .KHR_surface_protected_capabilities = true,
48bf215546Sopenharmony_ci#endif
49bf215546Sopenharmony_ci#ifdef VK_USE_PLATFORM_WAYLAND_KHR
50bf215546Sopenharmony_ci      .KHR_wayland_surface = true,
51bf215546Sopenharmony_ci#endif
52bf215546Sopenharmony_ci#ifdef VK_USE_PLATFORM_XCB_KHR
53bf215546Sopenharmony_ci      .KHR_xcb_surface = true,
54bf215546Sopenharmony_ci#endif
55bf215546Sopenharmony_ci#ifdef VK_USE_PLATFORM_XLIB_KHR
56bf215546Sopenharmony_ci      .KHR_xlib_surface = true,
57bf215546Sopenharmony_ci#endif
58bf215546Sopenharmony_ci   };
59bf215546Sopenharmony_ci
60bf215546Sopenharmony_cistatic const driOptionDescription vn_dri_options[] = {
61bf215546Sopenharmony_ci   /* clang-format off */
62bf215546Sopenharmony_ci   DRI_CONF_SECTION_PERFORMANCE
63bf215546Sopenharmony_ci      DRI_CONF_VK_X11_ENSURE_MIN_IMAGE_COUNT(false)
64bf215546Sopenharmony_ci      DRI_CONF_VK_X11_OVERRIDE_MIN_IMAGE_COUNT(0)
65bf215546Sopenharmony_ci      DRI_CONF_VK_X11_STRICT_IMAGE_COUNT(false)
66bf215546Sopenharmony_ci      DRI_CONF_VK_XWAYLAND_WAIT_READY(true)
67bf215546Sopenharmony_ci      DRI_CONF_VENUS_IMPLICIT_FENCING(false)
68bf215546Sopenharmony_ci   DRI_CONF_SECTION_END
69bf215546Sopenharmony_ci   DRI_CONF_SECTION_DEBUG
70bf215546Sopenharmony_ci      DRI_CONF_VK_WSI_FORCE_BGRA8_UNORM_FIRST(false)
71bf215546Sopenharmony_ci   DRI_CONF_SECTION_END
72bf215546Sopenharmony_ci   /* clang-format on */
73bf215546Sopenharmony_ci};
74bf215546Sopenharmony_ci
75bf215546Sopenharmony_cistatic VkResult
76bf215546Sopenharmony_civn_instance_init_renderer_versions(struct vn_instance *instance)
77bf215546Sopenharmony_ci{
78bf215546Sopenharmony_ci   uint32_t instance_version = 0;
79bf215546Sopenharmony_ci   VkResult result =
80bf215546Sopenharmony_ci      vn_call_vkEnumerateInstanceVersion(instance, &instance_version);
81bf215546Sopenharmony_ci   if (result != VK_SUCCESS) {
82bf215546Sopenharmony_ci      if (VN_DEBUG(INIT))
83bf215546Sopenharmony_ci         vn_log(instance, "failed to enumerate renderer instance version");
84bf215546Sopenharmony_ci      return result;
85bf215546Sopenharmony_ci   }
86bf215546Sopenharmony_ci
87bf215546Sopenharmony_ci   if (instance_version < VN_MIN_RENDERER_VERSION) {
88bf215546Sopenharmony_ci      if (VN_DEBUG(INIT)) {
89bf215546Sopenharmony_ci         vn_log(instance, "unsupported renderer instance version %d.%d",
90bf215546Sopenharmony_ci                VK_VERSION_MAJOR(instance_version),
91bf215546Sopenharmony_ci                VK_VERSION_MINOR(instance_version));
92bf215546Sopenharmony_ci      }
93bf215546Sopenharmony_ci      return VK_ERROR_INITIALIZATION_FAILED;
94bf215546Sopenharmony_ci   }
95bf215546Sopenharmony_ci
96bf215546Sopenharmony_ci   if (VN_DEBUG(INIT)) {
97bf215546Sopenharmony_ci      vn_log(instance, "renderer instance version %d.%d.%d",
98bf215546Sopenharmony_ci             VK_VERSION_MAJOR(instance_version),
99bf215546Sopenharmony_ci             VK_VERSION_MINOR(instance_version),
100bf215546Sopenharmony_ci             VK_VERSION_PATCH(instance_version));
101bf215546Sopenharmony_ci   }
102bf215546Sopenharmony_ci
103bf215546Sopenharmony_ci   /* request at least VN_MIN_RENDERER_VERSION internally */
104bf215546Sopenharmony_ci   instance->renderer_api_version =
105bf215546Sopenharmony_ci      MAX2(instance->base.base.app_info.api_version, VN_MIN_RENDERER_VERSION);
106bf215546Sopenharmony_ci
107bf215546Sopenharmony_ci   /* instance version for internal use is capped */
108bf215546Sopenharmony_ci   instance_version = MIN3(instance_version, instance->renderer_api_version,
109bf215546Sopenharmony_ci                           instance->renderer->info.vk_xml_version);
110bf215546Sopenharmony_ci   assert(instance_version >= VN_MIN_RENDERER_VERSION);
111bf215546Sopenharmony_ci
112bf215546Sopenharmony_ci   instance->renderer_version = instance_version;
113bf215546Sopenharmony_ci
114bf215546Sopenharmony_ci   return VK_SUCCESS;
115bf215546Sopenharmony_ci}
116bf215546Sopenharmony_ci
117bf215546Sopenharmony_cistatic VkResult
118bf215546Sopenharmony_civn_instance_init_ring(struct vn_instance *instance)
119bf215546Sopenharmony_ci{
120bf215546Sopenharmony_ci   const size_t buf_size = instance->experimental.largeRing
121bf215546Sopenharmony_ci                              ? VN_INSTANCE_LARGE_RING_SIZE
122bf215546Sopenharmony_ci                              : VN_INSTANCE_RING_SIZE;
123bf215546Sopenharmony_ci   /* 32-bit seqno for renderer roundtrips */
124bf215546Sopenharmony_ci   const size_t extra_size = sizeof(uint32_t);
125bf215546Sopenharmony_ci   struct vn_ring_layout layout;
126bf215546Sopenharmony_ci   vn_ring_get_layout(buf_size, extra_size, &layout);
127bf215546Sopenharmony_ci
128bf215546Sopenharmony_ci   instance->ring.shmem =
129bf215546Sopenharmony_ci      vn_renderer_shmem_create(instance->renderer, layout.shmem_size);
130bf215546Sopenharmony_ci   if (!instance->ring.shmem) {
131bf215546Sopenharmony_ci      if (VN_DEBUG(INIT))
132bf215546Sopenharmony_ci         vn_log(instance, "failed to allocate/map ring shmem");
133bf215546Sopenharmony_ci      return VK_ERROR_OUT_OF_HOST_MEMORY;
134bf215546Sopenharmony_ci   }
135bf215546Sopenharmony_ci
136bf215546Sopenharmony_ci   mtx_init(&instance->ring.mutex, mtx_plain);
137bf215546Sopenharmony_ci
138bf215546Sopenharmony_ci   struct vn_ring *ring = &instance->ring.ring;
139bf215546Sopenharmony_ci   vn_ring_init(ring, instance->renderer, &layout,
140bf215546Sopenharmony_ci                instance->ring.shmem->mmap_ptr);
141bf215546Sopenharmony_ci
142bf215546Sopenharmony_ci   instance->ring.id = (uintptr_t)ring;
143bf215546Sopenharmony_ci
144bf215546Sopenharmony_ci   const struct VkRingCreateInfoMESA info = {
145bf215546Sopenharmony_ci      .sType = VK_STRUCTURE_TYPE_RING_CREATE_INFO_MESA,
146bf215546Sopenharmony_ci      .resourceId = instance->ring.shmem->res_id,
147bf215546Sopenharmony_ci      .size = layout.shmem_size,
148bf215546Sopenharmony_ci      .idleTimeout = 50ull * 1000 * 1000,
149bf215546Sopenharmony_ci      .headOffset = layout.head_offset,
150bf215546Sopenharmony_ci      .tailOffset = layout.tail_offset,
151bf215546Sopenharmony_ci      .statusOffset = layout.status_offset,
152bf215546Sopenharmony_ci      .bufferOffset = layout.buffer_offset,
153bf215546Sopenharmony_ci      .bufferSize = layout.buffer_size,
154bf215546Sopenharmony_ci      .extraOffset = layout.extra_offset,
155bf215546Sopenharmony_ci      .extraSize = layout.extra_size,
156bf215546Sopenharmony_ci   };
157bf215546Sopenharmony_ci
158bf215546Sopenharmony_ci   uint32_t create_ring_data[64];
159bf215546Sopenharmony_ci   struct vn_cs_encoder local_enc = VN_CS_ENCODER_INITIALIZER_LOCAL(
160bf215546Sopenharmony_ci      create_ring_data, sizeof(create_ring_data));
161bf215546Sopenharmony_ci   vn_encode_vkCreateRingMESA(&local_enc, 0, instance->ring.id, &info);
162bf215546Sopenharmony_ci   vn_renderer_submit_simple(instance->renderer, create_ring_data,
163bf215546Sopenharmony_ci                             vn_cs_encoder_get_len(&local_enc));
164bf215546Sopenharmony_ci
165bf215546Sopenharmony_ci   vn_cs_encoder_init(&instance->ring.upload, instance,
166bf215546Sopenharmony_ci                      VN_CS_ENCODER_STORAGE_SHMEM_ARRAY, 1 * 1024 * 1024);
167bf215546Sopenharmony_ci
168bf215546Sopenharmony_ci   mtx_init(&instance->ring.roundtrip_mutex, mtx_plain);
169bf215546Sopenharmony_ci   instance->ring.roundtrip_next = 1;
170bf215546Sopenharmony_ci
171bf215546Sopenharmony_ci   return VK_SUCCESS;
172bf215546Sopenharmony_ci}
173bf215546Sopenharmony_ci
174bf215546Sopenharmony_cistatic struct vn_renderer_shmem *
175bf215546Sopenharmony_civn_instance_get_reply_shmem_locked(struct vn_instance *instance,
176bf215546Sopenharmony_ci                                   size_t size,
177bf215546Sopenharmony_ci                                   void **ptr);
178bf215546Sopenharmony_ci
179bf215546Sopenharmony_cistatic VkResult
180bf215546Sopenharmony_civn_instance_init_experimental_features(struct vn_instance *instance)
181bf215546Sopenharmony_ci{
182bf215546Sopenharmony_ci   if (instance->renderer->info.vk_mesa_venus_protocol_spec_version !=
183bf215546Sopenharmony_ci       100000) {
184bf215546Sopenharmony_ci      if (VN_DEBUG(INIT))
185bf215546Sopenharmony_ci         vn_log(instance, "renderer supports no experimental features");
186bf215546Sopenharmony_ci      return VK_SUCCESS;
187bf215546Sopenharmony_ci   }
188bf215546Sopenharmony_ci
189bf215546Sopenharmony_ci   size_t struct_size = sizeof(instance->experimental);
190bf215546Sopenharmony_ci
191bf215546Sopenharmony_ci   /* prepare the reply shmem */
192bf215546Sopenharmony_ci   const size_t reply_size =
193bf215546Sopenharmony_ci      vn_sizeof_vkGetVenusExperimentalFeatureData100000MESA_reply(
194bf215546Sopenharmony_ci         &struct_size, &instance->experimental);
195bf215546Sopenharmony_ci   void *reply_ptr;
196bf215546Sopenharmony_ci   struct vn_renderer_shmem *reply_shmem =
197bf215546Sopenharmony_ci      vn_instance_get_reply_shmem_locked(instance, reply_size, &reply_ptr);
198bf215546Sopenharmony_ci   if (!reply_shmem)
199bf215546Sopenharmony_ci      return VK_ERROR_OUT_OF_HOST_MEMORY;
200bf215546Sopenharmony_ci
201bf215546Sopenharmony_ci   /* encode the command */
202bf215546Sopenharmony_ci   uint32_t local_data[16];
203bf215546Sopenharmony_ci   struct vn_cs_encoder local_enc =
204bf215546Sopenharmony_ci      VN_CS_ENCODER_INITIALIZER_LOCAL(local_data, sizeof(local_data));
205bf215546Sopenharmony_ci   vn_encode_vkGetVenusExperimentalFeatureData100000MESA(
206bf215546Sopenharmony_ci      &local_enc, VK_COMMAND_GENERATE_REPLY_BIT_EXT, &struct_size,
207bf215546Sopenharmony_ci      &instance->experimental);
208bf215546Sopenharmony_ci
209bf215546Sopenharmony_ci   VkResult result = vn_renderer_submit_simple_sync(
210bf215546Sopenharmony_ci      instance->renderer, local_data, vn_cs_encoder_get_len(&local_enc));
211bf215546Sopenharmony_ci   if (result != VK_SUCCESS) {
212bf215546Sopenharmony_ci      vn_renderer_shmem_unref(instance->renderer, reply_shmem);
213bf215546Sopenharmony_ci      return result;
214bf215546Sopenharmony_ci   }
215bf215546Sopenharmony_ci
216bf215546Sopenharmony_ci   struct vn_cs_decoder reply_dec =
217bf215546Sopenharmony_ci      VN_CS_DECODER_INITIALIZER(reply_ptr, reply_size);
218bf215546Sopenharmony_ci   vn_decode_vkGetVenusExperimentalFeatureData100000MESA_reply(
219bf215546Sopenharmony_ci      &reply_dec, &struct_size, &instance->experimental);
220bf215546Sopenharmony_ci   vn_renderer_shmem_unref(instance->renderer, reply_shmem);
221bf215546Sopenharmony_ci
222bf215546Sopenharmony_ci   if (VN_DEBUG(INIT)) {
223bf215546Sopenharmony_ci      vn_log(instance,
224bf215546Sopenharmony_ci             "VkVenusExperimentalFeatures100000MESA is as below:"
225bf215546Sopenharmony_ci             "\n\tmemoryResourceAllocationSize = %u"
226bf215546Sopenharmony_ci             "\n\tglobalFencing = %u"
227bf215546Sopenharmony_ci             "\n\tlargeRing = %u",
228bf215546Sopenharmony_ci             instance->experimental.memoryResourceAllocationSize,
229bf215546Sopenharmony_ci             instance->experimental.globalFencing,
230bf215546Sopenharmony_ci             instance->experimental.largeRing);
231bf215546Sopenharmony_ci   }
232bf215546Sopenharmony_ci
233bf215546Sopenharmony_ci   return VK_SUCCESS;
234bf215546Sopenharmony_ci}
235bf215546Sopenharmony_ci
236bf215546Sopenharmony_cistatic VkResult
237bf215546Sopenharmony_civn_instance_init_renderer(struct vn_instance *instance)
238bf215546Sopenharmony_ci{
239bf215546Sopenharmony_ci   const VkAllocationCallbacks *alloc = &instance->base.base.alloc;
240bf215546Sopenharmony_ci
241bf215546Sopenharmony_ci   VkResult result = vn_renderer_create(instance, alloc, &instance->renderer);
242bf215546Sopenharmony_ci   if (result != VK_SUCCESS)
243bf215546Sopenharmony_ci      return result;
244bf215546Sopenharmony_ci
245bf215546Sopenharmony_ci   struct vn_renderer_info *renderer_info = &instance->renderer->info;
246bf215546Sopenharmony_ci   uint32_t version = vn_info_wire_format_version();
247bf215546Sopenharmony_ci   if (renderer_info->wire_format_version != version) {
248bf215546Sopenharmony_ci      if (VN_DEBUG(INIT)) {
249bf215546Sopenharmony_ci         vn_log(instance, "wire format version %d != %d",
250bf215546Sopenharmony_ci                renderer_info->wire_format_version, version);
251bf215546Sopenharmony_ci      }
252bf215546Sopenharmony_ci      return VK_ERROR_INITIALIZATION_FAILED;
253bf215546Sopenharmony_ci   }
254bf215546Sopenharmony_ci
255bf215546Sopenharmony_ci   version = vn_info_vk_xml_version();
256bf215546Sopenharmony_ci   if (renderer_info->vk_xml_version > version)
257bf215546Sopenharmony_ci      renderer_info->vk_xml_version = version;
258bf215546Sopenharmony_ci   if (renderer_info->vk_xml_version < VN_MIN_RENDERER_VERSION) {
259bf215546Sopenharmony_ci      if (VN_DEBUG(INIT)) {
260bf215546Sopenharmony_ci         vn_log(instance, "vk xml version %d.%d.%d < %d.%d.%d",
261bf215546Sopenharmony_ci                VK_VERSION_MAJOR(renderer_info->vk_xml_version),
262bf215546Sopenharmony_ci                VK_VERSION_MINOR(renderer_info->vk_xml_version),
263bf215546Sopenharmony_ci                VK_VERSION_PATCH(renderer_info->vk_xml_version),
264bf215546Sopenharmony_ci                VK_VERSION_MAJOR(VN_MIN_RENDERER_VERSION),
265bf215546Sopenharmony_ci                VK_VERSION_MINOR(VN_MIN_RENDERER_VERSION),
266bf215546Sopenharmony_ci                VK_VERSION_PATCH(VN_MIN_RENDERER_VERSION));
267bf215546Sopenharmony_ci      }
268bf215546Sopenharmony_ci      return VK_ERROR_INITIALIZATION_FAILED;
269bf215546Sopenharmony_ci   }
270bf215546Sopenharmony_ci
271bf215546Sopenharmony_ci   uint32_t spec_version =
272bf215546Sopenharmony_ci      vn_extension_get_spec_version("VK_EXT_command_serialization");
273bf215546Sopenharmony_ci   if (renderer_info->vk_ext_command_serialization_spec_version >
274bf215546Sopenharmony_ci       spec_version) {
275bf215546Sopenharmony_ci      renderer_info->vk_ext_command_serialization_spec_version = spec_version;
276bf215546Sopenharmony_ci   }
277bf215546Sopenharmony_ci
278bf215546Sopenharmony_ci   spec_version = vn_extension_get_spec_version("VK_MESA_venus_protocol");
279bf215546Sopenharmony_ci   if (renderer_info->vk_mesa_venus_protocol_spec_version > spec_version)
280bf215546Sopenharmony_ci      renderer_info->vk_mesa_venus_protocol_spec_version = spec_version;
281bf215546Sopenharmony_ci
282bf215546Sopenharmony_ci   if (VN_DEBUG(INIT)) {
283bf215546Sopenharmony_ci      vn_log(instance, "connected to renderer");
284bf215546Sopenharmony_ci      vn_log(instance, "wire format version %d",
285bf215546Sopenharmony_ci             renderer_info->wire_format_version);
286bf215546Sopenharmony_ci      vn_log(instance, "vk xml version %d.%d.%d",
287bf215546Sopenharmony_ci             VK_VERSION_MAJOR(renderer_info->vk_xml_version),
288bf215546Sopenharmony_ci             VK_VERSION_MINOR(renderer_info->vk_xml_version),
289bf215546Sopenharmony_ci             VK_VERSION_PATCH(renderer_info->vk_xml_version));
290bf215546Sopenharmony_ci      vn_log(instance, "VK_EXT_command_serialization spec version %d",
291bf215546Sopenharmony_ci             renderer_info->vk_ext_command_serialization_spec_version);
292bf215546Sopenharmony_ci      vn_log(instance, "VK_MESA_venus_protocol spec version %d",
293bf215546Sopenharmony_ci             renderer_info->vk_mesa_venus_protocol_spec_version);
294bf215546Sopenharmony_ci      vn_log(instance, "supports blob id 0: %d",
295bf215546Sopenharmony_ci             renderer_info->supports_blob_id_0);
296bf215546Sopenharmony_ci      vn_log(instance, "allow_vk_wait_syncs: %d",
297bf215546Sopenharmony_ci             renderer_info->allow_vk_wait_syncs);
298bf215546Sopenharmony_ci   }
299bf215546Sopenharmony_ci
300bf215546Sopenharmony_ci   return VK_SUCCESS;
301bf215546Sopenharmony_ci}
302bf215546Sopenharmony_ci
303bf215546Sopenharmony_ciVkResult
304bf215546Sopenharmony_civn_instance_submit_roundtrip(struct vn_instance *instance,
305bf215546Sopenharmony_ci                             uint32_t *roundtrip_seqno)
306bf215546Sopenharmony_ci{
307bf215546Sopenharmony_ci   uint32_t write_ring_extra_data[8];
308bf215546Sopenharmony_ci   struct vn_cs_encoder local_enc = VN_CS_ENCODER_INITIALIZER_LOCAL(
309bf215546Sopenharmony_ci      write_ring_extra_data, sizeof(write_ring_extra_data));
310bf215546Sopenharmony_ci
311bf215546Sopenharmony_ci   /* submit a vkWriteRingExtraMESA through the renderer */
312bf215546Sopenharmony_ci   mtx_lock(&instance->ring.roundtrip_mutex);
313bf215546Sopenharmony_ci   const uint32_t seqno = instance->ring.roundtrip_next++;
314bf215546Sopenharmony_ci   vn_encode_vkWriteRingExtraMESA(&local_enc, 0, instance->ring.id, 0, seqno);
315bf215546Sopenharmony_ci   VkResult result =
316bf215546Sopenharmony_ci      vn_renderer_submit_simple(instance->renderer, write_ring_extra_data,
317bf215546Sopenharmony_ci                                vn_cs_encoder_get_len(&local_enc));
318bf215546Sopenharmony_ci   mtx_unlock(&instance->ring.roundtrip_mutex);
319bf215546Sopenharmony_ci
320bf215546Sopenharmony_ci   *roundtrip_seqno = seqno;
321bf215546Sopenharmony_ci   return result;
322bf215546Sopenharmony_ci}
323bf215546Sopenharmony_ci
324bf215546Sopenharmony_cistatic bool
325bf215546Sopenharmony_ciroundtrip_seqno_ge(uint32_t a, uint32_t b)
326bf215546Sopenharmony_ci{
327bf215546Sopenharmony_ci   /* a >= b, but deal with wrapping as well */
328bf215546Sopenharmony_ci   return (a - b) <= INT32_MAX;
329bf215546Sopenharmony_ci}
330bf215546Sopenharmony_ci
331bf215546Sopenharmony_civoid
332bf215546Sopenharmony_civn_instance_wait_roundtrip(struct vn_instance *instance,
333bf215546Sopenharmony_ci                           uint32_t roundtrip_seqno)
334bf215546Sopenharmony_ci{
335bf215546Sopenharmony_ci   VN_TRACE_FUNC();
336bf215546Sopenharmony_ci   const struct vn_ring *ring = &instance->ring.ring;
337bf215546Sopenharmony_ci   const volatile atomic_uint *ptr = ring->shared.extra;
338bf215546Sopenharmony_ci   uint32_t iter = 0;
339bf215546Sopenharmony_ci   do {
340bf215546Sopenharmony_ci      const uint32_t cur = atomic_load_explicit(ptr, memory_order_acquire);
341bf215546Sopenharmony_ci      if (roundtrip_seqno_ge(cur, roundtrip_seqno))
342bf215546Sopenharmony_ci         break;
343bf215546Sopenharmony_ci      vn_relax(&iter, "roundtrip");
344bf215546Sopenharmony_ci   } while (true);
345bf215546Sopenharmony_ci}
346bf215546Sopenharmony_ci
347bf215546Sopenharmony_cistruct vn_instance_submission {
348bf215546Sopenharmony_ci   const struct vn_cs_encoder *cs;
349bf215546Sopenharmony_ci   struct vn_ring_submit *submit;
350bf215546Sopenharmony_ci
351bf215546Sopenharmony_ci   struct {
352bf215546Sopenharmony_ci      struct vn_cs_encoder cs;
353bf215546Sopenharmony_ci      struct vn_cs_encoder_buffer buffer;
354bf215546Sopenharmony_ci      uint32_t data[64];
355bf215546Sopenharmony_ci   } indirect;
356bf215546Sopenharmony_ci};
357bf215546Sopenharmony_ci
358bf215546Sopenharmony_cistatic const struct vn_cs_encoder *
359bf215546Sopenharmony_civn_instance_submission_get_cs(struct vn_instance_submission *submit,
360bf215546Sopenharmony_ci                              const struct vn_cs_encoder *cs,
361bf215546Sopenharmony_ci                              bool direct)
362bf215546Sopenharmony_ci{
363bf215546Sopenharmony_ci   if (direct)
364bf215546Sopenharmony_ci      return cs;
365bf215546Sopenharmony_ci
366bf215546Sopenharmony_ci   VkCommandStreamDescriptionMESA local_descs[8];
367bf215546Sopenharmony_ci   VkCommandStreamDescriptionMESA *descs = local_descs;
368bf215546Sopenharmony_ci   if (cs->buffer_count > ARRAY_SIZE(local_descs)) {
369bf215546Sopenharmony_ci      descs =
370bf215546Sopenharmony_ci         malloc(sizeof(VkCommandStreamDescriptionMESA) * cs->buffer_count);
371bf215546Sopenharmony_ci      if (!descs)
372bf215546Sopenharmony_ci         return NULL;
373bf215546Sopenharmony_ci   }
374bf215546Sopenharmony_ci
375bf215546Sopenharmony_ci   uint32_t desc_count = 0;
376bf215546Sopenharmony_ci   for (uint32_t i = 0; i < cs->buffer_count; i++) {
377bf215546Sopenharmony_ci      const struct vn_cs_encoder_buffer *buf = &cs->buffers[i];
378bf215546Sopenharmony_ci      if (buf->committed_size) {
379bf215546Sopenharmony_ci         descs[desc_count++] = (VkCommandStreamDescriptionMESA){
380bf215546Sopenharmony_ci            .resourceId = buf->shmem->res_id,
381bf215546Sopenharmony_ci            .offset = buf->offset,
382bf215546Sopenharmony_ci            .size = buf->committed_size,
383bf215546Sopenharmony_ci         };
384bf215546Sopenharmony_ci      }
385bf215546Sopenharmony_ci   }
386bf215546Sopenharmony_ci
387bf215546Sopenharmony_ci   const size_t exec_size = vn_sizeof_vkExecuteCommandStreamsMESA(
388bf215546Sopenharmony_ci      desc_count, descs, NULL, 0, NULL, 0);
389bf215546Sopenharmony_ci   void *exec_data = submit->indirect.data;
390bf215546Sopenharmony_ci   if (exec_size > sizeof(submit->indirect.data)) {
391bf215546Sopenharmony_ci      exec_data = malloc(exec_size);
392bf215546Sopenharmony_ci      if (!exec_data) {
393bf215546Sopenharmony_ci         if (descs != local_descs)
394bf215546Sopenharmony_ci            free(descs);
395bf215546Sopenharmony_ci         return NULL;
396bf215546Sopenharmony_ci      }
397bf215546Sopenharmony_ci   }
398bf215546Sopenharmony_ci
399bf215546Sopenharmony_ci   submit->indirect.buffer = VN_CS_ENCODER_BUFFER_INITIALIZER(exec_data);
400bf215546Sopenharmony_ci   submit->indirect.cs =
401bf215546Sopenharmony_ci      VN_CS_ENCODER_INITIALIZER(&submit->indirect.buffer, exec_size);
402bf215546Sopenharmony_ci   vn_encode_vkExecuteCommandStreamsMESA(&submit->indirect.cs, 0, desc_count,
403bf215546Sopenharmony_ci                                         descs, NULL, 0, NULL, 0);
404bf215546Sopenharmony_ci   vn_cs_encoder_commit(&submit->indirect.cs);
405bf215546Sopenharmony_ci
406bf215546Sopenharmony_ci   if (descs != local_descs)
407bf215546Sopenharmony_ci      free(descs);
408bf215546Sopenharmony_ci
409bf215546Sopenharmony_ci   return &submit->indirect.cs;
410bf215546Sopenharmony_ci}
411bf215546Sopenharmony_ci
412bf215546Sopenharmony_cistatic struct vn_ring_submit *
413bf215546Sopenharmony_civn_instance_submission_get_ring_submit(struct vn_ring *ring,
414bf215546Sopenharmony_ci                                       const struct vn_cs_encoder *cs,
415bf215546Sopenharmony_ci                                       struct vn_renderer_shmem *extra_shmem,
416bf215546Sopenharmony_ci                                       bool direct)
417bf215546Sopenharmony_ci{
418bf215546Sopenharmony_ci   const uint32_t shmem_count =
419bf215546Sopenharmony_ci      (direct ? 0 : cs->buffer_count) + (extra_shmem ? 1 : 0);
420bf215546Sopenharmony_ci   struct vn_ring_submit *submit = vn_ring_get_submit(ring, shmem_count);
421bf215546Sopenharmony_ci   if (!submit)
422bf215546Sopenharmony_ci      return NULL;
423bf215546Sopenharmony_ci
424bf215546Sopenharmony_ci   submit->shmem_count = shmem_count;
425bf215546Sopenharmony_ci   if (!direct) {
426bf215546Sopenharmony_ci      for (uint32_t i = 0; i < cs->buffer_count; i++) {
427bf215546Sopenharmony_ci         submit->shmems[i] =
428bf215546Sopenharmony_ci            vn_renderer_shmem_ref(ring->renderer, cs->buffers[i].shmem);
429bf215546Sopenharmony_ci      }
430bf215546Sopenharmony_ci   }
431bf215546Sopenharmony_ci   if (extra_shmem) {
432bf215546Sopenharmony_ci      submit->shmems[shmem_count - 1] =
433bf215546Sopenharmony_ci         vn_renderer_shmem_ref(ring->renderer, extra_shmem);
434bf215546Sopenharmony_ci   }
435bf215546Sopenharmony_ci
436bf215546Sopenharmony_ci   return submit;
437bf215546Sopenharmony_ci}
438bf215546Sopenharmony_ci
439bf215546Sopenharmony_cistatic void
440bf215546Sopenharmony_civn_instance_submission_cleanup(struct vn_instance_submission *submit)
441bf215546Sopenharmony_ci{
442bf215546Sopenharmony_ci   if (submit->cs == &submit->indirect.cs &&
443bf215546Sopenharmony_ci       submit->indirect.buffer.base != submit->indirect.data)
444bf215546Sopenharmony_ci      free(submit->indirect.buffer.base);
445bf215546Sopenharmony_ci}
446bf215546Sopenharmony_ci
447bf215546Sopenharmony_cistatic VkResult
448bf215546Sopenharmony_civn_instance_submission_prepare(struct vn_instance_submission *submit,
449bf215546Sopenharmony_ci                               const struct vn_cs_encoder *cs,
450bf215546Sopenharmony_ci                               struct vn_ring *ring,
451bf215546Sopenharmony_ci                               struct vn_renderer_shmem *extra_shmem,
452bf215546Sopenharmony_ci                               bool direct)
453bf215546Sopenharmony_ci{
454bf215546Sopenharmony_ci   submit->cs = vn_instance_submission_get_cs(submit, cs, direct);
455bf215546Sopenharmony_ci   if (!submit->cs)
456bf215546Sopenharmony_ci      return VK_ERROR_OUT_OF_HOST_MEMORY;
457bf215546Sopenharmony_ci
458bf215546Sopenharmony_ci   submit->submit =
459bf215546Sopenharmony_ci      vn_instance_submission_get_ring_submit(ring, cs, extra_shmem, direct);
460bf215546Sopenharmony_ci   if (!submit->submit) {
461bf215546Sopenharmony_ci      vn_instance_submission_cleanup(submit);
462bf215546Sopenharmony_ci      return VK_ERROR_OUT_OF_HOST_MEMORY;
463bf215546Sopenharmony_ci   }
464bf215546Sopenharmony_ci
465bf215546Sopenharmony_ci   return VK_SUCCESS;
466bf215546Sopenharmony_ci}
467bf215546Sopenharmony_ci
468bf215546Sopenharmony_cistatic bool
469bf215546Sopenharmony_civn_instance_submission_can_direct(const struct vn_instance *instance,
470bf215546Sopenharmony_ci                                  const struct vn_cs_encoder *cs)
471bf215546Sopenharmony_ci{
472bf215546Sopenharmony_ci   const size_t threshold = instance->experimental.largeRing
473bf215546Sopenharmony_ci                               ? VN_INSTANCE_LARGE_RING_DIRECT_THRESHOLD
474bf215546Sopenharmony_ci                               : VN_INSTANCE_RING_DIRECT_THRESHOLD;
475bf215546Sopenharmony_ci   return vn_cs_encoder_get_len(cs) <= threshold;
476bf215546Sopenharmony_ci}
477bf215546Sopenharmony_ci
478bf215546Sopenharmony_cistatic struct vn_cs_encoder *
479bf215546Sopenharmony_civn_instance_ring_cs_upload_locked(struct vn_instance *instance,
480bf215546Sopenharmony_ci                                  const struct vn_cs_encoder *cs)
481bf215546Sopenharmony_ci{
482bf215546Sopenharmony_ci   VN_TRACE_FUNC();
483bf215546Sopenharmony_ci   assert(cs->storage_type == VN_CS_ENCODER_STORAGE_POINTER &&
484bf215546Sopenharmony_ci          cs->buffer_count == 1);
485bf215546Sopenharmony_ci   const void *cs_data = cs->buffers[0].base;
486bf215546Sopenharmony_ci   const size_t cs_size = cs->total_committed_size;
487bf215546Sopenharmony_ci   assert(cs_size == vn_cs_encoder_get_len(cs));
488bf215546Sopenharmony_ci
489bf215546Sopenharmony_ci   struct vn_cs_encoder *upload = &instance->ring.upload;
490bf215546Sopenharmony_ci   vn_cs_encoder_reset(upload);
491bf215546Sopenharmony_ci
492bf215546Sopenharmony_ci   if (!vn_cs_encoder_reserve(upload, cs_size))
493bf215546Sopenharmony_ci      return NULL;
494bf215546Sopenharmony_ci
495bf215546Sopenharmony_ci   vn_cs_encoder_write(upload, cs_size, cs_data, cs_size);
496bf215546Sopenharmony_ci   vn_cs_encoder_commit(upload);
497bf215546Sopenharmony_ci
498bf215546Sopenharmony_ci   if (unlikely(!instance->renderer->info.supports_blob_id_0))
499bf215546Sopenharmony_ci      vn_instance_wait_roundtrip(instance, upload->current_buffer_roundtrip);
500bf215546Sopenharmony_ci
501bf215546Sopenharmony_ci   return upload;
502bf215546Sopenharmony_ci}
503bf215546Sopenharmony_ci
504bf215546Sopenharmony_cistatic VkResult
505bf215546Sopenharmony_civn_instance_ring_submit_locked(struct vn_instance *instance,
506bf215546Sopenharmony_ci                               const struct vn_cs_encoder *cs,
507bf215546Sopenharmony_ci                               struct vn_renderer_shmem *extra_shmem,
508bf215546Sopenharmony_ci                               uint32_t *ring_seqno)
509bf215546Sopenharmony_ci{
510bf215546Sopenharmony_ci   struct vn_ring *ring = &instance->ring.ring;
511bf215546Sopenharmony_ci
512bf215546Sopenharmony_ci   const bool direct = vn_instance_submission_can_direct(instance, cs);
513bf215546Sopenharmony_ci   if (!direct && cs->storage_type == VN_CS_ENCODER_STORAGE_POINTER) {
514bf215546Sopenharmony_ci      cs = vn_instance_ring_cs_upload_locked(instance, cs);
515bf215546Sopenharmony_ci      if (!cs)
516bf215546Sopenharmony_ci         return VK_ERROR_OUT_OF_HOST_MEMORY;
517bf215546Sopenharmony_ci      assert(cs->storage_type != VN_CS_ENCODER_STORAGE_POINTER);
518bf215546Sopenharmony_ci   }
519bf215546Sopenharmony_ci
520bf215546Sopenharmony_ci   struct vn_instance_submission submit;
521bf215546Sopenharmony_ci   VkResult result =
522bf215546Sopenharmony_ci      vn_instance_submission_prepare(&submit, cs, ring, extra_shmem, direct);
523bf215546Sopenharmony_ci   if (result != VK_SUCCESS)
524bf215546Sopenharmony_ci      return result;
525bf215546Sopenharmony_ci
526bf215546Sopenharmony_ci   uint32_t seqno;
527bf215546Sopenharmony_ci   const bool notify = vn_ring_submit(ring, submit.submit, submit.cs, &seqno);
528bf215546Sopenharmony_ci   if (notify) {
529bf215546Sopenharmony_ci      uint32_t notify_ring_data[8];
530bf215546Sopenharmony_ci      struct vn_cs_encoder local_enc = VN_CS_ENCODER_INITIALIZER_LOCAL(
531bf215546Sopenharmony_ci         notify_ring_data, sizeof(notify_ring_data));
532bf215546Sopenharmony_ci      vn_encode_vkNotifyRingMESA(&local_enc, 0, instance->ring.id, seqno, 0);
533bf215546Sopenharmony_ci      vn_renderer_submit_simple(instance->renderer, notify_ring_data,
534bf215546Sopenharmony_ci                                vn_cs_encoder_get_len(&local_enc));
535bf215546Sopenharmony_ci   }
536bf215546Sopenharmony_ci
537bf215546Sopenharmony_ci   vn_instance_submission_cleanup(&submit);
538bf215546Sopenharmony_ci
539bf215546Sopenharmony_ci   if (ring_seqno)
540bf215546Sopenharmony_ci      *ring_seqno = seqno;
541bf215546Sopenharmony_ci
542bf215546Sopenharmony_ci   return VK_SUCCESS;
543bf215546Sopenharmony_ci}
544bf215546Sopenharmony_ci
545bf215546Sopenharmony_ciVkResult
546bf215546Sopenharmony_civn_instance_ring_submit(struct vn_instance *instance,
547bf215546Sopenharmony_ci                        const struct vn_cs_encoder *cs)
548bf215546Sopenharmony_ci{
549bf215546Sopenharmony_ci   mtx_lock(&instance->ring.mutex);
550bf215546Sopenharmony_ci   VkResult result = vn_instance_ring_submit_locked(instance, cs, NULL, NULL);
551bf215546Sopenharmony_ci   mtx_unlock(&instance->ring.mutex);
552bf215546Sopenharmony_ci
553bf215546Sopenharmony_ci   return result;
554bf215546Sopenharmony_ci}
555bf215546Sopenharmony_ci
556bf215546Sopenharmony_cistatic struct vn_renderer_shmem *
557bf215546Sopenharmony_civn_instance_get_reply_shmem_locked(struct vn_instance *instance,
558bf215546Sopenharmony_ci                                   size_t size,
559bf215546Sopenharmony_ci                                   void **out_ptr)
560bf215546Sopenharmony_ci{
561bf215546Sopenharmony_ci   VN_TRACE_FUNC();
562bf215546Sopenharmony_ci   struct vn_renderer_shmem_pool *pool = &instance->reply_shmem_pool;
563bf215546Sopenharmony_ci   const struct vn_renderer_shmem *saved_pool_shmem = pool->shmem;
564bf215546Sopenharmony_ci
565bf215546Sopenharmony_ci   size_t offset;
566bf215546Sopenharmony_ci   struct vn_renderer_shmem *shmem =
567bf215546Sopenharmony_ci      vn_renderer_shmem_pool_alloc(instance->renderer, pool, size, &offset);
568bf215546Sopenharmony_ci   if (!shmem)
569bf215546Sopenharmony_ci      return NULL;
570bf215546Sopenharmony_ci
571bf215546Sopenharmony_ci   assert(shmem == pool->shmem);
572bf215546Sopenharmony_ci   *out_ptr = shmem->mmap_ptr + offset;
573bf215546Sopenharmony_ci
574bf215546Sopenharmony_ci   if (shmem != saved_pool_shmem) {
575bf215546Sopenharmony_ci      uint32_t set_reply_command_stream_data[16];
576bf215546Sopenharmony_ci      struct vn_cs_encoder local_enc = VN_CS_ENCODER_INITIALIZER_LOCAL(
577bf215546Sopenharmony_ci         set_reply_command_stream_data,
578bf215546Sopenharmony_ci         sizeof(set_reply_command_stream_data));
579bf215546Sopenharmony_ci      const struct VkCommandStreamDescriptionMESA stream = {
580bf215546Sopenharmony_ci         .resourceId = shmem->res_id,
581bf215546Sopenharmony_ci         .size = pool->size,
582bf215546Sopenharmony_ci      };
583bf215546Sopenharmony_ci      vn_encode_vkSetReplyCommandStreamMESA(&local_enc, 0, &stream);
584bf215546Sopenharmony_ci      vn_cs_encoder_commit(&local_enc);
585bf215546Sopenharmony_ci
586bf215546Sopenharmony_ci      /* vn_instance_init_experimental_features calls this before the ring is
587bf215546Sopenharmony_ci       * created
588bf215546Sopenharmony_ci       */
589bf215546Sopenharmony_ci      if (likely(instance->ring.id)) {
590bf215546Sopenharmony_ci         if (unlikely(!instance->renderer->info.supports_blob_id_0))
591bf215546Sopenharmony_ci            vn_instance_roundtrip(instance);
592bf215546Sopenharmony_ci
593bf215546Sopenharmony_ci         vn_instance_ring_submit_locked(instance, &local_enc, NULL, NULL);
594bf215546Sopenharmony_ci      } else {
595bf215546Sopenharmony_ci         vn_renderer_submit_simple(instance->renderer,
596bf215546Sopenharmony_ci                                   set_reply_command_stream_data,
597bf215546Sopenharmony_ci                                   vn_cs_encoder_get_len(&local_enc));
598bf215546Sopenharmony_ci      }
599bf215546Sopenharmony_ci   }
600bf215546Sopenharmony_ci
601bf215546Sopenharmony_ci   /* TODO avoid this seek command and go lock-free? */
602bf215546Sopenharmony_ci   uint32_t seek_reply_command_stream_data[8];
603bf215546Sopenharmony_ci   struct vn_cs_encoder local_enc = VN_CS_ENCODER_INITIALIZER_LOCAL(
604bf215546Sopenharmony_ci      seek_reply_command_stream_data, sizeof(seek_reply_command_stream_data));
605bf215546Sopenharmony_ci   vn_encode_vkSeekReplyCommandStreamMESA(&local_enc, 0, offset);
606bf215546Sopenharmony_ci   vn_cs_encoder_commit(&local_enc);
607bf215546Sopenharmony_ci
608bf215546Sopenharmony_ci   /* vn_instance_init_experimental_features calls this before the ring is
609bf215546Sopenharmony_ci    * created
610bf215546Sopenharmony_ci    */
611bf215546Sopenharmony_ci   if (likely(instance->ring.id)) {
612bf215546Sopenharmony_ci      vn_instance_ring_submit_locked(instance, &local_enc, NULL, NULL);
613bf215546Sopenharmony_ci   } else {
614bf215546Sopenharmony_ci      vn_renderer_submit_simple(instance->renderer,
615bf215546Sopenharmony_ci                                seek_reply_command_stream_data,
616bf215546Sopenharmony_ci                                vn_cs_encoder_get_len(&local_enc));
617bf215546Sopenharmony_ci   }
618bf215546Sopenharmony_ci
619bf215546Sopenharmony_ci   return shmem;
620bf215546Sopenharmony_ci}
621bf215546Sopenharmony_ci
622bf215546Sopenharmony_civoid
623bf215546Sopenharmony_civn_instance_submit_command(struct vn_instance *instance,
624bf215546Sopenharmony_ci                           struct vn_instance_submit_command *submit)
625bf215546Sopenharmony_ci{
626bf215546Sopenharmony_ci   void *reply_ptr = NULL;
627bf215546Sopenharmony_ci   submit->reply_shmem = NULL;
628bf215546Sopenharmony_ci
629bf215546Sopenharmony_ci   mtx_lock(&instance->ring.mutex);
630bf215546Sopenharmony_ci
631bf215546Sopenharmony_ci   if (vn_cs_encoder_is_empty(&submit->command))
632bf215546Sopenharmony_ci      goto fail;
633bf215546Sopenharmony_ci   vn_cs_encoder_commit(&submit->command);
634bf215546Sopenharmony_ci
635bf215546Sopenharmony_ci   if (submit->reply_size) {
636bf215546Sopenharmony_ci      submit->reply_shmem = vn_instance_get_reply_shmem_locked(
637bf215546Sopenharmony_ci         instance, submit->reply_size, &reply_ptr);
638bf215546Sopenharmony_ci      if (!submit->reply_shmem)
639bf215546Sopenharmony_ci         goto fail;
640bf215546Sopenharmony_ci   }
641bf215546Sopenharmony_ci
642bf215546Sopenharmony_ci   uint32_t ring_seqno;
643bf215546Sopenharmony_ci   VkResult result = vn_instance_ring_submit_locked(
644bf215546Sopenharmony_ci      instance, &submit->command, submit->reply_shmem, &ring_seqno);
645bf215546Sopenharmony_ci
646bf215546Sopenharmony_ci   mtx_unlock(&instance->ring.mutex);
647bf215546Sopenharmony_ci
648bf215546Sopenharmony_ci   submit->reply = VN_CS_DECODER_INITIALIZER(reply_ptr, submit->reply_size);
649bf215546Sopenharmony_ci
650bf215546Sopenharmony_ci   if (submit->reply_size && result == VK_SUCCESS)
651bf215546Sopenharmony_ci      vn_ring_wait(&instance->ring.ring, ring_seqno);
652bf215546Sopenharmony_ci
653bf215546Sopenharmony_ci   return;
654bf215546Sopenharmony_ci
655bf215546Sopenharmony_cifail:
656bf215546Sopenharmony_ci   instance->ring.command_dropped++;
657bf215546Sopenharmony_ci   mtx_unlock(&instance->ring.mutex);
658bf215546Sopenharmony_ci}
659bf215546Sopenharmony_ci
660bf215546Sopenharmony_ci/* instance commands */
661bf215546Sopenharmony_ci
662bf215546Sopenharmony_ciVkResult
663bf215546Sopenharmony_civn_EnumerateInstanceVersion(uint32_t *pApiVersion)
664bf215546Sopenharmony_ci{
665bf215546Sopenharmony_ci   *pApiVersion = VN_MAX_API_VERSION;
666bf215546Sopenharmony_ci   return VK_SUCCESS;
667bf215546Sopenharmony_ci}
668bf215546Sopenharmony_ci
669bf215546Sopenharmony_ciVkResult
670bf215546Sopenharmony_civn_EnumerateInstanceExtensionProperties(const char *pLayerName,
671bf215546Sopenharmony_ci                                        uint32_t *pPropertyCount,
672bf215546Sopenharmony_ci                                        VkExtensionProperties *pProperties)
673bf215546Sopenharmony_ci{
674bf215546Sopenharmony_ci   if (pLayerName)
675bf215546Sopenharmony_ci      return vn_error(NULL, VK_ERROR_LAYER_NOT_PRESENT);
676bf215546Sopenharmony_ci
677bf215546Sopenharmony_ci   return vk_enumerate_instance_extension_properties(
678bf215546Sopenharmony_ci      &vn_instance_supported_extensions, pPropertyCount, pProperties);
679bf215546Sopenharmony_ci}
680bf215546Sopenharmony_ci
681bf215546Sopenharmony_ciVkResult
682bf215546Sopenharmony_civn_EnumerateInstanceLayerProperties(uint32_t *pPropertyCount,
683bf215546Sopenharmony_ci                                    VkLayerProperties *pProperties)
684bf215546Sopenharmony_ci{
685bf215546Sopenharmony_ci   *pPropertyCount = 0;
686bf215546Sopenharmony_ci   return VK_SUCCESS;
687bf215546Sopenharmony_ci}
688bf215546Sopenharmony_ci
689bf215546Sopenharmony_ciVkResult
690bf215546Sopenharmony_civn_CreateInstance(const VkInstanceCreateInfo *pCreateInfo,
691bf215546Sopenharmony_ci                  const VkAllocationCallbacks *pAllocator,
692bf215546Sopenharmony_ci                  VkInstance *pInstance)
693bf215546Sopenharmony_ci{
694bf215546Sopenharmony_ci   VN_TRACE_FUNC();
695bf215546Sopenharmony_ci   const VkAllocationCallbacks *alloc =
696bf215546Sopenharmony_ci      pAllocator ? pAllocator : vk_default_allocator();
697bf215546Sopenharmony_ci   struct vn_instance *instance;
698bf215546Sopenharmony_ci   VkResult result;
699bf215546Sopenharmony_ci
700bf215546Sopenharmony_ci   vn_env_init();
701bf215546Sopenharmony_ci   vn_trace_init();
702bf215546Sopenharmony_ci
703bf215546Sopenharmony_ci   instance = vk_zalloc(alloc, sizeof(*instance), VN_DEFAULT_ALIGN,
704bf215546Sopenharmony_ci                        VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
705bf215546Sopenharmony_ci   if (!instance)
706bf215546Sopenharmony_ci      return vn_error(NULL, VK_ERROR_OUT_OF_HOST_MEMORY);
707bf215546Sopenharmony_ci
708bf215546Sopenharmony_ci   struct vk_instance_dispatch_table dispatch_table;
709bf215546Sopenharmony_ci   vk_instance_dispatch_table_from_entrypoints(
710bf215546Sopenharmony_ci      &dispatch_table, &vn_instance_entrypoints, true);
711bf215546Sopenharmony_ci   vk_instance_dispatch_table_from_entrypoints(
712bf215546Sopenharmony_ci      &dispatch_table, &wsi_instance_entrypoints, false);
713bf215546Sopenharmony_ci   result = vn_instance_base_init(&instance->base,
714bf215546Sopenharmony_ci                                  &vn_instance_supported_extensions,
715bf215546Sopenharmony_ci                                  &dispatch_table, pCreateInfo, alloc);
716bf215546Sopenharmony_ci   if (result != VK_SUCCESS) {
717bf215546Sopenharmony_ci      vk_free(alloc, instance);
718bf215546Sopenharmony_ci      return vn_error(NULL, result);
719bf215546Sopenharmony_ci   }
720bf215546Sopenharmony_ci
721bf215546Sopenharmony_ci   mtx_init(&instance->physical_device.mutex, mtx_plain);
722bf215546Sopenharmony_ci   mtx_init(&instance->cs_shmem.mutex, mtx_plain);
723bf215546Sopenharmony_ci
724bf215546Sopenharmony_ci   if (!vn_icd_supports_api_version(
725bf215546Sopenharmony_ci          instance->base.base.app_info.api_version)) {
726bf215546Sopenharmony_ci      result = VK_ERROR_INCOMPATIBLE_DRIVER;
727bf215546Sopenharmony_ci      goto fail;
728bf215546Sopenharmony_ci   }
729bf215546Sopenharmony_ci
730bf215546Sopenharmony_ci   if (pCreateInfo->enabledLayerCount) {
731bf215546Sopenharmony_ci      result = VK_ERROR_LAYER_NOT_PRESENT;
732bf215546Sopenharmony_ci      goto fail;
733bf215546Sopenharmony_ci   }
734bf215546Sopenharmony_ci
735bf215546Sopenharmony_ci   result = vn_instance_init_renderer(instance);
736bf215546Sopenharmony_ci   if (result != VK_SUCCESS)
737bf215546Sopenharmony_ci      goto fail;
738bf215546Sopenharmony_ci
739bf215546Sopenharmony_ci   vn_cs_renderer_protocol_info_init(instance);
740bf215546Sopenharmony_ci
741bf215546Sopenharmony_ci   vn_renderer_shmem_pool_init(instance->renderer,
742bf215546Sopenharmony_ci                               &instance->reply_shmem_pool, 1u << 20);
743bf215546Sopenharmony_ci
744bf215546Sopenharmony_ci   result = vn_instance_init_experimental_features(instance);
745bf215546Sopenharmony_ci   if (result != VK_SUCCESS)
746bf215546Sopenharmony_ci      goto fail;
747bf215546Sopenharmony_ci
748bf215546Sopenharmony_ci   result = vn_instance_init_ring(instance);
749bf215546Sopenharmony_ci   if (result != VK_SUCCESS)
750bf215546Sopenharmony_ci      goto fail;
751bf215546Sopenharmony_ci
752bf215546Sopenharmony_ci   result = vn_instance_init_renderer_versions(instance);
753bf215546Sopenharmony_ci   if (result != VK_SUCCESS)
754bf215546Sopenharmony_ci      goto fail;
755bf215546Sopenharmony_ci
756bf215546Sopenharmony_ci   vn_renderer_shmem_pool_init(instance->renderer, &instance->cs_shmem.pool,
757bf215546Sopenharmony_ci                               8u << 20);
758bf215546Sopenharmony_ci
759bf215546Sopenharmony_ci   VkInstanceCreateInfo local_create_info = *pCreateInfo;
760bf215546Sopenharmony_ci   local_create_info.ppEnabledExtensionNames = NULL;
761bf215546Sopenharmony_ci   local_create_info.enabledExtensionCount = 0;
762bf215546Sopenharmony_ci   pCreateInfo = &local_create_info;
763bf215546Sopenharmony_ci
764bf215546Sopenharmony_ci   VkApplicationInfo local_app_info;
765bf215546Sopenharmony_ci   if (instance->base.base.app_info.api_version <
766bf215546Sopenharmony_ci       instance->renderer_api_version) {
767bf215546Sopenharmony_ci      if (pCreateInfo->pApplicationInfo) {
768bf215546Sopenharmony_ci         local_app_info = *pCreateInfo->pApplicationInfo;
769bf215546Sopenharmony_ci         local_app_info.apiVersion = instance->renderer_api_version;
770bf215546Sopenharmony_ci      } else {
771bf215546Sopenharmony_ci         local_app_info = (const VkApplicationInfo){
772bf215546Sopenharmony_ci            .sType = VK_STRUCTURE_TYPE_APPLICATION_INFO,
773bf215546Sopenharmony_ci            .apiVersion = instance->renderer_api_version,
774bf215546Sopenharmony_ci         };
775bf215546Sopenharmony_ci      }
776bf215546Sopenharmony_ci      local_create_info.pApplicationInfo = &local_app_info;
777bf215546Sopenharmony_ci   }
778bf215546Sopenharmony_ci
779bf215546Sopenharmony_ci   VkInstance instance_handle = vn_instance_to_handle(instance);
780bf215546Sopenharmony_ci   result =
781bf215546Sopenharmony_ci      vn_call_vkCreateInstance(instance, pCreateInfo, NULL, &instance_handle);
782bf215546Sopenharmony_ci   if (result != VK_SUCCESS)
783bf215546Sopenharmony_ci      goto fail;
784bf215546Sopenharmony_ci
785bf215546Sopenharmony_ci   driParseOptionInfo(&instance->available_dri_options, vn_dri_options,
786bf215546Sopenharmony_ci                      ARRAY_SIZE(vn_dri_options));
787bf215546Sopenharmony_ci   driParseConfigFiles(&instance->dri_options,
788bf215546Sopenharmony_ci                       &instance->available_dri_options, 0, "venus", NULL,
789bf215546Sopenharmony_ci                       NULL, instance->base.base.app_info.app_name,
790bf215546Sopenharmony_ci                       instance->base.base.app_info.app_version,
791bf215546Sopenharmony_ci                       instance->base.base.app_info.engine_name,
792bf215546Sopenharmony_ci                       instance->base.base.app_info.engine_version);
793bf215546Sopenharmony_ci
794bf215546Sopenharmony_ci   instance->renderer->info.has_implicit_fencing =
795bf215546Sopenharmony_ci      driQueryOptionb(&instance->dri_options, "venus_implicit_fencing");
796bf215546Sopenharmony_ci
797bf215546Sopenharmony_ci   *pInstance = instance_handle;
798bf215546Sopenharmony_ci
799bf215546Sopenharmony_ci   return VK_SUCCESS;
800bf215546Sopenharmony_ci
801bf215546Sopenharmony_cifail:
802bf215546Sopenharmony_ci   if (instance->ring.shmem) {
803bf215546Sopenharmony_ci      uint32_t destroy_ring_data[4];
804bf215546Sopenharmony_ci      struct vn_cs_encoder local_enc = VN_CS_ENCODER_INITIALIZER_LOCAL(
805bf215546Sopenharmony_ci         destroy_ring_data, sizeof(destroy_ring_data));
806bf215546Sopenharmony_ci      vn_encode_vkDestroyRingMESA(&local_enc, 0, instance->ring.id);
807bf215546Sopenharmony_ci      vn_renderer_submit_simple(instance->renderer, destroy_ring_data,
808bf215546Sopenharmony_ci                                vn_cs_encoder_get_len(&local_enc));
809bf215546Sopenharmony_ci
810bf215546Sopenharmony_ci      mtx_destroy(&instance->ring.roundtrip_mutex);
811bf215546Sopenharmony_ci      vn_cs_encoder_fini(&instance->ring.upload);
812bf215546Sopenharmony_ci      vn_renderer_shmem_unref(instance->renderer, instance->ring.shmem);
813bf215546Sopenharmony_ci      vn_ring_fini(&instance->ring.ring);
814bf215546Sopenharmony_ci      mtx_destroy(&instance->ring.mutex);
815bf215546Sopenharmony_ci   }
816bf215546Sopenharmony_ci
817bf215546Sopenharmony_ci   vn_renderer_shmem_pool_fini(instance->renderer,
818bf215546Sopenharmony_ci                               &instance->reply_shmem_pool);
819bf215546Sopenharmony_ci
820bf215546Sopenharmony_ci   if (instance->renderer)
821bf215546Sopenharmony_ci      vn_renderer_destroy(instance->renderer, alloc);
822bf215546Sopenharmony_ci
823bf215546Sopenharmony_ci   mtx_destroy(&instance->physical_device.mutex);
824bf215546Sopenharmony_ci   mtx_destroy(&instance->cs_shmem.mutex);
825bf215546Sopenharmony_ci
826bf215546Sopenharmony_ci   vn_instance_base_fini(&instance->base);
827bf215546Sopenharmony_ci   vk_free(alloc, instance);
828bf215546Sopenharmony_ci
829bf215546Sopenharmony_ci   return vn_error(NULL, result);
830bf215546Sopenharmony_ci}
831bf215546Sopenharmony_ci
832bf215546Sopenharmony_civoid
833bf215546Sopenharmony_civn_DestroyInstance(VkInstance _instance,
834bf215546Sopenharmony_ci                   const VkAllocationCallbacks *pAllocator)
835bf215546Sopenharmony_ci{
836bf215546Sopenharmony_ci   VN_TRACE_FUNC();
837bf215546Sopenharmony_ci   struct vn_instance *instance = vn_instance_from_handle(_instance);
838bf215546Sopenharmony_ci   const VkAllocationCallbacks *alloc =
839bf215546Sopenharmony_ci      pAllocator ? pAllocator : &instance->base.base.alloc;
840bf215546Sopenharmony_ci
841bf215546Sopenharmony_ci   if (!instance)
842bf215546Sopenharmony_ci      return;
843bf215546Sopenharmony_ci
844bf215546Sopenharmony_ci   if (instance->physical_device.initialized) {
845bf215546Sopenharmony_ci      for (uint32_t i = 0; i < instance->physical_device.device_count; i++)
846bf215546Sopenharmony_ci         vn_physical_device_fini(&instance->physical_device.devices[i]);
847bf215546Sopenharmony_ci      vk_free(alloc, instance->physical_device.devices);
848bf215546Sopenharmony_ci      vk_free(alloc, instance->physical_device.groups);
849bf215546Sopenharmony_ci   }
850bf215546Sopenharmony_ci   mtx_destroy(&instance->physical_device.mutex);
851bf215546Sopenharmony_ci
852bf215546Sopenharmony_ci   vn_call_vkDestroyInstance(instance, _instance, NULL);
853bf215546Sopenharmony_ci
854bf215546Sopenharmony_ci   vn_renderer_shmem_pool_fini(instance->renderer, &instance->cs_shmem.pool);
855bf215546Sopenharmony_ci   mtx_destroy(&instance->cs_shmem.mutex);
856bf215546Sopenharmony_ci
857bf215546Sopenharmony_ci   uint32_t destroy_ring_data[4];
858bf215546Sopenharmony_ci   struct vn_cs_encoder local_enc = VN_CS_ENCODER_INITIALIZER_LOCAL(
859bf215546Sopenharmony_ci      destroy_ring_data, sizeof(destroy_ring_data));
860bf215546Sopenharmony_ci   vn_encode_vkDestroyRingMESA(&local_enc, 0, instance->ring.id);
861bf215546Sopenharmony_ci   vn_renderer_submit_simple(instance->renderer, destroy_ring_data,
862bf215546Sopenharmony_ci                             vn_cs_encoder_get_len(&local_enc));
863bf215546Sopenharmony_ci
864bf215546Sopenharmony_ci   mtx_destroy(&instance->ring.roundtrip_mutex);
865bf215546Sopenharmony_ci   vn_cs_encoder_fini(&instance->ring.upload);
866bf215546Sopenharmony_ci   vn_ring_fini(&instance->ring.ring);
867bf215546Sopenharmony_ci   mtx_destroy(&instance->ring.mutex);
868bf215546Sopenharmony_ci   vn_renderer_shmem_unref(instance->renderer, instance->ring.shmem);
869bf215546Sopenharmony_ci
870bf215546Sopenharmony_ci   vn_renderer_shmem_pool_fini(instance->renderer,
871bf215546Sopenharmony_ci                               &instance->reply_shmem_pool);
872bf215546Sopenharmony_ci
873bf215546Sopenharmony_ci   vn_renderer_destroy(instance->renderer, alloc);
874bf215546Sopenharmony_ci
875bf215546Sopenharmony_ci   driDestroyOptionCache(&instance->dri_options);
876bf215546Sopenharmony_ci   driDestroyOptionInfo(&instance->available_dri_options);
877bf215546Sopenharmony_ci
878bf215546Sopenharmony_ci   vn_instance_base_fini(&instance->base);
879bf215546Sopenharmony_ci   vk_free(alloc, instance);
880bf215546Sopenharmony_ci}
881bf215546Sopenharmony_ci
882bf215546Sopenharmony_ciPFN_vkVoidFunction
883bf215546Sopenharmony_civn_GetInstanceProcAddr(VkInstance _instance, const char *pName)
884bf215546Sopenharmony_ci{
885bf215546Sopenharmony_ci   struct vn_instance *instance = vn_instance_from_handle(_instance);
886bf215546Sopenharmony_ci   return vk_instance_get_proc_addr(&instance->base.base,
887bf215546Sopenharmony_ci                                    &vn_instance_entrypoints, pName);
888bf215546Sopenharmony_ci}
889