blob: 947a2f7bfe1c0c2ec5a6f8472f65dff4db78a2ec [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>
Jesse Hall53457db2016-12-14 16:54:06 -080024#include <dlfcn.h>
Chia-I Wu4901db72016-03-24 16:38:58 +080025#include <new>
Mark Salyzyn7823e122016-09-29 08:08:05 -070026
27#include <log/log.h>
Chia-I Wu9d518162016-03-24 14:55:27 +080028
Jesse Hall53457db2016-12-14 16:54:06 -080029#include <android/dlext.h>
30#include <cutils/properties.h>
Jiyong Park27c39e12017-05-08 13:00:02 +090031#include <graphicsenv/GraphicsEnv.h>
Chris Forbesfa25e632017-02-22 12:36:02 +130032#include <utils/Vector.h>
Jesse Hall53457db2016-12-14 16:54:06 -080033
Wei Wangf9b05ee2017-07-19 20:59:39 -070034#include "android-base/properties.h"
35
Chia-I Wu9d518162016-03-24 14:55:27 +080036#include "driver.h"
Jesse Hallb7c4e3b2016-04-11 13:51:38 -070037#include "stubhal.h"
Chia-I Wu9d518162016-03-24 14:55:27 +080038
Jesse Hall00e61ff2017-04-07 16:48:02 -070039// TODO(b/37049319) Get this from a header once one exists
40extern "C" {
41android_namespace_t* android_get_exported_namespace(const char*);
42}
43
Chia-I Wudbb7e9c2016-03-24 15:09:38 +080044// #define ENABLE_ALLOC_CALLSTACKS 1
45#if ENABLE_ALLOC_CALLSTACKS
46#include <utils/CallStack.h>
47#define ALOGD_CALLSTACK(...) \
48 do { \
49 ALOGD(__VA_ARGS__); \
50 android::CallStack callstack; \
51 callstack.update(); \
52 callstack.log(LOG_TAG, ANDROID_LOG_DEBUG, " "); \
53 } while (false)
54#else
55#define ALOGD_CALLSTACK(...) \
56 do { \
57 } while (false)
58#endif
59
Chia-I Wu9d518162016-03-24 14:55:27 +080060namespace vulkan {
61namespace driver {
62
Chia-I Wu136b8eb2016-03-24 15:01:52 +080063namespace {
64
Chia-I Wu31b2e4f2016-05-23 10:47:57 +080065class Hal {
66 public:
67 static bool Open();
68
69 static const Hal& Get() { return hal_; }
70 static const hwvulkan_device_t& Device() { return *Get().dev_; }
71
Chia-I Wu31938252016-05-23 15:31:02 +080072 int GetDebugReportIndex() const { return debug_report_index_; }
73
Chia-I Wu31b2e4f2016-05-23 10:47:57 +080074 private:
Chia-I Wu31938252016-05-23 15:31:02 +080075 Hal() : dev_(nullptr), debug_report_index_(-1) {}
Chia-I Wu31b2e4f2016-05-23 10:47:57 +080076 Hal(const Hal&) = delete;
77 Hal& operator=(const Hal&) = delete;
78
Chia-I Wu31938252016-05-23 15:31:02 +080079 bool InitDebugReportIndex();
80
Chia-I Wu31b2e4f2016-05-23 10:47:57 +080081 static Hal hal_;
82
83 const hwvulkan_device_t* dev_;
Chia-I Wu31938252016-05-23 15:31:02 +080084 int debug_report_index_;
Chia-I Wu31b2e4f2016-05-23 10:47:57 +080085};
86
Chia-I Wu4901db72016-03-24 16:38:58 +080087class CreateInfoWrapper {
88 public:
Chia-I Wu31b2e4f2016-05-23 10:47:57 +080089 CreateInfoWrapper(const VkInstanceCreateInfo& create_info,
Chia-I Wuff4a6c72016-03-24 16:05:56 +080090 const VkAllocationCallbacks& allocator);
Chia-I Wu4901db72016-03-24 16:38:58 +080091 CreateInfoWrapper(VkPhysicalDevice physical_dev,
92 const VkDeviceCreateInfo& create_info,
93 const VkAllocationCallbacks& allocator);
94 ~CreateInfoWrapper();
95
Chia-I Wu3e6c2d62016-04-11 13:55:56 +080096 VkResult Validate();
Chia-I Wu4901db72016-03-24 16:38:58 +080097
Chia-I Wu3e6c2d62016-04-11 13:55:56 +080098 const std::bitset<ProcHook::EXTENSION_COUNT>& GetHookExtensions() const;
99 const std::bitset<ProcHook::EXTENSION_COUNT>& GetHalExtensions() const;
Chia-I Wu4901db72016-03-24 16:38:58 +0800100
Chia-I Wuff4a6c72016-03-24 16:05:56 +0800101 explicit operator const VkInstanceCreateInfo*() const;
Chia-I Wu4901db72016-03-24 16:38:58 +0800102 explicit operator const VkDeviceCreateInfo*() const;
103
104 private:
105 struct ExtensionFilter {
106 VkExtensionProperties* exts;
107 uint32_t ext_count;
108
109 const char** names;
110 uint32_t name_count;
111 };
112
Chia-I Wu3e6c2d62016-04-11 13:55:56 +0800113 VkResult SanitizePNext();
Chia-I Wu4901db72016-03-24 16:38:58 +0800114
Chia-I Wu3e6c2d62016-04-11 13:55:56 +0800115 VkResult SanitizeLayers();
116 VkResult SanitizeExtensions();
Chia-I Wu4901db72016-03-24 16:38:58 +0800117
Chia-I Wu3e6c2d62016-04-11 13:55:56 +0800118 VkResult QueryExtensionCount(uint32_t& count) const;
119 VkResult EnumerateExtensions(uint32_t& count,
120 VkExtensionProperties* props) const;
121 VkResult InitExtensionFilter();
122 void FilterExtension(const char* name);
Chia-I Wu4901db72016-03-24 16:38:58 +0800123
124 const bool is_instance_;
125 const VkAllocationCallbacks& allocator_;
126
Chia-I Wu31b2e4f2016-05-23 10:47:57 +0800127 VkPhysicalDevice physical_dev_;
Chia-I Wu4901db72016-03-24 16:38:58 +0800128
129 union {
130 VkInstanceCreateInfo instance_info_;
131 VkDeviceCreateInfo dev_info_;
132 };
133
134 ExtensionFilter extension_filter_;
135
136 std::bitset<ProcHook::EXTENSION_COUNT> hook_extensions_;
137 std::bitset<ProcHook::EXTENSION_COUNT> hal_extensions_;
138};
139
Chia-I Wu31b2e4f2016-05-23 10:47:57 +0800140Hal Hal::hal_;
141
Jesse Hall53457db2016-12-14 16:54:06 -0800142void* LoadLibrary(const android_dlextinfo& dlextinfo,
143 const char* subname,
144 int subname_len) {
145 const char kLibFormat[] = "vulkan.%*s.so";
146 char* name = static_cast<char*>(
147 alloca(sizeof(kLibFormat) + static_cast<size_t>(subname_len)));
148 sprintf(name, kLibFormat, subname_len, subname);
149 return android_dlopen_ext(name, RTLD_LOCAL | RTLD_NOW, &dlextinfo);
150}
151
152const std::array<const char*, 2> HAL_SUBNAME_KEY_PROPERTIES = {{
153 "ro.hardware." HWVULKAN_HARDWARE_MODULE_ID,
154 "ro.board.platform",
155}};
156
Jesse Hall00e61ff2017-04-07 16:48:02 -0700157int LoadDriver(android_namespace_t* library_namespace,
158 const hwvulkan_module_t** module) {
Jesse Hall53457db2016-12-14 16:54:06 -0800159 const android_dlextinfo dlextinfo = {
160 .flags = ANDROID_DLEXT_USE_NAMESPACE,
Jesse Hall00e61ff2017-04-07 16:48:02 -0700161 .library_namespace = library_namespace,
Jesse Hall53457db2016-12-14 16:54:06 -0800162 };
Jesse Hall53457db2016-12-14 16:54:06 -0800163 void* so = nullptr;
164 char prop[PROPERTY_VALUE_MAX];
165 for (auto key : HAL_SUBNAME_KEY_PROPERTIES) {
166 int prop_len = property_get(key, prop, nullptr);
167 if (prop_len > 0) {
168 so = LoadLibrary(dlextinfo, prop, prop_len);
169 if (so)
170 break;
171 }
172 }
173 if (!so)
174 return -ENOENT;
175
Jesse Hall00e61ff2017-04-07 16:48:02 -0700176 auto hmi = static_cast<hw_module_t*>(dlsym(so, HAL_MODULE_INFO_SYM_AS_STR));
Jesse Hall53457db2016-12-14 16:54:06 -0800177 if (!hmi) {
178 ALOGE("couldn't find symbol '%s' in HAL library: %s", HAL_MODULE_INFO_SYM_AS_STR, dlerror());
179 dlclose(so);
180 return -EINVAL;
181 }
182 if (strcmp(hmi->id, HWVULKAN_HARDWARE_MODULE_ID) != 0) {
183 ALOGE("HAL id '%s' != '%s'", hmi->id, HWVULKAN_HARDWARE_MODULE_ID);
184 dlclose(so);
185 return -EINVAL;
186 }
187 hmi->dso = so;
Jesse Hall00e61ff2017-04-07 16:48:02 -0700188 *module = reinterpret_cast<const hwvulkan_module_t*>(hmi);
Jesse Hall53457db2016-12-14 16:54:06 -0800189 return 0;
190}
191
Jesse Hall00e61ff2017-04-07 16:48:02 -0700192int LoadBuiltinDriver(const hwvulkan_module_t** module) {
193 auto ns = android_get_exported_namespace("sphal");
194 if (!ns)
195 return -ENOENT;
196 return LoadDriver(ns, module);
197}
198
199int LoadUpdatedDriver(const hwvulkan_module_t** module) {
200 auto ns = android::GraphicsEnv::getInstance().getDriverNamespace();
201 if (!ns)
202 return -ENOENT;
203 return LoadDriver(ns, module);
204}
205
Chia-I Wu31b2e4f2016-05-23 10:47:57 +0800206bool Hal::Open() {
Jesse Halldc225072016-05-30 22:40:14 -0700207 ALOG_ASSERT(!hal_.dev_, "OpenHAL called more than once");
Chia-I Wu31b2e4f2016-05-23 10:47:57 +0800208
209 // Use a stub device unless we successfully open a real HAL device.
210 hal_.dev_ = &stubhal::kDevice;
211
Jesse Hall53457db2016-12-14 16:54:06 -0800212 int result;
213 const hwvulkan_module_t* module = nullptr;
214
Jesse Hall00e61ff2017-04-07 16:48:02 -0700215 result = LoadUpdatedDriver(&module);
Jesse Hall53457db2016-12-14 16:54:06 -0800216 if (result == -ENOENT) {
Jesse Hall00e61ff2017-04-07 16:48:02 -0700217 result = LoadBuiltinDriver(&module);
218 if (result != 0) {
219 // -ENOENT means the sphal namespace doesn't exist, not that there
220 // is a problem with the driver.
221 ALOGW_IF(
222 result != -ENOENT,
223 "Failed to load Vulkan driver into sphal namespace. This "
224 "usually means the driver has forbidden library dependencies."
225 "Please fix, this will soon stop working.");
226 result =
227 hw_get_module(HWVULKAN_HARDWARE_MODULE_ID,
228 reinterpret_cast<const hw_module_t**>(&module));
229 }
Jesse Hall53457db2016-12-14 16:54:06 -0800230 }
Chia-I Wu31b2e4f2016-05-23 10:47:57 +0800231 if (result != 0) {
Jesse Hall53457db2016-12-14 16:54:06 -0800232 ALOGV("unable to load Vulkan HAL, using stub HAL (result=%d)", result);
Chia-I Wu31b2e4f2016-05-23 10:47:57 +0800233 return true;
234 }
235
236 hwvulkan_device_t* device;
237 result =
238 module->common.methods->open(&module->common, HWVULKAN_DEVICE_0,
239 reinterpret_cast<hw_device_t**>(&device));
240 if (result != 0) {
241 // Any device with a Vulkan HAL should be able to open the device.
242 ALOGE("failed to open Vulkan HAL device: %s (%d)", strerror(-result),
243 result);
244 return false;
245 }
246
247 hal_.dev_ = device;
248
Chia-I Wu31938252016-05-23 15:31:02 +0800249 hal_.InitDebugReportIndex();
250
251 return true;
252}
253
254bool Hal::InitDebugReportIndex() {
255 uint32_t count;
256 if (dev_->EnumerateInstanceExtensionProperties(nullptr, &count, nullptr) !=
257 VK_SUCCESS) {
258 ALOGE("failed to get HAL instance extension count");
259 return false;
260 }
261
262 VkExtensionProperties* exts = reinterpret_cast<VkExtensionProperties*>(
263 malloc(sizeof(VkExtensionProperties) * count));
264 if (!exts) {
265 ALOGE("failed to allocate HAL instance extension array");
266 return false;
267 }
268
269 if (dev_->EnumerateInstanceExtensionProperties(nullptr, &count, exts) !=
270 VK_SUCCESS) {
271 ALOGE("failed to enumerate HAL instance extensions");
272 free(exts);
273 return false;
274 }
275
276 for (uint32_t i = 0; i < count; i++) {
277 if (strcmp(exts[i].extensionName, VK_EXT_DEBUG_REPORT_EXTENSION_NAME) ==
278 0) {
279 debug_report_index_ = static_cast<int>(i);
280 break;
281 }
282 }
283
284 free(exts);
285
Chia-I Wu31b2e4f2016-05-23 10:47:57 +0800286 return true;
287}
288
289CreateInfoWrapper::CreateInfoWrapper(const VkInstanceCreateInfo& create_info,
Chia-I Wuff4a6c72016-03-24 16:05:56 +0800290 const VkAllocationCallbacks& allocator)
291 : is_instance_(true),
292 allocator_(allocator),
Chia-I Wu31b2e4f2016-05-23 10:47:57 +0800293 physical_dev_(VK_NULL_HANDLE),
Chia-I Wuff4a6c72016-03-24 16:05:56 +0800294 instance_info_(create_info),
295 extension_filter_() {
296 hook_extensions_.set(ProcHook::EXTENSION_CORE);
297 hal_extensions_.set(ProcHook::EXTENSION_CORE);
298}
299
Chia-I Wu4901db72016-03-24 16:38:58 +0800300CreateInfoWrapper::CreateInfoWrapper(VkPhysicalDevice physical_dev,
301 const VkDeviceCreateInfo& create_info,
302 const VkAllocationCallbacks& allocator)
303 : is_instance_(false),
304 allocator_(allocator),
305 physical_dev_(physical_dev),
306 dev_info_(create_info),
307 extension_filter_() {
308 hook_extensions_.set(ProcHook::EXTENSION_CORE);
309 hal_extensions_.set(ProcHook::EXTENSION_CORE);
310}
311
312CreateInfoWrapper::~CreateInfoWrapper() {
313 allocator_.pfnFree(allocator_.pUserData, extension_filter_.exts);
314 allocator_.pfnFree(allocator_.pUserData, extension_filter_.names);
315}
316
Chia-I Wu3e6c2d62016-04-11 13:55:56 +0800317VkResult CreateInfoWrapper::Validate() {
318 VkResult result = SanitizePNext();
Chia-I Wu4901db72016-03-24 16:38:58 +0800319 if (result == VK_SUCCESS)
Chia-I Wu3e6c2d62016-04-11 13:55:56 +0800320 result = SanitizeLayers();
Chia-I Wu4901db72016-03-24 16:38:58 +0800321 if (result == VK_SUCCESS)
Chia-I Wu3e6c2d62016-04-11 13:55:56 +0800322 result = SanitizeExtensions();
Chia-I Wu4901db72016-03-24 16:38:58 +0800323
324 return result;
325}
326
327const std::bitset<ProcHook::EXTENSION_COUNT>&
Chia-I Wu3e6c2d62016-04-11 13:55:56 +0800328CreateInfoWrapper::GetHookExtensions() const {
Chia-I Wu4901db72016-03-24 16:38:58 +0800329 return hook_extensions_;
330}
331
332const std::bitset<ProcHook::EXTENSION_COUNT>&
Chia-I Wu3e6c2d62016-04-11 13:55:56 +0800333CreateInfoWrapper::GetHalExtensions() const {
Chia-I Wu4901db72016-03-24 16:38:58 +0800334 return hal_extensions_;
335}
336
Chia-I Wuff4a6c72016-03-24 16:05:56 +0800337CreateInfoWrapper::operator const VkInstanceCreateInfo*() const {
338 return &instance_info_;
339}
340
Chia-I Wu4901db72016-03-24 16:38:58 +0800341CreateInfoWrapper::operator const VkDeviceCreateInfo*() const {
342 return &dev_info_;
343}
344
Chia-I Wu3e6c2d62016-04-11 13:55:56 +0800345VkResult CreateInfoWrapper::SanitizePNext() {
Chia-I Wu4901db72016-03-24 16:38:58 +0800346 const struct StructHeader {
347 VkStructureType type;
348 const void* next;
349 } * header;
350
351 if (is_instance_) {
352 header = reinterpret_cast<const StructHeader*>(instance_info_.pNext);
353
354 // skip leading VK_STRUCTURE_TYPE_LOADER_INSTANCE_CREATE_INFOs
355 while (header &&
356 header->type == VK_STRUCTURE_TYPE_LOADER_INSTANCE_CREATE_INFO)
357 header = reinterpret_cast<const StructHeader*>(header->next);
358
359 instance_info_.pNext = header;
360 } else {
361 header = reinterpret_cast<const StructHeader*>(dev_info_.pNext);
362
363 // skip leading VK_STRUCTURE_TYPE_LOADER_DEVICE_CREATE_INFOs
364 while (header &&
365 header->type == VK_STRUCTURE_TYPE_LOADER_DEVICE_CREATE_INFO)
366 header = reinterpret_cast<const StructHeader*>(header->next);
367
368 dev_info_.pNext = header;
369 }
370
371 return VK_SUCCESS;
372}
373
Chia-I Wu3e6c2d62016-04-11 13:55:56 +0800374VkResult CreateInfoWrapper::SanitizeLayers() {
Chia-I Wu4901db72016-03-24 16:38:58 +0800375 auto& layer_names = (is_instance_) ? instance_info_.ppEnabledLayerNames
376 : dev_info_.ppEnabledLayerNames;
377 auto& layer_count = (is_instance_) ? instance_info_.enabledLayerCount
378 : dev_info_.enabledLayerCount;
379
380 // remove all layers
381 layer_names = nullptr;
382 layer_count = 0;
383
384 return VK_SUCCESS;
385}
386
Chia-I Wu3e6c2d62016-04-11 13:55:56 +0800387VkResult CreateInfoWrapper::SanitizeExtensions() {
Chia-I Wu4901db72016-03-24 16:38:58 +0800388 auto& ext_names = (is_instance_) ? instance_info_.ppEnabledExtensionNames
389 : dev_info_.ppEnabledExtensionNames;
390 auto& ext_count = (is_instance_) ? instance_info_.enabledExtensionCount
391 : dev_info_.enabledExtensionCount;
392 if (!ext_count)
393 return VK_SUCCESS;
394
Chia-I Wu3e6c2d62016-04-11 13:55:56 +0800395 VkResult result = InitExtensionFilter();
Chia-I Wu4901db72016-03-24 16:38:58 +0800396 if (result != VK_SUCCESS)
397 return result;
398
399 for (uint32_t i = 0; i < ext_count; i++)
Chia-I Wu3e6c2d62016-04-11 13:55:56 +0800400 FilterExtension(ext_names[i]);
Chia-I Wu4901db72016-03-24 16:38:58 +0800401
402 ext_names = extension_filter_.names;
403 ext_count = extension_filter_.name_count;
404
405 return VK_SUCCESS;
406}
407
Chia-I Wu3e6c2d62016-04-11 13:55:56 +0800408VkResult CreateInfoWrapper::QueryExtensionCount(uint32_t& count) const {
Chia-I Wu4901db72016-03-24 16:38:58 +0800409 if (is_instance_) {
Chia-I Wu31b2e4f2016-05-23 10:47:57 +0800410 return Hal::Device().EnumerateInstanceExtensionProperties(
411 nullptr, &count, nullptr);
Chia-I Wu4901db72016-03-24 16:38:58 +0800412 } else {
413 const auto& driver = GetData(physical_dev_).driver;
414 return driver.EnumerateDeviceExtensionProperties(physical_dev_, nullptr,
415 &count, nullptr);
416 }
417}
418
Chia-I Wu3e6c2d62016-04-11 13:55:56 +0800419VkResult CreateInfoWrapper::EnumerateExtensions(
Chia-I Wu4901db72016-03-24 16:38:58 +0800420 uint32_t& count,
421 VkExtensionProperties* props) const {
422 if (is_instance_) {
Chia-I Wu31b2e4f2016-05-23 10:47:57 +0800423 return Hal::Device().EnumerateInstanceExtensionProperties(
424 nullptr, &count, props);
Chia-I Wu4901db72016-03-24 16:38:58 +0800425 } else {
426 const auto& driver = GetData(physical_dev_).driver;
427 return driver.EnumerateDeviceExtensionProperties(physical_dev_, nullptr,
428 &count, props);
429 }
430}
431
Chia-I Wu3e6c2d62016-04-11 13:55:56 +0800432VkResult CreateInfoWrapper::InitExtensionFilter() {
Chia-I Wu4901db72016-03-24 16:38:58 +0800433 // query extension count
434 uint32_t count;
Chia-I Wu3e6c2d62016-04-11 13:55:56 +0800435 VkResult result = QueryExtensionCount(count);
Chia-I Wu4901db72016-03-24 16:38:58 +0800436 if (result != VK_SUCCESS || count == 0)
437 return result;
438
439 auto& filter = extension_filter_;
440 filter.exts =
441 reinterpret_cast<VkExtensionProperties*>(allocator_.pfnAllocation(
442 allocator_.pUserData, sizeof(VkExtensionProperties) * count,
443 alignof(VkExtensionProperties),
444 VK_SYSTEM_ALLOCATION_SCOPE_COMMAND));
445 if (!filter.exts)
446 return VK_ERROR_OUT_OF_HOST_MEMORY;
447
448 // enumerate extensions
Chia-I Wu3e6c2d62016-04-11 13:55:56 +0800449 result = EnumerateExtensions(count, filter.exts);
Chia-I Wu4901db72016-03-24 16:38:58 +0800450 if (result != VK_SUCCESS && result != VK_INCOMPLETE)
451 return result;
452
453 if (!count)
454 return VK_SUCCESS;
455
456 filter.ext_count = count;
457
458 // allocate name array
459 uint32_t enabled_ext_count = (is_instance_)
460 ? instance_info_.enabledExtensionCount
461 : dev_info_.enabledExtensionCount;
462 count = std::min(filter.ext_count, enabled_ext_count);
463 filter.names = reinterpret_cast<const char**>(allocator_.pfnAllocation(
464 allocator_.pUserData, sizeof(const char*) * count, alignof(const char*),
465 VK_SYSTEM_ALLOCATION_SCOPE_COMMAND));
466 if (!filter.names)
467 return VK_ERROR_OUT_OF_HOST_MEMORY;
468
469 return VK_SUCCESS;
470}
471
Chia-I Wu3e6c2d62016-04-11 13:55:56 +0800472void CreateInfoWrapper::FilterExtension(const char* name) {
Chia-I Wu4901db72016-03-24 16:38:58 +0800473 auto& filter = extension_filter_;
474
475 ProcHook::Extension ext_bit = GetProcHookExtension(name);
476 if (is_instance_) {
477 switch (ext_bit) {
478 case ProcHook::KHR_android_surface:
479 case ProcHook::KHR_surface:
Courtney Goeltzenleuchtere278daf2017-02-02 16:54:57 -0700480 case ProcHook::EXT_swapchain_colorspace:
Chris Forbes2452cf72017-03-16 16:30:17 +1300481 case ProcHook::KHR_get_surface_capabilities2:
Chia-I Wu4901db72016-03-24 16:38:58 +0800482 hook_extensions_.set(ext_bit);
483 // return now as these extensions do not require HAL support
484 return;
485 case ProcHook::EXT_debug_report:
486 // both we and HAL can take part in
487 hook_extensions_.set(ext_bit);
488 break;
489 case ProcHook::EXTENSION_UNKNOWN:
Chris Forbes6aa30db2017-02-20 17:12:53 +1300490 case ProcHook::KHR_get_physical_device_properties2:
Chia-I Wu4901db72016-03-24 16:38:58 +0800491 // HAL's extensions
492 break;
493 default:
494 ALOGW("Ignored invalid instance extension %s", name);
495 return;
496 }
497 } else {
498 switch (ext_bit) {
499 case ProcHook::KHR_swapchain:
500 // map VK_KHR_swapchain to VK_ANDROID_native_buffer
501 name = VK_ANDROID_NATIVE_BUFFER_EXTENSION_NAME;
502 ext_bit = ProcHook::ANDROID_native_buffer;
503 break;
Ian Elliott9e853732017-02-03 11:24:07 -0700504 case ProcHook::KHR_incremental_present:
Ian Elliott8a977262017-01-19 09:05:58 -0700505 case ProcHook::GOOGLE_display_timing:
Chris Forbesfa25e632017-02-22 12:36:02 +1300506 case ProcHook::KHR_shared_presentable_image:
Ian Elliott8a977262017-01-19 09:05:58 -0700507 hook_extensions_.set(ext_bit);
508 // return now as these extensions do not require HAL support
509 return;
Courtney Goeltzenleuchterd634c482017-01-05 15:55:31 -0700510 case ProcHook::EXT_hdr_metadata:
511 hook_extensions_.set(ext_bit);
512 break;
Chia-I Wu4901db72016-03-24 16:38:58 +0800513 case ProcHook::EXTENSION_UNKNOWN:
514 // HAL's extensions
515 break;
516 default:
517 ALOGW("Ignored invalid device extension %s", name);
518 return;
519 }
520 }
521
522 for (uint32_t i = 0; i < filter.ext_count; i++) {
523 const VkExtensionProperties& props = filter.exts[i];
524 // ignore unknown extensions
525 if (strcmp(name, props.extensionName) != 0)
526 continue;
527
Chia-I Wu4901db72016-03-24 16:38:58 +0800528 filter.names[filter.name_count++] = name;
Chia-I Wu1600e262016-04-12 09:40:06 +0800529 if (ext_bit != ProcHook::EXTENSION_UNKNOWN) {
530 if (ext_bit == ProcHook::ANDROID_native_buffer)
531 hook_extensions_.set(ProcHook::KHR_swapchain);
532
533 hal_extensions_.set(ext_bit);
534 }
Chia-I Wu4901db72016-03-24 16:38:58 +0800535
536 break;
537 }
538}
539
Chia-I Wudbb7e9c2016-03-24 15:09:38 +0800540VKAPI_ATTR void* DefaultAllocate(void*,
541 size_t size,
542 size_t alignment,
543 VkSystemAllocationScope) {
544 void* ptr = nullptr;
545 // Vulkan requires 'alignment' to be a power of two, but posix_memalign
546 // additionally requires that it be at least sizeof(void*).
547 int ret = posix_memalign(&ptr, std::max(alignment, sizeof(void*)), size);
548 ALOGD_CALLSTACK("Allocate: size=%zu align=%zu => (%d) %p", size, alignment,
549 ret, ptr);
550 return ret == 0 ? ptr : nullptr;
551}
552
553VKAPI_ATTR void* DefaultReallocate(void*,
554 void* ptr,
555 size_t size,
556 size_t alignment,
557 VkSystemAllocationScope) {
558 if (size == 0) {
559 free(ptr);
560 return nullptr;
561 }
562
563 // TODO(jessehall): Right now we never shrink allocations; if the new
564 // request is smaller than the existing chunk, we just continue using it.
565 // Right now the loader never reallocs, so this doesn't matter. If that
566 // changes, or if this code is copied into some other project, this should
567 // probably have a heuristic to allocate-copy-free when doing so will save
568 // "enough" space.
569 size_t old_size = ptr ? malloc_usable_size(ptr) : 0;
570 if (size <= old_size)
571 return ptr;
572
573 void* new_ptr = nullptr;
574 if (posix_memalign(&new_ptr, std::max(alignment, sizeof(void*)), size) != 0)
575 return nullptr;
576 if (ptr) {
577 memcpy(new_ptr, ptr, std::min(old_size, size));
578 free(ptr);
579 }
580 return new_ptr;
581}
582
583VKAPI_ATTR void DefaultFree(void*, void* ptr) {
584 ALOGD_CALLSTACK("Free: %p", ptr);
585 free(ptr);
586}
587
Chia-I Wuff4a6c72016-03-24 16:05:56 +0800588InstanceData* AllocateInstanceData(const VkAllocationCallbacks& allocator) {
589 void* data_mem = allocator.pfnAllocation(
590 allocator.pUserData, sizeof(InstanceData), alignof(InstanceData),
591 VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
592 if (!data_mem)
593 return nullptr;
594
595 return new (data_mem) InstanceData(allocator);
596}
597
598void FreeInstanceData(InstanceData* data,
599 const VkAllocationCallbacks& allocator) {
600 data->~InstanceData();
601 allocator.pfnFree(allocator.pUserData, data);
602}
603
Chia-I Wu950d6e12016-05-03 09:12:35 +0800604DeviceData* AllocateDeviceData(
605 const VkAllocationCallbacks& allocator,
606 const DebugReportCallbackList& debug_report_callbacks) {
Chia-I Wu4901db72016-03-24 16:38:58 +0800607 void* data_mem = allocator.pfnAllocation(
608 allocator.pUserData, sizeof(DeviceData), alignof(DeviceData),
609 VK_SYSTEM_ALLOCATION_SCOPE_DEVICE);
610 if (!data_mem)
611 return nullptr;
612
Chia-I Wu950d6e12016-05-03 09:12:35 +0800613 return new (data_mem) DeviceData(allocator, debug_report_callbacks);
Chia-I Wu4901db72016-03-24 16:38:58 +0800614}
615
616void FreeDeviceData(DeviceData* data, const VkAllocationCallbacks& allocator) {
617 data->~DeviceData();
618 allocator.pfnFree(allocator.pUserData, data);
619}
620
Chia-I Wu136b8eb2016-03-24 15:01:52 +0800621} // anonymous namespace
622
Chia-I Wu9d518162016-03-24 14:55:27 +0800623bool Debuggable() {
624 return (prctl(PR_GET_DUMPABLE, 0, 0, 0, 0) >= 0);
625}
626
Chia-I Wu136b8eb2016-03-24 15:01:52 +0800627bool OpenHAL() {
Chia-I Wu31b2e4f2016-05-23 10:47:57 +0800628 return Hal::Open();
Chia-I Wu136b8eb2016-03-24 15:01:52 +0800629}
630
Chia-I Wudbb7e9c2016-03-24 15:09:38 +0800631const VkAllocationCallbacks& GetDefaultAllocator() {
632 static const VkAllocationCallbacks kDefaultAllocCallbacks = {
633 .pUserData = nullptr,
634 .pfnAllocation = DefaultAllocate,
635 .pfnReallocation = DefaultReallocate,
636 .pfnFree = DefaultFree,
637 };
638
639 return kDefaultAllocCallbacks;
640}
641
Chia-I Wueb7db122016-03-24 09:11:06 +0800642PFN_vkVoidFunction GetInstanceProcAddr(VkInstance instance, const char* pName) {
643 const ProcHook* hook = GetProcHook(pName);
644 if (!hook)
Chia-I Wu31b2e4f2016-05-23 10:47:57 +0800645 return Hal::Device().GetInstanceProcAddr(instance, pName);
Chia-I Wueb7db122016-03-24 09:11:06 +0800646
647 if (!instance) {
648 if (hook->type == ProcHook::GLOBAL)
649 return hook->proc;
650
Chia-I Wu109f8982016-04-22 06:40:40 +0800651 // v0 layers expect
652 //
653 // vkGetInstanceProcAddr(VK_NULL_HANDLE, "vkCreateDevice");
654 //
655 // to work.
656 if (strcmp(pName, "vkCreateDevice") == 0)
657 return hook->proc;
658
Chia-I Wueb7db122016-03-24 09:11:06 +0800659 ALOGE(
Chia-I Wue201c3f2016-05-03 13:26:08 +0800660 "internal vkGetInstanceProcAddr called for %s without an instance",
Chia-I Wueb7db122016-03-24 09:11:06 +0800661 pName);
662
Chia-I Wu109f8982016-04-22 06:40:40 +0800663 return nullptr;
Chia-I Wueb7db122016-03-24 09:11:06 +0800664 }
665
666 PFN_vkVoidFunction proc;
667
668 switch (hook->type) {
669 case ProcHook::INSTANCE:
670 proc = (GetData(instance).hook_extensions[hook->extension])
671 ? hook->proc
Chia-I Wu36cc00a2016-04-13 16:52:06 +0800672 : nullptr;
Chia-I Wueb7db122016-03-24 09:11:06 +0800673 break;
674 case ProcHook::DEVICE:
675 proc = (hook->extension == ProcHook::EXTENSION_CORE)
676 ? hook->proc
677 : hook->checked_proc;
678 break;
679 default:
680 ALOGE(
Chia-I Wue201c3f2016-05-03 13:26:08 +0800681 "internal vkGetInstanceProcAddr called for %s with an instance",
Chia-I Wueb7db122016-03-24 09:11:06 +0800682 pName);
683 proc = nullptr;
684 break;
685 }
686
687 return proc;
688}
689
690PFN_vkVoidFunction GetDeviceProcAddr(VkDevice device, const char* pName) {
691 const ProcHook* hook = GetProcHook(pName);
692 if (!hook)
Chia-I Wucc5e2762016-03-24 13:01:16 +0800693 return GetData(device).driver.GetDeviceProcAddr(device, pName);
Chia-I Wueb7db122016-03-24 09:11:06 +0800694
695 if (hook->type != ProcHook::DEVICE) {
Chia-I Wue201c3f2016-05-03 13:26:08 +0800696 ALOGE("internal vkGetDeviceProcAddr called for %s", pName);
Chia-I Wueb7db122016-03-24 09:11:06 +0800697 return nullptr;
698 }
699
Chia-I Wu36cc00a2016-04-13 16:52:06 +0800700 return (GetData(device).hook_extensions[hook->extension]) ? hook->proc
701 : nullptr;
Chia-I Wueb7db122016-03-24 09:11:06 +0800702}
703
Chia-I Wuff4a6c72016-03-24 16:05:56 +0800704VkResult EnumerateInstanceExtensionProperties(
705 const char* pLayerName,
706 uint32_t* pPropertyCount,
707 VkExtensionProperties* pProperties) {
Ian Elliott34a327b2017-03-28 13:20:35 -0600708
709 android::Vector<VkExtensionProperties> loader_extensions;
710 loader_extensions.push_back({
711 VK_KHR_SURFACE_EXTENSION_NAME,
712 VK_KHR_SURFACE_SPEC_VERSION});
713 loader_extensions.push_back({
714 VK_KHR_ANDROID_SURFACE_EXTENSION_NAME,
715 VK_KHR_ANDROID_SURFACE_SPEC_VERSION});
716 loader_extensions.push_back({
717 VK_EXT_SWAPCHAIN_COLOR_SPACE_EXTENSION_NAME,
718 VK_EXT_SWAPCHAIN_COLOR_SPACE_SPEC_VERSION});
Chris Forbes16095002017-05-05 15:33:29 -0700719 loader_extensions.push_back({
720 VK_KHR_GET_SURFACE_CAPABILITIES_2_EXTENSION_NAME,
721 VK_KHR_GET_SURFACE_CAPABILITIES_2_SPEC_VERSION});
Ian Elliott34a327b2017-03-28 13:20:35 -0600722
Chia-I Wu31938252016-05-23 15:31:02 +0800723 static const VkExtensionProperties loader_debug_report_extension = {
724 VK_EXT_DEBUG_REPORT_EXTENSION_NAME, VK_EXT_DEBUG_REPORT_SPEC_VERSION,
725 };
Chia-I Wuff4a6c72016-03-24 16:05:56 +0800726
727 // enumerate our extensions first
728 if (!pLayerName && pProperties) {
729 uint32_t count = std::min(
730 *pPropertyCount, static_cast<uint32_t>(loader_extensions.size()));
731
732 std::copy_n(loader_extensions.begin(), count, pProperties);
733
734 if (count < loader_extensions.size()) {
735 *pPropertyCount = count;
736 return VK_INCOMPLETE;
737 }
738
739 pProperties += count;
740 *pPropertyCount -= count;
Chia-I Wu31938252016-05-23 15:31:02 +0800741
742 if (Hal::Get().GetDebugReportIndex() < 0) {
743 if (!*pPropertyCount) {
744 *pPropertyCount = count;
745 return VK_INCOMPLETE;
746 }
747
748 pProperties[0] = loader_debug_report_extension;
749 pProperties += 1;
750 *pPropertyCount -= 1;
751 }
Chia-I Wuff4a6c72016-03-24 16:05:56 +0800752 }
753
Chia-I Wu31b2e4f2016-05-23 10:47:57 +0800754 VkResult result = Hal::Device().EnumerateInstanceExtensionProperties(
Chia-I Wuff4a6c72016-03-24 16:05:56 +0800755 pLayerName, pPropertyCount, pProperties);
756
Chia-I Wu31938252016-05-23 15:31:02 +0800757 if (!pLayerName && (result == VK_SUCCESS || result == VK_INCOMPLETE)) {
758 int idx = Hal::Get().GetDebugReportIndex();
759 if (idx < 0) {
760 *pPropertyCount += 1;
761 } else if (pProperties &&
762 static_cast<uint32_t>(idx) < *pPropertyCount) {
763 pProperties[idx].specVersion =
764 std::min(pProperties[idx].specVersion,
765 loader_debug_report_extension.specVersion);
766 }
767
Chia-I Wuff4a6c72016-03-24 16:05:56 +0800768 *pPropertyCount += loader_extensions.size();
Chia-I Wu31938252016-05-23 15:31:02 +0800769 }
Chia-I Wuff4a6c72016-03-24 16:05:56 +0800770
771 return result;
772}
773
Chris Forbesfa25e632017-02-22 12:36:02 +1300774bool QueryPresentationProperties(
775 VkPhysicalDevice physicalDevice,
776 VkPhysicalDevicePresentationPropertiesANDROID *presentation_properties)
777{
778 const InstanceData& data = GetData(physicalDevice);
779
780 // GPDP2 must be present and enabled on the instance.
781 if (!data.driver.GetPhysicalDeviceProperties2KHR)
782 return false;
783
784 // Request the android-specific presentation properties via GPDP2
785 VkPhysicalDeviceProperties2KHR properties = {
786 VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2_KHR,
787 presentation_properties,
788 {}
789 };
790
791#pragma clang diagnostic push
792#pragma clang diagnostic ignored "-Wold-style-cast"
793 presentation_properties->sType =
794 VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PRESENTATION_PROPERTIES_ANDROID;
795#pragma clang diagnostic pop
796 presentation_properties->pNext = nullptr;
797 presentation_properties->sharedImage = VK_FALSE;
798
799 data.driver.GetPhysicalDeviceProperties2KHR(physicalDevice,
800 &properties);
801
802 return true;
803}
804
Chia-I Wu01cf3052016-03-24 16:16:21 +0800805VkResult EnumerateDeviceExtensionProperties(
806 VkPhysicalDevice physicalDevice,
807 const char* pLayerName,
808 uint32_t* pPropertyCount,
809 VkExtensionProperties* pProperties) {
810 const InstanceData& data = GetData(physicalDevice);
Chris Forbesfa25e632017-02-22 12:36:02 +1300811 // extensions that are unconditionally exposed by the loader
812 android::Vector<VkExtensionProperties> loader_extensions;
813 loader_extensions.push_back({
814 VK_KHR_INCREMENTAL_PRESENT_EXTENSION_NAME,
815 VK_KHR_INCREMENTAL_PRESENT_SPEC_VERSION});
Chris Forbesfa25e632017-02-22 12:36:02 +1300816
Chris Forbes16095002017-05-05 15:33:29 -0700817 VkPhysicalDevicePresentationPropertiesANDROID presentation_properties;
818 if (QueryPresentationProperties(physicalDevice, &presentation_properties) &&
819 presentation_properties.sharedImage) {
820 loader_extensions.push_back({
821 VK_KHR_SHARED_PRESENTABLE_IMAGE_EXTENSION_NAME,
822 VK_KHR_SHARED_PRESENTABLE_IMAGE_SPEC_VERSION});
Chris Forbesfa25e632017-02-22 12:36:02 +1300823 }
Ian Elliottd4b50aa2017-01-09 16:21:36 -0700824
Ian Elliott5c34de22017-04-10 14:42:30 -0600825 // conditionally add VK_GOOGLE_display_timing if present timestamps are
826 // supported by the driver:
Wei Wangf9b05ee2017-07-19 20:59:39 -0700827 const std::string timestamp_property("service.sf.present_timestamp");
828 android::base::WaitForPropertyCreation(timestamp_property);
829 if (android::base::GetBoolProperty(timestamp_property, true)) {
Ian Elliott5c34de22017-04-10 14:42:30 -0600830 loader_extensions.push_back({
831 VK_GOOGLE_DISPLAY_TIMING_EXTENSION_NAME,
832 VK_GOOGLE_DISPLAY_TIMING_SPEC_VERSION});
833 }
834
Ian Elliottd4b50aa2017-01-09 16:21:36 -0700835 // enumerate our extensions first
836 if (!pLayerName && pProperties) {
837 uint32_t count = std::min(
838 *pPropertyCount, static_cast<uint32_t>(loader_extensions.size()));
839
840 std::copy_n(loader_extensions.begin(), count, pProperties);
841
842 if (count < loader_extensions.size()) {
843 *pPropertyCount = count;
844 return VK_INCOMPLETE;
845 }
846
847 pProperties += count;
848 *pPropertyCount -= count;
849 }
Chia-I Wu01cf3052016-03-24 16:16:21 +0800850
851 VkResult result = data.driver.EnumerateDeviceExtensionProperties(
852 physicalDevice, pLayerName, pPropertyCount, pProperties);
Chia-I Wu01cf3052016-03-24 16:16:21 +0800853
Ian Elliottd4b50aa2017-01-09 16:21:36 -0700854 if (pProperties) {
855 // map VK_ANDROID_native_buffer to VK_KHR_swapchain
856 for (uint32_t i = 0; i < *pPropertyCount; i++) {
857 auto& prop = pProperties[i];
Chia-I Wu01cf3052016-03-24 16:16:21 +0800858
Ian Elliottd4b50aa2017-01-09 16:21:36 -0700859 if (strcmp(prop.extensionName,
860 VK_ANDROID_NATIVE_BUFFER_EXTENSION_NAME) != 0)
861 continue;
Chia-I Wu01cf3052016-03-24 16:16:21 +0800862
Ian Elliottd4b50aa2017-01-09 16:21:36 -0700863 memcpy(prop.extensionName, VK_KHR_SWAPCHAIN_EXTENSION_NAME,
864 sizeof(VK_KHR_SWAPCHAIN_EXTENSION_NAME));
865 prop.specVersion = VK_KHR_SWAPCHAIN_SPEC_VERSION;
866 }
867 }
Chia-I Wu01cf3052016-03-24 16:16:21 +0800868
Ian Elliottd4b50aa2017-01-09 16:21:36 -0700869 // restore loader extension count
870 if (!pLayerName && (result == VK_SUCCESS || result == VK_INCOMPLETE)) {
871 *pPropertyCount += loader_extensions.size();
Chia-I Wu01cf3052016-03-24 16:16:21 +0800872 }
873
874 return result;
875}
876
Chia-I Wuff4a6c72016-03-24 16:05:56 +0800877VkResult CreateInstance(const VkInstanceCreateInfo* pCreateInfo,
878 const VkAllocationCallbacks* pAllocator,
879 VkInstance* pInstance) {
880 const VkAllocationCallbacks& data_allocator =
881 (pAllocator) ? *pAllocator : GetDefaultAllocator();
882
Ian Elliottb36f4ee2017-05-08 15:59:09 -0600883 if (pCreateInfo->pApplicationInfo &&
884 pCreateInfo->pApplicationInfo->apiVersion >= VK_MAKE_VERSION(1, 1, 0)) {
885#pragma clang diagnostic push
886#pragma clang diagnostic ignored "-Wold-style-cast"
887 ALOGI(
888 "Requested Vulkan instance version %d.%d is greater than max "
889 "supported version (1.0)",
890 VK_VERSION_MAJOR(pCreateInfo->pApplicationInfo->apiVersion),
891 VK_VERSION_MINOR(pCreateInfo->pApplicationInfo->apiVersion));
892#pragma clang diagnostic pop
893 return VK_ERROR_INCOMPATIBLE_DRIVER;
894 }
895
Chia-I Wu31b2e4f2016-05-23 10:47:57 +0800896 CreateInfoWrapper wrapper(*pCreateInfo, data_allocator);
Chia-I Wu3e6c2d62016-04-11 13:55:56 +0800897 VkResult result = wrapper.Validate();
Chia-I Wuff4a6c72016-03-24 16:05:56 +0800898 if (result != VK_SUCCESS)
899 return result;
900
901 InstanceData* data = AllocateInstanceData(data_allocator);
902 if (!data)
903 return VK_ERROR_OUT_OF_HOST_MEMORY;
904
Chia-I Wu3e6c2d62016-04-11 13:55:56 +0800905 data->hook_extensions |= wrapper.GetHookExtensions();
Chia-I Wuff4a6c72016-03-24 16:05:56 +0800906
907 // call into the driver
908 VkInstance instance;
Chia-I Wu31b2e4f2016-05-23 10:47:57 +0800909 result = Hal::Device().CreateInstance(
Chia-I Wuff4a6c72016-03-24 16:05:56 +0800910 static_cast<const VkInstanceCreateInfo*>(wrapper), pAllocator,
911 &instance);
912 if (result != VK_SUCCESS) {
913 FreeInstanceData(data, data_allocator);
914 return result;
915 }
916
917 // initialize InstanceDriverTable
918 if (!SetData(instance, *data) ||
Chia-I Wu31b2e4f2016-05-23 10:47:57 +0800919 !InitDriverTable(instance, Hal::Device().GetInstanceProcAddr,
Chia-I Wucbe07ef2016-04-13 15:01:00 +0800920 wrapper.GetHalExtensions())) {
Chia-I Wuff4a6c72016-03-24 16:05:56 +0800921 data->driver.DestroyInstance = reinterpret_cast<PFN_vkDestroyInstance>(
Chia-I Wu31b2e4f2016-05-23 10:47:57 +0800922 Hal::Device().GetInstanceProcAddr(instance, "vkDestroyInstance"));
Chia-I Wuff4a6c72016-03-24 16:05:56 +0800923 if (data->driver.DestroyInstance)
924 data->driver.DestroyInstance(instance, pAllocator);
925
926 FreeInstanceData(data, data_allocator);
927
928 return VK_ERROR_INCOMPATIBLE_DRIVER;
929 }
930
931 data->get_device_proc_addr = reinterpret_cast<PFN_vkGetDeviceProcAddr>(
Chia-I Wu31b2e4f2016-05-23 10:47:57 +0800932 Hal::Device().GetInstanceProcAddr(instance, "vkGetDeviceProcAddr"));
Chia-I Wuff4a6c72016-03-24 16:05:56 +0800933 if (!data->get_device_proc_addr) {
934 data->driver.DestroyInstance(instance, pAllocator);
935 FreeInstanceData(data, data_allocator);
936
937 return VK_ERROR_INCOMPATIBLE_DRIVER;
938 }
939
940 *pInstance = instance;
941
942 return VK_SUCCESS;
943}
944
945void DestroyInstance(VkInstance instance,
946 const VkAllocationCallbacks* pAllocator) {
947 InstanceData& data = GetData(instance);
948 data.driver.DestroyInstance(instance, pAllocator);
949
950 VkAllocationCallbacks local_allocator;
951 if (!pAllocator) {
952 local_allocator = data.allocator;
953 pAllocator = &local_allocator;
954 }
955
956 FreeInstanceData(&data, *pAllocator);
957}
958
Chia-I Wu4901db72016-03-24 16:38:58 +0800959VkResult CreateDevice(VkPhysicalDevice physicalDevice,
960 const VkDeviceCreateInfo* pCreateInfo,
961 const VkAllocationCallbacks* pAllocator,
962 VkDevice* pDevice) {
963 const InstanceData& instance_data = GetData(physicalDevice);
964 const VkAllocationCallbacks& data_allocator =
965 (pAllocator) ? *pAllocator : instance_data.allocator;
966
967 CreateInfoWrapper wrapper(physicalDevice, *pCreateInfo, data_allocator);
Chia-I Wu3e6c2d62016-04-11 13:55:56 +0800968 VkResult result = wrapper.Validate();
Chia-I Wu4901db72016-03-24 16:38:58 +0800969 if (result != VK_SUCCESS)
970 return result;
971
Chia-I Wu950d6e12016-05-03 09:12:35 +0800972 DeviceData* data = AllocateDeviceData(data_allocator,
973 instance_data.debug_report_callbacks);
Chia-I Wu4901db72016-03-24 16:38:58 +0800974 if (!data)
975 return VK_ERROR_OUT_OF_HOST_MEMORY;
976
Chia-I Wu3e6c2d62016-04-11 13:55:56 +0800977 data->hook_extensions |= wrapper.GetHookExtensions();
Chia-I Wu4901db72016-03-24 16:38:58 +0800978
979 // call into the driver
980 VkDevice dev;
981 result = instance_data.driver.CreateDevice(
982 physicalDevice, static_cast<const VkDeviceCreateInfo*>(wrapper),
983 pAllocator, &dev);
984 if (result != VK_SUCCESS) {
985 FreeDeviceData(data, data_allocator);
986 return result;
987 }
988
989 // initialize DeviceDriverTable
990 if (!SetData(dev, *data) ||
Chia-I Wucbe07ef2016-04-13 15:01:00 +0800991 !InitDriverTable(dev, instance_data.get_device_proc_addr,
992 wrapper.GetHalExtensions())) {
Chia-I Wu4901db72016-03-24 16:38:58 +0800993 data->driver.DestroyDevice = reinterpret_cast<PFN_vkDestroyDevice>(
994 instance_data.get_device_proc_addr(dev, "vkDestroyDevice"));
995 if (data->driver.DestroyDevice)
996 data->driver.DestroyDevice(dev, pAllocator);
997
998 FreeDeviceData(data, data_allocator);
999
1000 return VK_ERROR_INCOMPATIBLE_DRIVER;
1001 }
Chris Forbesd8277912017-02-10 14:59:59 +13001002
1003 // sanity check ANDROID_native_buffer implementation, whose set of
1004 // entrypoints varies according to the spec version.
1005 if ((wrapper.GetHalExtensions()[ProcHook::ANDROID_native_buffer]) &&
1006 !data->driver.GetSwapchainGrallocUsageANDROID &&
1007 !data->driver.GetSwapchainGrallocUsage2ANDROID) {
1008 ALOGE("Driver's implementation of ANDROID_native_buffer is broken;"
1009 " must expose at least one of "
1010 "vkGetSwapchainGrallocUsageANDROID or "
1011 "vkGetSwapchainGrallocUsage2ANDROID");
1012
1013 data->driver.DestroyDevice(dev, pAllocator);
1014 FreeDeviceData(data, data_allocator);
1015
1016 return VK_ERROR_INCOMPATIBLE_DRIVER;
1017 }
1018
Jesse Hall85bb0c52017-02-09 22:13:02 -08001019 VkPhysicalDeviceProperties properties;
1020 instance_data.driver.GetPhysicalDeviceProperties(physicalDevice,
1021 &properties);
1022
Jesse Halldc225072016-05-30 22:40:14 -07001023 data->driver_device = dev;
Jesse Hall85bb0c52017-02-09 22:13:02 -08001024 data->driver_version = properties.driverVersion;
Chia-I Wu4901db72016-03-24 16:38:58 +08001025
1026 *pDevice = dev;
1027
1028 return VK_SUCCESS;
1029}
1030
1031void DestroyDevice(VkDevice device, const VkAllocationCallbacks* pAllocator) {
1032 DeviceData& data = GetData(device);
1033 data.driver.DestroyDevice(device, pAllocator);
1034
1035 VkAllocationCallbacks local_allocator;
1036 if (!pAllocator) {
1037 local_allocator = data.allocator;
1038 pAllocator = &local_allocator;
1039 }
1040
1041 FreeDeviceData(&data, *pAllocator);
1042}
1043
Chia-I Wuff4a6c72016-03-24 16:05:56 +08001044VkResult EnumeratePhysicalDevices(VkInstance instance,
1045 uint32_t* pPhysicalDeviceCount,
1046 VkPhysicalDevice* pPhysicalDevices) {
1047 const auto& data = GetData(instance);
1048
1049 VkResult result = data.driver.EnumeratePhysicalDevices(
1050 instance, pPhysicalDeviceCount, pPhysicalDevices);
1051 if ((result == VK_SUCCESS || result == VK_INCOMPLETE) && pPhysicalDevices) {
1052 for (uint32_t i = 0; i < *pPhysicalDeviceCount; i++)
1053 SetData(pPhysicalDevices[i], data);
1054 }
1055
1056 return result;
1057}
1058
Chia-I Wuba0be412016-03-24 16:24:40 +08001059void GetDeviceQueue(VkDevice device,
1060 uint32_t queueFamilyIndex,
1061 uint32_t queueIndex,
1062 VkQueue* pQueue) {
1063 const auto& data = GetData(device);
1064
1065 data.driver.GetDeviceQueue(device, queueFamilyIndex, queueIndex, pQueue);
1066 SetData(*pQueue, data);
1067}
1068
Chia-I Wu6a58a8a2016-03-24 16:29:51 +08001069VKAPI_ATTR VkResult
1070AllocateCommandBuffers(VkDevice device,
1071 const VkCommandBufferAllocateInfo* pAllocateInfo,
1072 VkCommandBuffer* pCommandBuffers) {
1073 const auto& data = GetData(device);
1074
1075 VkResult result = data.driver.AllocateCommandBuffers(device, pAllocateInfo,
1076 pCommandBuffers);
1077 if (result == VK_SUCCESS) {
1078 for (uint32_t i = 0; i < pAllocateInfo->commandBufferCount; i++)
1079 SetData(pCommandBuffers[i], data);
1080 }
1081
1082 return result;
1083}
1084
Chia-I Wu9d518162016-03-24 14:55:27 +08001085} // namespace driver
1086} // namespace vulkan