blob: 6c9a449d9c6c69a473f16f526b9da7392c0c4226 [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
Mark Salyzyn7823e122016-09-29 08:08:05 -070017#include <malloc.h>
Chia-I Wudbb7e9c2016-03-24 15:09:38 +080018#include <stdlib.h>
19#include <string.h>
Mark Salyzyn7823e122016-09-29 08:08:05 -070020#include <sys/prctl.h>
21
Chia-I Wudbb7e9c2016-03-24 15:09:38 +080022#include <algorithm>
Chia-I Wuff4a6c72016-03-24 16:05:56 +080023#include <array>
Chia-I Wu4901db72016-03-24 16:38:58 +080024#include <new>
Mark Salyzyn7823e122016-09-29 08:08:05 -070025
26#include <log/log.h>
Chia-I Wu9d518162016-03-24 14:55:27 +080027
28#include "driver.h"
Jesse Hallb7c4e3b2016-04-11 13:51:38 -070029#include "stubhal.h"
Chia-I Wu9d518162016-03-24 14:55:27 +080030
Chia-I Wudbb7e9c2016-03-24 15:09:38 +080031// #define ENABLE_ALLOC_CALLSTACKS 1
32#if ENABLE_ALLOC_CALLSTACKS
33#include <utils/CallStack.h>
34#define ALOGD_CALLSTACK(...) \
35 do { \
36 ALOGD(__VA_ARGS__); \
37 android::CallStack callstack; \
38 callstack.update(); \
39 callstack.log(LOG_TAG, ANDROID_LOG_DEBUG, " "); \
40 } while (false)
41#else
42#define ALOGD_CALLSTACK(...) \
43 do { \
44 } while (false)
45#endif
46
Chia-I Wu9d518162016-03-24 14:55:27 +080047namespace vulkan {
48namespace driver {
49
Chia-I Wu136b8eb2016-03-24 15:01:52 +080050namespace {
51
Chia-I Wu31b2e4f2016-05-23 10:47:57 +080052class Hal {
53 public:
54 static bool Open();
55
56 static const Hal& Get() { return hal_; }
57 static const hwvulkan_device_t& Device() { return *Get().dev_; }
58
Chia-I Wu31938252016-05-23 15:31:02 +080059 int GetDebugReportIndex() const { return debug_report_index_; }
60
Chia-I Wu31b2e4f2016-05-23 10:47:57 +080061 private:
Chia-I Wu31938252016-05-23 15:31:02 +080062 Hal() : dev_(nullptr), debug_report_index_(-1) {}
Chia-I Wu31b2e4f2016-05-23 10:47:57 +080063 Hal(const Hal&) = delete;
64 Hal& operator=(const Hal&) = delete;
65
Chia-I Wu31938252016-05-23 15:31:02 +080066 bool InitDebugReportIndex();
67
Chia-I Wu31b2e4f2016-05-23 10:47:57 +080068 static Hal hal_;
69
70 const hwvulkan_device_t* dev_;
Chia-I Wu31938252016-05-23 15:31:02 +080071 int debug_report_index_;
Chia-I Wu31b2e4f2016-05-23 10:47:57 +080072};
73
Chia-I Wu4901db72016-03-24 16:38:58 +080074class CreateInfoWrapper {
75 public:
Chia-I Wu31b2e4f2016-05-23 10:47:57 +080076 CreateInfoWrapper(const VkInstanceCreateInfo& create_info,
Chia-I Wuff4a6c72016-03-24 16:05:56 +080077 const VkAllocationCallbacks& allocator);
Chia-I Wu4901db72016-03-24 16:38:58 +080078 CreateInfoWrapper(VkPhysicalDevice physical_dev,
79 const VkDeviceCreateInfo& create_info,
80 const VkAllocationCallbacks& allocator);
81 ~CreateInfoWrapper();
82
Chia-I Wu3e6c2d62016-04-11 13:55:56 +080083 VkResult Validate();
Chia-I Wu4901db72016-03-24 16:38:58 +080084
Chia-I Wu3e6c2d62016-04-11 13:55:56 +080085 const std::bitset<ProcHook::EXTENSION_COUNT>& GetHookExtensions() const;
86 const std::bitset<ProcHook::EXTENSION_COUNT>& GetHalExtensions() const;
Chia-I Wu4901db72016-03-24 16:38:58 +080087
Chia-I Wuff4a6c72016-03-24 16:05:56 +080088 explicit operator const VkInstanceCreateInfo*() const;
Chia-I Wu4901db72016-03-24 16:38:58 +080089 explicit operator const VkDeviceCreateInfo*() const;
90
91 private:
92 struct ExtensionFilter {
93 VkExtensionProperties* exts;
94 uint32_t ext_count;
95
96 const char** names;
97 uint32_t name_count;
98 };
99
Chia-I Wu3e6c2d62016-04-11 13:55:56 +0800100 VkResult SanitizePNext();
Chia-I Wu4901db72016-03-24 16:38:58 +0800101
Chia-I Wu3e6c2d62016-04-11 13:55:56 +0800102 VkResult SanitizeLayers();
103 VkResult SanitizeExtensions();
Chia-I Wu4901db72016-03-24 16:38:58 +0800104
Chia-I Wu3e6c2d62016-04-11 13:55:56 +0800105 VkResult QueryExtensionCount(uint32_t& count) const;
106 VkResult EnumerateExtensions(uint32_t& count,
107 VkExtensionProperties* props) const;
108 VkResult InitExtensionFilter();
109 void FilterExtension(const char* name);
Chia-I Wu4901db72016-03-24 16:38:58 +0800110
111 const bool is_instance_;
112 const VkAllocationCallbacks& allocator_;
113
Chia-I Wu31b2e4f2016-05-23 10:47:57 +0800114 VkPhysicalDevice physical_dev_;
Chia-I Wu4901db72016-03-24 16:38:58 +0800115
116 union {
117 VkInstanceCreateInfo instance_info_;
118 VkDeviceCreateInfo dev_info_;
119 };
120
121 ExtensionFilter extension_filter_;
122
123 std::bitset<ProcHook::EXTENSION_COUNT> hook_extensions_;
124 std::bitset<ProcHook::EXTENSION_COUNT> hal_extensions_;
125};
126
Chia-I Wu31b2e4f2016-05-23 10:47:57 +0800127Hal Hal::hal_;
128
129bool Hal::Open() {
Jesse Halldc225072016-05-30 22:40:14 -0700130 ALOG_ASSERT(!hal_.dev_, "OpenHAL called more than once");
Chia-I Wu31b2e4f2016-05-23 10:47:57 +0800131
132 // Use a stub device unless we successfully open a real HAL device.
133 hal_.dev_ = &stubhal::kDevice;
134
135 const hwvulkan_module_t* module;
136 int result =
137 hw_get_module("vulkan", reinterpret_cast<const hw_module_t**>(&module));
138 if (result != 0) {
139 ALOGI("no Vulkan HAL present, using stub HAL");
140 return true;
141 }
142
143 hwvulkan_device_t* device;
144 result =
145 module->common.methods->open(&module->common, HWVULKAN_DEVICE_0,
146 reinterpret_cast<hw_device_t**>(&device));
147 if (result != 0) {
148 // Any device with a Vulkan HAL should be able to open the device.
149 ALOGE("failed to open Vulkan HAL device: %s (%d)", strerror(-result),
150 result);
151 return false;
152 }
153
154 hal_.dev_ = device;
155
Chia-I Wu31938252016-05-23 15:31:02 +0800156 hal_.InitDebugReportIndex();
157
158 return true;
159}
160
161bool Hal::InitDebugReportIndex() {
162 uint32_t count;
163 if (dev_->EnumerateInstanceExtensionProperties(nullptr, &count, nullptr) !=
164 VK_SUCCESS) {
165 ALOGE("failed to get HAL instance extension count");
166 return false;
167 }
168
169 VkExtensionProperties* exts = reinterpret_cast<VkExtensionProperties*>(
170 malloc(sizeof(VkExtensionProperties) * count));
171 if (!exts) {
172 ALOGE("failed to allocate HAL instance extension array");
173 return false;
174 }
175
176 if (dev_->EnumerateInstanceExtensionProperties(nullptr, &count, exts) !=
177 VK_SUCCESS) {
178 ALOGE("failed to enumerate HAL instance extensions");
179 free(exts);
180 return false;
181 }
182
183 for (uint32_t i = 0; i < count; i++) {
184 if (strcmp(exts[i].extensionName, VK_EXT_DEBUG_REPORT_EXTENSION_NAME) ==
185 0) {
186 debug_report_index_ = static_cast<int>(i);
187 break;
188 }
189 }
190
191 free(exts);
192
Chia-I Wu31b2e4f2016-05-23 10:47:57 +0800193 return true;
194}
195
196CreateInfoWrapper::CreateInfoWrapper(const VkInstanceCreateInfo& create_info,
Chia-I Wuff4a6c72016-03-24 16:05:56 +0800197 const VkAllocationCallbacks& allocator)
198 : is_instance_(true),
199 allocator_(allocator),
Chia-I Wu31b2e4f2016-05-23 10:47:57 +0800200 physical_dev_(VK_NULL_HANDLE),
Chia-I Wuff4a6c72016-03-24 16:05:56 +0800201 instance_info_(create_info),
202 extension_filter_() {
203 hook_extensions_.set(ProcHook::EXTENSION_CORE);
204 hal_extensions_.set(ProcHook::EXTENSION_CORE);
205}
206
Chia-I Wu4901db72016-03-24 16:38:58 +0800207CreateInfoWrapper::CreateInfoWrapper(VkPhysicalDevice physical_dev,
208 const VkDeviceCreateInfo& create_info,
209 const VkAllocationCallbacks& allocator)
210 : is_instance_(false),
211 allocator_(allocator),
212 physical_dev_(physical_dev),
213 dev_info_(create_info),
214 extension_filter_() {
215 hook_extensions_.set(ProcHook::EXTENSION_CORE);
216 hal_extensions_.set(ProcHook::EXTENSION_CORE);
217}
218
219CreateInfoWrapper::~CreateInfoWrapper() {
220 allocator_.pfnFree(allocator_.pUserData, extension_filter_.exts);
221 allocator_.pfnFree(allocator_.pUserData, extension_filter_.names);
222}
223
Chia-I Wu3e6c2d62016-04-11 13:55:56 +0800224VkResult CreateInfoWrapper::Validate() {
225 VkResult result = SanitizePNext();
Chia-I Wu4901db72016-03-24 16:38:58 +0800226 if (result == VK_SUCCESS)
Chia-I Wu3e6c2d62016-04-11 13:55:56 +0800227 result = SanitizeLayers();
Chia-I Wu4901db72016-03-24 16:38:58 +0800228 if (result == VK_SUCCESS)
Chia-I Wu3e6c2d62016-04-11 13:55:56 +0800229 result = SanitizeExtensions();
Chia-I Wu4901db72016-03-24 16:38:58 +0800230
231 return result;
232}
233
234const std::bitset<ProcHook::EXTENSION_COUNT>&
Chia-I Wu3e6c2d62016-04-11 13:55:56 +0800235CreateInfoWrapper::GetHookExtensions() const {
Chia-I Wu4901db72016-03-24 16:38:58 +0800236 return hook_extensions_;
237}
238
239const std::bitset<ProcHook::EXTENSION_COUNT>&
Chia-I Wu3e6c2d62016-04-11 13:55:56 +0800240CreateInfoWrapper::GetHalExtensions() const {
Chia-I Wu4901db72016-03-24 16:38:58 +0800241 return hal_extensions_;
242}
243
Chia-I Wuff4a6c72016-03-24 16:05:56 +0800244CreateInfoWrapper::operator const VkInstanceCreateInfo*() const {
245 return &instance_info_;
246}
247
Chia-I Wu4901db72016-03-24 16:38:58 +0800248CreateInfoWrapper::operator const VkDeviceCreateInfo*() const {
249 return &dev_info_;
250}
251
Chia-I Wu3e6c2d62016-04-11 13:55:56 +0800252VkResult CreateInfoWrapper::SanitizePNext() {
Chia-I Wu4901db72016-03-24 16:38:58 +0800253 const struct StructHeader {
254 VkStructureType type;
255 const void* next;
256 } * header;
257
258 if (is_instance_) {
259 header = reinterpret_cast<const StructHeader*>(instance_info_.pNext);
260
261 // skip leading VK_STRUCTURE_TYPE_LOADER_INSTANCE_CREATE_INFOs
262 while (header &&
263 header->type == VK_STRUCTURE_TYPE_LOADER_INSTANCE_CREATE_INFO)
264 header = reinterpret_cast<const StructHeader*>(header->next);
265
266 instance_info_.pNext = header;
267 } else {
268 header = reinterpret_cast<const StructHeader*>(dev_info_.pNext);
269
270 // skip leading VK_STRUCTURE_TYPE_LOADER_DEVICE_CREATE_INFOs
271 while (header &&
272 header->type == VK_STRUCTURE_TYPE_LOADER_DEVICE_CREATE_INFO)
273 header = reinterpret_cast<const StructHeader*>(header->next);
274
275 dev_info_.pNext = header;
276 }
277
278 return VK_SUCCESS;
279}
280
Chia-I Wu3e6c2d62016-04-11 13:55:56 +0800281VkResult CreateInfoWrapper::SanitizeLayers() {
Chia-I Wu4901db72016-03-24 16:38:58 +0800282 auto& layer_names = (is_instance_) ? instance_info_.ppEnabledLayerNames
283 : dev_info_.ppEnabledLayerNames;
284 auto& layer_count = (is_instance_) ? instance_info_.enabledLayerCount
285 : dev_info_.enabledLayerCount;
286
287 // remove all layers
288 layer_names = nullptr;
289 layer_count = 0;
290
291 return VK_SUCCESS;
292}
293
Chia-I Wu3e6c2d62016-04-11 13:55:56 +0800294VkResult CreateInfoWrapper::SanitizeExtensions() {
Chia-I Wu4901db72016-03-24 16:38:58 +0800295 auto& ext_names = (is_instance_) ? instance_info_.ppEnabledExtensionNames
296 : dev_info_.ppEnabledExtensionNames;
297 auto& ext_count = (is_instance_) ? instance_info_.enabledExtensionCount
298 : dev_info_.enabledExtensionCount;
299 if (!ext_count)
300 return VK_SUCCESS;
301
Chia-I Wu3e6c2d62016-04-11 13:55:56 +0800302 VkResult result = InitExtensionFilter();
Chia-I Wu4901db72016-03-24 16:38:58 +0800303 if (result != VK_SUCCESS)
304 return result;
305
306 for (uint32_t i = 0; i < ext_count; i++)
Chia-I Wu3e6c2d62016-04-11 13:55:56 +0800307 FilterExtension(ext_names[i]);
Chia-I Wu4901db72016-03-24 16:38:58 +0800308
309 ext_names = extension_filter_.names;
310 ext_count = extension_filter_.name_count;
311
312 return VK_SUCCESS;
313}
314
Chia-I Wu3e6c2d62016-04-11 13:55:56 +0800315VkResult CreateInfoWrapper::QueryExtensionCount(uint32_t& count) const {
Chia-I Wu4901db72016-03-24 16:38:58 +0800316 if (is_instance_) {
Chia-I Wu31b2e4f2016-05-23 10:47:57 +0800317 return Hal::Device().EnumerateInstanceExtensionProperties(
318 nullptr, &count, nullptr);
Chia-I Wu4901db72016-03-24 16:38:58 +0800319 } else {
320 const auto& driver = GetData(physical_dev_).driver;
321 return driver.EnumerateDeviceExtensionProperties(physical_dev_, nullptr,
322 &count, nullptr);
323 }
324}
325
Chia-I Wu3e6c2d62016-04-11 13:55:56 +0800326VkResult CreateInfoWrapper::EnumerateExtensions(
Chia-I Wu4901db72016-03-24 16:38:58 +0800327 uint32_t& count,
328 VkExtensionProperties* props) const {
329 if (is_instance_) {
Chia-I Wu31b2e4f2016-05-23 10:47:57 +0800330 return Hal::Device().EnumerateInstanceExtensionProperties(
331 nullptr, &count, props);
Chia-I Wu4901db72016-03-24 16:38:58 +0800332 } else {
333 const auto& driver = GetData(physical_dev_).driver;
334 return driver.EnumerateDeviceExtensionProperties(physical_dev_, nullptr,
335 &count, props);
336 }
337}
338
Chia-I Wu3e6c2d62016-04-11 13:55:56 +0800339VkResult CreateInfoWrapper::InitExtensionFilter() {
Chia-I Wu4901db72016-03-24 16:38:58 +0800340 // query extension count
341 uint32_t count;
Chia-I Wu3e6c2d62016-04-11 13:55:56 +0800342 VkResult result = QueryExtensionCount(count);
Chia-I Wu4901db72016-03-24 16:38:58 +0800343 if (result != VK_SUCCESS || count == 0)
344 return result;
345
346 auto& filter = extension_filter_;
347 filter.exts =
348 reinterpret_cast<VkExtensionProperties*>(allocator_.pfnAllocation(
349 allocator_.pUserData, sizeof(VkExtensionProperties) * count,
350 alignof(VkExtensionProperties),
351 VK_SYSTEM_ALLOCATION_SCOPE_COMMAND));
352 if (!filter.exts)
353 return VK_ERROR_OUT_OF_HOST_MEMORY;
354
355 // enumerate extensions
Chia-I Wu3e6c2d62016-04-11 13:55:56 +0800356 result = EnumerateExtensions(count, filter.exts);
Chia-I Wu4901db72016-03-24 16:38:58 +0800357 if (result != VK_SUCCESS && result != VK_INCOMPLETE)
358 return result;
359
360 if (!count)
361 return VK_SUCCESS;
362
363 filter.ext_count = count;
364
365 // allocate name array
366 uint32_t enabled_ext_count = (is_instance_)
367 ? instance_info_.enabledExtensionCount
368 : dev_info_.enabledExtensionCount;
369 count = std::min(filter.ext_count, enabled_ext_count);
370 filter.names = reinterpret_cast<const char**>(allocator_.pfnAllocation(
371 allocator_.pUserData, sizeof(const char*) * count, alignof(const char*),
372 VK_SYSTEM_ALLOCATION_SCOPE_COMMAND));
373 if (!filter.names)
374 return VK_ERROR_OUT_OF_HOST_MEMORY;
375
376 return VK_SUCCESS;
377}
378
Chia-I Wu3e6c2d62016-04-11 13:55:56 +0800379void CreateInfoWrapper::FilterExtension(const char* name) {
Chia-I Wu4901db72016-03-24 16:38:58 +0800380 auto& filter = extension_filter_;
381
382 ProcHook::Extension ext_bit = GetProcHookExtension(name);
383 if (is_instance_) {
384 switch (ext_bit) {
385 case ProcHook::KHR_android_surface:
386 case ProcHook::KHR_surface:
387 hook_extensions_.set(ext_bit);
388 // return now as these extensions do not require HAL support
389 return;
390 case ProcHook::EXT_debug_report:
391 // both we and HAL can take part in
392 hook_extensions_.set(ext_bit);
393 break;
394 case ProcHook::EXTENSION_UNKNOWN:
395 // HAL's extensions
396 break;
397 default:
398 ALOGW("Ignored invalid instance extension %s", name);
399 return;
400 }
401 } else {
402 switch (ext_bit) {
403 case ProcHook::KHR_swapchain:
404 // map VK_KHR_swapchain to VK_ANDROID_native_buffer
405 name = VK_ANDROID_NATIVE_BUFFER_EXTENSION_NAME;
406 ext_bit = ProcHook::ANDROID_native_buffer;
407 break;
Ian Elliott8a977262017-01-19 09:05:58 -0700408 case ProcHook::GOOGLE_display_timing:
409 hook_extensions_.set(ext_bit);
410 // return now as these extensions do not require HAL support
411 return;
Chia-I Wu4901db72016-03-24 16:38:58 +0800412 case ProcHook::EXTENSION_UNKNOWN:
413 // HAL's extensions
414 break;
415 default:
416 ALOGW("Ignored invalid device extension %s", name);
417 return;
418 }
419 }
420
421 for (uint32_t i = 0; i < filter.ext_count; i++) {
422 const VkExtensionProperties& props = filter.exts[i];
423 // ignore unknown extensions
424 if (strcmp(name, props.extensionName) != 0)
425 continue;
426
Chia-I Wu4901db72016-03-24 16:38:58 +0800427 filter.names[filter.name_count++] = name;
Chia-I Wu1600e262016-04-12 09:40:06 +0800428 if (ext_bit != ProcHook::EXTENSION_UNKNOWN) {
429 if (ext_bit == ProcHook::ANDROID_native_buffer)
430 hook_extensions_.set(ProcHook::KHR_swapchain);
431
432 hal_extensions_.set(ext_bit);
433 }
Chia-I Wu4901db72016-03-24 16:38:58 +0800434
435 break;
436 }
437}
438
Chia-I Wudbb7e9c2016-03-24 15:09:38 +0800439VKAPI_ATTR void* DefaultAllocate(void*,
440 size_t size,
441 size_t alignment,
442 VkSystemAllocationScope) {
443 void* ptr = nullptr;
444 // Vulkan requires 'alignment' to be a power of two, but posix_memalign
445 // additionally requires that it be at least sizeof(void*).
446 int ret = posix_memalign(&ptr, std::max(alignment, sizeof(void*)), size);
447 ALOGD_CALLSTACK("Allocate: size=%zu align=%zu => (%d) %p", size, alignment,
448 ret, ptr);
449 return ret == 0 ? ptr : nullptr;
450}
451
452VKAPI_ATTR void* DefaultReallocate(void*,
453 void* ptr,
454 size_t size,
455 size_t alignment,
456 VkSystemAllocationScope) {
457 if (size == 0) {
458 free(ptr);
459 return nullptr;
460 }
461
462 // TODO(jessehall): Right now we never shrink allocations; if the new
463 // request is smaller than the existing chunk, we just continue using it.
464 // Right now the loader never reallocs, so this doesn't matter. If that
465 // changes, or if this code is copied into some other project, this should
466 // probably have a heuristic to allocate-copy-free when doing so will save
467 // "enough" space.
468 size_t old_size = ptr ? malloc_usable_size(ptr) : 0;
469 if (size <= old_size)
470 return ptr;
471
472 void* new_ptr = nullptr;
473 if (posix_memalign(&new_ptr, std::max(alignment, sizeof(void*)), size) != 0)
474 return nullptr;
475 if (ptr) {
476 memcpy(new_ptr, ptr, std::min(old_size, size));
477 free(ptr);
478 }
479 return new_ptr;
480}
481
482VKAPI_ATTR void DefaultFree(void*, void* ptr) {
483 ALOGD_CALLSTACK("Free: %p", ptr);
484 free(ptr);
485}
486
Chia-I Wuff4a6c72016-03-24 16:05:56 +0800487InstanceData* AllocateInstanceData(const VkAllocationCallbacks& allocator) {
488 void* data_mem = allocator.pfnAllocation(
489 allocator.pUserData, sizeof(InstanceData), alignof(InstanceData),
490 VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
491 if (!data_mem)
492 return nullptr;
493
494 return new (data_mem) InstanceData(allocator);
495}
496
497void FreeInstanceData(InstanceData* data,
498 const VkAllocationCallbacks& allocator) {
499 data->~InstanceData();
500 allocator.pfnFree(allocator.pUserData, data);
501}
502
Chia-I Wu950d6e12016-05-03 09:12:35 +0800503DeviceData* AllocateDeviceData(
504 const VkAllocationCallbacks& allocator,
505 const DebugReportCallbackList& debug_report_callbacks) {
Chia-I Wu4901db72016-03-24 16:38:58 +0800506 void* data_mem = allocator.pfnAllocation(
507 allocator.pUserData, sizeof(DeviceData), alignof(DeviceData),
508 VK_SYSTEM_ALLOCATION_SCOPE_DEVICE);
509 if (!data_mem)
510 return nullptr;
511
Chia-I Wu950d6e12016-05-03 09:12:35 +0800512 return new (data_mem) DeviceData(allocator, debug_report_callbacks);
Chia-I Wu4901db72016-03-24 16:38:58 +0800513}
514
515void FreeDeviceData(DeviceData* data, const VkAllocationCallbacks& allocator) {
516 data->~DeviceData();
517 allocator.pfnFree(allocator.pUserData, data);
518}
519
Chia-I Wu136b8eb2016-03-24 15:01:52 +0800520} // anonymous namespace
521
Chia-I Wu9d518162016-03-24 14:55:27 +0800522bool Debuggable() {
523 return (prctl(PR_GET_DUMPABLE, 0, 0, 0, 0) >= 0);
524}
525
Chia-I Wu136b8eb2016-03-24 15:01:52 +0800526bool OpenHAL() {
Chia-I Wu31b2e4f2016-05-23 10:47:57 +0800527 return Hal::Open();
Chia-I Wu136b8eb2016-03-24 15:01:52 +0800528}
529
Chia-I Wudbb7e9c2016-03-24 15:09:38 +0800530const VkAllocationCallbacks& GetDefaultAllocator() {
531 static const VkAllocationCallbacks kDefaultAllocCallbacks = {
532 .pUserData = nullptr,
533 .pfnAllocation = DefaultAllocate,
534 .pfnReallocation = DefaultReallocate,
535 .pfnFree = DefaultFree,
536 };
537
538 return kDefaultAllocCallbacks;
539}
540
Chia-I Wueb7db122016-03-24 09:11:06 +0800541PFN_vkVoidFunction GetInstanceProcAddr(VkInstance instance, const char* pName) {
542 const ProcHook* hook = GetProcHook(pName);
543 if (!hook)
Chia-I Wu31b2e4f2016-05-23 10:47:57 +0800544 return Hal::Device().GetInstanceProcAddr(instance, pName);
Chia-I Wueb7db122016-03-24 09:11:06 +0800545
546 if (!instance) {
547 if (hook->type == ProcHook::GLOBAL)
548 return hook->proc;
549
Chia-I Wu109f8982016-04-22 06:40:40 +0800550 // v0 layers expect
551 //
552 // vkGetInstanceProcAddr(VK_NULL_HANDLE, "vkCreateDevice");
553 //
554 // to work.
555 if (strcmp(pName, "vkCreateDevice") == 0)
556 return hook->proc;
557
Chia-I Wueb7db122016-03-24 09:11:06 +0800558 ALOGE(
Chia-I Wue201c3f2016-05-03 13:26:08 +0800559 "internal vkGetInstanceProcAddr called for %s without an instance",
Chia-I Wueb7db122016-03-24 09:11:06 +0800560 pName);
561
Chia-I Wu109f8982016-04-22 06:40:40 +0800562 return nullptr;
Chia-I Wueb7db122016-03-24 09:11:06 +0800563 }
564
565 PFN_vkVoidFunction proc;
566
567 switch (hook->type) {
568 case ProcHook::INSTANCE:
569 proc = (GetData(instance).hook_extensions[hook->extension])
570 ? hook->proc
Chia-I Wu36cc00a2016-04-13 16:52:06 +0800571 : nullptr;
Chia-I Wueb7db122016-03-24 09:11:06 +0800572 break;
573 case ProcHook::DEVICE:
574 proc = (hook->extension == ProcHook::EXTENSION_CORE)
575 ? hook->proc
576 : hook->checked_proc;
577 break;
578 default:
579 ALOGE(
Chia-I Wue201c3f2016-05-03 13:26:08 +0800580 "internal vkGetInstanceProcAddr called for %s with an instance",
Chia-I Wueb7db122016-03-24 09:11:06 +0800581 pName);
582 proc = nullptr;
583 break;
584 }
585
586 return proc;
587}
588
589PFN_vkVoidFunction GetDeviceProcAddr(VkDevice device, const char* pName) {
590 const ProcHook* hook = GetProcHook(pName);
591 if (!hook)
Chia-I Wucc5e2762016-03-24 13:01:16 +0800592 return GetData(device).driver.GetDeviceProcAddr(device, pName);
Chia-I Wueb7db122016-03-24 09:11:06 +0800593
594 if (hook->type != ProcHook::DEVICE) {
Chia-I Wue201c3f2016-05-03 13:26:08 +0800595 ALOGE("internal vkGetDeviceProcAddr called for %s", pName);
Chia-I Wueb7db122016-03-24 09:11:06 +0800596 return nullptr;
597 }
598
Chia-I Wu36cc00a2016-04-13 16:52:06 +0800599 return (GetData(device).hook_extensions[hook->extension]) ? hook->proc
600 : nullptr;
Chia-I Wueb7db122016-03-24 09:11:06 +0800601}
602
Chia-I Wuff4a6c72016-03-24 16:05:56 +0800603VkResult EnumerateInstanceExtensionProperties(
604 const char* pLayerName,
605 uint32_t* pPropertyCount,
606 VkExtensionProperties* pProperties) {
607 static const std::array<VkExtensionProperties, 2> loader_extensions = {{
608 // WSI extensions
609 {VK_KHR_SURFACE_EXTENSION_NAME, VK_KHR_SURFACE_SPEC_VERSION},
610 {VK_KHR_ANDROID_SURFACE_EXTENSION_NAME,
611 VK_KHR_ANDROID_SURFACE_SPEC_VERSION},
612 }};
Chia-I Wu31938252016-05-23 15:31:02 +0800613 static const VkExtensionProperties loader_debug_report_extension = {
614 VK_EXT_DEBUG_REPORT_EXTENSION_NAME, VK_EXT_DEBUG_REPORT_SPEC_VERSION,
615 };
Chia-I Wuff4a6c72016-03-24 16:05:56 +0800616
617 // enumerate our extensions first
618 if (!pLayerName && pProperties) {
619 uint32_t count = std::min(
620 *pPropertyCount, static_cast<uint32_t>(loader_extensions.size()));
621
622 std::copy_n(loader_extensions.begin(), count, pProperties);
623
624 if (count < loader_extensions.size()) {
625 *pPropertyCount = count;
626 return VK_INCOMPLETE;
627 }
628
629 pProperties += count;
630 *pPropertyCount -= count;
Chia-I Wu31938252016-05-23 15:31:02 +0800631
632 if (Hal::Get().GetDebugReportIndex() < 0) {
633 if (!*pPropertyCount) {
634 *pPropertyCount = count;
635 return VK_INCOMPLETE;
636 }
637
638 pProperties[0] = loader_debug_report_extension;
639 pProperties += 1;
640 *pPropertyCount -= 1;
641 }
Chia-I Wuff4a6c72016-03-24 16:05:56 +0800642 }
643
Chia-I Wu31b2e4f2016-05-23 10:47:57 +0800644 VkResult result = Hal::Device().EnumerateInstanceExtensionProperties(
Chia-I Wuff4a6c72016-03-24 16:05:56 +0800645 pLayerName, pPropertyCount, pProperties);
646
Chia-I Wu31938252016-05-23 15:31:02 +0800647 if (!pLayerName && (result == VK_SUCCESS || result == VK_INCOMPLETE)) {
648 int idx = Hal::Get().GetDebugReportIndex();
649 if (idx < 0) {
650 *pPropertyCount += 1;
651 } else if (pProperties &&
652 static_cast<uint32_t>(idx) < *pPropertyCount) {
653 pProperties[idx].specVersion =
654 std::min(pProperties[idx].specVersion,
655 loader_debug_report_extension.specVersion);
656 }
657
Chia-I Wuff4a6c72016-03-24 16:05:56 +0800658 *pPropertyCount += loader_extensions.size();
Chia-I Wu31938252016-05-23 15:31:02 +0800659 }
Chia-I Wuff4a6c72016-03-24 16:05:56 +0800660
661 return result;
662}
663
Chia-I Wu01cf3052016-03-24 16:16:21 +0800664VkResult EnumerateDeviceExtensionProperties(
665 VkPhysicalDevice physicalDevice,
666 const char* pLayerName,
667 uint32_t* pPropertyCount,
668 VkExtensionProperties* pProperties) {
669 const InstanceData& data = GetData(physicalDevice);
Ian Elliott8a977262017-01-19 09:05:58 -0700670 static const std::array<VkExtensionProperties, 2> loader_extensions = {{
Ian Elliottd4b50aa2017-01-09 16:21:36 -0700671 // WSI extensions
672 {VK_KHR_INCREMENTAL_PRESENT_EXTENSION_NAME,
673 VK_KHR_INCREMENTAL_PRESENT_SPEC_VERSION},
Ian Elliott8a977262017-01-19 09:05:58 -0700674 {VK_GOOGLE_DISPLAY_TIMING_EXTENSION_NAME,
675 VK_GOOGLE_DISPLAY_TIMING_SPEC_VERSION},
Ian Elliottd4b50aa2017-01-09 16:21:36 -0700676 }};
677
678 // enumerate our extensions first
679 if (!pLayerName && pProperties) {
680 uint32_t count = std::min(
681 *pPropertyCount, static_cast<uint32_t>(loader_extensions.size()));
682
683 std::copy_n(loader_extensions.begin(), count, pProperties);
684
685 if (count < loader_extensions.size()) {
686 *pPropertyCount = count;
687 return VK_INCOMPLETE;
688 }
689
690 pProperties += count;
691 *pPropertyCount -= count;
692 }
Chia-I Wu01cf3052016-03-24 16:16:21 +0800693
694 VkResult result = data.driver.EnumerateDeviceExtensionProperties(
695 physicalDevice, pLayerName, pPropertyCount, pProperties);
Chia-I Wu01cf3052016-03-24 16:16:21 +0800696
Ian Elliottd4b50aa2017-01-09 16:21:36 -0700697 if (pProperties) {
698 // map VK_ANDROID_native_buffer to VK_KHR_swapchain
699 for (uint32_t i = 0; i < *pPropertyCount; i++) {
700 auto& prop = pProperties[i];
Chia-I Wu01cf3052016-03-24 16:16:21 +0800701
Ian Elliottd4b50aa2017-01-09 16:21:36 -0700702 if (strcmp(prop.extensionName,
703 VK_ANDROID_NATIVE_BUFFER_EXTENSION_NAME) != 0)
704 continue;
Chia-I Wu01cf3052016-03-24 16:16:21 +0800705
Ian Elliottd4b50aa2017-01-09 16:21:36 -0700706 memcpy(prop.extensionName, VK_KHR_SWAPCHAIN_EXTENSION_NAME,
707 sizeof(VK_KHR_SWAPCHAIN_EXTENSION_NAME));
708 prop.specVersion = VK_KHR_SWAPCHAIN_SPEC_VERSION;
709 }
710 }
Chia-I Wu01cf3052016-03-24 16:16:21 +0800711
Ian Elliottd4b50aa2017-01-09 16:21:36 -0700712 // restore loader extension count
713 if (!pLayerName && (result == VK_SUCCESS || result == VK_INCOMPLETE)) {
714 *pPropertyCount += loader_extensions.size();
Chia-I Wu01cf3052016-03-24 16:16:21 +0800715 }
716
717 return result;
718}
719
Chia-I Wuff4a6c72016-03-24 16:05:56 +0800720VkResult CreateInstance(const VkInstanceCreateInfo* pCreateInfo,
721 const VkAllocationCallbacks* pAllocator,
722 VkInstance* pInstance) {
723 const VkAllocationCallbacks& data_allocator =
724 (pAllocator) ? *pAllocator : GetDefaultAllocator();
725
Chia-I Wu31b2e4f2016-05-23 10:47:57 +0800726 CreateInfoWrapper wrapper(*pCreateInfo, data_allocator);
Chia-I Wu3e6c2d62016-04-11 13:55:56 +0800727 VkResult result = wrapper.Validate();
Chia-I Wuff4a6c72016-03-24 16:05:56 +0800728 if (result != VK_SUCCESS)
729 return result;
730
731 InstanceData* data = AllocateInstanceData(data_allocator);
732 if (!data)
733 return VK_ERROR_OUT_OF_HOST_MEMORY;
734
Chia-I Wu3e6c2d62016-04-11 13:55:56 +0800735 data->hook_extensions |= wrapper.GetHookExtensions();
Chia-I Wuff4a6c72016-03-24 16:05:56 +0800736
737 // call into the driver
738 VkInstance instance;
Chia-I Wu31b2e4f2016-05-23 10:47:57 +0800739 result = Hal::Device().CreateInstance(
Chia-I Wuff4a6c72016-03-24 16:05:56 +0800740 static_cast<const VkInstanceCreateInfo*>(wrapper), pAllocator,
741 &instance);
742 if (result != VK_SUCCESS) {
743 FreeInstanceData(data, data_allocator);
744 return result;
745 }
746
747 // initialize InstanceDriverTable
748 if (!SetData(instance, *data) ||
Chia-I Wu31b2e4f2016-05-23 10:47:57 +0800749 !InitDriverTable(instance, Hal::Device().GetInstanceProcAddr,
Chia-I Wucbe07ef2016-04-13 15:01:00 +0800750 wrapper.GetHalExtensions())) {
Chia-I Wuff4a6c72016-03-24 16:05:56 +0800751 data->driver.DestroyInstance = reinterpret_cast<PFN_vkDestroyInstance>(
Chia-I Wu31b2e4f2016-05-23 10:47:57 +0800752 Hal::Device().GetInstanceProcAddr(instance, "vkDestroyInstance"));
Chia-I Wuff4a6c72016-03-24 16:05:56 +0800753 if (data->driver.DestroyInstance)
754 data->driver.DestroyInstance(instance, pAllocator);
755
756 FreeInstanceData(data, data_allocator);
757
758 return VK_ERROR_INCOMPATIBLE_DRIVER;
759 }
760
761 data->get_device_proc_addr = reinterpret_cast<PFN_vkGetDeviceProcAddr>(
Chia-I Wu31b2e4f2016-05-23 10:47:57 +0800762 Hal::Device().GetInstanceProcAddr(instance, "vkGetDeviceProcAddr"));
Chia-I Wuff4a6c72016-03-24 16:05:56 +0800763 if (!data->get_device_proc_addr) {
764 data->driver.DestroyInstance(instance, pAllocator);
765 FreeInstanceData(data, data_allocator);
766
767 return VK_ERROR_INCOMPATIBLE_DRIVER;
768 }
769
770 *pInstance = instance;
771
772 return VK_SUCCESS;
773}
774
775void DestroyInstance(VkInstance instance,
776 const VkAllocationCallbacks* pAllocator) {
777 InstanceData& data = GetData(instance);
778 data.driver.DestroyInstance(instance, pAllocator);
779
780 VkAllocationCallbacks local_allocator;
781 if (!pAllocator) {
782 local_allocator = data.allocator;
783 pAllocator = &local_allocator;
784 }
785
786 FreeInstanceData(&data, *pAllocator);
787}
788
Chia-I Wu4901db72016-03-24 16:38:58 +0800789VkResult CreateDevice(VkPhysicalDevice physicalDevice,
790 const VkDeviceCreateInfo* pCreateInfo,
791 const VkAllocationCallbacks* pAllocator,
792 VkDevice* pDevice) {
793 const InstanceData& instance_data = GetData(physicalDevice);
794 const VkAllocationCallbacks& data_allocator =
795 (pAllocator) ? *pAllocator : instance_data.allocator;
796
797 CreateInfoWrapper wrapper(physicalDevice, *pCreateInfo, data_allocator);
Chia-I Wu3e6c2d62016-04-11 13:55:56 +0800798 VkResult result = wrapper.Validate();
Chia-I Wu4901db72016-03-24 16:38:58 +0800799 if (result != VK_SUCCESS)
800 return result;
801
Chia-I Wu950d6e12016-05-03 09:12:35 +0800802 DeviceData* data = AllocateDeviceData(data_allocator,
803 instance_data.debug_report_callbacks);
Chia-I Wu4901db72016-03-24 16:38:58 +0800804 if (!data)
805 return VK_ERROR_OUT_OF_HOST_MEMORY;
806
Chia-I Wu3e6c2d62016-04-11 13:55:56 +0800807 data->hook_extensions |= wrapper.GetHookExtensions();
Chia-I Wu4901db72016-03-24 16:38:58 +0800808
809 // call into the driver
810 VkDevice dev;
811 result = instance_data.driver.CreateDevice(
812 physicalDevice, static_cast<const VkDeviceCreateInfo*>(wrapper),
813 pAllocator, &dev);
814 if (result != VK_SUCCESS) {
815 FreeDeviceData(data, data_allocator);
816 return result;
817 }
818
819 // initialize DeviceDriverTable
820 if (!SetData(dev, *data) ||
Chia-I Wucbe07ef2016-04-13 15:01:00 +0800821 !InitDriverTable(dev, instance_data.get_device_proc_addr,
822 wrapper.GetHalExtensions())) {
Chia-I Wu4901db72016-03-24 16:38:58 +0800823 data->driver.DestroyDevice = reinterpret_cast<PFN_vkDestroyDevice>(
824 instance_data.get_device_proc_addr(dev, "vkDestroyDevice"));
825 if (data->driver.DestroyDevice)
826 data->driver.DestroyDevice(dev, pAllocator);
827
828 FreeDeviceData(data, data_allocator);
829
830 return VK_ERROR_INCOMPATIBLE_DRIVER;
831 }
Jesse Halldc225072016-05-30 22:40:14 -0700832 data->driver_device = dev;
Chia-I Wu4901db72016-03-24 16:38:58 +0800833
834 *pDevice = dev;
835
836 return VK_SUCCESS;
837}
838
839void DestroyDevice(VkDevice device, const VkAllocationCallbacks* pAllocator) {
840 DeviceData& data = GetData(device);
841 data.driver.DestroyDevice(device, pAllocator);
842
843 VkAllocationCallbacks local_allocator;
844 if (!pAllocator) {
845 local_allocator = data.allocator;
846 pAllocator = &local_allocator;
847 }
848
849 FreeDeviceData(&data, *pAllocator);
850}
851
Chia-I Wuff4a6c72016-03-24 16:05:56 +0800852VkResult EnumeratePhysicalDevices(VkInstance instance,
853 uint32_t* pPhysicalDeviceCount,
854 VkPhysicalDevice* pPhysicalDevices) {
855 const auto& data = GetData(instance);
856
857 VkResult result = data.driver.EnumeratePhysicalDevices(
858 instance, pPhysicalDeviceCount, pPhysicalDevices);
859 if ((result == VK_SUCCESS || result == VK_INCOMPLETE) && pPhysicalDevices) {
860 for (uint32_t i = 0; i < *pPhysicalDeviceCount; i++)
861 SetData(pPhysicalDevices[i], data);
862 }
863
864 return result;
865}
866
Chia-I Wuba0be412016-03-24 16:24:40 +0800867void GetDeviceQueue(VkDevice device,
868 uint32_t queueFamilyIndex,
869 uint32_t queueIndex,
870 VkQueue* pQueue) {
871 const auto& data = GetData(device);
872
873 data.driver.GetDeviceQueue(device, queueFamilyIndex, queueIndex, pQueue);
874 SetData(*pQueue, data);
875}
876
Chia-I Wu6a58a8a2016-03-24 16:29:51 +0800877VKAPI_ATTR VkResult
878AllocateCommandBuffers(VkDevice device,
879 const VkCommandBufferAllocateInfo* pAllocateInfo,
880 VkCommandBuffer* pCommandBuffers) {
881 const auto& data = GetData(device);
882
883 VkResult result = data.driver.AllocateCommandBuffers(device, pAllocateInfo,
884 pCommandBuffers);
885 if (result == VK_SUCCESS) {
886 for (uint32_t i = 0; i < pAllocateInfo->commandBufferCount; i++)
887 SetData(pCommandBuffers[i], data);
888 }
889
890 return result;
891}
892
Chia-I Wu9d518162016-03-24 14:55:27 +0800893} // namespace driver
894} // namespace vulkan