driver.cpp revision 319382517afe913285df5bbf76a8a484e6adfbd0
1/* 2 * Copyright 2016 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17#include <stdlib.h> 18#include <string.h> 19#include <algorithm> 20#include <array> 21#include <new> 22#include <malloc.h> 23#include <sys/prctl.h> 24 25#include "driver.h" 26#include "stubhal.h" 27 28// #define ENABLE_ALLOC_CALLSTACKS 1 29#if ENABLE_ALLOC_CALLSTACKS 30#include <utils/CallStack.h> 31#define ALOGD_CALLSTACK(...) \ 32 do { \ 33 ALOGD(__VA_ARGS__); \ 34 android::CallStack callstack; \ 35 callstack.update(); \ 36 callstack.log(LOG_TAG, ANDROID_LOG_DEBUG, " "); \ 37 } while (false) 38#else 39#define ALOGD_CALLSTACK(...) \ 40 do { \ 41 } while (false) 42#endif 43 44namespace vulkan { 45namespace driver { 46 47namespace { 48 49class Hal { 50 public: 51 static bool Open(); 52 53 static const Hal& Get() { return hal_; } 54 static const hwvulkan_device_t& Device() { return *Get().dev_; } 55 56 int GetDebugReportIndex() const { return debug_report_index_; } 57 58 private: 59 Hal() : dev_(nullptr), debug_report_index_(-1) {} 60 Hal(const Hal&) = delete; 61 Hal& operator=(const Hal&) = delete; 62 63 bool InitDebugReportIndex(); 64 65 static Hal hal_; 66 67 const hwvulkan_device_t* dev_; 68 int debug_report_index_; 69}; 70 71class CreateInfoWrapper { 72 public: 73 CreateInfoWrapper(const VkInstanceCreateInfo& create_info, 74 const VkAllocationCallbacks& allocator); 75 CreateInfoWrapper(VkPhysicalDevice physical_dev, 76 const VkDeviceCreateInfo& create_info, 77 const VkAllocationCallbacks& allocator); 78 ~CreateInfoWrapper(); 79 80 VkResult Validate(); 81 82 const std::bitset<ProcHook::EXTENSION_COUNT>& GetHookExtensions() const; 83 const std::bitset<ProcHook::EXTENSION_COUNT>& GetHalExtensions() const; 84 85 explicit operator const VkInstanceCreateInfo*() const; 86 explicit operator const VkDeviceCreateInfo*() const; 87 88 private: 89 struct ExtensionFilter { 90 VkExtensionProperties* exts; 91 uint32_t ext_count; 92 93 const char** names; 94 uint32_t name_count; 95 }; 96 97 VkResult SanitizePNext(); 98 99 VkResult SanitizeLayers(); 100 VkResult SanitizeExtensions(); 101 102 VkResult QueryExtensionCount(uint32_t& count) const; 103 VkResult EnumerateExtensions(uint32_t& count, 104 VkExtensionProperties* props) const; 105 VkResult InitExtensionFilter(); 106 void FilterExtension(const char* name); 107 108 const bool is_instance_; 109 const VkAllocationCallbacks& allocator_; 110 111 VkPhysicalDevice physical_dev_; 112 113 union { 114 VkInstanceCreateInfo instance_info_; 115 VkDeviceCreateInfo dev_info_; 116 }; 117 118 ExtensionFilter extension_filter_; 119 120 std::bitset<ProcHook::EXTENSION_COUNT> hook_extensions_; 121 std::bitset<ProcHook::EXTENSION_COUNT> hal_extensions_; 122}; 123 124Hal Hal::hal_; 125 126bool Hal::Open() { 127 ALOG_ASSERT(!dev_, "OpenHAL called more than once"); 128 129 // Use a stub device unless we successfully open a real HAL device. 130 hal_.dev_ = &stubhal::kDevice; 131 132 const hwvulkan_module_t* module; 133 int result = 134 hw_get_module("vulkan", reinterpret_cast<const hw_module_t**>(&module)); 135 if (result != 0) { 136 ALOGI("no Vulkan HAL present, using stub HAL"); 137 return true; 138 } 139 140 hwvulkan_device_t* device; 141 result = 142 module->common.methods->open(&module->common, HWVULKAN_DEVICE_0, 143 reinterpret_cast<hw_device_t**>(&device)); 144 if (result != 0) { 145 // Any device with a Vulkan HAL should be able to open the device. 146 ALOGE("failed to open Vulkan HAL device: %s (%d)", strerror(-result), 147 result); 148 return false; 149 } 150 151 hal_.dev_ = device; 152 153 hal_.InitDebugReportIndex(); 154 155 return true; 156} 157 158bool Hal::InitDebugReportIndex() { 159 uint32_t count; 160 if (dev_->EnumerateInstanceExtensionProperties(nullptr, &count, nullptr) != 161 VK_SUCCESS) { 162 ALOGE("failed to get HAL instance extension count"); 163 return false; 164 } 165 166 VkExtensionProperties* exts = reinterpret_cast<VkExtensionProperties*>( 167 malloc(sizeof(VkExtensionProperties) * count)); 168 if (!exts) { 169 ALOGE("failed to allocate HAL instance extension array"); 170 return false; 171 } 172 173 if (dev_->EnumerateInstanceExtensionProperties(nullptr, &count, exts) != 174 VK_SUCCESS) { 175 ALOGE("failed to enumerate HAL instance extensions"); 176 free(exts); 177 return false; 178 } 179 180 for (uint32_t i = 0; i < count; i++) { 181 if (strcmp(exts[i].extensionName, VK_EXT_DEBUG_REPORT_EXTENSION_NAME) == 182 0) { 183 debug_report_index_ = static_cast<int>(i); 184 break; 185 } 186 } 187 188 free(exts); 189 190 return true; 191} 192 193CreateInfoWrapper::CreateInfoWrapper(const VkInstanceCreateInfo& create_info, 194 const VkAllocationCallbacks& allocator) 195 : is_instance_(true), 196 allocator_(allocator), 197 physical_dev_(VK_NULL_HANDLE), 198 instance_info_(create_info), 199 extension_filter_() { 200 hook_extensions_.set(ProcHook::EXTENSION_CORE); 201 hal_extensions_.set(ProcHook::EXTENSION_CORE); 202} 203 204CreateInfoWrapper::CreateInfoWrapper(VkPhysicalDevice physical_dev, 205 const VkDeviceCreateInfo& create_info, 206 const VkAllocationCallbacks& allocator) 207 : is_instance_(false), 208 allocator_(allocator), 209 physical_dev_(physical_dev), 210 dev_info_(create_info), 211 extension_filter_() { 212 hook_extensions_.set(ProcHook::EXTENSION_CORE); 213 hal_extensions_.set(ProcHook::EXTENSION_CORE); 214} 215 216CreateInfoWrapper::~CreateInfoWrapper() { 217 allocator_.pfnFree(allocator_.pUserData, extension_filter_.exts); 218 allocator_.pfnFree(allocator_.pUserData, extension_filter_.names); 219} 220 221VkResult CreateInfoWrapper::Validate() { 222 VkResult result = SanitizePNext(); 223 if (result == VK_SUCCESS) 224 result = SanitizeLayers(); 225 if (result == VK_SUCCESS) 226 result = SanitizeExtensions(); 227 228 return result; 229} 230 231const std::bitset<ProcHook::EXTENSION_COUNT>& 232CreateInfoWrapper::GetHookExtensions() const { 233 return hook_extensions_; 234} 235 236const std::bitset<ProcHook::EXTENSION_COUNT>& 237CreateInfoWrapper::GetHalExtensions() const { 238 return hal_extensions_; 239} 240 241CreateInfoWrapper::operator const VkInstanceCreateInfo*() const { 242 return &instance_info_; 243} 244 245CreateInfoWrapper::operator const VkDeviceCreateInfo*() const { 246 return &dev_info_; 247} 248 249VkResult CreateInfoWrapper::SanitizePNext() { 250 const struct StructHeader { 251 VkStructureType type; 252 const void* next; 253 } * header; 254 255 if (is_instance_) { 256 header = reinterpret_cast<const StructHeader*>(instance_info_.pNext); 257 258 // skip leading VK_STRUCTURE_TYPE_LOADER_INSTANCE_CREATE_INFOs 259 while (header && 260 header->type == VK_STRUCTURE_TYPE_LOADER_INSTANCE_CREATE_INFO) 261 header = reinterpret_cast<const StructHeader*>(header->next); 262 263 instance_info_.pNext = header; 264 } else { 265 header = reinterpret_cast<const StructHeader*>(dev_info_.pNext); 266 267 // skip leading VK_STRUCTURE_TYPE_LOADER_DEVICE_CREATE_INFOs 268 while (header && 269 header->type == VK_STRUCTURE_TYPE_LOADER_DEVICE_CREATE_INFO) 270 header = reinterpret_cast<const StructHeader*>(header->next); 271 272 dev_info_.pNext = header; 273 } 274 275 return VK_SUCCESS; 276} 277 278VkResult CreateInfoWrapper::SanitizeLayers() { 279 auto& layer_names = (is_instance_) ? instance_info_.ppEnabledLayerNames 280 : dev_info_.ppEnabledLayerNames; 281 auto& layer_count = (is_instance_) ? instance_info_.enabledLayerCount 282 : dev_info_.enabledLayerCount; 283 284 // remove all layers 285 layer_names = nullptr; 286 layer_count = 0; 287 288 return VK_SUCCESS; 289} 290 291VkResult CreateInfoWrapper::SanitizeExtensions() { 292 auto& ext_names = (is_instance_) ? instance_info_.ppEnabledExtensionNames 293 : dev_info_.ppEnabledExtensionNames; 294 auto& ext_count = (is_instance_) ? instance_info_.enabledExtensionCount 295 : dev_info_.enabledExtensionCount; 296 if (!ext_count) 297 return VK_SUCCESS; 298 299 VkResult result = InitExtensionFilter(); 300 if (result != VK_SUCCESS) 301 return result; 302 303 for (uint32_t i = 0; i < ext_count; i++) 304 FilterExtension(ext_names[i]); 305 306 ext_names = extension_filter_.names; 307 ext_count = extension_filter_.name_count; 308 309 return VK_SUCCESS; 310} 311 312VkResult CreateInfoWrapper::QueryExtensionCount(uint32_t& count) const { 313 if (is_instance_) { 314 return Hal::Device().EnumerateInstanceExtensionProperties( 315 nullptr, &count, nullptr); 316 } else { 317 const auto& driver = GetData(physical_dev_).driver; 318 return driver.EnumerateDeviceExtensionProperties(physical_dev_, nullptr, 319 &count, nullptr); 320 } 321} 322 323VkResult CreateInfoWrapper::EnumerateExtensions( 324 uint32_t& count, 325 VkExtensionProperties* props) const { 326 if (is_instance_) { 327 return Hal::Device().EnumerateInstanceExtensionProperties( 328 nullptr, &count, props); 329 } else { 330 const auto& driver = GetData(physical_dev_).driver; 331 return driver.EnumerateDeviceExtensionProperties(physical_dev_, nullptr, 332 &count, props); 333 } 334} 335 336VkResult CreateInfoWrapper::InitExtensionFilter() { 337 // query extension count 338 uint32_t count; 339 VkResult result = QueryExtensionCount(count); 340 if (result != VK_SUCCESS || count == 0) 341 return result; 342 343 auto& filter = extension_filter_; 344 filter.exts = 345 reinterpret_cast<VkExtensionProperties*>(allocator_.pfnAllocation( 346 allocator_.pUserData, sizeof(VkExtensionProperties) * count, 347 alignof(VkExtensionProperties), 348 VK_SYSTEM_ALLOCATION_SCOPE_COMMAND)); 349 if (!filter.exts) 350 return VK_ERROR_OUT_OF_HOST_MEMORY; 351 352 // enumerate extensions 353 result = EnumerateExtensions(count, filter.exts); 354 if (result != VK_SUCCESS && result != VK_INCOMPLETE) 355 return result; 356 357 if (!count) 358 return VK_SUCCESS; 359 360 filter.ext_count = count; 361 362 // allocate name array 363 uint32_t enabled_ext_count = (is_instance_) 364 ? instance_info_.enabledExtensionCount 365 : dev_info_.enabledExtensionCount; 366 count = std::min(filter.ext_count, enabled_ext_count); 367 filter.names = reinterpret_cast<const char**>(allocator_.pfnAllocation( 368 allocator_.pUserData, sizeof(const char*) * count, alignof(const char*), 369 VK_SYSTEM_ALLOCATION_SCOPE_COMMAND)); 370 if (!filter.names) 371 return VK_ERROR_OUT_OF_HOST_MEMORY; 372 373 return VK_SUCCESS; 374} 375 376void CreateInfoWrapper::FilterExtension(const char* name) { 377 auto& filter = extension_filter_; 378 379 ProcHook::Extension ext_bit = GetProcHookExtension(name); 380 if (is_instance_) { 381 switch (ext_bit) { 382 case ProcHook::KHR_android_surface: 383 case ProcHook::KHR_surface: 384 hook_extensions_.set(ext_bit); 385 // return now as these extensions do not require HAL support 386 return; 387 case ProcHook::EXT_debug_report: 388 // both we and HAL can take part in 389 hook_extensions_.set(ext_bit); 390 break; 391 case ProcHook::EXTENSION_UNKNOWN: 392 // HAL's extensions 393 break; 394 default: 395 ALOGW("Ignored invalid instance extension %s", name); 396 return; 397 } 398 } else { 399 switch (ext_bit) { 400 case ProcHook::KHR_swapchain: 401 // map VK_KHR_swapchain to VK_ANDROID_native_buffer 402 name = VK_ANDROID_NATIVE_BUFFER_EXTENSION_NAME; 403 ext_bit = ProcHook::ANDROID_native_buffer; 404 break; 405 case ProcHook::EXTENSION_UNKNOWN: 406 // HAL's extensions 407 break; 408 default: 409 ALOGW("Ignored invalid device extension %s", name); 410 return; 411 } 412 } 413 414 for (uint32_t i = 0; i < filter.ext_count; i++) { 415 const VkExtensionProperties& props = filter.exts[i]; 416 // ignore unknown extensions 417 if (strcmp(name, props.extensionName) != 0) 418 continue; 419 420 filter.names[filter.name_count++] = name; 421 if (ext_bit != ProcHook::EXTENSION_UNKNOWN) { 422 if (ext_bit == ProcHook::ANDROID_native_buffer) 423 hook_extensions_.set(ProcHook::KHR_swapchain); 424 425 hal_extensions_.set(ext_bit); 426 } 427 428 break; 429 } 430} 431 432VKAPI_ATTR void* DefaultAllocate(void*, 433 size_t size, 434 size_t alignment, 435 VkSystemAllocationScope) { 436 void* ptr = nullptr; 437 // Vulkan requires 'alignment' to be a power of two, but posix_memalign 438 // additionally requires that it be at least sizeof(void*). 439 int ret = posix_memalign(&ptr, std::max(alignment, sizeof(void*)), size); 440 ALOGD_CALLSTACK("Allocate: size=%zu align=%zu => (%d) %p", size, alignment, 441 ret, ptr); 442 return ret == 0 ? ptr : nullptr; 443} 444 445VKAPI_ATTR void* DefaultReallocate(void*, 446 void* ptr, 447 size_t size, 448 size_t alignment, 449 VkSystemAllocationScope) { 450 if (size == 0) { 451 free(ptr); 452 return nullptr; 453 } 454 455 // TODO(jessehall): Right now we never shrink allocations; if the new 456 // request is smaller than the existing chunk, we just continue using it. 457 // Right now the loader never reallocs, so this doesn't matter. If that 458 // changes, or if this code is copied into some other project, this should 459 // probably have a heuristic to allocate-copy-free when doing so will save 460 // "enough" space. 461 size_t old_size = ptr ? malloc_usable_size(ptr) : 0; 462 if (size <= old_size) 463 return ptr; 464 465 void* new_ptr = nullptr; 466 if (posix_memalign(&new_ptr, std::max(alignment, sizeof(void*)), size) != 0) 467 return nullptr; 468 if (ptr) { 469 memcpy(new_ptr, ptr, std::min(old_size, size)); 470 free(ptr); 471 } 472 return new_ptr; 473} 474 475VKAPI_ATTR void DefaultFree(void*, void* ptr) { 476 ALOGD_CALLSTACK("Free: %p", ptr); 477 free(ptr); 478} 479 480InstanceData* AllocateInstanceData(const VkAllocationCallbacks& allocator) { 481 void* data_mem = allocator.pfnAllocation( 482 allocator.pUserData, sizeof(InstanceData), alignof(InstanceData), 483 VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE); 484 if (!data_mem) 485 return nullptr; 486 487 return new (data_mem) InstanceData(allocator); 488} 489 490void FreeInstanceData(InstanceData* data, 491 const VkAllocationCallbacks& allocator) { 492 data->~InstanceData(); 493 allocator.pfnFree(allocator.pUserData, data); 494} 495 496DeviceData* AllocateDeviceData( 497 const VkAllocationCallbacks& allocator, 498 const DebugReportCallbackList& debug_report_callbacks) { 499 void* data_mem = allocator.pfnAllocation( 500 allocator.pUserData, sizeof(DeviceData), alignof(DeviceData), 501 VK_SYSTEM_ALLOCATION_SCOPE_DEVICE); 502 if (!data_mem) 503 return nullptr; 504 505 return new (data_mem) DeviceData(allocator, debug_report_callbacks); 506} 507 508void FreeDeviceData(DeviceData* data, const VkAllocationCallbacks& allocator) { 509 data->~DeviceData(); 510 allocator.pfnFree(allocator.pUserData, data); 511} 512 513} // anonymous namespace 514 515bool Debuggable() { 516 return (prctl(PR_GET_DUMPABLE, 0, 0, 0, 0) >= 0); 517} 518 519bool OpenHAL() { 520 return Hal::Open(); 521} 522 523const VkAllocationCallbacks& GetDefaultAllocator() { 524 static const VkAllocationCallbacks kDefaultAllocCallbacks = { 525 .pUserData = nullptr, 526 .pfnAllocation = DefaultAllocate, 527 .pfnReallocation = DefaultReallocate, 528 .pfnFree = DefaultFree, 529 }; 530 531 return kDefaultAllocCallbacks; 532} 533 534PFN_vkVoidFunction GetInstanceProcAddr(VkInstance instance, const char* pName) { 535 const ProcHook* hook = GetProcHook(pName); 536 if (!hook) 537 return Hal::Device().GetInstanceProcAddr(instance, pName); 538 539 if (!instance) { 540 if (hook->type == ProcHook::GLOBAL) 541 return hook->proc; 542 543 // v0 layers expect 544 // 545 // vkGetInstanceProcAddr(VK_NULL_HANDLE, "vkCreateDevice"); 546 // 547 // to work. 548 if (strcmp(pName, "vkCreateDevice") == 0) 549 return hook->proc; 550 551 ALOGE( 552 "internal vkGetInstanceProcAddr called for %s without an instance", 553 pName); 554 555 return nullptr; 556 } 557 558 PFN_vkVoidFunction proc; 559 560 switch (hook->type) { 561 case ProcHook::INSTANCE: 562 proc = (GetData(instance).hook_extensions[hook->extension]) 563 ? hook->proc 564 : nullptr; 565 break; 566 case ProcHook::DEVICE: 567 proc = (hook->extension == ProcHook::EXTENSION_CORE) 568 ? hook->proc 569 : hook->checked_proc; 570 break; 571 default: 572 ALOGE( 573 "internal vkGetInstanceProcAddr called for %s with an instance", 574 pName); 575 proc = nullptr; 576 break; 577 } 578 579 return proc; 580} 581 582PFN_vkVoidFunction GetDeviceProcAddr(VkDevice device, const char* pName) { 583 const ProcHook* hook = GetProcHook(pName); 584 if (!hook) 585 return GetData(device).driver.GetDeviceProcAddr(device, pName); 586 587 if (hook->type != ProcHook::DEVICE) { 588 ALOGE("internal vkGetDeviceProcAddr called for %s", pName); 589 return nullptr; 590 } 591 592 return (GetData(device).hook_extensions[hook->extension]) ? hook->proc 593 : nullptr; 594} 595 596VkResult EnumerateInstanceExtensionProperties( 597 const char* pLayerName, 598 uint32_t* pPropertyCount, 599 VkExtensionProperties* pProperties) { 600 static const std::array<VkExtensionProperties, 2> loader_extensions = {{ 601 // WSI extensions 602 {VK_KHR_SURFACE_EXTENSION_NAME, VK_KHR_SURFACE_SPEC_VERSION}, 603 {VK_KHR_ANDROID_SURFACE_EXTENSION_NAME, 604 VK_KHR_ANDROID_SURFACE_SPEC_VERSION}, 605 }}; 606 static const VkExtensionProperties loader_debug_report_extension = { 607 VK_EXT_DEBUG_REPORT_EXTENSION_NAME, VK_EXT_DEBUG_REPORT_SPEC_VERSION, 608 }; 609 610 // enumerate our extensions first 611 if (!pLayerName && pProperties) { 612 uint32_t count = std::min( 613 *pPropertyCount, static_cast<uint32_t>(loader_extensions.size())); 614 615 std::copy_n(loader_extensions.begin(), count, pProperties); 616 617 if (count < loader_extensions.size()) { 618 *pPropertyCount = count; 619 return VK_INCOMPLETE; 620 } 621 622 pProperties += count; 623 *pPropertyCount -= count; 624 625 if (Hal::Get().GetDebugReportIndex() < 0) { 626 if (!*pPropertyCount) { 627 *pPropertyCount = count; 628 return VK_INCOMPLETE; 629 } 630 631 pProperties[0] = loader_debug_report_extension; 632 pProperties += 1; 633 *pPropertyCount -= 1; 634 } 635 } 636 637 VkResult result = Hal::Device().EnumerateInstanceExtensionProperties( 638 pLayerName, pPropertyCount, pProperties); 639 640 if (!pLayerName && (result == VK_SUCCESS || result == VK_INCOMPLETE)) { 641 int idx = Hal::Get().GetDebugReportIndex(); 642 if (idx < 0) { 643 *pPropertyCount += 1; 644 } else if (pProperties && 645 static_cast<uint32_t>(idx) < *pPropertyCount) { 646 pProperties[idx].specVersion = 647 std::min(pProperties[idx].specVersion, 648 loader_debug_report_extension.specVersion); 649 } 650 651 *pPropertyCount += loader_extensions.size(); 652 } 653 654 return result; 655} 656 657VkResult EnumerateDeviceExtensionProperties( 658 VkPhysicalDevice physicalDevice, 659 const char* pLayerName, 660 uint32_t* pPropertyCount, 661 VkExtensionProperties* pProperties) { 662 const InstanceData& data = GetData(physicalDevice); 663 664 VkResult result = data.driver.EnumerateDeviceExtensionProperties( 665 physicalDevice, pLayerName, pPropertyCount, pProperties); 666 if (result != VK_SUCCESS && result != VK_INCOMPLETE) 667 return result; 668 669 if (!pProperties) 670 return result; 671 672 // map VK_ANDROID_native_buffer to VK_KHR_swapchain 673 for (uint32_t i = 0; i < *pPropertyCount; i++) { 674 auto& prop = pProperties[i]; 675 676 if (strcmp(prop.extensionName, 677 VK_ANDROID_NATIVE_BUFFER_EXTENSION_NAME) != 0) 678 continue; 679 680 memcpy(prop.extensionName, VK_KHR_SWAPCHAIN_EXTENSION_NAME, 681 sizeof(VK_KHR_SWAPCHAIN_EXTENSION_NAME)); 682 prop.specVersion = VK_KHR_SWAPCHAIN_SPEC_VERSION; 683 } 684 685 return result; 686} 687 688VkResult CreateInstance(const VkInstanceCreateInfo* pCreateInfo, 689 const VkAllocationCallbacks* pAllocator, 690 VkInstance* pInstance) { 691 const VkAllocationCallbacks& data_allocator = 692 (pAllocator) ? *pAllocator : GetDefaultAllocator(); 693 694 CreateInfoWrapper wrapper(*pCreateInfo, data_allocator); 695 VkResult result = wrapper.Validate(); 696 if (result != VK_SUCCESS) 697 return result; 698 699 InstanceData* data = AllocateInstanceData(data_allocator); 700 if (!data) 701 return VK_ERROR_OUT_OF_HOST_MEMORY; 702 703 data->hook_extensions |= wrapper.GetHookExtensions(); 704 705 // call into the driver 706 VkInstance instance; 707 result = Hal::Device().CreateInstance( 708 static_cast<const VkInstanceCreateInfo*>(wrapper), pAllocator, 709 &instance); 710 if (result != VK_SUCCESS) { 711 FreeInstanceData(data, data_allocator); 712 return result; 713 } 714 715 // initialize InstanceDriverTable 716 if (!SetData(instance, *data) || 717 !InitDriverTable(instance, Hal::Device().GetInstanceProcAddr, 718 wrapper.GetHalExtensions())) { 719 data->driver.DestroyInstance = reinterpret_cast<PFN_vkDestroyInstance>( 720 Hal::Device().GetInstanceProcAddr(instance, "vkDestroyInstance")); 721 if (data->driver.DestroyInstance) 722 data->driver.DestroyInstance(instance, pAllocator); 723 724 FreeInstanceData(data, data_allocator); 725 726 return VK_ERROR_INCOMPATIBLE_DRIVER; 727 } 728 729 data->get_device_proc_addr = reinterpret_cast<PFN_vkGetDeviceProcAddr>( 730 Hal::Device().GetInstanceProcAddr(instance, "vkGetDeviceProcAddr")); 731 if (!data->get_device_proc_addr) { 732 data->driver.DestroyInstance(instance, pAllocator); 733 FreeInstanceData(data, data_allocator); 734 735 return VK_ERROR_INCOMPATIBLE_DRIVER; 736 } 737 738 *pInstance = instance; 739 740 return VK_SUCCESS; 741} 742 743void DestroyInstance(VkInstance instance, 744 const VkAllocationCallbacks* pAllocator) { 745 InstanceData& data = GetData(instance); 746 data.driver.DestroyInstance(instance, pAllocator); 747 748 VkAllocationCallbacks local_allocator; 749 if (!pAllocator) { 750 local_allocator = data.allocator; 751 pAllocator = &local_allocator; 752 } 753 754 FreeInstanceData(&data, *pAllocator); 755} 756 757VkResult CreateDevice(VkPhysicalDevice physicalDevice, 758 const VkDeviceCreateInfo* pCreateInfo, 759 const VkAllocationCallbacks* pAllocator, 760 VkDevice* pDevice) { 761 const InstanceData& instance_data = GetData(physicalDevice); 762 const VkAllocationCallbacks& data_allocator = 763 (pAllocator) ? *pAllocator : instance_data.allocator; 764 765 CreateInfoWrapper wrapper(physicalDevice, *pCreateInfo, data_allocator); 766 VkResult result = wrapper.Validate(); 767 if (result != VK_SUCCESS) 768 return result; 769 770 DeviceData* data = AllocateDeviceData(data_allocator, 771 instance_data.debug_report_callbacks); 772 if (!data) 773 return VK_ERROR_OUT_OF_HOST_MEMORY; 774 775 data->hook_extensions |= wrapper.GetHookExtensions(); 776 777 // call into the driver 778 VkDevice dev; 779 result = instance_data.driver.CreateDevice( 780 physicalDevice, static_cast<const VkDeviceCreateInfo*>(wrapper), 781 pAllocator, &dev); 782 if (result != VK_SUCCESS) { 783 FreeDeviceData(data, data_allocator); 784 return result; 785 } 786 787 // initialize DeviceDriverTable 788 if (!SetData(dev, *data) || 789 !InitDriverTable(dev, instance_data.get_device_proc_addr, 790 wrapper.GetHalExtensions())) { 791 data->driver.DestroyDevice = reinterpret_cast<PFN_vkDestroyDevice>( 792 instance_data.get_device_proc_addr(dev, "vkDestroyDevice")); 793 if (data->driver.DestroyDevice) 794 data->driver.DestroyDevice(dev, pAllocator); 795 796 FreeDeviceData(data, data_allocator); 797 798 return VK_ERROR_INCOMPATIBLE_DRIVER; 799 } 800 801 *pDevice = dev; 802 803 return VK_SUCCESS; 804} 805 806void DestroyDevice(VkDevice device, const VkAllocationCallbacks* pAllocator) { 807 DeviceData& data = GetData(device); 808 data.driver.DestroyDevice(device, pAllocator); 809 810 VkAllocationCallbacks local_allocator; 811 if (!pAllocator) { 812 local_allocator = data.allocator; 813 pAllocator = &local_allocator; 814 } 815 816 FreeDeviceData(&data, *pAllocator); 817} 818 819VkResult EnumeratePhysicalDevices(VkInstance instance, 820 uint32_t* pPhysicalDeviceCount, 821 VkPhysicalDevice* pPhysicalDevices) { 822 const auto& data = GetData(instance); 823 824 VkResult result = data.driver.EnumeratePhysicalDevices( 825 instance, pPhysicalDeviceCount, pPhysicalDevices); 826 if ((result == VK_SUCCESS || result == VK_INCOMPLETE) && pPhysicalDevices) { 827 for (uint32_t i = 0; i < *pPhysicalDeviceCount; i++) 828 SetData(pPhysicalDevices[i], data); 829 } 830 831 return result; 832} 833 834void GetDeviceQueue(VkDevice device, 835 uint32_t queueFamilyIndex, 836 uint32_t queueIndex, 837 VkQueue* pQueue) { 838 const auto& data = GetData(device); 839 840 data.driver.GetDeviceQueue(device, queueFamilyIndex, queueIndex, pQueue); 841 SetData(*pQueue, data); 842} 843 844VKAPI_ATTR VkResult 845AllocateCommandBuffers(VkDevice device, 846 const VkCommandBufferAllocateInfo* pAllocateInfo, 847 VkCommandBuffer* pCommandBuffers) { 848 const auto& data = GetData(device); 849 850 VkResult result = data.driver.AllocateCommandBuffers(device, pAllocateInfo, 851 pCommandBuffers); 852 if (result == VK_SUCCESS) { 853 for (uint32_t i = 0; i < pAllocateInfo->commandBufferCount; i++) 854 SetData(pCommandBuffers[i], data); 855 } 856 857 return result; 858} 859 860} // namespace driver 861} // namespace vulkan 862