blob: bbb435bec59cbc40f668f9d914fc198db3887044 [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 Wu31b2e4f2016-05-23 10:47:57 +080049class 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 private:
57 Hal() : dev_(nullptr) {}
58 Hal(const Hal&) = delete;
59 Hal& operator=(const Hal&) = delete;
60
61 static Hal hal_;
62
63 const hwvulkan_device_t* dev_;
64};
65
Chia-I Wu4901db72016-03-24 16:38:58 +080066class CreateInfoWrapper {
67 public:
Chia-I Wu31b2e4f2016-05-23 10:47:57 +080068 CreateInfoWrapper(const VkInstanceCreateInfo& create_info,
Chia-I Wuff4a6c72016-03-24 16:05:56 +080069 const VkAllocationCallbacks& allocator);
Chia-I Wu4901db72016-03-24 16:38:58 +080070 CreateInfoWrapper(VkPhysicalDevice physical_dev,
71 const VkDeviceCreateInfo& create_info,
72 const VkAllocationCallbacks& allocator);
73 ~CreateInfoWrapper();
74
Chia-I Wu3e6c2d62016-04-11 13:55:56 +080075 VkResult Validate();
Chia-I Wu4901db72016-03-24 16:38:58 +080076
Chia-I Wu3e6c2d62016-04-11 13:55:56 +080077 const std::bitset<ProcHook::EXTENSION_COUNT>& GetHookExtensions() const;
78 const std::bitset<ProcHook::EXTENSION_COUNT>& GetHalExtensions() const;
Chia-I Wu4901db72016-03-24 16:38:58 +080079
Chia-I Wuff4a6c72016-03-24 16:05:56 +080080 explicit operator const VkInstanceCreateInfo*() const;
Chia-I Wu4901db72016-03-24 16:38:58 +080081 explicit operator const VkDeviceCreateInfo*() const;
82
83 private:
84 struct ExtensionFilter {
85 VkExtensionProperties* exts;
86 uint32_t ext_count;
87
88 const char** names;
89 uint32_t name_count;
90 };
91
Chia-I Wu3e6c2d62016-04-11 13:55:56 +080092 VkResult SanitizePNext();
Chia-I Wu4901db72016-03-24 16:38:58 +080093
Chia-I Wu3e6c2d62016-04-11 13:55:56 +080094 VkResult SanitizeLayers();
95 VkResult SanitizeExtensions();
Chia-I Wu4901db72016-03-24 16:38:58 +080096
Chia-I Wu3e6c2d62016-04-11 13:55:56 +080097 VkResult QueryExtensionCount(uint32_t& count) const;
98 VkResult EnumerateExtensions(uint32_t& count,
99 VkExtensionProperties* props) const;
100 VkResult InitExtensionFilter();
101 void FilterExtension(const char* name);
Chia-I Wu4901db72016-03-24 16:38:58 +0800102
103 const bool is_instance_;
104 const VkAllocationCallbacks& allocator_;
105
Chia-I Wu31b2e4f2016-05-23 10:47:57 +0800106 VkPhysicalDevice physical_dev_;
Chia-I Wu4901db72016-03-24 16:38:58 +0800107
108 union {
109 VkInstanceCreateInfo instance_info_;
110 VkDeviceCreateInfo dev_info_;
111 };
112
113 ExtensionFilter extension_filter_;
114
115 std::bitset<ProcHook::EXTENSION_COUNT> hook_extensions_;
116 std::bitset<ProcHook::EXTENSION_COUNT> hal_extensions_;
117};
118
Chia-I Wu31b2e4f2016-05-23 10:47:57 +0800119Hal Hal::hal_;
120
121bool Hal::Open() {
122 ALOG_ASSERT(!dev_, "OpenHAL called more than once");
123
124 // Use a stub device unless we successfully open a real HAL device.
125 hal_.dev_ = &stubhal::kDevice;
126
127 const hwvulkan_module_t* module;
128 int result =
129 hw_get_module("vulkan", reinterpret_cast<const hw_module_t**>(&module));
130 if (result != 0) {
131 ALOGI("no Vulkan HAL present, using stub HAL");
132 return true;
133 }
134
135 hwvulkan_device_t* device;
136 result =
137 module->common.methods->open(&module->common, HWVULKAN_DEVICE_0,
138 reinterpret_cast<hw_device_t**>(&device));
139 if (result != 0) {
140 // Any device with a Vulkan HAL should be able to open the device.
141 ALOGE("failed to open Vulkan HAL device: %s (%d)", strerror(-result),
142 result);
143 return false;
144 }
145
146 hal_.dev_ = device;
147
148 return true;
149}
150
151CreateInfoWrapper::CreateInfoWrapper(const VkInstanceCreateInfo& create_info,
Chia-I Wuff4a6c72016-03-24 16:05:56 +0800152 const VkAllocationCallbacks& allocator)
153 : is_instance_(true),
154 allocator_(allocator),
Chia-I Wu31b2e4f2016-05-23 10:47:57 +0800155 physical_dev_(VK_NULL_HANDLE),
Chia-I Wuff4a6c72016-03-24 16:05:56 +0800156 instance_info_(create_info),
157 extension_filter_() {
158 hook_extensions_.set(ProcHook::EXTENSION_CORE);
159 hal_extensions_.set(ProcHook::EXTENSION_CORE);
160}
161
Chia-I Wu4901db72016-03-24 16:38:58 +0800162CreateInfoWrapper::CreateInfoWrapper(VkPhysicalDevice physical_dev,
163 const VkDeviceCreateInfo& create_info,
164 const VkAllocationCallbacks& allocator)
165 : is_instance_(false),
166 allocator_(allocator),
167 physical_dev_(physical_dev),
168 dev_info_(create_info),
169 extension_filter_() {
170 hook_extensions_.set(ProcHook::EXTENSION_CORE);
171 hal_extensions_.set(ProcHook::EXTENSION_CORE);
172}
173
174CreateInfoWrapper::~CreateInfoWrapper() {
175 allocator_.pfnFree(allocator_.pUserData, extension_filter_.exts);
176 allocator_.pfnFree(allocator_.pUserData, extension_filter_.names);
177}
178
Chia-I Wu3e6c2d62016-04-11 13:55:56 +0800179VkResult CreateInfoWrapper::Validate() {
180 VkResult result = SanitizePNext();
Chia-I Wu4901db72016-03-24 16:38:58 +0800181 if (result == VK_SUCCESS)
Chia-I Wu3e6c2d62016-04-11 13:55:56 +0800182 result = SanitizeLayers();
Chia-I Wu4901db72016-03-24 16:38:58 +0800183 if (result == VK_SUCCESS)
Chia-I Wu3e6c2d62016-04-11 13:55:56 +0800184 result = SanitizeExtensions();
Chia-I Wu4901db72016-03-24 16:38:58 +0800185
186 return result;
187}
188
189const std::bitset<ProcHook::EXTENSION_COUNT>&
Chia-I Wu3e6c2d62016-04-11 13:55:56 +0800190CreateInfoWrapper::GetHookExtensions() const {
Chia-I Wu4901db72016-03-24 16:38:58 +0800191 return hook_extensions_;
192}
193
194const std::bitset<ProcHook::EXTENSION_COUNT>&
Chia-I Wu3e6c2d62016-04-11 13:55:56 +0800195CreateInfoWrapper::GetHalExtensions() const {
Chia-I Wu4901db72016-03-24 16:38:58 +0800196 return hal_extensions_;
197}
198
Chia-I Wuff4a6c72016-03-24 16:05:56 +0800199CreateInfoWrapper::operator const VkInstanceCreateInfo*() const {
200 return &instance_info_;
201}
202
Chia-I Wu4901db72016-03-24 16:38:58 +0800203CreateInfoWrapper::operator const VkDeviceCreateInfo*() const {
204 return &dev_info_;
205}
206
Chia-I Wu3e6c2d62016-04-11 13:55:56 +0800207VkResult CreateInfoWrapper::SanitizePNext() {
Chia-I Wu4901db72016-03-24 16:38:58 +0800208 const struct StructHeader {
209 VkStructureType type;
210 const void* next;
211 } * header;
212
213 if (is_instance_) {
214 header = reinterpret_cast<const StructHeader*>(instance_info_.pNext);
215
216 // skip leading VK_STRUCTURE_TYPE_LOADER_INSTANCE_CREATE_INFOs
217 while (header &&
218 header->type == VK_STRUCTURE_TYPE_LOADER_INSTANCE_CREATE_INFO)
219 header = reinterpret_cast<const StructHeader*>(header->next);
220
221 instance_info_.pNext = header;
222 } else {
223 header = reinterpret_cast<const StructHeader*>(dev_info_.pNext);
224
225 // skip leading VK_STRUCTURE_TYPE_LOADER_DEVICE_CREATE_INFOs
226 while (header &&
227 header->type == VK_STRUCTURE_TYPE_LOADER_DEVICE_CREATE_INFO)
228 header = reinterpret_cast<const StructHeader*>(header->next);
229
230 dev_info_.pNext = header;
231 }
232
233 return VK_SUCCESS;
234}
235
Chia-I Wu3e6c2d62016-04-11 13:55:56 +0800236VkResult CreateInfoWrapper::SanitizeLayers() {
Chia-I Wu4901db72016-03-24 16:38:58 +0800237 auto& layer_names = (is_instance_) ? instance_info_.ppEnabledLayerNames
238 : dev_info_.ppEnabledLayerNames;
239 auto& layer_count = (is_instance_) ? instance_info_.enabledLayerCount
240 : dev_info_.enabledLayerCount;
241
242 // remove all layers
243 layer_names = nullptr;
244 layer_count = 0;
245
246 return VK_SUCCESS;
247}
248
Chia-I Wu3e6c2d62016-04-11 13:55:56 +0800249VkResult CreateInfoWrapper::SanitizeExtensions() {
Chia-I Wu4901db72016-03-24 16:38:58 +0800250 auto& ext_names = (is_instance_) ? instance_info_.ppEnabledExtensionNames
251 : dev_info_.ppEnabledExtensionNames;
252 auto& ext_count = (is_instance_) ? instance_info_.enabledExtensionCount
253 : dev_info_.enabledExtensionCount;
254 if (!ext_count)
255 return VK_SUCCESS;
256
Chia-I Wu3e6c2d62016-04-11 13:55:56 +0800257 VkResult result = InitExtensionFilter();
Chia-I Wu4901db72016-03-24 16:38:58 +0800258 if (result != VK_SUCCESS)
259 return result;
260
261 for (uint32_t i = 0; i < ext_count; i++)
Chia-I Wu3e6c2d62016-04-11 13:55:56 +0800262 FilterExtension(ext_names[i]);
Chia-I Wu4901db72016-03-24 16:38:58 +0800263
264 ext_names = extension_filter_.names;
265 ext_count = extension_filter_.name_count;
266
267 return VK_SUCCESS;
268}
269
Chia-I Wu3e6c2d62016-04-11 13:55:56 +0800270VkResult CreateInfoWrapper::QueryExtensionCount(uint32_t& count) const {
Chia-I Wu4901db72016-03-24 16:38:58 +0800271 if (is_instance_) {
Chia-I Wu31b2e4f2016-05-23 10:47:57 +0800272 return Hal::Device().EnumerateInstanceExtensionProperties(
273 nullptr, &count, nullptr);
Chia-I Wu4901db72016-03-24 16:38:58 +0800274 } else {
275 const auto& driver = GetData(physical_dev_).driver;
276 return driver.EnumerateDeviceExtensionProperties(physical_dev_, nullptr,
277 &count, nullptr);
278 }
279}
280
Chia-I Wu3e6c2d62016-04-11 13:55:56 +0800281VkResult CreateInfoWrapper::EnumerateExtensions(
Chia-I Wu4901db72016-03-24 16:38:58 +0800282 uint32_t& count,
283 VkExtensionProperties* props) const {
284 if (is_instance_) {
Chia-I Wu31b2e4f2016-05-23 10:47:57 +0800285 return Hal::Device().EnumerateInstanceExtensionProperties(
286 nullptr, &count, props);
Chia-I Wu4901db72016-03-24 16:38:58 +0800287 } else {
288 const auto& driver = GetData(physical_dev_).driver;
289 return driver.EnumerateDeviceExtensionProperties(physical_dev_, nullptr,
290 &count, props);
291 }
292}
293
Chia-I Wu3e6c2d62016-04-11 13:55:56 +0800294VkResult CreateInfoWrapper::InitExtensionFilter() {
Chia-I Wu4901db72016-03-24 16:38:58 +0800295 // query extension count
296 uint32_t count;
Chia-I Wu3e6c2d62016-04-11 13:55:56 +0800297 VkResult result = QueryExtensionCount(count);
Chia-I Wu4901db72016-03-24 16:38:58 +0800298 if (result != VK_SUCCESS || count == 0)
299 return result;
300
301 auto& filter = extension_filter_;
302 filter.exts =
303 reinterpret_cast<VkExtensionProperties*>(allocator_.pfnAllocation(
304 allocator_.pUserData, sizeof(VkExtensionProperties) * count,
305 alignof(VkExtensionProperties),
306 VK_SYSTEM_ALLOCATION_SCOPE_COMMAND));
307 if (!filter.exts)
308 return VK_ERROR_OUT_OF_HOST_MEMORY;
309
310 // enumerate extensions
Chia-I Wu3e6c2d62016-04-11 13:55:56 +0800311 result = EnumerateExtensions(count, filter.exts);
Chia-I Wu4901db72016-03-24 16:38:58 +0800312 if (result != VK_SUCCESS && result != VK_INCOMPLETE)
313 return result;
314
315 if (!count)
316 return VK_SUCCESS;
317
318 filter.ext_count = count;
319
320 // allocate name array
321 uint32_t enabled_ext_count = (is_instance_)
322 ? instance_info_.enabledExtensionCount
323 : dev_info_.enabledExtensionCount;
324 count = std::min(filter.ext_count, enabled_ext_count);
325 filter.names = reinterpret_cast<const char**>(allocator_.pfnAllocation(
326 allocator_.pUserData, sizeof(const char*) * count, alignof(const char*),
327 VK_SYSTEM_ALLOCATION_SCOPE_COMMAND));
328 if (!filter.names)
329 return VK_ERROR_OUT_OF_HOST_MEMORY;
330
331 return VK_SUCCESS;
332}
333
Chia-I Wu3e6c2d62016-04-11 13:55:56 +0800334void CreateInfoWrapper::FilterExtension(const char* name) {
Chia-I Wu4901db72016-03-24 16:38:58 +0800335 auto& filter = extension_filter_;
336
337 ProcHook::Extension ext_bit = GetProcHookExtension(name);
338 if (is_instance_) {
339 switch (ext_bit) {
340 case ProcHook::KHR_android_surface:
341 case ProcHook::KHR_surface:
342 hook_extensions_.set(ext_bit);
343 // return now as these extensions do not require HAL support
344 return;
345 case ProcHook::EXT_debug_report:
346 // both we and HAL can take part in
347 hook_extensions_.set(ext_bit);
348 break;
349 case ProcHook::EXTENSION_UNKNOWN:
350 // HAL's extensions
351 break;
352 default:
353 ALOGW("Ignored invalid instance extension %s", name);
354 return;
355 }
356 } else {
357 switch (ext_bit) {
358 case ProcHook::KHR_swapchain:
359 // map VK_KHR_swapchain to VK_ANDROID_native_buffer
360 name = VK_ANDROID_NATIVE_BUFFER_EXTENSION_NAME;
361 ext_bit = ProcHook::ANDROID_native_buffer;
362 break;
363 case ProcHook::EXTENSION_UNKNOWN:
364 // HAL's extensions
365 break;
366 default:
367 ALOGW("Ignored invalid device extension %s", name);
368 return;
369 }
370 }
371
372 for (uint32_t i = 0; i < filter.ext_count; i++) {
373 const VkExtensionProperties& props = filter.exts[i];
374 // ignore unknown extensions
375 if (strcmp(name, props.extensionName) != 0)
376 continue;
377
Chia-I Wu4901db72016-03-24 16:38:58 +0800378 filter.names[filter.name_count++] = name;
Chia-I Wu1600e262016-04-12 09:40:06 +0800379 if (ext_bit != ProcHook::EXTENSION_UNKNOWN) {
380 if (ext_bit == ProcHook::ANDROID_native_buffer)
381 hook_extensions_.set(ProcHook::KHR_swapchain);
382
383 hal_extensions_.set(ext_bit);
384 }
Chia-I Wu4901db72016-03-24 16:38:58 +0800385
386 break;
387 }
388}
389
Chia-I Wudbb7e9c2016-03-24 15:09:38 +0800390VKAPI_ATTR void* DefaultAllocate(void*,
391 size_t size,
392 size_t alignment,
393 VkSystemAllocationScope) {
394 void* ptr = nullptr;
395 // Vulkan requires 'alignment' to be a power of two, but posix_memalign
396 // additionally requires that it be at least sizeof(void*).
397 int ret = posix_memalign(&ptr, std::max(alignment, sizeof(void*)), size);
398 ALOGD_CALLSTACK("Allocate: size=%zu align=%zu => (%d) %p", size, alignment,
399 ret, ptr);
400 return ret == 0 ? ptr : nullptr;
401}
402
403VKAPI_ATTR void* DefaultReallocate(void*,
404 void* ptr,
405 size_t size,
406 size_t alignment,
407 VkSystemAllocationScope) {
408 if (size == 0) {
409 free(ptr);
410 return nullptr;
411 }
412
413 // TODO(jessehall): Right now we never shrink allocations; if the new
414 // request is smaller than the existing chunk, we just continue using it.
415 // Right now the loader never reallocs, so this doesn't matter. If that
416 // changes, or if this code is copied into some other project, this should
417 // probably have a heuristic to allocate-copy-free when doing so will save
418 // "enough" space.
419 size_t old_size = ptr ? malloc_usable_size(ptr) : 0;
420 if (size <= old_size)
421 return ptr;
422
423 void* new_ptr = nullptr;
424 if (posix_memalign(&new_ptr, std::max(alignment, sizeof(void*)), size) != 0)
425 return nullptr;
426 if (ptr) {
427 memcpy(new_ptr, ptr, std::min(old_size, size));
428 free(ptr);
429 }
430 return new_ptr;
431}
432
433VKAPI_ATTR void DefaultFree(void*, void* ptr) {
434 ALOGD_CALLSTACK("Free: %p", ptr);
435 free(ptr);
436}
437
Chia-I Wuff4a6c72016-03-24 16:05:56 +0800438InstanceData* AllocateInstanceData(const VkAllocationCallbacks& allocator) {
439 void* data_mem = allocator.pfnAllocation(
440 allocator.pUserData, sizeof(InstanceData), alignof(InstanceData),
441 VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
442 if (!data_mem)
443 return nullptr;
444
445 return new (data_mem) InstanceData(allocator);
446}
447
448void FreeInstanceData(InstanceData* data,
449 const VkAllocationCallbacks& allocator) {
450 data->~InstanceData();
451 allocator.pfnFree(allocator.pUserData, data);
452}
453
Chia-I Wu950d6e12016-05-03 09:12:35 +0800454DeviceData* AllocateDeviceData(
455 const VkAllocationCallbacks& allocator,
456 const DebugReportCallbackList& debug_report_callbacks) {
Chia-I Wu4901db72016-03-24 16:38:58 +0800457 void* data_mem = allocator.pfnAllocation(
458 allocator.pUserData, sizeof(DeviceData), alignof(DeviceData),
459 VK_SYSTEM_ALLOCATION_SCOPE_DEVICE);
460 if (!data_mem)
461 return nullptr;
462
Chia-I Wu950d6e12016-05-03 09:12:35 +0800463 return new (data_mem) DeviceData(allocator, debug_report_callbacks);
Chia-I Wu4901db72016-03-24 16:38:58 +0800464}
465
466void FreeDeviceData(DeviceData* data, const VkAllocationCallbacks& allocator) {
467 data->~DeviceData();
468 allocator.pfnFree(allocator.pUserData, data);
469}
470
Chia-I Wu136b8eb2016-03-24 15:01:52 +0800471} // anonymous namespace
472
Chia-I Wu9d518162016-03-24 14:55:27 +0800473bool Debuggable() {
474 return (prctl(PR_GET_DUMPABLE, 0, 0, 0, 0) >= 0);
475}
476
Chia-I Wu136b8eb2016-03-24 15:01:52 +0800477bool OpenHAL() {
Chia-I Wu31b2e4f2016-05-23 10:47:57 +0800478 return Hal::Open();
Chia-I Wu136b8eb2016-03-24 15:01:52 +0800479}
480
Chia-I Wudbb7e9c2016-03-24 15:09:38 +0800481const VkAllocationCallbacks& GetDefaultAllocator() {
482 static const VkAllocationCallbacks kDefaultAllocCallbacks = {
483 .pUserData = nullptr,
484 .pfnAllocation = DefaultAllocate,
485 .pfnReallocation = DefaultReallocate,
486 .pfnFree = DefaultFree,
487 };
488
489 return kDefaultAllocCallbacks;
490}
491
Chia-I Wueb7db122016-03-24 09:11:06 +0800492PFN_vkVoidFunction GetInstanceProcAddr(VkInstance instance, const char* pName) {
493 const ProcHook* hook = GetProcHook(pName);
494 if (!hook)
Chia-I Wu31b2e4f2016-05-23 10:47:57 +0800495 return Hal::Device().GetInstanceProcAddr(instance, pName);
Chia-I Wueb7db122016-03-24 09:11:06 +0800496
497 if (!instance) {
498 if (hook->type == ProcHook::GLOBAL)
499 return hook->proc;
500
Chia-I Wu109f8982016-04-22 06:40:40 +0800501 // v0 layers expect
502 //
503 // vkGetInstanceProcAddr(VK_NULL_HANDLE, "vkCreateDevice");
504 //
505 // to work.
506 if (strcmp(pName, "vkCreateDevice") == 0)
507 return hook->proc;
508
Chia-I Wueb7db122016-03-24 09:11:06 +0800509 ALOGE(
Chia-I Wue201c3f2016-05-03 13:26:08 +0800510 "internal vkGetInstanceProcAddr called for %s without an instance",
Chia-I Wueb7db122016-03-24 09:11:06 +0800511 pName);
512
Chia-I Wu109f8982016-04-22 06:40:40 +0800513 return nullptr;
Chia-I Wueb7db122016-03-24 09:11:06 +0800514 }
515
516 PFN_vkVoidFunction proc;
517
518 switch (hook->type) {
519 case ProcHook::INSTANCE:
520 proc = (GetData(instance).hook_extensions[hook->extension])
521 ? hook->proc
Chia-I Wu36cc00a2016-04-13 16:52:06 +0800522 : nullptr;
Chia-I Wueb7db122016-03-24 09:11:06 +0800523 break;
524 case ProcHook::DEVICE:
525 proc = (hook->extension == ProcHook::EXTENSION_CORE)
526 ? hook->proc
527 : hook->checked_proc;
528 break;
529 default:
530 ALOGE(
Chia-I Wue201c3f2016-05-03 13:26:08 +0800531 "internal vkGetInstanceProcAddr called for %s with an instance",
Chia-I Wueb7db122016-03-24 09:11:06 +0800532 pName);
533 proc = nullptr;
534 break;
535 }
536
537 return proc;
538}
539
540PFN_vkVoidFunction GetDeviceProcAddr(VkDevice device, const char* pName) {
541 const ProcHook* hook = GetProcHook(pName);
542 if (!hook)
Chia-I Wucc5e2762016-03-24 13:01:16 +0800543 return GetData(device).driver.GetDeviceProcAddr(device, pName);
Chia-I Wueb7db122016-03-24 09:11:06 +0800544
545 if (hook->type != ProcHook::DEVICE) {
Chia-I Wue201c3f2016-05-03 13:26:08 +0800546 ALOGE("internal vkGetDeviceProcAddr called for %s", pName);
Chia-I Wueb7db122016-03-24 09:11:06 +0800547 return nullptr;
548 }
549
Chia-I Wu36cc00a2016-04-13 16:52:06 +0800550 return (GetData(device).hook_extensions[hook->extension]) ? hook->proc
551 : nullptr;
Chia-I Wueb7db122016-03-24 09:11:06 +0800552}
553
Chia-I Wuff4a6c72016-03-24 16:05:56 +0800554VkResult EnumerateInstanceExtensionProperties(
555 const char* pLayerName,
556 uint32_t* pPropertyCount,
557 VkExtensionProperties* pProperties) {
558 static const std::array<VkExtensionProperties, 2> loader_extensions = {{
559 // WSI extensions
560 {VK_KHR_SURFACE_EXTENSION_NAME, VK_KHR_SURFACE_SPEC_VERSION},
561 {VK_KHR_ANDROID_SURFACE_EXTENSION_NAME,
562 VK_KHR_ANDROID_SURFACE_SPEC_VERSION},
563 }};
564
565 // enumerate our extensions first
566 if (!pLayerName && pProperties) {
567 uint32_t count = std::min(
568 *pPropertyCount, static_cast<uint32_t>(loader_extensions.size()));
569
570 std::copy_n(loader_extensions.begin(), count, pProperties);
571
572 if (count < loader_extensions.size()) {
573 *pPropertyCount = count;
574 return VK_INCOMPLETE;
575 }
576
577 pProperties += count;
578 *pPropertyCount -= count;
579 }
580
Chia-I Wu31b2e4f2016-05-23 10:47:57 +0800581 VkResult result = Hal::Device().EnumerateInstanceExtensionProperties(
Chia-I Wuff4a6c72016-03-24 16:05:56 +0800582 pLayerName, pPropertyCount, pProperties);
583
584 if (!pLayerName && (result == VK_SUCCESS || result == VK_INCOMPLETE))
585 *pPropertyCount += loader_extensions.size();
586
587 return result;
588}
589
Chia-I Wu01cf3052016-03-24 16:16:21 +0800590VkResult EnumerateDeviceExtensionProperties(
591 VkPhysicalDevice physicalDevice,
592 const char* pLayerName,
593 uint32_t* pPropertyCount,
594 VkExtensionProperties* pProperties) {
595 const InstanceData& data = GetData(physicalDevice);
596
597 VkResult result = data.driver.EnumerateDeviceExtensionProperties(
598 physicalDevice, pLayerName, pPropertyCount, pProperties);
599 if (result != VK_SUCCESS && result != VK_INCOMPLETE)
600 return result;
601
602 if (!pProperties)
603 return result;
604
605 // map VK_ANDROID_native_buffer to VK_KHR_swapchain
606 for (uint32_t i = 0; i < *pPropertyCount; i++) {
607 auto& prop = pProperties[i];
608
609 if (strcmp(prop.extensionName,
610 VK_ANDROID_NATIVE_BUFFER_EXTENSION_NAME) != 0)
611 continue;
612
613 memcpy(prop.extensionName, VK_KHR_SWAPCHAIN_EXTENSION_NAME,
614 sizeof(VK_KHR_SWAPCHAIN_EXTENSION_NAME));
615 prop.specVersion = VK_KHR_SWAPCHAIN_SPEC_VERSION;
616 }
617
618 return result;
619}
620
Chia-I Wuff4a6c72016-03-24 16:05:56 +0800621VkResult CreateInstance(const VkInstanceCreateInfo* pCreateInfo,
622 const VkAllocationCallbacks* pAllocator,
623 VkInstance* pInstance) {
624 const VkAllocationCallbacks& data_allocator =
625 (pAllocator) ? *pAllocator : GetDefaultAllocator();
626
Chia-I Wu31b2e4f2016-05-23 10:47:57 +0800627 CreateInfoWrapper wrapper(*pCreateInfo, data_allocator);
Chia-I Wu3e6c2d62016-04-11 13:55:56 +0800628 VkResult result = wrapper.Validate();
Chia-I Wuff4a6c72016-03-24 16:05:56 +0800629 if (result != VK_SUCCESS)
630 return result;
631
632 InstanceData* data = AllocateInstanceData(data_allocator);
633 if (!data)
634 return VK_ERROR_OUT_OF_HOST_MEMORY;
635
Chia-I Wu3e6c2d62016-04-11 13:55:56 +0800636 data->hook_extensions |= wrapper.GetHookExtensions();
Chia-I Wuff4a6c72016-03-24 16:05:56 +0800637
638 // call into the driver
639 VkInstance instance;
Chia-I Wu31b2e4f2016-05-23 10:47:57 +0800640 result = Hal::Device().CreateInstance(
Chia-I Wuff4a6c72016-03-24 16:05:56 +0800641 static_cast<const VkInstanceCreateInfo*>(wrapper), pAllocator,
642 &instance);
643 if (result != VK_SUCCESS) {
644 FreeInstanceData(data, data_allocator);
645 return result;
646 }
647
648 // initialize InstanceDriverTable
649 if (!SetData(instance, *data) ||
Chia-I Wu31b2e4f2016-05-23 10:47:57 +0800650 !InitDriverTable(instance, Hal::Device().GetInstanceProcAddr,
Chia-I Wucbe07ef2016-04-13 15:01:00 +0800651 wrapper.GetHalExtensions())) {
Chia-I Wuff4a6c72016-03-24 16:05:56 +0800652 data->driver.DestroyInstance = reinterpret_cast<PFN_vkDestroyInstance>(
Chia-I Wu31b2e4f2016-05-23 10:47:57 +0800653 Hal::Device().GetInstanceProcAddr(instance, "vkDestroyInstance"));
Chia-I Wuff4a6c72016-03-24 16:05:56 +0800654 if (data->driver.DestroyInstance)
655 data->driver.DestroyInstance(instance, pAllocator);
656
657 FreeInstanceData(data, data_allocator);
658
659 return VK_ERROR_INCOMPATIBLE_DRIVER;
660 }
661
662 data->get_device_proc_addr = reinterpret_cast<PFN_vkGetDeviceProcAddr>(
Chia-I Wu31b2e4f2016-05-23 10:47:57 +0800663 Hal::Device().GetInstanceProcAddr(instance, "vkGetDeviceProcAddr"));
Chia-I Wuff4a6c72016-03-24 16:05:56 +0800664 if (!data->get_device_proc_addr) {
665 data->driver.DestroyInstance(instance, pAllocator);
666 FreeInstanceData(data, data_allocator);
667
668 return VK_ERROR_INCOMPATIBLE_DRIVER;
669 }
670
671 *pInstance = instance;
672
673 return VK_SUCCESS;
674}
675
676void DestroyInstance(VkInstance instance,
677 const VkAllocationCallbacks* pAllocator) {
678 InstanceData& data = GetData(instance);
679 data.driver.DestroyInstance(instance, pAllocator);
680
681 VkAllocationCallbacks local_allocator;
682 if (!pAllocator) {
683 local_allocator = data.allocator;
684 pAllocator = &local_allocator;
685 }
686
687 FreeInstanceData(&data, *pAllocator);
688}
689
Chia-I Wu4901db72016-03-24 16:38:58 +0800690VkResult CreateDevice(VkPhysicalDevice physicalDevice,
691 const VkDeviceCreateInfo* pCreateInfo,
692 const VkAllocationCallbacks* pAllocator,
693 VkDevice* pDevice) {
694 const InstanceData& instance_data = GetData(physicalDevice);
695 const VkAllocationCallbacks& data_allocator =
696 (pAllocator) ? *pAllocator : instance_data.allocator;
697
698 CreateInfoWrapper wrapper(physicalDevice, *pCreateInfo, data_allocator);
Chia-I Wu3e6c2d62016-04-11 13:55:56 +0800699 VkResult result = wrapper.Validate();
Chia-I Wu4901db72016-03-24 16:38:58 +0800700 if (result != VK_SUCCESS)
701 return result;
702
Chia-I Wu950d6e12016-05-03 09:12:35 +0800703 DeviceData* data = AllocateDeviceData(data_allocator,
704 instance_data.debug_report_callbacks);
Chia-I Wu4901db72016-03-24 16:38:58 +0800705 if (!data)
706 return VK_ERROR_OUT_OF_HOST_MEMORY;
707
Chia-I Wu3e6c2d62016-04-11 13:55:56 +0800708 data->hook_extensions |= wrapper.GetHookExtensions();
Chia-I Wu4901db72016-03-24 16:38:58 +0800709
710 // call into the driver
711 VkDevice dev;
712 result = instance_data.driver.CreateDevice(
713 physicalDevice, static_cast<const VkDeviceCreateInfo*>(wrapper),
714 pAllocator, &dev);
715 if (result != VK_SUCCESS) {
716 FreeDeviceData(data, data_allocator);
717 return result;
718 }
719
720 // initialize DeviceDriverTable
721 if (!SetData(dev, *data) ||
Chia-I Wucbe07ef2016-04-13 15:01:00 +0800722 !InitDriverTable(dev, instance_data.get_device_proc_addr,
723 wrapper.GetHalExtensions())) {
Chia-I Wu4901db72016-03-24 16:38:58 +0800724 data->driver.DestroyDevice = reinterpret_cast<PFN_vkDestroyDevice>(
725 instance_data.get_device_proc_addr(dev, "vkDestroyDevice"));
726 if (data->driver.DestroyDevice)
727 data->driver.DestroyDevice(dev, pAllocator);
728
729 FreeDeviceData(data, data_allocator);
730
731 return VK_ERROR_INCOMPATIBLE_DRIVER;
732 }
733
734 *pDevice = dev;
735
736 return VK_SUCCESS;
737}
738
739void DestroyDevice(VkDevice device, const VkAllocationCallbacks* pAllocator) {
740 DeviceData& data = GetData(device);
741 data.driver.DestroyDevice(device, pAllocator);
742
743 VkAllocationCallbacks local_allocator;
744 if (!pAllocator) {
745 local_allocator = data.allocator;
746 pAllocator = &local_allocator;
747 }
748
749 FreeDeviceData(&data, *pAllocator);
750}
751
Chia-I Wuff4a6c72016-03-24 16:05:56 +0800752VkResult EnumeratePhysicalDevices(VkInstance instance,
753 uint32_t* pPhysicalDeviceCount,
754 VkPhysicalDevice* pPhysicalDevices) {
755 const auto& data = GetData(instance);
756
757 VkResult result = data.driver.EnumeratePhysicalDevices(
758 instance, pPhysicalDeviceCount, pPhysicalDevices);
759 if ((result == VK_SUCCESS || result == VK_INCOMPLETE) && pPhysicalDevices) {
760 for (uint32_t i = 0; i < *pPhysicalDeviceCount; i++)
761 SetData(pPhysicalDevices[i], data);
762 }
763
764 return result;
765}
766
Chia-I Wuba0be412016-03-24 16:24:40 +0800767void GetDeviceQueue(VkDevice device,
768 uint32_t queueFamilyIndex,
769 uint32_t queueIndex,
770 VkQueue* pQueue) {
771 const auto& data = GetData(device);
772
773 data.driver.GetDeviceQueue(device, queueFamilyIndex, queueIndex, pQueue);
774 SetData(*pQueue, data);
775}
776
Chia-I Wu6a58a8a2016-03-24 16:29:51 +0800777VKAPI_ATTR VkResult
778AllocateCommandBuffers(VkDevice device,
779 const VkCommandBufferAllocateInfo* pAllocateInfo,
780 VkCommandBuffer* pCommandBuffers) {
781 const auto& data = GetData(device);
782
783 VkResult result = data.driver.AllocateCommandBuffers(device, pAllocateInfo,
784 pCommandBuffers);
785 if (result == VK_SUCCESS) {
786 for (uint32_t i = 0; i < pAllocateInfo->commandBufferCount; i++)
787 SetData(pCommandBuffers[i], data);
788 }
789
790 return result;
791}
792
Chia-I Wu9d518162016-03-24 14:55:27 +0800793} // namespace driver
794} // namespace vulkan