blob: 72b09813abb15fa0b3c403b7656521a8bdd32792 [file] [log] [blame]
Chia-I Wu9d518162016-03-24 14:55:27 +08001/*
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
Chia-I Wudbb7e9c2016-03-24 15:09:38 +080017#include <stdlib.h>
18#include <string.h>
19#include <algorithm>
Chia-I Wuff4a6c72016-03-24 16:05:56 +080020#include <array>
Chia-I Wu4901db72016-03-24 16:38:58 +080021#include <new>
Chia-I Wudbb7e9c2016-03-24 15:09:38 +080022#include <malloc.h>
Chia-I Wu9d518162016-03-24 14:55:27 +080023#include <sys/prctl.h>
24
25#include "driver.h"
Jesse Hallb7c4e3b2016-04-11 13:51:38 -070026#include "stubhal.h"
Chia-I Wu9d518162016-03-24 14:55:27 +080027
Chia-I Wudbb7e9c2016-03-24 15:09:38 +080028// #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
Chia-I Wu9d518162016-03-24 14:55:27 +080044namespace vulkan {
45namespace driver {
46
Chia-I Wu136b8eb2016-03-24 15:01:52 +080047namespace {
48
Chia-I Wu4901db72016-03-24 16:38:58 +080049class CreateInfoWrapper {
50 public:
Jesse Hallb7c4e3b2016-04-11 13:51:38 -070051 CreateInfoWrapper(const hwvulkan_device_t* hw_dev,
Chia-I Wuff4a6c72016-03-24 16:05:56 +080052 const VkInstanceCreateInfo& create_info,
53 const VkAllocationCallbacks& allocator);
Chia-I Wu4901db72016-03-24 16:38:58 +080054 CreateInfoWrapper(VkPhysicalDevice physical_dev,
55 const VkDeviceCreateInfo& create_info,
56 const VkAllocationCallbacks& allocator);
57 ~CreateInfoWrapper();
58
Chia-I Wu3e6c2d62016-04-11 13:55:56 +080059 VkResult Validate();
Chia-I Wu4901db72016-03-24 16:38:58 +080060
Chia-I Wu3e6c2d62016-04-11 13:55:56 +080061 const std::bitset<ProcHook::EXTENSION_COUNT>& GetHookExtensions() const;
62 const std::bitset<ProcHook::EXTENSION_COUNT>& GetHalExtensions() const;
Chia-I Wu4901db72016-03-24 16:38:58 +080063
Chia-I Wuff4a6c72016-03-24 16:05:56 +080064 explicit operator const VkInstanceCreateInfo*() const;
Chia-I Wu4901db72016-03-24 16:38:58 +080065 explicit operator const VkDeviceCreateInfo*() const;
66
67 private:
68 struct ExtensionFilter {
69 VkExtensionProperties* exts;
70 uint32_t ext_count;
71
72 const char** names;
73 uint32_t name_count;
74 };
75
Chia-I Wu3e6c2d62016-04-11 13:55:56 +080076 VkResult SanitizePNext();
Chia-I Wu4901db72016-03-24 16:38:58 +080077
Chia-I Wu3e6c2d62016-04-11 13:55:56 +080078 VkResult SanitizeLayers();
79 VkResult SanitizeExtensions();
Chia-I Wu4901db72016-03-24 16:38:58 +080080
Chia-I Wu3e6c2d62016-04-11 13:55:56 +080081 VkResult QueryExtensionCount(uint32_t& count) const;
82 VkResult EnumerateExtensions(uint32_t& count,
83 VkExtensionProperties* props) const;
84 VkResult InitExtensionFilter();
85 void FilterExtension(const char* name);
Chia-I Wu4901db72016-03-24 16:38:58 +080086
87 const bool is_instance_;
88 const VkAllocationCallbacks& allocator_;
89
90 union {
Jesse Hallb7c4e3b2016-04-11 13:51:38 -070091 const hwvulkan_device_t* hw_dev_;
Chia-I Wu4901db72016-03-24 16:38:58 +080092 VkPhysicalDevice physical_dev_;
93 };
94
95 union {
96 VkInstanceCreateInfo instance_info_;
97 VkDeviceCreateInfo dev_info_;
98 };
99
100 ExtensionFilter extension_filter_;
101
102 std::bitset<ProcHook::EXTENSION_COUNT> hook_extensions_;
103 std::bitset<ProcHook::EXTENSION_COUNT> hal_extensions_;
104};
105
Jesse Hallb7c4e3b2016-04-11 13:51:38 -0700106CreateInfoWrapper::CreateInfoWrapper(const hwvulkan_device_t* hw_dev,
Chia-I Wuff4a6c72016-03-24 16:05:56 +0800107 const VkInstanceCreateInfo& create_info,
108 const VkAllocationCallbacks& allocator)
109 : is_instance_(true),
110 allocator_(allocator),
111 hw_dev_(hw_dev),
112 instance_info_(create_info),
113 extension_filter_() {
114 hook_extensions_.set(ProcHook::EXTENSION_CORE);
115 hal_extensions_.set(ProcHook::EXTENSION_CORE);
116}
117
Chia-I Wu4901db72016-03-24 16:38:58 +0800118CreateInfoWrapper::CreateInfoWrapper(VkPhysicalDevice physical_dev,
119 const VkDeviceCreateInfo& create_info,
120 const VkAllocationCallbacks& allocator)
121 : is_instance_(false),
122 allocator_(allocator),
123 physical_dev_(physical_dev),
124 dev_info_(create_info),
125 extension_filter_() {
126 hook_extensions_.set(ProcHook::EXTENSION_CORE);
127 hal_extensions_.set(ProcHook::EXTENSION_CORE);
128}
129
130CreateInfoWrapper::~CreateInfoWrapper() {
131 allocator_.pfnFree(allocator_.pUserData, extension_filter_.exts);
132 allocator_.pfnFree(allocator_.pUserData, extension_filter_.names);
133}
134
Chia-I Wu3e6c2d62016-04-11 13:55:56 +0800135VkResult CreateInfoWrapper::Validate() {
136 VkResult result = SanitizePNext();
Chia-I Wu4901db72016-03-24 16:38:58 +0800137 if (result == VK_SUCCESS)
Chia-I Wu3e6c2d62016-04-11 13:55:56 +0800138 result = SanitizeLayers();
Chia-I Wu4901db72016-03-24 16:38:58 +0800139 if (result == VK_SUCCESS)
Chia-I Wu3e6c2d62016-04-11 13:55:56 +0800140 result = SanitizeExtensions();
Chia-I Wu4901db72016-03-24 16:38:58 +0800141
142 return result;
143}
144
145const std::bitset<ProcHook::EXTENSION_COUNT>&
Chia-I Wu3e6c2d62016-04-11 13:55:56 +0800146CreateInfoWrapper::GetHookExtensions() const {
Chia-I Wu4901db72016-03-24 16:38:58 +0800147 return hook_extensions_;
148}
149
150const std::bitset<ProcHook::EXTENSION_COUNT>&
Chia-I Wu3e6c2d62016-04-11 13:55:56 +0800151CreateInfoWrapper::GetHalExtensions() const {
Chia-I Wu4901db72016-03-24 16:38:58 +0800152 return hal_extensions_;
153}
154
Chia-I Wuff4a6c72016-03-24 16:05:56 +0800155CreateInfoWrapper::operator const VkInstanceCreateInfo*() const {
156 return &instance_info_;
157}
158
Chia-I Wu4901db72016-03-24 16:38:58 +0800159CreateInfoWrapper::operator const VkDeviceCreateInfo*() const {
160 return &dev_info_;
161}
162
Chia-I Wu3e6c2d62016-04-11 13:55:56 +0800163VkResult CreateInfoWrapper::SanitizePNext() {
Chia-I Wu4901db72016-03-24 16:38:58 +0800164 const struct StructHeader {
165 VkStructureType type;
166 const void* next;
167 } * header;
168
169 if (is_instance_) {
170 header = reinterpret_cast<const StructHeader*>(instance_info_.pNext);
171
172 // skip leading VK_STRUCTURE_TYPE_LOADER_INSTANCE_CREATE_INFOs
173 while (header &&
174 header->type == VK_STRUCTURE_TYPE_LOADER_INSTANCE_CREATE_INFO)
175 header = reinterpret_cast<const StructHeader*>(header->next);
176
177 instance_info_.pNext = header;
178 } else {
179 header = reinterpret_cast<const StructHeader*>(dev_info_.pNext);
180
181 // skip leading VK_STRUCTURE_TYPE_LOADER_DEVICE_CREATE_INFOs
182 while (header &&
183 header->type == VK_STRUCTURE_TYPE_LOADER_DEVICE_CREATE_INFO)
184 header = reinterpret_cast<const StructHeader*>(header->next);
185
186 dev_info_.pNext = header;
187 }
188
189 return VK_SUCCESS;
190}
191
Chia-I Wu3e6c2d62016-04-11 13:55:56 +0800192VkResult CreateInfoWrapper::SanitizeLayers() {
Chia-I Wu4901db72016-03-24 16:38:58 +0800193 auto& layer_names = (is_instance_) ? instance_info_.ppEnabledLayerNames
194 : dev_info_.ppEnabledLayerNames;
195 auto& layer_count = (is_instance_) ? instance_info_.enabledLayerCount
196 : dev_info_.enabledLayerCount;
197
198 // remove all layers
199 layer_names = nullptr;
200 layer_count = 0;
201
202 return VK_SUCCESS;
203}
204
Chia-I Wu3e6c2d62016-04-11 13:55:56 +0800205VkResult CreateInfoWrapper::SanitizeExtensions() {
Chia-I Wu4901db72016-03-24 16:38:58 +0800206 auto& ext_names = (is_instance_) ? instance_info_.ppEnabledExtensionNames
207 : dev_info_.ppEnabledExtensionNames;
208 auto& ext_count = (is_instance_) ? instance_info_.enabledExtensionCount
209 : dev_info_.enabledExtensionCount;
210 if (!ext_count)
211 return VK_SUCCESS;
212
Chia-I Wu3e6c2d62016-04-11 13:55:56 +0800213 VkResult result = InitExtensionFilter();
Chia-I Wu4901db72016-03-24 16:38:58 +0800214 if (result != VK_SUCCESS)
215 return result;
216
217 for (uint32_t i = 0; i < ext_count; i++)
Chia-I Wu3e6c2d62016-04-11 13:55:56 +0800218 FilterExtension(ext_names[i]);
Chia-I Wu4901db72016-03-24 16:38:58 +0800219
220 ext_names = extension_filter_.names;
221 ext_count = extension_filter_.name_count;
222
223 return VK_SUCCESS;
224}
225
Chia-I Wu3e6c2d62016-04-11 13:55:56 +0800226VkResult CreateInfoWrapper::QueryExtensionCount(uint32_t& count) const {
Chia-I Wu4901db72016-03-24 16:38:58 +0800227 if (is_instance_) {
228 return hw_dev_->EnumerateInstanceExtensionProperties(nullptr, &count,
229 nullptr);
230 } else {
231 const auto& driver = GetData(physical_dev_).driver;
232 return driver.EnumerateDeviceExtensionProperties(physical_dev_, nullptr,
233 &count, nullptr);
234 }
235}
236
Chia-I Wu3e6c2d62016-04-11 13:55:56 +0800237VkResult CreateInfoWrapper::EnumerateExtensions(
Chia-I Wu4901db72016-03-24 16:38:58 +0800238 uint32_t& count,
239 VkExtensionProperties* props) const {
240 if (is_instance_) {
241 return hw_dev_->EnumerateInstanceExtensionProperties(nullptr, &count,
242 props);
243 } else {
244 const auto& driver = GetData(physical_dev_).driver;
245 return driver.EnumerateDeviceExtensionProperties(physical_dev_, nullptr,
246 &count, props);
247 }
248}
249
Chia-I Wu3e6c2d62016-04-11 13:55:56 +0800250VkResult CreateInfoWrapper::InitExtensionFilter() {
Chia-I Wu4901db72016-03-24 16:38:58 +0800251 // query extension count
252 uint32_t count;
Chia-I Wu3e6c2d62016-04-11 13:55:56 +0800253 VkResult result = QueryExtensionCount(count);
Chia-I Wu4901db72016-03-24 16:38:58 +0800254 if (result != VK_SUCCESS || count == 0)
255 return result;
256
257 auto& filter = extension_filter_;
258 filter.exts =
259 reinterpret_cast<VkExtensionProperties*>(allocator_.pfnAllocation(
260 allocator_.pUserData, sizeof(VkExtensionProperties) * count,
261 alignof(VkExtensionProperties),
262 VK_SYSTEM_ALLOCATION_SCOPE_COMMAND));
263 if (!filter.exts)
264 return VK_ERROR_OUT_OF_HOST_MEMORY;
265
266 // enumerate extensions
Chia-I Wu3e6c2d62016-04-11 13:55:56 +0800267 result = EnumerateExtensions(count, filter.exts);
Chia-I Wu4901db72016-03-24 16:38:58 +0800268 if (result != VK_SUCCESS && result != VK_INCOMPLETE)
269 return result;
270
271 if (!count)
272 return VK_SUCCESS;
273
274 filter.ext_count = count;
275
276 // allocate name array
277 uint32_t enabled_ext_count = (is_instance_)
278 ? instance_info_.enabledExtensionCount
279 : dev_info_.enabledExtensionCount;
280 count = std::min(filter.ext_count, enabled_ext_count);
281 filter.names = reinterpret_cast<const char**>(allocator_.pfnAllocation(
282 allocator_.pUserData, sizeof(const char*) * count, alignof(const char*),
283 VK_SYSTEM_ALLOCATION_SCOPE_COMMAND));
284 if (!filter.names)
285 return VK_ERROR_OUT_OF_HOST_MEMORY;
286
287 return VK_SUCCESS;
288}
289
Chia-I Wu3e6c2d62016-04-11 13:55:56 +0800290void CreateInfoWrapper::FilterExtension(const char* name) {
Chia-I Wu4901db72016-03-24 16:38:58 +0800291 auto& filter = extension_filter_;
292
293 ProcHook::Extension ext_bit = GetProcHookExtension(name);
294 if (is_instance_) {
295 switch (ext_bit) {
296 case ProcHook::KHR_android_surface:
297 case ProcHook::KHR_surface:
298 hook_extensions_.set(ext_bit);
299 // return now as these extensions do not require HAL support
300 return;
301 case ProcHook::EXT_debug_report:
302 // both we and HAL can take part in
303 hook_extensions_.set(ext_bit);
304 break;
305 case ProcHook::EXTENSION_UNKNOWN:
306 // HAL's extensions
307 break;
308 default:
309 ALOGW("Ignored invalid instance extension %s", name);
310 return;
311 }
312 } else {
313 switch (ext_bit) {
314 case ProcHook::KHR_swapchain:
315 // map VK_KHR_swapchain to VK_ANDROID_native_buffer
316 name = VK_ANDROID_NATIVE_BUFFER_EXTENSION_NAME;
317 ext_bit = ProcHook::ANDROID_native_buffer;
318 break;
319 case ProcHook::EXTENSION_UNKNOWN:
320 // HAL's extensions
321 break;
322 default:
323 ALOGW("Ignored invalid device extension %s", name);
324 return;
325 }
326 }
327
328 for (uint32_t i = 0; i < filter.ext_count; i++) {
329 const VkExtensionProperties& props = filter.exts[i];
330 // ignore unknown extensions
331 if (strcmp(name, props.extensionName) != 0)
332 continue;
333
334 if (ext_bit == ProcHook::ANDROID_native_buffer)
335 hook_extensions_.set(ProcHook::KHR_swapchain);
336
337 filter.names[filter.name_count++] = name;
338 hal_extensions_.set(ext_bit);
339
340 break;
341 }
342}
343
Jesse Hallb7c4e3b2016-04-11 13:51:38 -0700344const hwvulkan_device_t* g_hwdevice = nullptr;
Chia-I Wu136b8eb2016-03-24 15:01:52 +0800345
Chia-I Wudbb7e9c2016-03-24 15:09:38 +0800346VKAPI_ATTR void* DefaultAllocate(void*,
347 size_t size,
348 size_t alignment,
349 VkSystemAllocationScope) {
350 void* ptr = nullptr;
351 // Vulkan requires 'alignment' to be a power of two, but posix_memalign
352 // additionally requires that it be at least sizeof(void*).
353 int ret = posix_memalign(&ptr, std::max(alignment, sizeof(void*)), size);
354 ALOGD_CALLSTACK("Allocate: size=%zu align=%zu => (%d) %p", size, alignment,
355 ret, ptr);
356 return ret == 0 ? ptr : nullptr;
357}
358
359VKAPI_ATTR void* DefaultReallocate(void*,
360 void* ptr,
361 size_t size,
362 size_t alignment,
363 VkSystemAllocationScope) {
364 if (size == 0) {
365 free(ptr);
366 return nullptr;
367 }
368
369 // TODO(jessehall): Right now we never shrink allocations; if the new
370 // request is smaller than the existing chunk, we just continue using it.
371 // Right now the loader never reallocs, so this doesn't matter. If that
372 // changes, or if this code is copied into some other project, this should
373 // probably have a heuristic to allocate-copy-free when doing so will save
374 // "enough" space.
375 size_t old_size = ptr ? malloc_usable_size(ptr) : 0;
376 if (size <= old_size)
377 return ptr;
378
379 void* new_ptr = nullptr;
380 if (posix_memalign(&new_ptr, std::max(alignment, sizeof(void*)), size) != 0)
381 return nullptr;
382 if (ptr) {
383 memcpy(new_ptr, ptr, std::min(old_size, size));
384 free(ptr);
385 }
386 return new_ptr;
387}
388
389VKAPI_ATTR void DefaultFree(void*, void* ptr) {
390 ALOGD_CALLSTACK("Free: %p", ptr);
391 free(ptr);
392}
393
Chia-I Wuff4a6c72016-03-24 16:05:56 +0800394InstanceData* AllocateInstanceData(const VkAllocationCallbacks& allocator) {
395 void* data_mem = allocator.pfnAllocation(
396 allocator.pUserData, sizeof(InstanceData), alignof(InstanceData),
397 VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
398 if (!data_mem)
399 return nullptr;
400
401 return new (data_mem) InstanceData(allocator);
402}
403
404void FreeInstanceData(InstanceData* data,
405 const VkAllocationCallbacks& allocator) {
406 data->~InstanceData();
407 allocator.pfnFree(allocator.pUserData, data);
408}
409
Chia-I Wu4901db72016-03-24 16:38:58 +0800410DeviceData* AllocateDeviceData(const VkAllocationCallbacks& allocator) {
411 void* data_mem = allocator.pfnAllocation(
412 allocator.pUserData, sizeof(DeviceData), alignof(DeviceData),
413 VK_SYSTEM_ALLOCATION_SCOPE_DEVICE);
414 if (!data_mem)
415 return nullptr;
416
417 return new (data_mem) DeviceData(allocator);
418}
419
420void FreeDeviceData(DeviceData* data, const VkAllocationCallbacks& allocator) {
421 data->~DeviceData();
422 allocator.pfnFree(allocator.pUserData, data);
423}
424
Chia-I Wu136b8eb2016-03-24 15:01:52 +0800425} // anonymous namespace
426
Chia-I Wu9d518162016-03-24 14:55:27 +0800427bool Debuggable() {
428 return (prctl(PR_GET_DUMPABLE, 0, 0, 0, 0) >= 0);
429}
430
Chia-I Wu136b8eb2016-03-24 15:01:52 +0800431bool OpenHAL() {
Jesse Hallb7c4e3b2016-04-11 13:51:38 -0700432 ALOG_ASSERT(!g_hwdevice, "OpenHAL called more than once");
433
434 // Use a stub device unless we successfully open a real HAL device.
435 g_hwdevice = &stubhal::kDevice;
Chia-I Wu136b8eb2016-03-24 15:01:52 +0800436
437 const hwvulkan_module_t* module;
438 int result =
439 hw_get_module("vulkan", reinterpret_cast<const hw_module_t**>(&module));
440 if (result != 0) {
Jesse Hallb7c4e3b2016-04-11 13:51:38 -0700441 ALOGV("no Vulkan HAL present, using stub HAL");
442 return true;
Chia-I Wu136b8eb2016-03-24 15:01:52 +0800443 }
444
445 hwvulkan_device_t* device;
446 result =
447 module->common.methods->open(&module->common, HWVULKAN_DEVICE_0,
448 reinterpret_cast<hw_device_t**>(&device));
449 if (result != 0) {
Jesse Hallb7c4e3b2016-04-11 13:51:38 -0700450 // Any device with a Vulkan HAL should be able to open the device.
451 ALOGE("failed to open Vulkan HAL device: %s (%d)", strerror(-result),
Chia-I Wu136b8eb2016-03-24 15:01:52 +0800452 result);
453 return false;
454 }
455
Chia-I Wu136b8eb2016-03-24 15:01:52 +0800456 g_hwdevice = device;
457
458 return true;
459}
460
Chia-I Wudbb7e9c2016-03-24 15:09:38 +0800461const VkAllocationCallbacks& GetDefaultAllocator() {
462 static const VkAllocationCallbacks kDefaultAllocCallbacks = {
463 .pUserData = nullptr,
464 .pfnAllocation = DefaultAllocate,
465 .pfnReallocation = DefaultReallocate,
466 .pfnFree = DefaultFree,
467 };
468
469 return kDefaultAllocCallbacks;
470}
471
Chia-I Wueb7db122016-03-24 09:11:06 +0800472PFN_vkVoidFunction GetInstanceProcAddr(VkInstance instance, const char* pName) {
473 const ProcHook* hook = GetProcHook(pName);
474 if (!hook)
475 return g_hwdevice->GetInstanceProcAddr(instance, pName);
476
477 if (!instance) {
478 if (hook->type == ProcHook::GLOBAL)
479 return hook->proc;
480
481 ALOGE(
482 "Invalid use of vkGetInstanceProcAddr to query %s without an "
483 "instance",
484 pName);
485
486 // Some naughty layers expect
487 //
488 // vkGetInstanceProcAddr(VK_NULL_HANDLE, "vkCreateDevice");
489 //
490 // to work.
491 return (strcmp(pName, "vkCreateDevice") == 0) ? hook->proc : nullptr;
492 }
493
494 PFN_vkVoidFunction proc;
495
496 switch (hook->type) {
497 case ProcHook::INSTANCE:
498 proc = (GetData(instance).hook_extensions[hook->extension])
499 ? hook->proc
500 : hook->disabled_proc;
501 break;
502 case ProcHook::DEVICE:
503 proc = (hook->extension == ProcHook::EXTENSION_CORE)
504 ? hook->proc
505 : hook->checked_proc;
506 break;
507 default:
508 ALOGE(
509 "Invalid use of vkGetInstanceProcAddr to query %s with an "
510 "instance",
511 pName);
512 proc = nullptr;
513 break;
514 }
515
516 return proc;
517}
518
519PFN_vkVoidFunction GetDeviceProcAddr(VkDevice device, const char* pName) {
520 const ProcHook* hook = GetProcHook(pName);
521 if (!hook)
Chia-I Wucc5e2762016-03-24 13:01:16 +0800522 return GetData(device).driver.GetDeviceProcAddr(device, pName);
Chia-I Wueb7db122016-03-24 09:11:06 +0800523
524 if (hook->type != ProcHook::DEVICE) {
525 ALOGE("Invalid use of vkGetDeviceProcAddr to query %s", pName);
526 return nullptr;
527 }
528
529 return (GetData(device).hook_extensions[hook->extension])
530 ? hook->proc
531 : hook->disabled_proc;
532}
533
Chia-I Wuff4a6c72016-03-24 16:05:56 +0800534VkResult EnumerateInstanceExtensionProperties(
535 const char* pLayerName,
536 uint32_t* pPropertyCount,
537 VkExtensionProperties* pProperties) {
538 static const std::array<VkExtensionProperties, 2> loader_extensions = {{
539 // WSI extensions
540 {VK_KHR_SURFACE_EXTENSION_NAME, VK_KHR_SURFACE_SPEC_VERSION},
541 {VK_KHR_ANDROID_SURFACE_EXTENSION_NAME,
542 VK_KHR_ANDROID_SURFACE_SPEC_VERSION},
543 }};
544
545 // enumerate our extensions first
546 if (!pLayerName && pProperties) {
547 uint32_t count = std::min(
548 *pPropertyCount, static_cast<uint32_t>(loader_extensions.size()));
549
550 std::copy_n(loader_extensions.begin(), count, pProperties);
551
552 if (count < loader_extensions.size()) {
553 *pPropertyCount = count;
554 return VK_INCOMPLETE;
555 }
556
557 pProperties += count;
558 *pPropertyCount -= count;
559 }
560
561 VkResult result = g_hwdevice->EnumerateInstanceExtensionProperties(
562 pLayerName, pPropertyCount, pProperties);
563
564 if (!pLayerName && (result == VK_SUCCESS || result == VK_INCOMPLETE))
565 *pPropertyCount += loader_extensions.size();
566
567 return result;
568}
569
Chia-I Wu01cf3052016-03-24 16:16:21 +0800570VkResult EnumerateDeviceExtensionProperties(
571 VkPhysicalDevice physicalDevice,
572 const char* pLayerName,
573 uint32_t* pPropertyCount,
574 VkExtensionProperties* pProperties) {
575 const InstanceData& data = GetData(physicalDevice);
576
577 VkResult result = data.driver.EnumerateDeviceExtensionProperties(
578 physicalDevice, pLayerName, pPropertyCount, pProperties);
579 if (result != VK_SUCCESS && result != VK_INCOMPLETE)
580 return result;
581
582 if (!pProperties)
583 return result;
584
585 // map VK_ANDROID_native_buffer to VK_KHR_swapchain
586 for (uint32_t i = 0; i < *pPropertyCount; i++) {
587 auto& prop = pProperties[i];
588
589 if (strcmp(prop.extensionName,
590 VK_ANDROID_NATIVE_BUFFER_EXTENSION_NAME) != 0)
591 continue;
592
593 memcpy(prop.extensionName, VK_KHR_SWAPCHAIN_EXTENSION_NAME,
594 sizeof(VK_KHR_SWAPCHAIN_EXTENSION_NAME));
595 prop.specVersion = VK_KHR_SWAPCHAIN_SPEC_VERSION;
596 }
597
598 return result;
599}
600
Chia-I Wuff4a6c72016-03-24 16:05:56 +0800601VkResult CreateInstance(const VkInstanceCreateInfo* pCreateInfo,
602 const VkAllocationCallbacks* pAllocator,
603 VkInstance* pInstance) {
604 const VkAllocationCallbacks& data_allocator =
605 (pAllocator) ? *pAllocator : GetDefaultAllocator();
606
607 CreateInfoWrapper wrapper(g_hwdevice, *pCreateInfo, data_allocator);
Chia-I Wu3e6c2d62016-04-11 13:55:56 +0800608 VkResult result = wrapper.Validate();
Chia-I Wuff4a6c72016-03-24 16:05:56 +0800609 if (result != VK_SUCCESS)
610 return result;
611
612 InstanceData* data = AllocateInstanceData(data_allocator);
613 if (!data)
614 return VK_ERROR_OUT_OF_HOST_MEMORY;
615
Chia-I Wu3e6c2d62016-04-11 13:55:56 +0800616 data->hook_extensions |= wrapper.GetHookExtensions();
617 data->hal_extensions |= wrapper.GetHalExtensions();
Chia-I Wuff4a6c72016-03-24 16:05:56 +0800618
619 // call into the driver
620 VkInstance instance;
621 result = g_hwdevice->CreateInstance(
622 static_cast<const VkInstanceCreateInfo*>(wrapper), pAllocator,
623 &instance);
624 if (result != VK_SUCCESS) {
625 FreeInstanceData(data, data_allocator);
626 return result;
627 }
628
629 // initialize InstanceDriverTable
630 if (!SetData(instance, *data) ||
631 !InitDriverTable(instance, g_hwdevice->GetInstanceProcAddr)) {
632 data->driver.DestroyInstance = reinterpret_cast<PFN_vkDestroyInstance>(
633 g_hwdevice->GetInstanceProcAddr(instance, "vkDestroyInstance"));
634 if (data->driver.DestroyInstance)
635 data->driver.DestroyInstance(instance, pAllocator);
636
637 FreeInstanceData(data, data_allocator);
638
639 return VK_ERROR_INCOMPATIBLE_DRIVER;
640 }
641
642 data->get_device_proc_addr = reinterpret_cast<PFN_vkGetDeviceProcAddr>(
643 g_hwdevice->GetInstanceProcAddr(instance, "vkGetDeviceProcAddr"));
644 if (!data->get_device_proc_addr) {
645 data->driver.DestroyInstance(instance, pAllocator);
646 FreeInstanceData(data, data_allocator);
647
648 return VK_ERROR_INCOMPATIBLE_DRIVER;
649 }
650
651 *pInstance = instance;
652
653 return VK_SUCCESS;
654}
655
656void DestroyInstance(VkInstance instance,
657 const VkAllocationCallbacks* pAllocator) {
658 InstanceData& data = GetData(instance);
659 data.driver.DestroyInstance(instance, pAllocator);
660
661 VkAllocationCallbacks local_allocator;
662 if (!pAllocator) {
663 local_allocator = data.allocator;
664 pAllocator = &local_allocator;
665 }
666
667 FreeInstanceData(&data, *pAllocator);
668}
669
Chia-I Wu4901db72016-03-24 16:38:58 +0800670VkResult CreateDevice(VkPhysicalDevice physicalDevice,
671 const VkDeviceCreateInfo* pCreateInfo,
672 const VkAllocationCallbacks* pAllocator,
673 VkDevice* pDevice) {
674 const InstanceData& instance_data = GetData(physicalDevice);
675 const VkAllocationCallbacks& data_allocator =
676 (pAllocator) ? *pAllocator : instance_data.allocator;
677
678 CreateInfoWrapper wrapper(physicalDevice, *pCreateInfo, data_allocator);
Chia-I Wu3e6c2d62016-04-11 13:55:56 +0800679 VkResult result = wrapper.Validate();
Chia-I Wu4901db72016-03-24 16:38:58 +0800680 if (result != VK_SUCCESS)
681 return result;
682
683 DeviceData* data = AllocateDeviceData(data_allocator);
684 if (!data)
685 return VK_ERROR_OUT_OF_HOST_MEMORY;
686
Chia-I Wu3e6c2d62016-04-11 13:55:56 +0800687 data->hook_extensions |= wrapper.GetHookExtensions();
688 data->hal_extensions |= wrapper.GetHalExtensions();
Chia-I Wu4901db72016-03-24 16:38:58 +0800689
690 // call into the driver
691 VkDevice dev;
692 result = instance_data.driver.CreateDevice(
693 physicalDevice, static_cast<const VkDeviceCreateInfo*>(wrapper),
694 pAllocator, &dev);
695 if (result != VK_SUCCESS) {
696 FreeDeviceData(data, data_allocator);
697 return result;
698 }
699
700 // initialize DeviceDriverTable
701 if (!SetData(dev, *data) ||
702 !InitDriverTable(dev, instance_data.get_device_proc_addr)) {
703 data->driver.DestroyDevice = reinterpret_cast<PFN_vkDestroyDevice>(
704 instance_data.get_device_proc_addr(dev, "vkDestroyDevice"));
705 if (data->driver.DestroyDevice)
706 data->driver.DestroyDevice(dev, pAllocator);
707
708 FreeDeviceData(data, data_allocator);
709
710 return VK_ERROR_INCOMPATIBLE_DRIVER;
711 }
712
713 *pDevice = dev;
714
715 return VK_SUCCESS;
716}
717
718void DestroyDevice(VkDevice device, const VkAllocationCallbacks* pAllocator) {
719 DeviceData& data = GetData(device);
720 data.driver.DestroyDevice(device, pAllocator);
721
722 VkAllocationCallbacks local_allocator;
723 if (!pAllocator) {
724 local_allocator = data.allocator;
725 pAllocator = &local_allocator;
726 }
727
728 FreeDeviceData(&data, *pAllocator);
729}
730
Chia-I Wuff4a6c72016-03-24 16:05:56 +0800731VkResult EnumeratePhysicalDevices(VkInstance instance,
732 uint32_t* pPhysicalDeviceCount,
733 VkPhysicalDevice* pPhysicalDevices) {
734 const auto& data = GetData(instance);
735
736 VkResult result = data.driver.EnumeratePhysicalDevices(
737 instance, pPhysicalDeviceCount, pPhysicalDevices);
738 if ((result == VK_SUCCESS || result == VK_INCOMPLETE) && pPhysicalDevices) {
739 for (uint32_t i = 0; i < *pPhysicalDeviceCount; i++)
740 SetData(pPhysicalDevices[i], data);
741 }
742
743 return result;
744}
745
Chia-I Wuba0be412016-03-24 16:24:40 +0800746void GetDeviceQueue(VkDevice device,
747 uint32_t queueFamilyIndex,
748 uint32_t queueIndex,
749 VkQueue* pQueue) {
750 const auto& data = GetData(device);
751
752 data.driver.GetDeviceQueue(device, queueFamilyIndex, queueIndex, pQueue);
753 SetData(*pQueue, data);
754}
755
Chia-I Wu6a58a8a2016-03-24 16:29:51 +0800756VKAPI_ATTR VkResult
757AllocateCommandBuffers(VkDevice device,
758 const VkCommandBufferAllocateInfo* pAllocateInfo,
759 VkCommandBuffer* pCommandBuffers) {
760 const auto& data = GetData(device);
761
762 VkResult result = data.driver.AllocateCommandBuffers(device, pAllocateInfo,
763 pCommandBuffers);
764 if (result == VK_SUCCESS) {
765 for (uint32_t i = 0; i < pAllocateInfo->commandBufferCount; i++)
766 SetData(pCommandBuffers[i], data);
767 }
768
769 return result;
770}
771
Chia-I Wu9d518162016-03-24 14:55:27 +0800772} // namespace driver
773} // namespace vulkan