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
20 #include <dlfcn.h>
21 #include <algorithm>
22 #include <array>
23 #include <new>
24
25 #include <log/log.h>
26
27 #include <android/dlext.h>
28 #include <cutils/properties.h>
29
30 #include "driver.h"
31 #include "stubhal.h"
32
33 #include "base/System.h"
34 #include "base/PathUtils.h"
35
36 #include <vector>
37
38 using android::base::pj;
39
40 // TODO(b/37049319) Get this from a header once one exists
41 extern "C" {
42 android_namespace_t* android_get_exported_namespace(const char*);
43 }
44
45 // #define ENABLE_ALLOC_CALLSTACKS 1
46 #if ENABLE_ALLOC_CALLSTACKS
47 #include <utils/CallStack.h>
48 #define ALOGD_CALLSTACK(...) \
49 do { \
50 ALOGD(__VA_ARGS__); \
51 android::CallStack callstack; \
52 callstack.update(); \
53 callstack.log(LOG_TAG, ANDROID_LOG_DEBUG, " "); \
54 } while (false)
55 #else
56 #define ALOGD_CALLSTACK(...) \
57 do { \
58 } while (false)
59 #endif
60
61 namespace vulkan {
62 namespace driver {
63
64 namespace {
65
66 class Hal {
67 public:
68 static bool Open();
69
Get()70 static const Hal& Get() { return hal_; }
Device()71 static const hwvulkan_device_t& Device() { return *Get().dev_; }
72
GetDebugReportIndex() const73 int GetDebugReportIndex() const { return debug_report_index_; }
74
75 private:
Hal()76 Hal() : dev_(nullptr), debug_report_index_(-1) {}
77 Hal(const Hal&) = delete;
78 Hal& operator=(const Hal&) = delete;
79
80 bool InitDebugReportIndex();
81
82 static Hal hal_;
83
84 const hwvulkan_device_t* dev_;
85 int debug_report_index_;
86 };
87
88 class CreateInfoWrapper {
89 public:
90 CreateInfoWrapper(const VkInstanceCreateInfo& create_info,
91 const VkAllocationCallbacks& allocator);
92 CreateInfoWrapper(VkPhysicalDevice physical_dev,
93 const VkDeviceCreateInfo& create_info,
94 const VkAllocationCallbacks& allocator);
95 ~CreateInfoWrapper();
96
97 VkResult Validate();
98 void DowngradeApiVersion();
99
100 const std::bitset<ProcHook::EXTENSION_COUNT>& GetHookExtensions() const;
101 const std::bitset<ProcHook::EXTENSION_COUNT>& GetHalExtensions() const;
102
103 explicit operator const VkInstanceCreateInfo*() const;
104 explicit operator const VkDeviceCreateInfo*() const;
105
106 private:
107 struct ExtensionFilter {
108 VkExtensionProperties* exts;
109 uint32_t ext_count;
110
111 const char** names;
112 uint32_t name_count;
113 };
114
115 VkResult SanitizePNext();
116
117 VkResult SanitizeLayers();
118 VkResult SanitizeExtensions();
119
120 VkResult QueryExtensionCount(uint32_t& count) const;
121 VkResult EnumerateExtensions(uint32_t& count,
122 VkExtensionProperties* props) const;
123 VkResult InitExtensionFilter();
124 void FilterExtension(const char* name);
125
126 const bool is_instance_;
127 const VkAllocationCallbacks& allocator_;
128
129 VkPhysicalDevice physical_dev_;
130
131 union {
132 VkInstanceCreateInfo instance_info_;
133 VkDeviceCreateInfo dev_info_;
134 };
135
136 VkApplicationInfo application_info_;
137
138 ExtensionFilter extension_filter_;
139
140 std::bitset<ProcHook::EXTENSION_COUNT> hook_extensions_;
141 std::bitset<ProcHook::EXTENSION_COUNT> hal_extensions_;
142 };
143
144 Hal Hal::hal_;
145
146 #ifdef __APPLE__
147 #define LIBSUFFIX ".dylib"
148 #else
149 #define LIBSUFFIX ".so"
150 #endif
151 // The cmake build system prefixes all libraries with lib
152 #define LIBPREFIX "lib"
153
LoadLibrary(const android_dlextinfo & dlextinfo,const char * subname,int subname_len)154 void* LoadLibrary(const android_dlextinfo& dlextinfo,
155 const char* subname,
156 int subname_len) {
157
158 const char kLibFormat[] = LIBPREFIX "vulkan.%*s" LIBSUFFIX;
159 char* name = static_cast<char*>(
160 alloca(sizeof(kLibFormat) + static_cast<size_t>(subname_len)));
161 sprintf(name, kLibFormat, subname_len, subname);
162
163 auto progDir = android::base::getProgramDirectory();
164 auto expectedLibPath = pj({progDir, "lib64", name});
165
166 auto res = android_dlopen_ext(expectedLibPath.c_str(), RTLD_LOCAL | RTLD_NOW,
167 &dlextinfo);
168 if (!res) {
169 fprintf(stderr, "%s: failed. dlerror; [%s]\n", __func__, dlerror());
170 }
171
172 return res;
173 }
174
175 const std::array<const char*, 2> HAL_SUBNAME_KEY_PROPERTIES = {{
176 "ro.hardware." HWVULKAN_HARDWARE_MODULE_ID,
177 "ro.board.platform",
178 }};
179
LoadDriver(android_namespace_t * library_namespace,const hwvulkan_module_t ** module)180 int LoadDriver(android_namespace_t* library_namespace,
181 const hwvulkan_module_t** module) {
182 const android_dlextinfo dlextinfo = {
183 .flags = ANDROID_DLEXT_USE_NAMESPACE,
184 .library_namespace = library_namespace,
185 };
186
187 // Emulator: Load vulkan.ranchu
188 void* so = LoadLibrary(dlextinfo, "ranchu", strlen("ranchu"));;
189 if (!so)
190 return -ENOENT;
191
192 auto hmi = static_cast<hw_module_t*>(dlsym(so, HAL_MODULE_INFO_SYM_AS_STR));
193 if (!hmi) {
194 ALOGE("couldn't find symbol '%s' in HAL library: %s", HAL_MODULE_INFO_SYM_AS_STR, dlerror());
195 dlclose(so);
196 return -EINVAL;
197 }
198 if (strcmp(hmi->id, HWVULKAN_HARDWARE_MODULE_ID) != 0) {
199 ALOGE("HAL id '%s' != '%s'", hmi->id, HWVULKAN_HARDWARE_MODULE_ID);
200 dlclose(so);
201 return -EINVAL;
202 }
203 hmi->dso = so;
204 *module = reinterpret_cast<const hwvulkan_module_t*>(hmi);
205 return 0;
206 }
207
LoadBuiltinDriver(const hwvulkan_module_t ** module)208 int LoadBuiltinDriver(const hwvulkan_module_t** module) {
209 return LoadDriver(nullptr, module);
210 }
211
LoadUpdatedDriver(const hwvulkan_module_t ** module)212 int LoadUpdatedDriver(const hwvulkan_module_t** module) {
213 return LoadDriver(nullptr, module);
214 }
215
Open()216 bool Hal::Open() {
217 ALOG_ASSERT(!hal_.dev_, "OpenHAL called more than once");
218
219 // Use a stub device unless we successfully open a real HAL device.
220 hal_.dev_ = &stubhal::kDevice;
221
222 int result;
223 const hwvulkan_module_t* module = nullptr;
224
225 result = LoadUpdatedDriver(&module);
226 if (result == -ENOENT) {
227 result = LoadBuiltinDriver(&module);
228 if (result != 0) {
229 // -ENOENT means the sphal namespace doesn't exist, not that there
230 // is a problem with the driver.
231 ALOGE(
232 "Failed to load Vulkan driver into sphal namespace. This "
233 "usually means the driver has forbidden library dependencies."
234 "Please fix, this will soon stop working.");
235 abort();
236 // result =
237 // hw_get_module(HWVULKAN_HARDWARE_MODULE_ID,
238 // reinterpret_cast<const hw_module_t**>(&module));
239 }
240 }
241 if (result != 0) {
242 ALOGV("unable to load Vulkan HAL, using stub HAL (result=%d)", result);
243 return true;
244 }
245
246 hwvulkan_device_t* device;
247 result =
248 module->common.methods->open(&module->common, HWVULKAN_DEVICE_0,
249 reinterpret_cast<hw_device_t**>(&device));
250 if (result != 0) {
251 // Any device with a Vulkan HAL should be able to open the device.
252 ALOGE("failed to open Vulkan HAL device: %s (%d)", strerror(-result),
253 result);
254 return false;
255 }
256
257 hal_.dev_ = device;
258
259 hal_.InitDebugReportIndex();
260
261 return true;
262 }
263
InitDebugReportIndex()264 bool Hal::InitDebugReportIndex() {
265 uint32_t count;
266 if (dev_->EnumerateInstanceExtensionProperties(nullptr, &count, nullptr) !=
267 VK_SUCCESS) {
268 ALOGE("failed to get HAL instance extension count");
269 return false;
270 }
271
272 VkExtensionProperties* exts = reinterpret_cast<VkExtensionProperties*>(
273 malloc(sizeof(VkExtensionProperties) * count));
274 if (!exts) {
275 ALOGE("failed to allocate HAL instance extension array");
276 return false;
277 }
278
279 if (dev_->EnumerateInstanceExtensionProperties(nullptr, &count, exts) !=
280 VK_SUCCESS) {
281 ALOGE("failed to enumerate HAL instance extensions");
282 free(exts);
283 return false;
284 }
285
286 for (uint32_t i = 0; i < count; i++) {
287 if (strcmp(exts[i].extensionName, VK_EXT_DEBUG_REPORT_EXTENSION_NAME) ==
288 0) {
289 debug_report_index_ = static_cast<int>(i);
290 break;
291 }
292 }
293
294 free(exts);
295
296 return true;
297 }
298
CreateInfoWrapper(const VkInstanceCreateInfo & create_info,const VkAllocationCallbacks & allocator)299 CreateInfoWrapper::CreateInfoWrapper(const VkInstanceCreateInfo& create_info,
300 const VkAllocationCallbacks& allocator)
301 : is_instance_(true),
302 allocator_(allocator),
303 physical_dev_(VK_NULL_HANDLE),
304 instance_info_(create_info),
305 extension_filter_() {
306 hook_extensions_.set(ProcHook::EXTENSION_CORE);
307 hal_extensions_.set(ProcHook::EXTENSION_CORE);
308 }
309
CreateInfoWrapper(VkPhysicalDevice physical_dev,const VkDeviceCreateInfo & create_info,const VkAllocationCallbacks & allocator)310 CreateInfoWrapper::CreateInfoWrapper(VkPhysicalDevice physical_dev,
311 const VkDeviceCreateInfo& create_info,
312 const VkAllocationCallbacks& allocator)
313 : is_instance_(false),
314 allocator_(allocator),
315 physical_dev_(physical_dev),
316 dev_info_(create_info),
317 extension_filter_() {
318 hook_extensions_.set(ProcHook::EXTENSION_CORE);
319 hal_extensions_.set(ProcHook::EXTENSION_CORE);
320 }
321
~CreateInfoWrapper()322 CreateInfoWrapper::~CreateInfoWrapper() {
323 allocator_.pfnFree(allocator_.pUserData, extension_filter_.exts);
324 allocator_.pfnFree(allocator_.pUserData, extension_filter_.names);
325 }
326
Validate()327 VkResult CreateInfoWrapper::Validate() {
328 VkResult result = SanitizePNext();
329 if (result == VK_SUCCESS)
330 result = SanitizeLayers();
331 if (result == VK_SUCCESS)
332 result = SanitizeExtensions();
333
334 return result;
335 }
336
337 const std::bitset<ProcHook::EXTENSION_COUNT>&
GetHookExtensions() const338 CreateInfoWrapper::GetHookExtensions() const {
339 return hook_extensions_;
340 }
341
342 const std::bitset<ProcHook::EXTENSION_COUNT>&
GetHalExtensions() const343 CreateInfoWrapper::GetHalExtensions() const {
344 return hal_extensions_;
345 }
346
operator const VkInstanceCreateInfo*() const347 CreateInfoWrapper::operator const VkInstanceCreateInfo*() const {
348 return &instance_info_;
349 }
350
operator const VkDeviceCreateInfo*() const351 CreateInfoWrapper::operator const VkDeviceCreateInfo*() const {
352 return &dev_info_;
353 }
354
SanitizePNext()355 VkResult CreateInfoWrapper::SanitizePNext() {
356 const struct StructHeader {
357 VkStructureType type;
358 const void* next;
359 } * header;
360
361 if (is_instance_) {
362 header = reinterpret_cast<const StructHeader*>(instance_info_.pNext);
363
364 // skip leading VK_STRUCTURE_TYPE_LOADER_INSTANCE_CREATE_INFOs
365 while (header &&
366 header->type == VK_STRUCTURE_TYPE_LOADER_INSTANCE_CREATE_INFO)
367 header = reinterpret_cast<const StructHeader*>(header->next);
368
369 instance_info_.pNext = header;
370 } else {
371 header = reinterpret_cast<const StructHeader*>(dev_info_.pNext);
372
373 // skip leading VK_STRUCTURE_TYPE_LOADER_DEVICE_CREATE_INFOs
374 while (header &&
375 header->type == VK_STRUCTURE_TYPE_LOADER_DEVICE_CREATE_INFO)
376 header = reinterpret_cast<const StructHeader*>(header->next);
377
378 dev_info_.pNext = header;
379 }
380
381 return VK_SUCCESS;
382 }
383
SanitizeLayers()384 VkResult CreateInfoWrapper::SanitizeLayers() {
385 auto& layer_names = (is_instance_) ? instance_info_.ppEnabledLayerNames
386 : dev_info_.ppEnabledLayerNames;
387 auto& layer_count = (is_instance_) ? instance_info_.enabledLayerCount
388 : dev_info_.enabledLayerCount;
389
390 // remove all layers
391 layer_names = nullptr;
392 layer_count = 0;
393
394 return VK_SUCCESS;
395 }
396
SanitizeExtensions()397 VkResult CreateInfoWrapper::SanitizeExtensions() {
398 auto& ext_names = (is_instance_) ? instance_info_.ppEnabledExtensionNames
399 : dev_info_.ppEnabledExtensionNames;
400 auto& ext_count = (is_instance_) ? instance_info_.enabledExtensionCount
401 : dev_info_.enabledExtensionCount;
402 if (!ext_count)
403 return VK_SUCCESS;
404
405 VkResult result = InitExtensionFilter();
406 if (result != VK_SUCCESS)
407 return result;
408
409 for (uint32_t i = 0; i < ext_count; i++)
410 FilterExtension(ext_names[i]);
411
412 // Enable device extensions that contain physical-device commands, so that
413 // vkGetInstanceProcAddr will return those physical-device commands.
414 if (is_instance_) {
415 hook_extensions_.set(ProcHook::KHR_swapchain);
416 }
417
418 ext_names = extension_filter_.names;
419 ext_count = extension_filter_.name_count;
420
421 return VK_SUCCESS;
422 }
423
QueryExtensionCount(uint32_t & count) const424 VkResult CreateInfoWrapper::QueryExtensionCount(uint32_t& count) const {
425 if (is_instance_) {
426 return Hal::Device().EnumerateInstanceExtensionProperties(
427 nullptr, &count, nullptr);
428 } else {
429 const auto& driver = GetData(physical_dev_).driver;
430 return driver.EnumerateDeviceExtensionProperties(physical_dev_, nullptr,
431 &count, nullptr);
432 }
433 }
434
EnumerateExtensions(uint32_t & count,VkExtensionProperties * props) const435 VkResult CreateInfoWrapper::EnumerateExtensions(
436 uint32_t& count,
437 VkExtensionProperties* props) const {
438 if (is_instance_) {
439 return Hal::Device().EnumerateInstanceExtensionProperties(
440 nullptr, &count, props);
441 } else {
442 const auto& driver = GetData(physical_dev_).driver;
443 return driver.EnumerateDeviceExtensionProperties(physical_dev_, nullptr,
444 &count, props);
445 }
446 }
447
InitExtensionFilter()448 VkResult CreateInfoWrapper::InitExtensionFilter() {
449 // query extension count
450 uint32_t count;
451 VkResult result = QueryExtensionCount(count);
452 if (result != VK_SUCCESS || count == 0)
453 return result;
454
455 auto& filter = extension_filter_;
456 filter.exts =
457 reinterpret_cast<VkExtensionProperties*>(allocator_.pfnAllocation(
458 allocator_.pUserData, sizeof(VkExtensionProperties) * count,
459 alignof(VkExtensionProperties),
460 VK_SYSTEM_ALLOCATION_SCOPE_COMMAND));
461 if (!filter.exts)
462 return VK_ERROR_OUT_OF_HOST_MEMORY;
463
464 // enumerate extensions
465 result = EnumerateExtensions(count, filter.exts);
466 if (result != VK_SUCCESS && result != VK_INCOMPLETE)
467 return result;
468
469 if (!count)
470 return VK_SUCCESS;
471
472 filter.ext_count = count;
473
474 // allocate name array
475 uint32_t enabled_ext_count = (is_instance_)
476 ? instance_info_.enabledExtensionCount
477 : dev_info_.enabledExtensionCount;
478 count = std::min(filter.ext_count, enabled_ext_count);
479 filter.names = reinterpret_cast<const char**>(allocator_.pfnAllocation(
480 allocator_.pUserData, sizeof(const char*) * count, alignof(const char*),
481 VK_SYSTEM_ALLOCATION_SCOPE_COMMAND));
482 if (!filter.names)
483 return VK_ERROR_OUT_OF_HOST_MEMORY;
484
485 return VK_SUCCESS;
486 }
487
FilterExtension(const char * name)488 void CreateInfoWrapper::FilterExtension(const char* name) {
489 auto& filter = extension_filter_;
490
491 ProcHook::Extension ext_bit = GetProcHookExtension(name);
492 if (is_instance_) {
493 switch (ext_bit) {
494 case ProcHook::KHR_android_surface:
495 case ProcHook::KHR_surface:
496 case ProcHook::EXT_swapchain_colorspace:
497 case ProcHook::KHR_get_surface_capabilities2:
498 hook_extensions_.set(ext_bit);
499 // return now as these extensions do not require HAL support
500 return;
501 case ProcHook::EXT_debug_report:
502 // both we and HAL can take part in
503 hook_extensions_.set(ext_bit);
504 break;
505 case ProcHook::KHR_get_physical_device_properties2:
506 case ProcHook::EXTENSION_UNKNOWN:
507 // Extensions we don't need to do anything about at this level
508 break;
509
510 case ProcHook::KHR_incremental_present:
511 case ProcHook::KHR_shared_presentable_image:
512 case ProcHook::KHR_swapchain:
513 case ProcHook::EXT_hdr_metadata:
514 case ProcHook::ANDROID_external_memory_android_hardware_buffer:
515 case ProcHook::ANDROID_native_buffer:
516 case ProcHook::GOOGLE_display_timing:
517 case ProcHook::EXTENSION_CORE:
518 case ProcHook::EXTENSION_COUNT:
519 // Device and meta extensions. If we ever get here it's a bug in
520 // our code. But enumerating them lets us avoid having a default
521 // case, and default hides other bugs.
522 ALOGE(
523 "CreateInfoWrapper::FilterExtension: invalid instance "
524 "extension '%s'. FIX ME",
525 name);
526 return;
527
528 // Don't use a default case. Without it, -Wswitch will tell us
529 // at compile time if someone adds a new ProcHook extension but
530 // doesn't handle it above. That's a real bug that has
531 // not-immediately-obvious effects.
532 //
533 // default:
534 // break;
535 }
536 } else {
537 switch (ext_bit) {
538 case ProcHook::KHR_swapchain:
539 // map VK_KHR_swapchain to VK_ANDROID_native_buffer
540 name = VK_ANDROID_NATIVE_BUFFER_EXTENSION_NAME;
541 ext_bit = ProcHook::ANDROID_native_buffer;
542 break;
543 case ProcHook::KHR_incremental_present:
544 case ProcHook::GOOGLE_display_timing:
545 case ProcHook::KHR_shared_presentable_image:
546 hook_extensions_.set(ext_bit);
547 // return now as these extensions do not require HAL support
548 return;
549 case ProcHook::EXT_hdr_metadata:
550 hook_extensions_.set(ext_bit);
551 break;
552 case ProcHook::ANDROID_external_memory_android_hardware_buffer:
553 case ProcHook::EXTENSION_UNKNOWN:
554 // Extensions we don't need to do anything about at this level
555 break;
556
557 case ProcHook::KHR_android_surface:
558 case ProcHook::KHR_get_physical_device_properties2:
559 case ProcHook::KHR_get_surface_capabilities2:
560 case ProcHook::KHR_surface:
561 case ProcHook::EXT_debug_report:
562 case ProcHook::EXT_swapchain_colorspace:
563 case ProcHook::ANDROID_native_buffer:
564 case ProcHook::EXTENSION_CORE:
565 case ProcHook::EXTENSION_COUNT:
566 // Instance and meta extensions. If we ever get here it's a bug
567 // in our code. But enumerating them lets us avoid having a
568 // default case, and default hides other bugs.
569 ALOGE(
570 "CreateInfoWrapper::FilterExtension: invalid device "
571 "extension '%s'. FIX ME",
572 name);
573 return;
574
575 // Don't use a default case. Without it, -Wswitch will tell us
576 // at compile time if someone adds a new ProcHook extension but
577 // doesn't handle it above. That's a real bug that has
578 // not-immediately-obvious effects.
579 //
580 // default:
581 // break;
582 }
583 }
584
585 for (uint32_t i = 0; i < filter.ext_count; i++) {
586 const VkExtensionProperties& props = filter.exts[i];
587 // ignore unknown extensions
588 if (strcmp(name, props.extensionName) != 0)
589 continue;
590
591 filter.names[filter.name_count++] = name;
592 if (ext_bit != ProcHook::EXTENSION_UNKNOWN) {
593 if (ext_bit == ProcHook::ANDROID_native_buffer)
594 hook_extensions_.set(ProcHook::KHR_swapchain);
595
596 hal_extensions_.set(ext_bit);
597 }
598
599 break;
600 }
601 }
602
DowngradeApiVersion()603 void CreateInfoWrapper::DowngradeApiVersion() {
604 // If pApplicationInfo is NULL, apiVersion is assumed to be 1.0:
605 if (instance_info_.pApplicationInfo) {
606 application_info_ = *instance_info_.pApplicationInfo;
607 instance_info_.pApplicationInfo = &application_info_;
608 application_info_.apiVersion = VK_API_VERSION_1_0;
609 }
610 }
611
DefaultAllocate(void *,size_t size,size_t alignment,VkSystemAllocationScope)612 VKAPI_ATTR void* DefaultAllocate(void*,
613 size_t size,
614 size_t alignment,
615 VkSystemAllocationScope) {
616 void* ptr = nullptr;
617 // Vulkan requires 'alignment' to be a power of two, but posix_memalign
618 // additionally requires that it be at least sizeof(void*).
619 int ret = posix_memalign(&ptr, std::max(alignment, sizeof(void*)), size);
620 ALOGD_CALLSTACK("Allocate: size=%zu align=%zu => (%d) %p", size, alignment,
621 ret, ptr);
622 return ret == 0 ? ptr : nullptr;
623 }
624
DefaultReallocate(void *,void * ptr,size_t size,size_t alignment,VkSystemAllocationScope)625 VKAPI_ATTR void* DefaultReallocate(void*,
626 void* ptr,
627 size_t size,
628 size_t alignment,
629 VkSystemAllocationScope) {
630 free(ptr);
631
632 void* new_ptr = nullptr;
633 if (posix_memalign(&new_ptr, std::max(alignment, sizeof(void*)), size) != 0)
634 return nullptr;
635
636 return new_ptr;
637 }
638
DefaultFree(void *,void * ptr)639 VKAPI_ATTR void DefaultFree(void*, void* ptr) {
640 ALOGD_CALLSTACK("Free: %p", ptr);
641 free(ptr);
642 }
643
AllocateInstanceData(const VkAllocationCallbacks & allocator)644 InstanceData* AllocateInstanceData(const VkAllocationCallbacks& allocator) {
645 void* data_mem = allocator.pfnAllocation(
646 allocator.pUserData, sizeof(InstanceData), alignof(InstanceData),
647 VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
648 if (!data_mem)
649 return nullptr;
650
651 return new (data_mem) InstanceData(allocator);
652 }
653
FreeInstanceData(InstanceData * data,const VkAllocationCallbacks & allocator)654 void FreeInstanceData(InstanceData* data,
655 const VkAllocationCallbacks& allocator) {
656 data->~InstanceData();
657 allocator.pfnFree(allocator.pUserData, data);
658 }
659
AllocateDeviceData(const VkAllocationCallbacks & allocator,const DebugReportCallbackList & debug_report_callbacks)660 DeviceData* AllocateDeviceData(
661 const VkAllocationCallbacks& allocator,
662 const DebugReportCallbackList& debug_report_callbacks) {
663 void* data_mem = allocator.pfnAllocation(
664 allocator.pUserData, sizeof(DeviceData), alignof(DeviceData),
665 VK_SYSTEM_ALLOCATION_SCOPE_DEVICE);
666 if (!data_mem)
667 return nullptr;
668
669 return new (data_mem) DeviceData(allocator, debug_report_callbacks);
670 }
671
FreeDeviceData(DeviceData * data,const VkAllocationCallbacks & allocator)672 void FreeDeviceData(DeviceData* data, const VkAllocationCallbacks& allocator) {
673 data->~DeviceData();
674 allocator.pfnFree(allocator.pUserData, data);
675 }
676
677 } // anonymous namespace
678
Debuggable()679 bool Debuggable() {
680 return false;
681 }
682
OpenHAL()683 bool OpenHAL() {
684 return Hal::Open();
685 }
686
GetDefaultAllocator()687 const VkAllocationCallbacks& GetDefaultAllocator() {
688 static const VkAllocationCallbacks kDefaultAllocCallbacks = {
689 .pUserData = nullptr,
690 .pfnAllocation = DefaultAllocate,
691 .pfnReallocation = DefaultReallocate,
692 .pfnFree = DefaultFree,
693 };
694
695 return kDefaultAllocCallbacks;
696 }
697
GetInstanceProcAddr(VkInstance instance,const char * pName)698 PFN_vkVoidFunction GetInstanceProcAddr(VkInstance instance, const char* pName) {
699 const ProcHook* hook = GetProcHook(pName);
700 if (!hook)
701 return Hal::Device().GetInstanceProcAddr(instance, pName);
702
703 if (!instance) {
704 if (hook->type == ProcHook::GLOBAL)
705 return hook->proc;
706
707 // v0 layers expect
708 //
709 // vkGetInstanceProcAddr(VK_NULL_HANDLE, "vkCreateDevice");
710 //
711 // to work.
712 if (strcmp(pName, "vkCreateDevice") == 0)
713 return hook->proc;
714
715 ALOGE(
716 "internal vkGetInstanceProcAddr called for %s without an instance",
717 pName);
718
719 return nullptr;
720 }
721
722 PFN_vkVoidFunction proc;
723
724 switch (hook->type) {
725 case ProcHook::INSTANCE:
726 proc = (GetData(instance).hook_extensions[hook->extension])
727 ? hook->proc
728 : nullptr;
729 break;
730 case ProcHook::DEVICE:
731 proc = (hook->extension == ProcHook::EXTENSION_CORE)
732 ? hook->proc
733 : hook->checked_proc;
734 break;
735 default:
736 ALOGE(
737 "internal vkGetInstanceProcAddr called for %s with an instance",
738 pName);
739 proc = nullptr;
740 break;
741 }
742
743 return proc;
744 }
745
GetDeviceProcAddr(VkDevice device,const char * pName)746 PFN_vkVoidFunction GetDeviceProcAddr(VkDevice device, const char* pName) {
747 const ProcHook* hook = GetProcHook(pName);
748 if (!hook)
749 return GetData(device).driver.GetDeviceProcAddr(device, pName);
750
751 if (hook->type != ProcHook::DEVICE) {
752 ALOGE("internal vkGetDeviceProcAddr called for %s", pName);
753 return nullptr;
754 }
755
756 return (GetData(device).hook_extensions[hook->extension]) ? hook->proc
757 : nullptr;
758 }
759
EnumerateInstanceExtensionProperties(const char * pLayerName,uint32_t * pPropertyCount,VkExtensionProperties * pProperties)760 VkResult EnumerateInstanceExtensionProperties(
761 const char* pLayerName,
762 uint32_t* pPropertyCount,
763 VkExtensionProperties* pProperties) {
764
765 std::vector<VkExtensionProperties> loader_extensions;
766 loader_extensions.push_back(VkExtensionProperties{
767 VK_KHR_SURFACE_EXTENSION_NAME, VK_KHR_SURFACE_SPEC_VERSION});
768 loader_extensions.push_back(
769 VkExtensionProperties{VK_KHR_ANDROID_SURFACE_EXTENSION_NAME,
770 VK_KHR_ANDROID_SURFACE_SPEC_VERSION});
771 loader_extensions.push_back(
772 VkExtensionProperties{VK_EXT_SWAPCHAIN_COLOR_SPACE_EXTENSION_NAME,
773 VK_EXT_SWAPCHAIN_COLOR_SPACE_SPEC_VERSION});
774 loader_extensions.push_back(
775 VkExtensionProperties{VK_KHR_GET_SURFACE_CAPABILITIES_2_EXTENSION_NAME,
776 VK_KHR_GET_SURFACE_CAPABILITIES_2_SPEC_VERSION});
777
778 static const VkExtensionProperties loader_debug_report_extension = {
779 VK_EXT_DEBUG_REPORT_EXTENSION_NAME, VK_EXT_DEBUG_REPORT_SPEC_VERSION,
780 };
781
782 // enumerate our extensions first
783 if (!pLayerName && pProperties) {
784 uint32_t count = std::min(
785 *pPropertyCount, static_cast<uint32_t>(loader_extensions.size()));
786
787 std::copy_n(loader_extensions.begin(), count, pProperties);
788
789 if (count < loader_extensions.size()) {
790 *pPropertyCount = count;
791 return VK_INCOMPLETE;
792 }
793
794 pProperties += count;
795 *pPropertyCount -= count;
796
797 if (Hal::Get().GetDebugReportIndex() < 0) {
798 if (!*pPropertyCount) {
799 *pPropertyCount = count;
800 return VK_INCOMPLETE;
801 }
802
803 pProperties[0] = loader_debug_report_extension;
804 pProperties += 1;
805 *pPropertyCount -= 1;
806 }
807 }
808
809 VkResult result = Hal::Device().EnumerateInstanceExtensionProperties(
810 pLayerName, pPropertyCount, pProperties);
811
812 if (!pLayerName && (result == VK_SUCCESS || result == VK_INCOMPLETE)) {
813 int idx = Hal::Get().GetDebugReportIndex();
814 if (idx < 0) {
815 *pPropertyCount += 1;
816 } else if (pProperties &&
817 static_cast<uint32_t>(idx) < *pPropertyCount) {
818 pProperties[idx].specVersion =
819 std::min(pProperties[idx].specVersion,
820 loader_debug_report_extension.specVersion);
821 }
822
823 *pPropertyCount += loader_extensions.size();
824 }
825
826 return result;
827 }
828
QueryPresentationProperties(VkPhysicalDevice physicalDevice,VkPhysicalDevicePresentationPropertiesANDROID * presentation_properties)829 bool QueryPresentationProperties(
830 VkPhysicalDevice physicalDevice,
831 VkPhysicalDevicePresentationPropertiesANDROID *presentation_properties)
832 {
833 const InstanceData& data = GetData(physicalDevice);
834
835 // GPDP2 must be present and enabled on the instance.
836 if (!data.driver.GetPhysicalDeviceProperties2KHR &&
837 !data.driver.GetPhysicalDeviceProperties2)
838 return false;
839
840 // Request the android-specific presentation properties via GPDP2
841 VkPhysicalDeviceProperties2KHR properties = {
842 VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2_KHR,
843 presentation_properties,
844 {}
845 };
846
847 #pragma clang diagnostic push
848 #pragma clang diagnostic ignored "-Wold-style-cast"
849 presentation_properties->sType =
850 VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PRESENTATION_PROPERTIES_ANDROID;
851 #pragma clang diagnostic pop
852 presentation_properties->pNext = nullptr;
853 presentation_properties->sharedImage = VK_FALSE;
854
855 if (data.driver.GetPhysicalDeviceProperties2KHR) {
856 data.driver.GetPhysicalDeviceProperties2KHR(physicalDevice,
857 &properties);
858 } else {
859 data.driver.GetPhysicalDeviceProperties2(physicalDevice, &properties);
860 }
861
862 return true;
863 }
864
EnumerateDeviceExtensionProperties(VkPhysicalDevice physicalDevice,const char * pLayerName,uint32_t * pPropertyCount,VkExtensionProperties * pProperties)865 VkResult EnumerateDeviceExtensionProperties(
866 VkPhysicalDevice physicalDevice,
867 const char* pLayerName,
868 uint32_t* pPropertyCount,
869 VkExtensionProperties* pProperties) {
870 const InstanceData& data = GetData(physicalDevice);
871 // extensions that are unconditionally exposed by the loader
872 std::vector<VkExtensionProperties> loader_extensions;
873 loader_extensions.push_back(
874 VkExtensionProperties{VK_KHR_INCREMENTAL_PRESENT_EXTENSION_NAME,
875 VK_KHR_INCREMENTAL_PRESENT_SPEC_VERSION});
876
877 bool hdrBoardConfig = false;
878 if (hdrBoardConfig) {
879 loader_extensions.push_back(
880 VkExtensionProperties{VK_EXT_HDR_METADATA_EXTENSION_NAME,
881 VK_EXT_HDR_METADATA_SPEC_VERSION});
882 }
883
884 VkPhysicalDevicePresentationPropertiesANDROID presentation_properties;
885 if (QueryPresentationProperties(physicalDevice, &presentation_properties) &&
886 presentation_properties.sharedImage) {
887 loader_extensions.push_back(
888 VkExtensionProperties{VK_KHR_SHARED_PRESENTABLE_IMAGE_EXTENSION_NAME,
889 VK_KHR_SHARED_PRESENTABLE_IMAGE_SPEC_VERSION});
890 }
891
892 // conditionally add VK_GOOGLE_display_timing if present timestamps are
893 // supported by the driver:
894 // const std::string timestamp_property("service.sf.present_timestamp");
895 // android::base::WaitForPropertyCreation(timestamp_property);
896 // if (android::base::GetBoolProperty(timestamp_property, true)) {
897 // loader_extensions.push_back({
898 // VK_GOOGLE_DISPLAY_TIMING_EXTENSION_NAME,
899 // VK_GOOGLE_DISPLAY_TIMING_SPEC_VERSION});
900 // }
901
902 // enumerate our extensions first
903 if (!pLayerName && pProperties) {
904 uint32_t count = std::min(
905 *pPropertyCount, static_cast<uint32_t>(loader_extensions.size()));
906
907 std::copy_n(loader_extensions.begin(), count, pProperties);
908
909 if (count < loader_extensions.size()) {
910 *pPropertyCount = count;
911 return VK_INCOMPLETE;
912 }
913
914 pProperties += count;
915 *pPropertyCount -= count;
916 }
917
918 VkResult result = data.driver.EnumerateDeviceExtensionProperties(
919 physicalDevice, pLayerName, pPropertyCount, pProperties);
920
921 if (pProperties) {
922 // map VK_ANDROID_native_buffer to VK_KHR_swapchain
923 for (uint32_t i = 0; i < *pPropertyCount; i++) {
924 auto& prop = pProperties[i];
925
926 if (strcmp(prop.extensionName,
927 VK_ANDROID_NATIVE_BUFFER_EXTENSION_NAME) != 0)
928 continue;
929
930 memcpy(prop.extensionName, VK_KHR_SWAPCHAIN_EXTENSION_NAME,
931 sizeof(VK_KHR_SWAPCHAIN_EXTENSION_NAME));
932 prop.specVersion = VK_KHR_SWAPCHAIN_SPEC_VERSION;
933 }
934 }
935
936 // restore loader extension count
937 if (!pLayerName && (result == VK_SUCCESS || result == VK_INCOMPLETE)) {
938 *pPropertyCount += loader_extensions.size();
939 }
940
941 return result;
942 }
943
CreateInstance(const VkInstanceCreateInfo * pCreateInfo,const VkAllocationCallbacks * pAllocator,VkInstance * pInstance)944 VkResult CreateInstance(const VkInstanceCreateInfo* pCreateInfo,
945 const VkAllocationCallbacks* pAllocator,
946 VkInstance* pInstance) {
947 const VkAllocationCallbacks& data_allocator =
948 (pAllocator) ? *pAllocator : GetDefaultAllocator();
949
950 CreateInfoWrapper wrapper(*pCreateInfo, data_allocator);
951 VkResult result = wrapper.Validate();
952 if (result != VK_SUCCESS)
953 return result;
954
955 InstanceData* data = AllocateInstanceData(data_allocator);
956 if (!data)
957 return VK_ERROR_OUT_OF_HOST_MEMORY;
958
959 data->hook_extensions |= wrapper.GetHookExtensions();
960
961 #pragma clang diagnostic push
962 #pragma clang diagnostic ignored "-Wold-style-cast"
963 uint32_t api_version = ((pCreateInfo->pApplicationInfo)
964 ? pCreateInfo->pApplicationInfo->apiVersion
965 : VK_API_VERSION_1_0);
966 uint32_t api_major_version = VK_VERSION_MAJOR(api_version);
967 uint32_t api_minor_version = VK_VERSION_MINOR(api_version);
968 uint32_t icd_api_version;
969 PFN_vkEnumerateInstanceVersion pfn_enumerate_instance_version =
970 reinterpret_cast<PFN_vkEnumerateInstanceVersion>(
971 Hal::Device().GetInstanceProcAddr(NULL,
972 "vkEnumerateInstanceVersion"));
973 if (!pfn_enumerate_instance_version) {
974 icd_api_version = VK_API_VERSION_1_0;
975 } else {
976 result = (*pfn_enumerate_instance_version)(&icd_api_version);
977 }
978 uint32_t icd_api_major_version = VK_VERSION_MAJOR(icd_api_version);
979 uint32_t icd_api_minor_version = VK_VERSION_MINOR(icd_api_version);
980
981 if ((icd_api_major_version == 1) && (icd_api_minor_version == 0) &&
982 ((api_major_version > 1) || (api_minor_version > 0))) {
983 api_version = VK_API_VERSION_1_0;
984 wrapper.DowngradeApiVersion();
985 }
986 #pragma clang diagnostic pop
987
988 // call into the driver
989 VkInstance instance;
990 result = Hal::Device().CreateInstance(
991 static_cast<const VkInstanceCreateInfo*>(wrapper), pAllocator,
992 &instance);
993 if (result != VK_SUCCESS) {
994 FreeInstanceData(data, data_allocator);
995 return result;
996 }
997
998 // initialize InstanceDriverTable
999 if (!SetData(instance, *data) ||
1000 !InitDriverTable(instance, Hal::Device().GetInstanceProcAddr,
1001 wrapper.GetHalExtensions())) {
1002 data->driver.DestroyInstance = reinterpret_cast<PFN_vkDestroyInstance>(
1003 Hal::Device().GetInstanceProcAddr(instance, "vkDestroyInstance"));
1004 if (data->driver.DestroyInstance)
1005 data->driver.DestroyInstance(instance, pAllocator);
1006
1007 FreeInstanceData(data, data_allocator);
1008
1009 return VK_ERROR_INCOMPATIBLE_DRIVER;
1010 }
1011
1012 data->get_device_proc_addr = reinterpret_cast<PFN_vkGetDeviceProcAddr>(
1013 Hal::Device().GetInstanceProcAddr(instance, "vkGetDeviceProcAddr"));
1014 if (!data->get_device_proc_addr) {
1015 data->driver.DestroyInstance(instance, pAllocator);
1016 FreeInstanceData(data, data_allocator);
1017
1018 return VK_ERROR_INCOMPATIBLE_DRIVER;
1019 }
1020
1021 *pInstance = instance;
1022
1023 return VK_SUCCESS;
1024 }
1025
DestroyInstance(VkInstance instance,const VkAllocationCallbacks * pAllocator)1026 void DestroyInstance(VkInstance instance,
1027 const VkAllocationCallbacks* pAllocator) {
1028 InstanceData& data = GetData(instance);
1029 data.driver.DestroyInstance(instance, pAllocator);
1030
1031 VkAllocationCallbacks local_allocator;
1032 if (!pAllocator) {
1033 local_allocator = data.allocator;
1034 pAllocator = &local_allocator;
1035 }
1036
1037 FreeInstanceData(&data, *pAllocator);
1038 }
1039
CreateDevice(VkPhysicalDevice physicalDevice,const VkDeviceCreateInfo * pCreateInfo,const VkAllocationCallbacks * pAllocator,VkDevice * pDevice)1040 VkResult CreateDevice(VkPhysicalDevice physicalDevice,
1041 const VkDeviceCreateInfo* pCreateInfo,
1042 const VkAllocationCallbacks* pAllocator,
1043 VkDevice* pDevice) {
1044 const InstanceData& instance_data = GetData(physicalDevice);
1045 const VkAllocationCallbacks& data_allocator =
1046 (pAllocator) ? *pAllocator : instance_data.allocator;
1047
1048 CreateInfoWrapper wrapper(physicalDevice, *pCreateInfo, data_allocator);
1049 VkResult result = wrapper.Validate();
1050 if (result != VK_SUCCESS)
1051 return result;
1052
1053 DeviceData* data = AllocateDeviceData(data_allocator,
1054 instance_data.debug_report_callbacks);
1055 if (!data)
1056 return VK_ERROR_OUT_OF_HOST_MEMORY;
1057
1058 data->hook_extensions |= wrapper.GetHookExtensions();
1059
1060 // call into the driver
1061 VkDevice dev;
1062 result = instance_data.driver.CreateDevice(
1063 physicalDevice, static_cast<const VkDeviceCreateInfo*>(wrapper),
1064 pAllocator, &dev);
1065 if (result != VK_SUCCESS) {
1066 FreeDeviceData(data, data_allocator);
1067 return result;
1068 }
1069
1070 // initialize DeviceDriverTable
1071 if (!SetData(dev, *data) ||
1072 !InitDriverTable(dev, instance_data.get_device_proc_addr,
1073 wrapper.GetHalExtensions())) {
1074 data->driver.DestroyDevice = reinterpret_cast<PFN_vkDestroyDevice>(
1075 instance_data.get_device_proc_addr(dev, "vkDestroyDevice"));
1076 if (data->driver.DestroyDevice)
1077 data->driver.DestroyDevice(dev, pAllocator);
1078
1079 FreeDeviceData(data, data_allocator);
1080
1081 return VK_ERROR_INCOMPATIBLE_DRIVER;
1082 }
1083
1084 // sanity check ANDROID_native_buffer implementation, whose set of
1085 // entrypoints varies according to the spec version.
1086 if ((wrapper.GetHalExtensions()[ProcHook::ANDROID_native_buffer]) &&
1087 !data->driver.GetSwapchainGrallocUsageANDROID &&
1088 !data->driver.GetSwapchainGrallocUsage2ANDROID) {
1089 ALOGE("Driver's implementation of ANDROID_native_buffer is broken;"
1090 " must expose at least one of "
1091 "vkGetSwapchainGrallocUsageANDROID or "
1092 "vkGetSwapchainGrallocUsage2ANDROID");
1093
1094 data->driver.DestroyDevice(dev, pAllocator);
1095 FreeDeviceData(data, data_allocator);
1096
1097 return VK_ERROR_INCOMPATIBLE_DRIVER;
1098 }
1099
1100 VkPhysicalDeviceProperties properties;
1101 instance_data.driver.GetPhysicalDeviceProperties(physicalDevice,
1102 &properties);
1103
1104 data->driver_device = dev;
1105 data->driver_version = properties.driverVersion;
1106
1107 *pDevice = dev;
1108
1109 return VK_SUCCESS;
1110 }
1111
DestroyDevice(VkDevice device,const VkAllocationCallbacks * pAllocator)1112 void DestroyDevice(VkDevice device, const VkAllocationCallbacks* pAllocator) {
1113 DeviceData& data = GetData(device);
1114 data.driver.DestroyDevice(device, pAllocator);
1115
1116 VkAllocationCallbacks local_allocator;
1117 if (!pAllocator) {
1118 local_allocator = data.allocator;
1119 pAllocator = &local_allocator;
1120 }
1121
1122 FreeDeviceData(&data, *pAllocator);
1123 }
1124
EnumeratePhysicalDevices(VkInstance instance,uint32_t * pPhysicalDeviceCount,VkPhysicalDevice * pPhysicalDevices)1125 VkResult EnumeratePhysicalDevices(VkInstance instance,
1126 uint32_t* pPhysicalDeviceCount,
1127 VkPhysicalDevice* pPhysicalDevices) {
1128 const auto& data = GetData(instance);
1129
1130 VkResult result = data.driver.EnumeratePhysicalDevices(
1131 instance, pPhysicalDeviceCount, pPhysicalDevices);
1132 if ((result == VK_SUCCESS || result == VK_INCOMPLETE) && pPhysicalDevices) {
1133 for (uint32_t i = 0; i < *pPhysicalDeviceCount; i++)
1134 SetData(pPhysicalDevices[i], data);
1135 }
1136
1137 return result;
1138 }
1139
EnumeratePhysicalDeviceGroups(VkInstance instance,uint32_t * pPhysicalDeviceGroupCount,VkPhysicalDeviceGroupProperties * pPhysicalDeviceGroupProperties)1140 VkResult EnumeratePhysicalDeviceGroups(
1141 VkInstance instance,
1142 uint32_t* pPhysicalDeviceGroupCount,
1143 VkPhysicalDeviceGroupProperties* pPhysicalDeviceGroupProperties) {
1144 VkResult result = VK_SUCCESS;
1145 const auto& data = GetData(instance);
1146
1147 if (!data.driver.EnumeratePhysicalDeviceGroups) {
1148 uint32_t device_count = 0;
1149 result = EnumeratePhysicalDevices(instance, &device_count, nullptr);
1150 if (result < 0)
1151 return result;
1152
1153 if (!pPhysicalDeviceGroupProperties) {
1154 *pPhysicalDeviceGroupCount = device_count;
1155 return result;
1156 }
1157
1158 if (!device_count) {
1159 *pPhysicalDeviceGroupCount = 0;
1160 return result;
1161 }
1162 device_count = std::min(device_count, *pPhysicalDeviceGroupCount);
1163 if (!device_count)
1164 return VK_INCOMPLETE;
1165
1166 std::vector<VkPhysicalDevice> devices;
1167 devices.resize(device_count);
1168 *pPhysicalDeviceGroupCount = device_count;
1169 result = EnumeratePhysicalDevices(instance, &device_count,
1170 devices.data());
1171 if (result < 0)
1172 return result;
1173
1174 for (uint32_t i = 0; i < device_count; ++i) {
1175 pPhysicalDeviceGroupProperties[i].physicalDeviceCount = 1;
1176 pPhysicalDeviceGroupProperties[i].physicalDevices[0] = devices[i];
1177 pPhysicalDeviceGroupProperties[i].subsetAllocation = 0;
1178 }
1179 } else {
1180 result = data.driver.EnumeratePhysicalDeviceGroups(
1181 instance, pPhysicalDeviceGroupCount,
1182 pPhysicalDeviceGroupProperties);
1183 if ((result == VK_SUCCESS || result == VK_INCOMPLETE) &&
1184 *pPhysicalDeviceGroupCount && pPhysicalDeviceGroupProperties) {
1185 for (uint32_t i = 0; i < *pPhysicalDeviceGroupCount; i++) {
1186 for (uint32_t j = 0;
1187 j < pPhysicalDeviceGroupProperties[i].physicalDeviceCount;
1188 j++) {
1189 SetData(
1190 pPhysicalDeviceGroupProperties[i].physicalDevices[j],
1191 data);
1192 }
1193 }
1194 }
1195 }
1196
1197 return result;
1198 }
1199
GetDeviceQueue(VkDevice device,uint32_t queueFamilyIndex,uint32_t queueIndex,VkQueue * pQueue)1200 void GetDeviceQueue(VkDevice device,
1201 uint32_t queueFamilyIndex,
1202 uint32_t queueIndex,
1203 VkQueue* pQueue) {
1204 const auto& data = GetData(device);
1205
1206 data.driver.GetDeviceQueue(device, queueFamilyIndex, queueIndex, pQueue);
1207 SetData(*pQueue, data);
1208 }
1209
GetDeviceQueue2(VkDevice device,const VkDeviceQueueInfo2 * pQueueInfo,VkQueue * pQueue)1210 void GetDeviceQueue2(VkDevice device,
1211 const VkDeviceQueueInfo2* pQueueInfo,
1212 VkQueue* pQueue) {
1213 const auto& data = GetData(device);
1214
1215 data.driver.GetDeviceQueue2(device, pQueueInfo, pQueue);
1216 if (*pQueue != VK_NULL_HANDLE) SetData(*pQueue, data);
1217 }
1218
1219 VKAPI_ATTR VkResult
AllocateCommandBuffers(VkDevice device,const VkCommandBufferAllocateInfo * pAllocateInfo,VkCommandBuffer * pCommandBuffers)1220 AllocateCommandBuffers(VkDevice device,
1221 const VkCommandBufferAllocateInfo* pAllocateInfo,
1222 VkCommandBuffer* pCommandBuffers) {
1223 const auto& data = GetData(device);
1224
1225 VkResult result = data.driver.AllocateCommandBuffers(device, pAllocateInfo,
1226 pCommandBuffers);
1227 if (result == VK_SUCCESS) {
1228 for (uint32_t i = 0; i < pAllocateInfo->commandBufferCount; i++)
1229 SetData(pCommandBuffers[i], data);
1230 }
1231
1232 return result;
1233 }
1234
1235 } // namespace driver
1236 } // namespace vulkan
1237