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