blob: 741a0ce15ce36906621a59cb22312dbb95dfc334 [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>
Jesse Hallafd02882016-12-14 16:54:06 -080021#include <dlfcn.h>
Chia-I Wu4901db72016-03-24 16:38:58 +080022#include <new>
Chia-I Wudbb7e9c2016-03-24 15:09:38 +080023#include <malloc.h>
Chia-I Wu9d518162016-03-24 14:55:27 +080024#include <sys/prctl.h>
25
Jesse Hallafd02882016-12-14 16:54:06 -080026#include <android/dlext.h>
27#include <cutils/properties.h>
28#include <gui/GraphicsEnv.h>
29
Chia-I Wu9d518162016-03-24 14:55:27 +080030#include "driver.h"
Jesse Hallb7c4e3b2016-04-11 13:51:38 -070031#include "stubhal.h"
Chia-I Wu9d518162016-03-24 14:55:27 +080032
Chia-I Wudbb7e9c2016-03-24 15:09:38 +080033// #define ENABLE_ALLOC_CALLSTACKS 1
34#if ENABLE_ALLOC_CALLSTACKS
35#include <utils/CallStack.h>
36#define ALOGD_CALLSTACK(...) \
37 do { \
38 ALOGD(__VA_ARGS__); \
39 android::CallStack callstack; \
40 callstack.update(); \
41 callstack.log(LOG_TAG, ANDROID_LOG_DEBUG, " "); \
42 } while (false)
43#else
44#define ALOGD_CALLSTACK(...) \
45 do { \
46 } while (false)
47#endif
48
Chia-I Wu9d518162016-03-24 14:55:27 +080049namespace vulkan {
50namespace driver {
51
Chia-I Wu136b8eb2016-03-24 15:01:52 +080052namespace {
53
Chia-I Wu31b2e4f2016-05-23 10:47:57 +080054class Hal {
55 public:
56 static bool Open();
57
58 static const Hal& Get() { return hal_; }
59 static const hwvulkan_device_t& Device() { return *Get().dev_; }
60
Chia-I Wu31938252016-05-23 15:31:02 +080061 int GetDebugReportIndex() const { return debug_report_index_; }
62
Chia-I Wu31b2e4f2016-05-23 10:47:57 +080063 private:
Chia-I Wu31938252016-05-23 15:31:02 +080064 Hal() : dev_(nullptr), debug_report_index_(-1) {}
Chia-I Wu31b2e4f2016-05-23 10:47:57 +080065 Hal(const Hal&) = delete;
66 Hal& operator=(const Hal&) = delete;
67
Chia-I Wu31938252016-05-23 15:31:02 +080068 bool InitDebugReportIndex();
69
Chia-I Wu31b2e4f2016-05-23 10:47:57 +080070 static Hal hal_;
71
72 const hwvulkan_device_t* dev_;
Chia-I Wu31938252016-05-23 15:31:02 +080073 int debug_report_index_;
Chia-I Wu31b2e4f2016-05-23 10:47:57 +080074};
75
Chia-I Wu4901db72016-03-24 16:38:58 +080076class CreateInfoWrapper {
77 public:
Chia-I Wu31b2e4f2016-05-23 10:47:57 +080078 CreateInfoWrapper(const VkInstanceCreateInfo& create_info,
Chia-I Wuff4a6c72016-03-24 16:05:56 +080079 const VkAllocationCallbacks& allocator);
Chia-I Wu4901db72016-03-24 16:38:58 +080080 CreateInfoWrapper(VkPhysicalDevice physical_dev,
81 const VkDeviceCreateInfo& create_info,
82 const VkAllocationCallbacks& allocator);
83 ~CreateInfoWrapper();
84
Chia-I Wu3e6c2d62016-04-11 13:55:56 +080085 VkResult Validate();
Chia-I Wu4901db72016-03-24 16:38:58 +080086
Chia-I Wu3e6c2d62016-04-11 13:55:56 +080087 const std::bitset<ProcHook::EXTENSION_COUNT>& GetHookExtensions() const;
88 const std::bitset<ProcHook::EXTENSION_COUNT>& GetHalExtensions() const;
Chia-I Wu4901db72016-03-24 16:38:58 +080089
Chia-I Wuff4a6c72016-03-24 16:05:56 +080090 explicit operator const VkInstanceCreateInfo*() const;
Chia-I Wu4901db72016-03-24 16:38:58 +080091 explicit operator const VkDeviceCreateInfo*() const;
92
93 private:
94 struct ExtensionFilter {
95 VkExtensionProperties* exts;
96 uint32_t ext_count;
97
98 const char** names;
99 uint32_t name_count;
100 };
101
Chia-I Wu3e6c2d62016-04-11 13:55:56 +0800102 VkResult SanitizePNext();
Chia-I Wu4901db72016-03-24 16:38:58 +0800103
Chia-I Wu3e6c2d62016-04-11 13:55:56 +0800104 VkResult SanitizeLayers();
105 VkResult SanitizeExtensions();
Chia-I Wu4901db72016-03-24 16:38:58 +0800106
Chia-I Wu3e6c2d62016-04-11 13:55:56 +0800107 VkResult QueryExtensionCount(uint32_t& count) const;
108 VkResult EnumerateExtensions(uint32_t& count,
109 VkExtensionProperties* props) const;
110 VkResult InitExtensionFilter();
111 void FilterExtension(const char* name);
Chia-I Wu4901db72016-03-24 16:38:58 +0800112
113 const bool is_instance_;
114 const VkAllocationCallbacks& allocator_;
115
Chia-I Wu31b2e4f2016-05-23 10:47:57 +0800116 VkPhysicalDevice physical_dev_;
Chia-I Wu4901db72016-03-24 16:38:58 +0800117
118 union {
119 VkInstanceCreateInfo instance_info_;
120 VkDeviceCreateInfo dev_info_;
121 };
122
123 ExtensionFilter extension_filter_;
124
125 std::bitset<ProcHook::EXTENSION_COUNT> hook_extensions_;
126 std::bitset<ProcHook::EXTENSION_COUNT> hal_extensions_;
127};
128
Chia-I Wu31b2e4f2016-05-23 10:47:57 +0800129Hal Hal::hal_;
130
Jesse Hallafd02882016-12-14 16:54:06 -0800131void* LoadLibrary(const android_dlextinfo& dlextinfo,
132 const char* subname,
133 int subname_len) {
134 const char kLibFormat[] = "vulkan.%*s.so";
135 char* name = static_cast<char*>(
136 alloca(sizeof(kLibFormat) + static_cast<size_t>(subname_len)));
137 sprintf(name, kLibFormat, subname_len, subname);
138 return android_dlopen_ext(name, RTLD_LOCAL | RTLD_NOW, &dlextinfo);
139}
140
141const std::array<const char*, 2> HAL_SUBNAME_KEY_PROPERTIES = {{
142 "ro.hardware." HWVULKAN_HARDWARE_MODULE_ID,
143 "ro.board.platform",
144}};
145
146int LoadUpdatedDriver(const hw_module_t** module) {
147 const android_dlextinfo dlextinfo = {
148 .flags = ANDROID_DLEXT_USE_NAMESPACE,
149 .library_namespace = android::GraphicsEnv::getInstance().getDriverNamespace(),
150 };
151 if (!dlextinfo.library_namespace)
152 return -ENOENT;
153
154 void* so = nullptr;
155 char prop[PROPERTY_VALUE_MAX];
156 for (auto key : HAL_SUBNAME_KEY_PROPERTIES) {
157 int prop_len = property_get(key, prop, nullptr);
158 if (prop_len > 0) {
159 so = LoadLibrary(dlextinfo, prop, prop_len);
160 if (so)
161 break;
162 }
163 }
164 if (!so)
165 return -ENOENT;
166
167 hw_module_t* hmi = static_cast<hw_module_t*>(dlsym(so, HAL_MODULE_INFO_SYM_AS_STR));
168 if (!hmi) {
169 ALOGE("couldn't find symbol '%s' in HAL library: %s", HAL_MODULE_INFO_SYM_AS_STR, dlerror());
170 dlclose(so);
171 return -EINVAL;
172 }
173 if (strcmp(hmi->id, HWVULKAN_HARDWARE_MODULE_ID) != 0) {
174 ALOGE("HAL id '%s' != '%s'", hmi->id, HWVULKAN_HARDWARE_MODULE_ID);
175 dlclose(so);
176 return -EINVAL;
177 }
178 hmi->dso = so;
179 *module = hmi;
180 ALOGD("loaded updated driver");
181 return 0;
182}
183
Chia-I Wu31b2e4f2016-05-23 10:47:57 +0800184bool Hal::Open() {
Jesse Halldc225072016-05-30 22:40:14 -0700185 ALOG_ASSERT(!hal_.dev_, "OpenHAL called more than once");
Chia-I Wu31b2e4f2016-05-23 10:47:57 +0800186
187 // Use a stub device unless we successfully open a real HAL device.
188 hal_.dev_ = &stubhal::kDevice;
189
Jesse Hallafd02882016-12-14 16:54:06 -0800190 int result;
191 const hwvulkan_module_t* module = nullptr;
192
193 result = LoadUpdatedDriver(reinterpret_cast<const hw_module_t**>(&module));
194 if (result == -ENOENT) {
195 result = hw_get_module(HWVULKAN_HARDWARE_MODULE_ID, reinterpret_cast<const hw_module_t**>(&module));
196 }
Chia-I Wu31b2e4f2016-05-23 10:47:57 +0800197 if (result != 0) {
Jesse Hallafd02882016-12-14 16:54:06 -0800198 ALOGV("unable to load Vulkan HAL, using stub HAL (result=%d)", result);
Chia-I Wu31b2e4f2016-05-23 10:47:57 +0800199 return true;
200 }
201
202 hwvulkan_device_t* device;
203 result =
204 module->common.methods->open(&module->common, HWVULKAN_DEVICE_0,
205 reinterpret_cast<hw_device_t**>(&device));
206 if (result != 0) {
207 // Any device with a Vulkan HAL should be able to open the device.
208 ALOGE("failed to open Vulkan HAL device: %s (%d)", strerror(-result),
209 result);
210 return false;
211 }
212
213 hal_.dev_ = device;
214
Chia-I Wu31938252016-05-23 15:31:02 +0800215 hal_.InitDebugReportIndex();
216
217 return true;
218}
219
220bool Hal::InitDebugReportIndex() {
221 uint32_t count;
222 if (dev_->EnumerateInstanceExtensionProperties(nullptr, &count, nullptr) !=
223 VK_SUCCESS) {
224 ALOGE("failed to get HAL instance extension count");
225 return false;
226 }
227
228 VkExtensionProperties* exts = reinterpret_cast<VkExtensionProperties*>(
229 malloc(sizeof(VkExtensionProperties) * count));
230 if (!exts) {
231 ALOGE("failed to allocate HAL instance extension array");
232 return false;
233 }
234
235 if (dev_->EnumerateInstanceExtensionProperties(nullptr, &count, exts) !=
236 VK_SUCCESS) {
237 ALOGE("failed to enumerate HAL instance extensions");
238 free(exts);
239 return false;
240 }
241
242 for (uint32_t i = 0; i < count; i++) {
243 if (strcmp(exts[i].extensionName, VK_EXT_DEBUG_REPORT_EXTENSION_NAME) ==
244 0) {
245 debug_report_index_ = static_cast<int>(i);
246 break;
247 }
248 }
249
250 free(exts);
251
Chia-I Wu31b2e4f2016-05-23 10:47:57 +0800252 return true;
253}
254
255CreateInfoWrapper::CreateInfoWrapper(const VkInstanceCreateInfo& create_info,
Chia-I Wuff4a6c72016-03-24 16:05:56 +0800256 const VkAllocationCallbacks& allocator)
257 : is_instance_(true),
258 allocator_(allocator),
Chia-I Wu31b2e4f2016-05-23 10:47:57 +0800259 physical_dev_(VK_NULL_HANDLE),
Chia-I Wuff4a6c72016-03-24 16:05:56 +0800260 instance_info_(create_info),
261 extension_filter_() {
262 hook_extensions_.set(ProcHook::EXTENSION_CORE);
263 hal_extensions_.set(ProcHook::EXTENSION_CORE);
264}
265
Chia-I Wu4901db72016-03-24 16:38:58 +0800266CreateInfoWrapper::CreateInfoWrapper(VkPhysicalDevice physical_dev,
267 const VkDeviceCreateInfo& create_info,
268 const VkAllocationCallbacks& allocator)
269 : is_instance_(false),
270 allocator_(allocator),
271 physical_dev_(physical_dev),
272 dev_info_(create_info),
273 extension_filter_() {
274 hook_extensions_.set(ProcHook::EXTENSION_CORE);
275 hal_extensions_.set(ProcHook::EXTENSION_CORE);
276}
277
278CreateInfoWrapper::~CreateInfoWrapper() {
279 allocator_.pfnFree(allocator_.pUserData, extension_filter_.exts);
280 allocator_.pfnFree(allocator_.pUserData, extension_filter_.names);
281}
282
Chia-I Wu3e6c2d62016-04-11 13:55:56 +0800283VkResult CreateInfoWrapper::Validate() {
284 VkResult result = SanitizePNext();
Chia-I Wu4901db72016-03-24 16:38:58 +0800285 if (result == VK_SUCCESS)
Chia-I Wu3e6c2d62016-04-11 13:55:56 +0800286 result = SanitizeLayers();
Chia-I Wu4901db72016-03-24 16:38:58 +0800287 if (result == VK_SUCCESS)
Chia-I Wu3e6c2d62016-04-11 13:55:56 +0800288 result = SanitizeExtensions();
Chia-I Wu4901db72016-03-24 16:38:58 +0800289
290 return result;
291}
292
293const std::bitset<ProcHook::EXTENSION_COUNT>&
Chia-I Wu3e6c2d62016-04-11 13:55:56 +0800294CreateInfoWrapper::GetHookExtensions() const {
Chia-I Wu4901db72016-03-24 16:38:58 +0800295 return hook_extensions_;
296}
297
298const std::bitset<ProcHook::EXTENSION_COUNT>&
Chia-I Wu3e6c2d62016-04-11 13:55:56 +0800299CreateInfoWrapper::GetHalExtensions() const {
Chia-I Wu4901db72016-03-24 16:38:58 +0800300 return hal_extensions_;
301}
302
Chia-I Wuff4a6c72016-03-24 16:05:56 +0800303CreateInfoWrapper::operator const VkInstanceCreateInfo*() const {
304 return &instance_info_;
305}
306
Chia-I Wu4901db72016-03-24 16:38:58 +0800307CreateInfoWrapper::operator const VkDeviceCreateInfo*() const {
308 return &dev_info_;
309}
310
Chia-I Wu3e6c2d62016-04-11 13:55:56 +0800311VkResult CreateInfoWrapper::SanitizePNext() {
Chia-I Wu4901db72016-03-24 16:38:58 +0800312 const struct StructHeader {
313 VkStructureType type;
314 const void* next;
315 } * header;
316
317 if (is_instance_) {
318 header = reinterpret_cast<const StructHeader*>(instance_info_.pNext);
319
320 // skip leading VK_STRUCTURE_TYPE_LOADER_INSTANCE_CREATE_INFOs
321 while (header &&
322 header->type == VK_STRUCTURE_TYPE_LOADER_INSTANCE_CREATE_INFO)
323 header = reinterpret_cast<const StructHeader*>(header->next);
324
325 instance_info_.pNext = header;
326 } else {
327 header = reinterpret_cast<const StructHeader*>(dev_info_.pNext);
328
329 // skip leading VK_STRUCTURE_TYPE_LOADER_DEVICE_CREATE_INFOs
330 while (header &&
331 header->type == VK_STRUCTURE_TYPE_LOADER_DEVICE_CREATE_INFO)
332 header = reinterpret_cast<const StructHeader*>(header->next);
333
334 dev_info_.pNext = header;
335 }
336
337 return VK_SUCCESS;
338}
339
Chia-I Wu3e6c2d62016-04-11 13:55:56 +0800340VkResult CreateInfoWrapper::SanitizeLayers() {
Chia-I Wu4901db72016-03-24 16:38:58 +0800341 auto& layer_names = (is_instance_) ? instance_info_.ppEnabledLayerNames
342 : dev_info_.ppEnabledLayerNames;
343 auto& layer_count = (is_instance_) ? instance_info_.enabledLayerCount
344 : dev_info_.enabledLayerCount;
345
346 // remove all layers
347 layer_names = nullptr;
348 layer_count = 0;
349
350 return VK_SUCCESS;
351}
352
Chia-I Wu3e6c2d62016-04-11 13:55:56 +0800353VkResult CreateInfoWrapper::SanitizeExtensions() {
Chia-I Wu4901db72016-03-24 16:38:58 +0800354 auto& ext_names = (is_instance_) ? instance_info_.ppEnabledExtensionNames
355 : dev_info_.ppEnabledExtensionNames;
356 auto& ext_count = (is_instance_) ? instance_info_.enabledExtensionCount
357 : dev_info_.enabledExtensionCount;
358 if (!ext_count)
359 return VK_SUCCESS;
360
Chia-I Wu3e6c2d62016-04-11 13:55:56 +0800361 VkResult result = InitExtensionFilter();
Chia-I Wu4901db72016-03-24 16:38:58 +0800362 if (result != VK_SUCCESS)
363 return result;
364
365 for (uint32_t i = 0; i < ext_count; i++)
Chia-I Wu3e6c2d62016-04-11 13:55:56 +0800366 FilterExtension(ext_names[i]);
Chia-I Wu4901db72016-03-24 16:38:58 +0800367
368 ext_names = extension_filter_.names;
369 ext_count = extension_filter_.name_count;
370
371 return VK_SUCCESS;
372}
373
Chia-I Wu3e6c2d62016-04-11 13:55:56 +0800374VkResult CreateInfoWrapper::QueryExtensionCount(uint32_t& count) const {
Chia-I Wu4901db72016-03-24 16:38:58 +0800375 if (is_instance_) {
Chia-I Wu31b2e4f2016-05-23 10:47:57 +0800376 return Hal::Device().EnumerateInstanceExtensionProperties(
377 nullptr, &count, nullptr);
Chia-I Wu4901db72016-03-24 16:38:58 +0800378 } else {
379 const auto& driver = GetData(physical_dev_).driver;
380 return driver.EnumerateDeviceExtensionProperties(physical_dev_, nullptr,
381 &count, nullptr);
382 }
383}
384
Chia-I Wu3e6c2d62016-04-11 13:55:56 +0800385VkResult CreateInfoWrapper::EnumerateExtensions(
Chia-I Wu4901db72016-03-24 16:38:58 +0800386 uint32_t& count,
387 VkExtensionProperties* props) const {
388 if (is_instance_) {
Chia-I Wu31b2e4f2016-05-23 10:47:57 +0800389 return Hal::Device().EnumerateInstanceExtensionProperties(
390 nullptr, &count, props);
Chia-I Wu4901db72016-03-24 16:38:58 +0800391 } else {
392 const auto& driver = GetData(physical_dev_).driver;
393 return driver.EnumerateDeviceExtensionProperties(physical_dev_, nullptr,
394 &count, props);
395 }
396}
397
Chia-I Wu3e6c2d62016-04-11 13:55:56 +0800398VkResult CreateInfoWrapper::InitExtensionFilter() {
Chia-I Wu4901db72016-03-24 16:38:58 +0800399 // query extension count
400 uint32_t count;
Chia-I Wu3e6c2d62016-04-11 13:55:56 +0800401 VkResult result = QueryExtensionCount(count);
Chia-I Wu4901db72016-03-24 16:38:58 +0800402 if (result != VK_SUCCESS || count == 0)
403 return result;
404
405 auto& filter = extension_filter_;
406 filter.exts =
407 reinterpret_cast<VkExtensionProperties*>(allocator_.pfnAllocation(
408 allocator_.pUserData, sizeof(VkExtensionProperties) * count,
409 alignof(VkExtensionProperties),
410 VK_SYSTEM_ALLOCATION_SCOPE_COMMAND));
411 if (!filter.exts)
412 return VK_ERROR_OUT_OF_HOST_MEMORY;
413
414 // enumerate extensions
Chia-I Wu3e6c2d62016-04-11 13:55:56 +0800415 result = EnumerateExtensions(count, filter.exts);
Chia-I Wu4901db72016-03-24 16:38:58 +0800416 if (result != VK_SUCCESS && result != VK_INCOMPLETE)
417 return result;
418
419 if (!count)
420 return VK_SUCCESS;
421
422 filter.ext_count = count;
423
424 // allocate name array
425 uint32_t enabled_ext_count = (is_instance_)
426 ? instance_info_.enabledExtensionCount
427 : dev_info_.enabledExtensionCount;
428 count = std::min(filter.ext_count, enabled_ext_count);
429 filter.names = reinterpret_cast<const char**>(allocator_.pfnAllocation(
430 allocator_.pUserData, sizeof(const char*) * count, alignof(const char*),
431 VK_SYSTEM_ALLOCATION_SCOPE_COMMAND));
432 if (!filter.names)
433 return VK_ERROR_OUT_OF_HOST_MEMORY;
434
435 return VK_SUCCESS;
436}
437
Chia-I Wu3e6c2d62016-04-11 13:55:56 +0800438void CreateInfoWrapper::FilterExtension(const char* name) {
Chia-I Wu4901db72016-03-24 16:38:58 +0800439 auto& filter = extension_filter_;
440
441 ProcHook::Extension ext_bit = GetProcHookExtension(name);
442 if (is_instance_) {
443 switch (ext_bit) {
444 case ProcHook::KHR_android_surface:
445 case ProcHook::KHR_surface:
446 hook_extensions_.set(ext_bit);
447 // return now as these extensions do not require HAL support
448 return;
449 case ProcHook::EXT_debug_report:
450 // both we and HAL can take part in
451 hook_extensions_.set(ext_bit);
452 break;
453 case ProcHook::EXTENSION_UNKNOWN:
454 // HAL's extensions
455 break;
456 default:
457 ALOGW("Ignored invalid instance extension %s", name);
458 return;
459 }
460 } else {
461 switch (ext_bit) {
462 case ProcHook::KHR_swapchain:
463 // map VK_KHR_swapchain to VK_ANDROID_native_buffer
464 name = VK_ANDROID_NATIVE_BUFFER_EXTENSION_NAME;
465 ext_bit = ProcHook::ANDROID_native_buffer;
466 break;
467 case ProcHook::EXTENSION_UNKNOWN:
468 // HAL's extensions
469 break;
470 default:
471 ALOGW("Ignored invalid device extension %s", name);
472 return;
473 }
474 }
475
476 for (uint32_t i = 0; i < filter.ext_count; i++) {
477 const VkExtensionProperties& props = filter.exts[i];
478 // ignore unknown extensions
479 if (strcmp(name, props.extensionName) != 0)
480 continue;
481
Chia-I Wu4901db72016-03-24 16:38:58 +0800482 filter.names[filter.name_count++] = name;
Chia-I Wu1600e262016-04-12 09:40:06 +0800483 if (ext_bit != ProcHook::EXTENSION_UNKNOWN) {
484 if (ext_bit == ProcHook::ANDROID_native_buffer)
485 hook_extensions_.set(ProcHook::KHR_swapchain);
486
487 hal_extensions_.set(ext_bit);
488 }
Chia-I Wu4901db72016-03-24 16:38:58 +0800489
490 break;
491 }
492}
493
Chia-I Wudbb7e9c2016-03-24 15:09:38 +0800494VKAPI_ATTR void* DefaultAllocate(void*,
495 size_t size,
496 size_t alignment,
497 VkSystemAllocationScope) {
498 void* ptr = nullptr;
499 // Vulkan requires 'alignment' to be a power of two, but posix_memalign
500 // additionally requires that it be at least sizeof(void*).
501 int ret = posix_memalign(&ptr, std::max(alignment, sizeof(void*)), size);
502 ALOGD_CALLSTACK("Allocate: size=%zu align=%zu => (%d) %p", size, alignment,
503 ret, ptr);
504 return ret == 0 ? ptr : nullptr;
505}
506
507VKAPI_ATTR void* DefaultReallocate(void*,
508 void* ptr,
509 size_t size,
510 size_t alignment,
511 VkSystemAllocationScope) {
512 if (size == 0) {
513 free(ptr);
514 return nullptr;
515 }
516
517 // TODO(jessehall): Right now we never shrink allocations; if the new
518 // request is smaller than the existing chunk, we just continue using it.
519 // Right now the loader never reallocs, so this doesn't matter. If that
520 // changes, or if this code is copied into some other project, this should
521 // probably have a heuristic to allocate-copy-free when doing so will save
522 // "enough" space.
523 size_t old_size = ptr ? malloc_usable_size(ptr) : 0;
524 if (size <= old_size)
525 return ptr;
526
527 void* new_ptr = nullptr;
528 if (posix_memalign(&new_ptr, std::max(alignment, sizeof(void*)), size) != 0)
529 return nullptr;
530 if (ptr) {
531 memcpy(new_ptr, ptr, std::min(old_size, size));
532 free(ptr);
533 }
534 return new_ptr;
535}
536
537VKAPI_ATTR void DefaultFree(void*, void* ptr) {
538 ALOGD_CALLSTACK("Free: %p", ptr);
539 free(ptr);
540}
541
Chia-I Wuff4a6c72016-03-24 16:05:56 +0800542InstanceData* AllocateInstanceData(const VkAllocationCallbacks& allocator) {
543 void* data_mem = allocator.pfnAllocation(
544 allocator.pUserData, sizeof(InstanceData), alignof(InstanceData),
545 VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
546 if (!data_mem)
547 return nullptr;
548
549 return new (data_mem) InstanceData(allocator);
550}
551
552void FreeInstanceData(InstanceData* data,
553 const VkAllocationCallbacks& allocator) {
554 data->~InstanceData();
555 allocator.pfnFree(allocator.pUserData, data);
556}
557
Chia-I Wu950d6e12016-05-03 09:12:35 +0800558DeviceData* AllocateDeviceData(
559 const VkAllocationCallbacks& allocator,
560 const DebugReportCallbackList& debug_report_callbacks) {
Chia-I Wu4901db72016-03-24 16:38:58 +0800561 void* data_mem = allocator.pfnAllocation(
562 allocator.pUserData, sizeof(DeviceData), alignof(DeviceData),
563 VK_SYSTEM_ALLOCATION_SCOPE_DEVICE);
564 if (!data_mem)
565 return nullptr;
566
Chia-I Wu950d6e12016-05-03 09:12:35 +0800567 return new (data_mem) DeviceData(allocator, debug_report_callbacks);
Chia-I Wu4901db72016-03-24 16:38:58 +0800568}
569
570void FreeDeviceData(DeviceData* data, const VkAllocationCallbacks& allocator) {
571 data->~DeviceData();
572 allocator.pfnFree(allocator.pUserData, data);
573}
574
Chia-I Wu136b8eb2016-03-24 15:01:52 +0800575} // anonymous namespace
576
Chia-I Wu9d518162016-03-24 14:55:27 +0800577bool Debuggable() {
578 return (prctl(PR_GET_DUMPABLE, 0, 0, 0, 0) >= 0);
579}
580
Chia-I Wu136b8eb2016-03-24 15:01:52 +0800581bool OpenHAL() {
Chia-I Wu31b2e4f2016-05-23 10:47:57 +0800582 return Hal::Open();
Chia-I Wu136b8eb2016-03-24 15:01:52 +0800583}
584
Chia-I Wudbb7e9c2016-03-24 15:09:38 +0800585const VkAllocationCallbacks& GetDefaultAllocator() {
586 static const VkAllocationCallbacks kDefaultAllocCallbacks = {
587 .pUserData = nullptr,
588 .pfnAllocation = DefaultAllocate,
589 .pfnReallocation = DefaultReallocate,
590 .pfnFree = DefaultFree,
591 };
592
593 return kDefaultAllocCallbacks;
594}
595
Chia-I Wueb7db122016-03-24 09:11:06 +0800596PFN_vkVoidFunction GetInstanceProcAddr(VkInstance instance, const char* pName) {
597 const ProcHook* hook = GetProcHook(pName);
598 if (!hook)
Chia-I Wu31b2e4f2016-05-23 10:47:57 +0800599 return Hal::Device().GetInstanceProcAddr(instance, pName);
Chia-I Wueb7db122016-03-24 09:11:06 +0800600
601 if (!instance) {
602 if (hook->type == ProcHook::GLOBAL)
603 return hook->proc;
604
Chia-I Wu109f8982016-04-22 06:40:40 +0800605 // v0 layers expect
606 //
607 // vkGetInstanceProcAddr(VK_NULL_HANDLE, "vkCreateDevice");
608 //
609 // to work.
610 if (strcmp(pName, "vkCreateDevice") == 0)
611 return hook->proc;
612
Chia-I Wueb7db122016-03-24 09:11:06 +0800613 ALOGE(
Chia-I Wue201c3f2016-05-03 13:26:08 +0800614 "internal vkGetInstanceProcAddr called for %s without an instance",
Chia-I Wueb7db122016-03-24 09:11:06 +0800615 pName);
616
Chia-I Wu109f8982016-04-22 06:40:40 +0800617 return nullptr;
Chia-I Wueb7db122016-03-24 09:11:06 +0800618 }
619
620 PFN_vkVoidFunction proc;
621
622 switch (hook->type) {
623 case ProcHook::INSTANCE:
624 proc = (GetData(instance).hook_extensions[hook->extension])
625 ? hook->proc
Chia-I Wu36cc00a2016-04-13 16:52:06 +0800626 : nullptr;
Chia-I Wueb7db122016-03-24 09:11:06 +0800627 break;
628 case ProcHook::DEVICE:
629 proc = (hook->extension == ProcHook::EXTENSION_CORE)
630 ? hook->proc
631 : hook->checked_proc;
632 break;
633 default:
634 ALOGE(
Chia-I Wue201c3f2016-05-03 13:26:08 +0800635 "internal vkGetInstanceProcAddr called for %s with an instance",
Chia-I Wueb7db122016-03-24 09:11:06 +0800636 pName);
637 proc = nullptr;
638 break;
639 }
640
641 return proc;
642}
643
644PFN_vkVoidFunction GetDeviceProcAddr(VkDevice device, const char* pName) {
645 const ProcHook* hook = GetProcHook(pName);
646 if (!hook)
Chia-I Wucc5e2762016-03-24 13:01:16 +0800647 return GetData(device).driver.GetDeviceProcAddr(device, pName);
Chia-I Wueb7db122016-03-24 09:11:06 +0800648
649 if (hook->type != ProcHook::DEVICE) {
Chia-I Wue201c3f2016-05-03 13:26:08 +0800650 ALOGE("internal vkGetDeviceProcAddr called for %s", pName);
Chia-I Wueb7db122016-03-24 09:11:06 +0800651 return nullptr;
652 }
653
Chia-I Wu36cc00a2016-04-13 16:52:06 +0800654 return (GetData(device).hook_extensions[hook->extension]) ? hook->proc
655 : nullptr;
Chia-I Wueb7db122016-03-24 09:11:06 +0800656}
657
Chia-I Wuff4a6c72016-03-24 16:05:56 +0800658VkResult EnumerateInstanceExtensionProperties(
659 const char* pLayerName,
660 uint32_t* pPropertyCount,
661 VkExtensionProperties* pProperties) {
662 static const std::array<VkExtensionProperties, 2> loader_extensions = {{
663 // WSI extensions
664 {VK_KHR_SURFACE_EXTENSION_NAME, VK_KHR_SURFACE_SPEC_VERSION},
665 {VK_KHR_ANDROID_SURFACE_EXTENSION_NAME,
666 VK_KHR_ANDROID_SURFACE_SPEC_VERSION},
667 }};
Chia-I Wu31938252016-05-23 15:31:02 +0800668 static const VkExtensionProperties loader_debug_report_extension = {
669 VK_EXT_DEBUG_REPORT_EXTENSION_NAME, VK_EXT_DEBUG_REPORT_SPEC_VERSION,
670 };
Chia-I Wuff4a6c72016-03-24 16:05:56 +0800671
672 // enumerate our extensions first
673 if (!pLayerName && pProperties) {
674 uint32_t count = std::min(
675 *pPropertyCount, static_cast<uint32_t>(loader_extensions.size()));
676
677 std::copy_n(loader_extensions.begin(), count, pProperties);
678
679 if (count < loader_extensions.size()) {
680 *pPropertyCount = count;
681 return VK_INCOMPLETE;
682 }
683
684 pProperties += count;
685 *pPropertyCount -= count;
Chia-I Wu31938252016-05-23 15:31:02 +0800686
687 if (Hal::Get().GetDebugReportIndex() < 0) {
688 if (!*pPropertyCount) {
689 *pPropertyCount = count;
690 return VK_INCOMPLETE;
691 }
692
693 pProperties[0] = loader_debug_report_extension;
694 pProperties += 1;
695 *pPropertyCount -= 1;
696 }
Chia-I Wuff4a6c72016-03-24 16:05:56 +0800697 }
698
Chia-I Wu31b2e4f2016-05-23 10:47:57 +0800699 VkResult result = Hal::Device().EnumerateInstanceExtensionProperties(
Chia-I Wuff4a6c72016-03-24 16:05:56 +0800700 pLayerName, pPropertyCount, pProperties);
701
Chia-I Wu31938252016-05-23 15:31:02 +0800702 if (!pLayerName && (result == VK_SUCCESS || result == VK_INCOMPLETE)) {
703 int idx = Hal::Get().GetDebugReportIndex();
704 if (idx < 0) {
705 *pPropertyCount += 1;
706 } else if (pProperties &&
707 static_cast<uint32_t>(idx) < *pPropertyCount) {
708 pProperties[idx].specVersion =
709 std::min(pProperties[idx].specVersion,
710 loader_debug_report_extension.specVersion);
711 }
712
Chia-I Wuff4a6c72016-03-24 16:05:56 +0800713 *pPropertyCount += loader_extensions.size();
Chia-I Wu31938252016-05-23 15:31:02 +0800714 }
Chia-I Wuff4a6c72016-03-24 16:05:56 +0800715
716 return result;
717}
718
Chia-I Wu01cf3052016-03-24 16:16:21 +0800719VkResult EnumerateDeviceExtensionProperties(
720 VkPhysicalDevice physicalDevice,
721 const char* pLayerName,
722 uint32_t* pPropertyCount,
723 VkExtensionProperties* pProperties) {
724 const InstanceData& data = GetData(physicalDevice);
725
726 VkResult result = data.driver.EnumerateDeviceExtensionProperties(
727 physicalDevice, pLayerName, pPropertyCount, pProperties);
728 if (result != VK_SUCCESS && result != VK_INCOMPLETE)
729 return result;
730
731 if (!pProperties)
732 return result;
733
734 // map VK_ANDROID_native_buffer to VK_KHR_swapchain
735 for (uint32_t i = 0; i < *pPropertyCount; i++) {
736 auto& prop = pProperties[i];
737
738 if (strcmp(prop.extensionName,
739 VK_ANDROID_NATIVE_BUFFER_EXTENSION_NAME) != 0)
740 continue;
741
742 memcpy(prop.extensionName, VK_KHR_SWAPCHAIN_EXTENSION_NAME,
743 sizeof(VK_KHR_SWAPCHAIN_EXTENSION_NAME));
744 prop.specVersion = VK_KHR_SWAPCHAIN_SPEC_VERSION;
745 }
746
747 return result;
748}
749
Chia-I Wuff4a6c72016-03-24 16:05:56 +0800750VkResult CreateInstance(const VkInstanceCreateInfo* pCreateInfo,
751 const VkAllocationCallbacks* pAllocator,
752 VkInstance* pInstance) {
753 const VkAllocationCallbacks& data_allocator =
754 (pAllocator) ? *pAllocator : GetDefaultAllocator();
755
Chia-I Wu31b2e4f2016-05-23 10:47:57 +0800756 CreateInfoWrapper wrapper(*pCreateInfo, data_allocator);
Chia-I Wu3e6c2d62016-04-11 13:55:56 +0800757 VkResult result = wrapper.Validate();
Chia-I Wuff4a6c72016-03-24 16:05:56 +0800758 if (result != VK_SUCCESS)
759 return result;
760
761 InstanceData* data = AllocateInstanceData(data_allocator);
762 if (!data)
763 return VK_ERROR_OUT_OF_HOST_MEMORY;
764
Chia-I Wu3e6c2d62016-04-11 13:55:56 +0800765 data->hook_extensions |= wrapper.GetHookExtensions();
Chia-I Wuff4a6c72016-03-24 16:05:56 +0800766
767 // call into the driver
768 VkInstance instance;
Chia-I Wu31b2e4f2016-05-23 10:47:57 +0800769 result = Hal::Device().CreateInstance(
Chia-I Wuff4a6c72016-03-24 16:05:56 +0800770 static_cast<const VkInstanceCreateInfo*>(wrapper), pAllocator,
771 &instance);
772 if (result != VK_SUCCESS) {
773 FreeInstanceData(data, data_allocator);
774 return result;
775 }
776
777 // initialize InstanceDriverTable
778 if (!SetData(instance, *data) ||
Chia-I Wu31b2e4f2016-05-23 10:47:57 +0800779 !InitDriverTable(instance, Hal::Device().GetInstanceProcAddr,
Chia-I Wucbe07ef2016-04-13 15:01:00 +0800780 wrapper.GetHalExtensions())) {
Chia-I Wuff4a6c72016-03-24 16:05:56 +0800781 data->driver.DestroyInstance = reinterpret_cast<PFN_vkDestroyInstance>(
Chia-I Wu31b2e4f2016-05-23 10:47:57 +0800782 Hal::Device().GetInstanceProcAddr(instance, "vkDestroyInstance"));
Chia-I Wuff4a6c72016-03-24 16:05:56 +0800783 if (data->driver.DestroyInstance)
784 data->driver.DestroyInstance(instance, pAllocator);
785
786 FreeInstanceData(data, data_allocator);
787
788 return VK_ERROR_INCOMPATIBLE_DRIVER;
789 }
790
791 data->get_device_proc_addr = reinterpret_cast<PFN_vkGetDeviceProcAddr>(
Chia-I Wu31b2e4f2016-05-23 10:47:57 +0800792 Hal::Device().GetInstanceProcAddr(instance, "vkGetDeviceProcAddr"));
Chia-I Wuff4a6c72016-03-24 16:05:56 +0800793 if (!data->get_device_proc_addr) {
794 data->driver.DestroyInstance(instance, pAllocator);
795 FreeInstanceData(data, data_allocator);
796
797 return VK_ERROR_INCOMPATIBLE_DRIVER;
798 }
799
800 *pInstance = instance;
801
802 return VK_SUCCESS;
803}
804
805void DestroyInstance(VkInstance instance,
806 const VkAllocationCallbacks* pAllocator) {
807 InstanceData& data = GetData(instance);
808 data.driver.DestroyInstance(instance, pAllocator);
809
810 VkAllocationCallbacks local_allocator;
811 if (!pAllocator) {
812 local_allocator = data.allocator;
813 pAllocator = &local_allocator;
814 }
815
816 FreeInstanceData(&data, *pAllocator);
817}
818
Chia-I Wu4901db72016-03-24 16:38:58 +0800819VkResult CreateDevice(VkPhysicalDevice physicalDevice,
820 const VkDeviceCreateInfo* pCreateInfo,
821 const VkAllocationCallbacks* pAllocator,
822 VkDevice* pDevice) {
823 const InstanceData& instance_data = GetData(physicalDevice);
824 const VkAllocationCallbacks& data_allocator =
825 (pAllocator) ? *pAllocator : instance_data.allocator;
826
827 CreateInfoWrapper wrapper(physicalDevice, *pCreateInfo, data_allocator);
Chia-I Wu3e6c2d62016-04-11 13:55:56 +0800828 VkResult result = wrapper.Validate();
Chia-I Wu4901db72016-03-24 16:38:58 +0800829 if (result != VK_SUCCESS)
830 return result;
831
Chia-I Wu950d6e12016-05-03 09:12:35 +0800832 DeviceData* data = AllocateDeviceData(data_allocator,
833 instance_data.debug_report_callbacks);
Chia-I Wu4901db72016-03-24 16:38:58 +0800834 if (!data)
835 return VK_ERROR_OUT_OF_HOST_MEMORY;
836
Chia-I Wu3e6c2d62016-04-11 13:55:56 +0800837 data->hook_extensions |= wrapper.GetHookExtensions();
Chia-I Wu4901db72016-03-24 16:38:58 +0800838
839 // call into the driver
840 VkDevice dev;
841 result = instance_data.driver.CreateDevice(
842 physicalDevice, static_cast<const VkDeviceCreateInfo*>(wrapper),
843 pAllocator, &dev);
844 if (result != VK_SUCCESS) {
845 FreeDeviceData(data, data_allocator);
846 return result;
847 }
848
849 // initialize DeviceDriverTable
850 if (!SetData(dev, *data) ||
Chia-I Wucbe07ef2016-04-13 15:01:00 +0800851 !InitDriverTable(dev, instance_data.get_device_proc_addr,
852 wrapper.GetHalExtensions())) {
Chia-I Wu4901db72016-03-24 16:38:58 +0800853 data->driver.DestroyDevice = reinterpret_cast<PFN_vkDestroyDevice>(
854 instance_data.get_device_proc_addr(dev, "vkDestroyDevice"));
855 if (data->driver.DestroyDevice)
856 data->driver.DestroyDevice(dev, pAllocator);
857
858 FreeDeviceData(data, data_allocator);
859
860 return VK_ERROR_INCOMPATIBLE_DRIVER;
861 }
Jesse Halldc225072016-05-30 22:40:14 -0700862 data->driver_device = dev;
Chia-I Wu4901db72016-03-24 16:38:58 +0800863
864 *pDevice = dev;
865
866 return VK_SUCCESS;
867}
868
869void DestroyDevice(VkDevice device, const VkAllocationCallbacks* pAllocator) {
870 DeviceData& data = GetData(device);
871 data.driver.DestroyDevice(device, pAllocator);
872
873 VkAllocationCallbacks local_allocator;
874 if (!pAllocator) {
875 local_allocator = data.allocator;
876 pAllocator = &local_allocator;
877 }
878
879 FreeDeviceData(&data, *pAllocator);
880}
881
Chia-I Wuff4a6c72016-03-24 16:05:56 +0800882VkResult EnumeratePhysicalDevices(VkInstance instance,
883 uint32_t* pPhysicalDeviceCount,
884 VkPhysicalDevice* pPhysicalDevices) {
885 const auto& data = GetData(instance);
886
887 VkResult result = data.driver.EnumeratePhysicalDevices(
888 instance, pPhysicalDeviceCount, pPhysicalDevices);
889 if ((result == VK_SUCCESS || result == VK_INCOMPLETE) && pPhysicalDevices) {
890 for (uint32_t i = 0; i < *pPhysicalDeviceCount; i++)
891 SetData(pPhysicalDevices[i], data);
892 }
893
894 return result;
895}
896
Chia-I Wuba0be412016-03-24 16:24:40 +0800897void GetDeviceQueue(VkDevice device,
898 uint32_t queueFamilyIndex,
899 uint32_t queueIndex,
900 VkQueue* pQueue) {
901 const auto& data = GetData(device);
902
903 data.driver.GetDeviceQueue(device, queueFamilyIndex, queueIndex, pQueue);
904 SetData(*pQueue, data);
905}
906
Chia-I Wu6a58a8a2016-03-24 16:29:51 +0800907VKAPI_ATTR VkResult
908AllocateCommandBuffers(VkDevice device,
909 const VkCommandBufferAllocateInfo* pAllocateInfo,
910 VkCommandBuffer* pCommandBuffers) {
911 const auto& data = GetData(device);
912
913 VkResult result = data.driver.AllocateCommandBuffers(device, pAllocateInfo,
914 pCommandBuffers);
915 if (result == VK_SUCCESS) {
916 for (uint32_t i = 0; i < pAllocateInfo->commandBufferCount; i++)
917 SetData(pCommandBuffers[i], data);
918 }
919
920 return result;
921}
922
Chia-I Wu9d518162016-03-24 14:55:27 +0800923} // namespace driver
924} // namespace vulkan