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