blob: 5fbf5f52d16fb52f20cbba302d6487f9ab76324e [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>
Mathias Agopian991d2542017-02-06 13:51:32 -080031#include <ui/GraphicsEnv.h>
Chris Forbesfa25e632017-02-22 12:36:02 +130032#include <utils/Vector.h>
Jesse Hall53457db2016-12-14 16:54:06 -080033
Chia-I Wu9d518162016-03-24 14:55:27 +080034#include "driver.h"
Jesse Hallb7c4e3b2016-04-11 13:51:38 -070035#include "stubhal.h"
Chia-I Wu9d518162016-03-24 14:55:27 +080036
Ian Elliott34a327b2017-03-28 13:20:35 -060037// Set to true to enable exposing unratified extensions for development
38static const bool kEnableUnratifiedExtensions = false;
39
Chia-I Wudbb7e9c2016-03-24 15:09:38 +080040// #define ENABLE_ALLOC_CALLSTACKS 1
41#if ENABLE_ALLOC_CALLSTACKS
42#include <utils/CallStack.h>
43#define ALOGD_CALLSTACK(...) \
44 do { \
45 ALOGD(__VA_ARGS__); \
46 android::CallStack callstack; \
47 callstack.update(); \
48 callstack.log(LOG_TAG, ANDROID_LOG_DEBUG, " "); \
49 } while (false)
50#else
51#define ALOGD_CALLSTACK(...) \
52 do { \
53 } while (false)
54#endif
55
Chia-I Wu9d518162016-03-24 14:55:27 +080056namespace vulkan {
57namespace driver {
58
Chia-I Wu136b8eb2016-03-24 15:01:52 +080059namespace {
60
Chia-I Wu31b2e4f2016-05-23 10:47:57 +080061class Hal {
62 public:
63 static bool Open();
64
65 static const Hal& Get() { return hal_; }
66 static const hwvulkan_device_t& Device() { return *Get().dev_; }
67
Chia-I Wu31938252016-05-23 15:31:02 +080068 int GetDebugReportIndex() const { return debug_report_index_; }
69
Chia-I Wu31b2e4f2016-05-23 10:47:57 +080070 private:
Chia-I Wu31938252016-05-23 15:31:02 +080071 Hal() : dev_(nullptr), debug_report_index_(-1) {}
Chia-I Wu31b2e4f2016-05-23 10:47:57 +080072 Hal(const Hal&) = delete;
73 Hal& operator=(const Hal&) = delete;
74
Chia-I Wu31938252016-05-23 15:31:02 +080075 bool InitDebugReportIndex();
76
Chia-I Wu31b2e4f2016-05-23 10:47:57 +080077 static Hal hal_;
78
79 const hwvulkan_device_t* dev_;
Chia-I Wu31938252016-05-23 15:31:02 +080080 int debug_report_index_;
Chia-I Wu31b2e4f2016-05-23 10:47:57 +080081};
82
Chia-I Wu4901db72016-03-24 16:38:58 +080083class CreateInfoWrapper {
84 public:
Chia-I Wu31b2e4f2016-05-23 10:47:57 +080085 CreateInfoWrapper(const VkInstanceCreateInfo& create_info,
Chia-I Wuff4a6c72016-03-24 16:05:56 +080086 const VkAllocationCallbacks& allocator);
Chia-I Wu4901db72016-03-24 16:38:58 +080087 CreateInfoWrapper(VkPhysicalDevice physical_dev,
88 const VkDeviceCreateInfo& create_info,
89 const VkAllocationCallbacks& allocator);
90 ~CreateInfoWrapper();
91
Chia-I Wu3e6c2d62016-04-11 13:55:56 +080092 VkResult Validate();
Chia-I Wu4901db72016-03-24 16:38:58 +080093
Chia-I Wu3e6c2d62016-04-11 13:55:56 +080094 const std::bitset<ProcHook::EXTENSION_COUNT>& GetHookExtensions() const;
95 const std::bitset<ProcHook::EXTENSION_COUNT>& GetHalExtensions() const;
Chia-I Wu4901db72016-03-24 16:38:58 +080096
Chia-I Wuff4a6c72016-03-24 16:05:56 +080097 explicit operator const VkInstanceCreateInfo*() const;
Chia-I Wu4901db72016-03-24 16:38:58 +080098 explicit operator const VkDeviceCreateInfo*() const;
99
100 private:
101 struct ExtensionFilter {
102 VkExtensionProperties* exts;
103 uint32_t ext_count;
104
105 const char** names;
106 uint32_t name_count;
107 };
108
Chia-I Wu3e6c2d62016-04-11 13:55:56 +0800109 VkResult SanitizePNext();
Chia-I Wu4901db72016-03-24 16:38:58 +0800110
Chia-I Wu3e6c2d62016-04-11 13:55:56 +0800111 VkResult SanitizeLayers();
112 VkResult SanitizeExtensions();
Chia-I Wu4901db72016-03-24 16:38:58 +0800113
Chia-I Wu3e6c2d62016-04-11 13:55:56 +0800114 VkResult QueryExtensionCount(uint32_t& count) const;
115 VkResult EnumerateExtensions(uint32_t& count,
116 VkExtensionProperties* props) const;
117 VkResult InitExtensionFilter();
118 void FilterExtension(const char* name);
Chia-I Wu4901db72016-03-24 16:38:58 +0800119
120 const bool is_instance_;
121 const VkAllocationCallbacks& allocator_;
122
Chia-I Wu31b2e4f2016-05-23 10:47:57 +0800123 VkPhysicalDevice physical_dev_;
Chia-I Wu4901db72016-03-24 16:38:58 +0800124
125 union {
126 VkInstanceCreateInfo instance_info_;
127 VkDeviceCreateInfo dev_info_;
128 };
129
130 ExtensionFilter extension_filter_;
131
132 std::bitset<ProcHook::EXTENSION_COUNT> hook_extensions_;
133 std::bitset<ProcHook::EXTENSION_COUNT> hal_extensions_;
134};
135
Chia-I Wu31b2e4f2016-05-23 10:47:57 +0800136Hal Hal::hal_;
137
Jesse Hall53457db2016-12-14 16:54:06 -0800138void* LoadLibrary(const android_dlextinfo& dlextinfo,
139 const char* subname,
140 int subname_len) {
141 const char kLibFormat[] = "vulkan.%*s.so";
142 char* name = static_cast<char*>(
143 alloca(sizeof(kLibFormat) + static_cast<size_t>(subname_len)));
144 sprintf(name, kLibFormat, subname_len, subname);
145 return android_dlopen_ext(name, RTLD_LOCAL | RTLD_NOW, &dlextinfo);
146}
147
148const std::array<const char*, 2> HAL_SUBNAME_KEY_PROPERTIES = {{
149 "ro.hardware." HWVULKAN_HARDWARE_MODULE_ID,
150 "ro.board.platform",
151}};
152
153int LoadUpdatedDriver(const hw_module_t** module) {
154 const android_dlextinfo dlextinfo = {
155 .flags = ANDROID_DLEXT_USE_NAMESPACE,
156 .library_namespace = android::GraphicsEnv::getInstance().getDriverNamespace(),
157 };
158 if (!dlextinfo.library_namespace)
159 return -ENOENT;
160
161 void* so = nullptr;
162 char prop[PROPERTY_VALUE_MAX];
163 for (auto key : HAL_SUBNAME_KEY_PROPERTIES) {
164 int prop_len = property_get(key, prop, nullptr);
165 if (prop_len > 0) {
166 so = LoadLibrary(dlextinfo, prop, prop_len);
167 if (so)
168 break;
169 }
170 }
171 if (!so)
172 return -ENOENT;
173
174 hw_module_t* hmi = static_cast<hw_module_t*>(dlsym(so, HAL_MODULE_INFO_SYM_AS_STR));
175 if (!hmi) {
176 ALOGE("couldn't find symbol '%s' in HAL library: %s", HAL_MODULE_INFO_SYM_AS_STR, dlerror());
177 dlclose(so);
178 return -EINVAL;
179 }
180 if (strcmp(hmi->id, HWVULKAN_HARDWARE_MODULE_ID) != 0) {
181 ALOGE("HAL id '%s' != '%s'", hmi->id, HWVULKAN_HARDWARE_MODULE_ID);
182 dlclose(so);
183 return -EINVAL;
184 }
185 hmi->dso = so;
186 *module = hmi;
187 ALOGD("loaded updated driver");
188 return 0;
189}
190
Chia-I Wu31b2e4f2016-05-23 10:47:57 +0800191bool Hal::Open() {
Jesse Halldc225072016-05-30 22:40:14 -0700192 ALOG_ASSERT(!hal_.dev_, "OpenHAL called more than once");
Chia-I Wu31b2e4f2016-05-23 10:47:57 +0800193
194 // Use a stub device unless we successfully open a real HAL device.
195 hal_.dev_ = &stubhal::kDevice;
196
Jesse Hall53457db2016-12-14 16:54:06 -0800197 int result;
198 const hwvulkan_module_t* module = nullptr;
199
200 result = LoadUpdatedDriver(reinterpret_cast<const hw_module_t**>(&module));
201 if (result == -ENOENT) {
202 result = hw_get_module(HWVULKAN_HARDWARE_MODULE_ID, reinterpret_cast<const hw_module_t**>(&module));
203 }
Chia-I Wu31b2e4f2016-05-23 10:47:57 +0800204 if (result != 0) {
Jesse Hall53457db2016-12-14 16:54:06 -0800205 ALOGV("unable to load Vulkan HAL, using stub HAL (result=%d)", result);
Chia-I Wu31b2e4f2016-05-23 10:47:57 +0800206 return true;
207 }
208
209 hwvulkan_device_t* device;
210 result =
211 module->common.methods->open(&module->common, HWVULKAN_DEVICE_0,
212 reinterpret_cast<hw_device_t**>(&device));
213 if (result != 0) {
214 // Any device with a Vulkan HAL should be able to open the device.
215 ALOGE("failed to open Vulkan HAL device: %s (%d)", strerror(-result),
216 result);
217 return false;
218 }
219
220 hal_.dev_ = device;
221
Chia-I Wu31938252016-05-23 15:31:02 +0800222 hal_.InitDebugReportIndex();
223
224 return true;
225}
226
227bool Hal::InitDebugReportIndex() {
228 uint32_t count;
229 if (dev_->EnumerateInstanceExtensionProperties(nullptr, &count, nullptr) !=
230 VK_SUCCESS) {
231 ALOGE("failed to get HAL instance extension count");
232 return false;
233 }
234
235 VkExtensionProperties* exts = reinterpret_cast<VkExtensionProperties*>(
236 malloc(sizeof(VkExtensionProperties) * count));
237 if (!exts) {
238 ALOGE("failed to allocate HAL instance extension array");
239 return false;
240 }
241
242 if (dev_->EnumerateInstanceExtensionProperties(nullptr, &count, exts) !=
243 VK_SUCCESS) {
244 ALOGE("failed to enumerate HAL instance extensions");
245 free(exts);
246 return false;
247 }
248
249 for (uint32_t i = 0; i < count; i++) {
250 if (strcmp(exts[i].extensionName, VK_EXT_DEBUG_REPORT_EXTENSION_NAME) ==
251 0) {
252 debug_report_index_ = static_cast<int>(i);
253 break;
254 }
255 }
256
257 free(exts);
258
Chia-I Wu31b2e4f2016-05-23 10:47:57 +0800259 return true;
260}
261
262CreateInfoWrapper::CreateInfoWrapper(const VkInstanceCreateInfo& create_info,
Chia-I Wuff4a6c72016-03-24 16:05:56 +0800263 const VkAllocationCallbacks& allocator)
264 : is_instance_(true),
265 allocator_(allocator),
Chia-I Wu31b2e4f2016-05-23 10:47:57 +0800266 physical_dev_(VK_NULL_HANDLE),
Chia-I Wuff4a6c72016-03-24 16:05:56 +0800267 instance_info_(create_info),
268 extension_filter_() {
269 hook_extensions_.set(ProcHook::EXTENSION_CORE);
270 hal_extensions_.set(ProcHook::EXTENSION_CORE);
271}
272
Chia-I Wu4901db72016-03-24 16:38:58 +0800273CreateInfoWrapper::CreateInfoWrapper(VkPhysicalDevice physical_dev,
274 const VkDeviceCreateInfo& create_info,
275 const VkAllocationCallbacks& allocator)
276 : is_instance_(false),
277 allocator_(allocator),
278 physical_dev_(physical_dev),
279 dev_info_(create_info),
280 extension_filter_() {
281 hook_extensions_.set(ProcHook::EXTENSION_CORE);
282 hal_extensions_.set(ProcHook::EXTENSION_CORE);
283}
284
285CreateInfoWrapper::~CreateInfoWrapper() {
286 allocator_.pfnFree(allocator_.pUserData, extension_filter_.exts);
287 allocator_.pfnFree(allocator_.pUserData, extension_filter_.names);
288}
289
Chia-I Wu3e6c2d62016-04-11 13:55:56 +0800290VkResult CreateInfoWrapper::Validate() {
291 VkResult result = SanitizePNext();
Chia-I Wu4901db72016-03-24 16:38:58 +0800292 if (result == VK_SUCCESS)
Chia-I Wu3e6c2d62016-04-11 13:55:56 +0800293 result = SanitizeLayers();
Chia-I Wu4901db72016-03-24 16:38:58 +0800294 if (result == VK_SUCCESS)
Chia-I Wu3e6c2d62016-04-11 13:55:56 +0800295 result = SanitizeExtensions();
Chia-I Wu4901db72016-03-24 16:38:58 +0800296
297 return result;
298}
299
300const std::bitset<ProcHook::EXTENSION_COUNT>&
Chia-I Wu3e6c2d62016-04-11 13:55:56 +0800301CreateInfoWrapper::GetHookExtensions() const {
Chia-I Wu4901db72016-03-24 16:38:58 +0800302 return hook_extensions_;
303}
304
305const std::bitset<ProcHook::EXTENSION_COUNT>&
Chia-I Wu3e6c2d62016-04-11 13:55:56 +0800306CreateInfoWrapper::GetHalExtensions() const {
Chia-I Wu4901db72016-03-24 16:38:58 +0800307 return hal_extensions_;
308}
309
Chia-I Wuff4a6c72016-03-24 16:05:56 +0800310CreateInfoWrapper::operator const VkInstanceCreateInfo*() const {
311 return &instance_info_;
312}
313
Chia-I Wu4901db72016-03-24 16:38:58 +0800314CreateInfoWrapper::operator const VkDeviceCreateInfo*() const {
315 return &dev_info_;
316}
317
Chia-I Wu3e6c2d62016-04-11 13:55:56 +0800318VkResult CreateInfoWrapper::SanitizePNext() {
Chia-I Wu4901db72016-03-24 16:38:58 +0800319 const struct StructHeader {
320 VkStructureType type;
321 const void* next;
322 } * header;
323
324 if (is_instance_) {
325 header = reinterpret_cast<const StructHeader*>(instance_info_.pNext);
326
327 // skip leading VK_STRUCTURE_TYPE_LOADER_INSTANCE_CREATE_INFOs
328 while (header &&
329 header->type == VK_STRUCTURE_TYPE_LOADER_INSTANCE_CREATE_INFO)
330 header = reinterpret_cast<const StructHeader*>(header->next);
331
332 instance_info_.pNext = header;
333 } else {
334 header = reinterpret_cast<const StructHeader*>(dev_info_.pNext);
335
336 // skip leading VK_STRUCTURE_TYPE_LOADER_DEVICE_CREATE_INFOs
337 while (header &&
338 header->type == VK_STRUCTURE_TYPE_LOADER_DEVICE_CREATE_INFO)
339 header = reinterpret_cast<const StructHeader*>(header->next);
340
341 dev_info_.pNext = header;
342 }
343
344 return VK_SUCCESS;
345}
346
Chia-I Wu3e6c2d62016-04-11 13:55:56 +0800347VkResult CreateInfoWrapper::SanitizeLayers() {
Chia-I Wu4901db72016-03-24 16:38:58 +0800348 auto& layer_names = (is_instance_) ? instance_info_.ppEnabledLayerNames
349 : dev_info_.ppEnabledLayerNames;
350 auto& layer_count = (is_instance_) ? instance_info_.enabledLayerCount
351 : dev_info_.enabledLayerCount;
352
353 // remove all layers
354 layer_names = nullptr;
355 layer_count = 0;
356
357 return VK_SUCCESS;
358}
359
Chia-I Wu3e6c2d62016-04-11 13:55:56 +0800360VkResult CreateInfoWrapper::SanitizeExtensions() {
Chia-I Wu4901db72016-03-24 16:38:58 +0800361 auto& ext_names = (is_instance_) ? instance_info_.ppEnabledExtensionNames
362 : dev_info_.ppEnabledExtensionNames;
363 auto& ext_count = (is_instance_) ? instance_info_.enabledExtensionCount
364 : dev_info_.enabledExtensionCount;
365 if (!ext_count)
366 return VK_SUCCESS;
367
Chia-I Wu3e6c2d62016-04-11 13:55:56 +0800368 VkResult result = InitExtensionFilter();
Chia-I Wu4901db72016-03-24 16:38:58 +0800369 if (result != VK_SUCCESS)
370 return result;
371
372 for (uint32_t i = 0; i < ext_count; i++)
Chia-I Wu3e6c2d62016-04-11 13:55:56 +0800373 FilterExtension(ext_names[i]);
Chia-I Wu4901db72016-03-24 16:38:58 +0800374
375 ext_names = extension_filter_.names;
376 ext_count = extension_filter_.name_count;
377
378 return VK_SUCCESS;
379}
380
Chia-I Wu3e6c2d62016-04-11 13:55:56 +0800381VkResult CreateInfoWrapper::QueryExtensionCount(uint32_t& count) const {
Chia-I Wu4901db72016-03-24 16:38:58 +0800382 if (is_instance_) {
Chia-I Wu31b2e4f2016-05-23 10:47:57 +0800383 return Hal::Device().EnumerateInstanceExtensionProperties(
384 nullptr, &count, nullptr);
Chia-I Wu4901db72016-03-24 16:38:58 +0800385 } else {
386 const auto& driver = GetData(physical_dev_).driver;
387 return driver.EnumerateDeviceExtensionProperties(physical_dev_, nullptr,
388 &count, nullptr);
389 }
390}
391
Chia-I Wu3e6c2d62016-04-11 13:55:56 +0800392VkResult CreateInfoWrapper::EnumerateExtensions(
Chia-I Wu4901db72016-03-24 16:38:58 +0800393 uint32_t& count,
394 VkExtensionProperties* props) const {
395 if (is_instance_) {
Chia-I Wu31b2e4f2016-05-23 10:47:57 +0800396 return Hal::Device().EnumerateInstanceExtensionProperties(
397 nullptr, &count, props);
Chia-I Wu4901db72016-03-24 16:38:58 +0800398 } else {
399 const auto& driver = GetData(physical_dev_).driver;
400 return driver.EnumerateDeviceExtensionProperties(physical_dev_, nullptr,
401 &count, props);
402 }
403}
404
Chia-I Wu3e6c2d62016-04-11 13:55:56 +0800405VkResult CreateInfoWrapper::InitExtensionFilter() {
Chia-I Wu4901db72016-03-24 16:38:58 +0800406 // query extension count
407 uint32_t count;
Chia-I Wu3e6c2d62016-04-11 13:55:56 +0800408 VkResult result = QueryExtensionCount(count);
Chia-I Wu4901db72016-03-24 16:38:58 +0800409 if (result != VK_SUCCESS || count == 0)
410 return result;
411
412 auto& filter = extension_filter_;
413 filter.exts =
414 reinterpret_cast<VkExtensionProperties*>(allocator_.pfnAllocation(
415 allocator_.pUserData, sizeof(VkExtensionProperties) * count,
416 alignof(VkExtensionProperties),
417 VK_SYSTEM_ALLOCATION_SCOPE_COMMAND));
418 if (!filter.exts)
419 return VK_ERROR_OUT_OF_HOST_MEMORY;
420
421 // enumerate extensions
Chia-I Wu3e6c2d62016-04-11 13:55:56 +0800422 result = EnumerateExtensions(count, filter.exts);
Chia-I Wu4901db72016-03-24 16:38:58 +0800423 if (result != VK_SUCCESS && result != VK_INCOMPLETE)
424 return result;
425
426 if (!count)
427 return VK_SUCCESS;
428
429 filter.ext_count = count;
430
431 // allocate name array
432 uint32_t enabled_ext_count = (is_instance_)
433 ? instance_info_.enabledExtensionCount
434 : dev_info_.enabledExtensionCount;
435 count = std::min(filter.ext_count, enabled_ext_count);
436 filter.names = reinterpret_cast<const char**>(allocator_.pfnAllocation(
437 allocator_.pUserData, sizeof(const char*) * count, alignof(const char*),
438 VK_SYSTEM_ALLOCATION_SCOPE_COMMAND));
439 if (!filter.names)
440 return VK_ERROR_OUT_OF_HOST_MEMORY;
441
442 return VK_SUCCESS;
443}
444
Chia-I Wu3e6c2d62016-04-11 13:55:56 +0800445void CreateInfoWrapper::FilterExtension(const char* name) {
Chia-I Wu4901db72016-03-24 16:38:58 +0800446 auto& filter = extension_filter_;
447
448 ProcHook::Extension ext_bit = GetProcHookExtension(name);
449 if (is_instance_) {
450 switch (ext_bit) {
451 case ProcHook::KHR_android_surface:
452 case ProcHook::KHR_surface:
Courtney Goeltzenleuchtere278daf2017-02-02 16:54:57 -0700453 case ProcHook::EXT_swapchain_colorspace:
Chris Forbes2452cf72017-03-16 16:30:17 +1300454 case ProcHook::KHR_get_surface_capabilities2:
Chia-I Wu4901db72016-03-24 16:38:58 +0800455 hook_extensions_.set(ext_bit);
456 // return now as these extensions do not require HAL support
457 return;
458 case ProcHook::EXT_debug_report:
459 // both we and HAL can take part in
460 hook_extensions_.set(ext_bit);
461 break;
462 case ProcHook::EXTENSION_UNKNOWN:
Chris Forbes6aa30db2017-02-20 17:12:53 +1300463 case ProcHook::KHR_get_physical_device_properties2:
Chia-I Wu4901db72016-03-24 16:38:58 +0800464 // HAL's extensions
465 break;
466 default:
467 ALOGW("Ignored invalid instance extension %s", name);
468 return;
469 }
470 } else {
471 switch (ext_bit) {
472 case ProcHook::KHR_swapchain:
473 // map VK_KHR_swapchain to VK_ANDROID_native_buffer
474 name = VK_ANDROID_NATIVE_BUFFER_EXTENSION_NAME;
475 ext_bit = ProcHook::ANDROID_native_buffer;
476 break;
Ian Elliott9e853732017-02-03 11:24:07 -0700477 case ProcHook::KHR_incremental_present:
Ian Elliott8a977262017-01-19 09:05:58 -0700478 case ProcHook::GOOGLE_display_timing:
Chris Forbesfa25e632017-02-22 12:36:02 +1300479 case ProcHook::KHR_shared_presentable_image:
Ian Elliott8a977262017-01-19 09:05:58 -0700480 hook_extensions_.set(ext_bit);
481 // return now as these extensions do not require HAL support
482 return;
Courtney Goeltzenleuchterd634c482017-01-05 15:55:31 -0700483 case ProcHook::EXT_hdr_metadata:
484 hook_extensions_.set(ext_bit);
485 break;
Chia-I Wu4901db72016-03-24 16:38:58 +0800486 case ProcHook::EXTENSION_UNKNOWN:
487 // HAL's extensions
488 break;
489 default:
490 ALOGW("Ignored invalid device extension %s", name);
491 return;
492 }
493 }
494
495 for (uint32_t i = 0; i < filter.ext_count; i++) {
496 const VkExtensionProperties& props = filter.exts[i];
497 // ignore unknown extensions
498 if (strcmp(name, props.extensionName) != 0)
499 continue;
500
Chia-I Wu4901db72016-03-24 16:38:58 +0800501 filter.names[filter.name_count++] = name;
Chia-I Wu1600e262016-04-12 09:40:06 +0800502 if (ext_bit != ProcHook::EXTENSION_UNKNOWN) {
503 if (ext_bit == ProcHook::ANDROID_native_buffer)
504 hook_extensions_.set(ProcHook::KHR_swapchain);
505
506 hal_extensions_.set(ext_bit);
507 }
Chia-I Wu4901db72016-03-24 16:38:58 +0800508
509 break;
510 }
511}
512
Chia-I Wudbb7e9c2016-03-24 15:09:38 +0800513VKAPI_ATTR void* DefaultAllocate(void*,
514 size_t size,
515 size_t alignment,
516 VkSystemAllocationScope) {
517 void* ptr = nullptr;
518 // Vulkan requires 'alignment' to be a power of two, but posix_memalign
519 // additionally requires that it be at least sizeof(void*).
520 int ret = posix_memalign(&ptr, std::max(alignment, sizeof(void*)), size);
521 ALOGD_CALLSTACK("Allocate: size=%zu align=%zu => (%d) %p", size, alignment,
522 ret, ptr);
523 return ret == 0 ? ptr : nullptr;
524}
525
526VKAPI_ATTR void* DefaultReallocate(void*,
527 void* ptr,
528 size_t size,
529 size_t alignment,
530 VkSystemAllocationScope) {
531 if (size == 0) {
532 free(ptr);
533 return nullptr;
534 }
535
536 // TODO(jessehall): Right now we never shrink allocations; if the new
537 // request is smaller than the existing chunk, we just continue using it.
538 // Right now the loader never reallocs, so this doesn't matter. If that
539 // changes, or if this code is copied into some other project, this should
540 // probably have a heuristic to allocate-copy-free when doing so will save
541 // "enough" space.
542 size_t old_size = ptr ? malloc_usable_size(ptr) : 0;
543 if (size <= old_size)
544 return ptr;
545
546 void* new_ptr = nullptr;
547 if (posix_memalign(&new_ptr, std::max(alignment, sizeof(void*)), size) != 0)
548 return nullptr;
549 if (ptr) {
550 memcpy(new_ptr, ptr, std::min(old_size, size));
551 free(ptr);
552 }
553 return new_ptr;
554}
555
556VKAPI_ATTR void DefaultFree(void*, void* ptr) {
557 ALOGD_CALLSTACK("Free: %p", ptr);
558 free(ptr);
559}
560
Chia-I Wuff4a6c72016-03-24 16:05:56 +0800561InstanceData* AllocateInstanceData(const VkAllocationCallbacks& allocator) {
562 void* data_mem = allocator.pfnAllocation(
563 allocator.pUserData, sizeof(InstanceData), alignof(InstanceData),
564 VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
565 if (!data_mem)
566 return nullptr;
567
568 return new (data_mem) InstanceData(allocator);
569}
570
571void FreeInstanceData(InstanceData* data,
572 const VkAllocationCallbacks& allocator) {
573 data->~InstanceData();
574 allocator.pfnFree(allocator.pUserData, data);
575}
576
Chia-I Wu950d6e12016-05-03 09:12:35 +0800577DeviceData* AllocateDeviceData(
578 const VkAllocationCallbacks& allocator,
579 const DebugReportCallbackList& debug_report_callbacks) {
Chia-I Wu4901db72016-03-24 16:38:58 +0800580 void* data_mem = allocator.pfnAllocation(
581 allocator.pUserData, sizeof(DeviceData), alignof(DeviceData),
582 VK_SYSTEM_ALLOCATION_SCOPE_DEVICE);
583 if (!data_mem)
584 return nullptr;
585
Chia-I Wu950d6e12016-05-03 09:12:35 +0800586 return new (data_mem) DeviceData(allocator, debug_report_callbacks);
Chia-I Wu4901db72016-03-24 16:38:58 +0800587}
588
589void FreeDeviceData(DeviceData* data, const VkAllocationCallbacks& allocator) {
590 data->~DeviceData();
591 allocator.pfnFree(allocator.pUserData, data);
592}
593
Chia-I Wu136b8eb2016-03-24 15:01:52 +0800594} // anonymous namespace
595
Chia-I Wu9d518162016-03-24 14:55:27 +0800596bool Debuggable() {
597 return (prctl(PR_GET_DUMPABLE, 0, 0, 0, 0) >= 0);
598}
599
Chia-I Wu136b8eb2016-03-24 15:01:52 +0800600bool OpenHAL() {
Chia-I Wu31b2e4f2016-05-23 10:47:57 +0800601 return Hal::Open();
Chia-I Wu136b8eb2016-03-24 15:01:52 +0800602}
603
Chia-I Wudbb7e9c2016-03-24 15:09:38 +0800604const VkAllocationCallbacks& GetDefaultAllocator() {
605 static const VkAllocationCallbacks kDefaultAllocCallbacks = {
606 .pUserData = nullptr,
607 .pfnAllocation = DefaultAllocate,
608 .pfnReallocation = DefaultReallocate,
609 .pfnFree = DefaultFree,
610 };
611
612 return kDefaultAllocCallbacks;
613}
614
Chia-I Wueb7db122016-03-24 09:11:06 +0800615PFN_vkVoidFunction GetInstanceProcAddr(VkInstance instance, const char* pName) {
616 const ProcHook* hook = GetProcHook(pName);
617 if (!hook)
Chia-I Wu31b2e4f2016-05-23 10:47:57 +0800618 return Hal::Device().GetInstanceProcAddr(instance, pName);
Chia-I Wueb7db122016-03-24 09:11:06 +0800619
620 if (!instance) {
621 if (hook->type == ProcHook::GLOBAL)
622 return hook->proc;
623
Chia-I Wu109f8982016-04-22 06:40:40 +0800624 // v0 layers expect
625 //
626 // vkGetInstanceProcAddr(VK_NULL_HANDLE, "vkCreateDevice");
627 //
628 // to work.
629 if (strcmp(pName, "vkCreateDevice") == 0)
630 return hook->proc;
631
Chia-I Wueb7db122016-03-24 09:11:06 +0800632 ALOGE(
Chia-I Wue201c3f2016-05-03 13:26:08 +0800633 "internal vkGetInstanceProcAddr called for %s without an instance",
Chia-I Wueb7db122016-03-24 09:11:06 +0800634 pName);
635
Chia-I Wu109f8982016-04-22 06:40:40 +0800636 return nullptr;
Chia-I Wueb7db122016-03-24 09:11:06 +0800637 }
638
639 PFN_vkVoidFunction proc;
640
641 switch (hook->type) {
642 case ProcHook::INSTANCE:
643 proc = (GetData(instance).hook_extensions[hook->extension])
644 ? hook->proc
Chia-I Wu36cc00a2016-04-13 16:52:06 +0800645 : nullptr;
Chia-I Wueb7db122016-03-24 09:11:06 +0800646 break;
647 case ProcHook::DEVICE:
648 proc = (hook->extension == ProcHook::EXTENSION_CORE)
649 ? hook->proc
650 : hook->checked_proc;
651 break;
652 default:
653 ALOGE(
Chia-I Wue201c3f2016-05-03 13:26:08 +0800654 "internal vkGetInstanceProcAddr called for %s with an instance",
Chia-I Wueb7db122016-03-24 09:11:06 +0800655 pName);
656 proc = nullptr;
657 break;
658 }
659
660 return proc;
661}
662
663PFN_vkVoidFunction GetDeviceProcAddr(VkDevice device, const char* pName) {
664 const ProcHook* hook = GetProcHook(pName);
665 if (!hook)
Chia-I Wucc5e2762016-03-24 13:01:16 +0800666 return GetData(device).driver.GetDeviceProcAddr(device, pName);
Chia-I Wueb7db122016-03-24 09:11:06 +0800667
668 if (hook->type != ProcHook::DEVICE) {
Chia-I Wue201c3f2016-05-03 13:26:08 +0800669 ALOGE("internal vkGetDeviceProcAddr called for %s", pName);
Chia-I Wueb7db122016-03-24 09:11:06 +0800670 return nullptr;
671 }
672
Chia-I Wu36cc00a2016-04-13 16:52:06 +0800673 return (GetData(device).hook_extensions[hook->extension]) ? hook->proc
674 : nullptr;
Chia-I Wueb7db122016-03-24 09:11:06 +0800675}
676
Chia-I Wuff4a6c72016-03-24 16:05:56 +0800677VkResult EnumerateInstanceExtensionProperties(
678 const char* pLayerName,
679 uint32_t* pPropertyCount,
680 VkExtensionProperties* pProperties) {
Ian Elliott34a327b2017-03-28 13:20:35 -0600681
682 android::Vector<VkExtensionProperties> loader_extensions;
683 loader_extensions.push_back({
684 VK_KHR_SURFACE_EXTENSION_NAME,
685 VK_KHR_SURFACE_SPEC_VERSION});
686 loader_extensions.push_back({
687 VK_KHR_ANDROID_SURFACE_EXTENSION_NAME,
688 VK_KHR_ANDROID_SURFACE_SPEC_VERSION});
689 loader_extensions.push_back({
690 VK_EXT_SWAPCHAIN_COLOR_SPACE_EXTENSION_NAME,
691 VK_EXT_SWAPCHAIN_COLOR_SPACE_SPEC_VERSION});
692
693 if (kEnableUnratifiedExtensions) {
694 loader_extensions.push_back({
695 VK_KHR_GET_SURFACE_CAPABILITIES_2_EXTENSION_NAME,
696 VK_KHR_GET_SURFACE_CAPABILITIES_2_SPEC_VERSION});
697 }
698
Chia-I Wu31938252016-05-23 15:31:02 +0800699 static const VkExtensionProperties loader_debug_report_extension = {
700 VK_EXT_DEBUG_REPORT_EXTENSION_NAME, VK_EXT_DEBUG_REPORT_SPEC_VERSION,
701 };
Chia-I Wuff4a6c72016-03-24 16:05:56 +0800702
703 // enumerate our extensions first
704 if (!pLayerName && pProperties) {
705 uint32_t count = std::min(
706 *pPropertyCount, static_cast<uint32_t>(loader_extensions.size()));
707
708 std::copy_n(loader_extensions.begin(), count, pProperties);
709
710 if (count < loader_extensions.size()) {
711 *pPropertyCount = count;
712 return VK_INCOMPLETE;
713 }
714
715 pProperties += count;
716 *pPropertyCount -= count;
Chia-I Wu31938252016-05-23 15:31:02 +0800717
718 if (Hal::Get().GetDebugReportIndex() < 0) {
719 if (!*pPropertyCount) {
720 *pPropertyCount = count;
721 return VK_INCOMPLETE;
722 }
723
724 pProperties[0] = loader_debug_report_extension;
725 pProperties += 1;
726 *pPropertyCount -= 1;
727 }
Chia-I Wuff4a6c72016-03-24 16:05:56 +0800728 }
729
Chia-I Wu31b2e4f2016-05-23 10:47:57 +0800730 VkResult result = Hal::Device().EnumerateInstanceExtensionProperties(
Chia-I Wuff4a6c72016-03-24 16:05:56 +0800731 pLayerName, pPropertyCount, pProperties);
732
Chia-I Wu31938252016-05-23 15:31:02 +0800733 if (!pLayerName && (result == VK_SUCCESS || result == VK_INCOMPLETE)) {
734 int idx = Hal::Get().GetDebugReportIndex();
735 if (idx < 0) {
736 *pPropertyCount += 1;
737 } else if (pProperties &&
738 static_cast<uint32_t>(idx) < *pPropertyCount) {
739 pProperties[idx].specVersion =
740 std::min(pProperties[idx].specVersion,
741 loader_debug_report_extension.specVersion);
742 }
743
Chia-I Wuff4a6c72016-03-24 16:05:56 +0800744 *pPropertyCount += loader_extensions.size();
Chia-I Wu31938252016-05-23 15:31:02 +0800745 }
Chia-I Wuff4a6c72016-03-24 16:05:56 +0800746
747 return result;
748}
749
Chris Forbesfa25e632017-02-22 12:36:02 +1300750bool QueryPresentationProperties(
751 VkPhysicalDevice physicalDevice,
752 VkPhysicalDevicePresentationPropertiesANDROID *presentation_properties)
753{
754 const InstanceData& data = GetData(physicalDevice);
755
756 // GPDP2 must be present and enabled on the instance.
757 if (!data.driver.GetPhysicalDeviceProperties2KHR)
758 return false;
759
760 // Request the android-specific presentation properties via GPDP2
761 VkPhysicalDeviceProperties2KHR properties = {
762 VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2_KHR,
763 presentation_properties,
764 {}
765 };
766
767#pragma clang diagnostic push
768#pragma clang diagnostic ignored "-Wold-style-cast"
769 presentation_properties->sType =
770 VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PRESENTATION_PROPERTIES_ANDROID;
771#pragma clang diagnostic pop
772 presentation_properties->pNext = nullptr;
773 presentation_properties->sharedImage = VK_FALSE;
774
775 data.driver.GetPhysicalDeviceProperties2KHR(physicalDevice,
776 &properties);
777
778 return true;
779}
780
Chia-I Wu01cf3052016-03-24 16:16:21 +0800781VkResult EnumerateDeviceExtensionProperties(
782 VkPhysicalDevice physicalDevice,
783 const char* pLayerName,
784 uint32_t* pPropertyCount,
785 VkExtensionProperties* pProperties) {
786 const InstanceData& data = GetData(physicalDevice);
Chris Forbesfa25e632017-02-22 12:36:02 +1300787 // extensions that are unconditionally exposed by the loader
788 android::Vector<VkExtensionProperties> loader_extensions;
789 loader_extensions.push_back({
790 VK_KHR_INCREMENTAL_PRESENT_EXTENSION_NAME,
791 VK_KHR_INCREMENTAL_PRESENT_SPEC_VERSION});
792 loader_extensions.push_back({
793 VK_GOOGLE_DISPLAY_TIMING_EXTENSION_NAME,
794 VK_GOOGLE_DISPLAY_TIMING_SPEC_VERSION});
Chris Forbesfa25e632017-02-22 12:36:02 +1300795
Ian Elliott34a327b2017-03-28 13:20:35 -0600796 if (kEnableUnratifiedExtensions) {
797 // conditionally add shared_presentable_image if supportable
798 VkPhysicalDevicePresentationPropertiesANDROID presentation_properties;
799 if (QueryPresentationProperties(physicalDevice, &presentation_properties) &&
800 presentation_properties.sharedImage) {
801 loader_extensions.push_back({
802 VK_KHR_SHARED_PRESENTABLE_IMAGE_EXTENSION_NAME,
803 VK_KHR_SHARED_PRESENTABLE_IMAGE_SPEC_VERSION});
804 }
Chris Forbesfa25e632017-02-22 12:36:02 +1300805 }
Ian Elliottd4b50aa2017-01-09 16:21:36 -0700806
807 // enumerate our extensions first
808 if (!pLayerName && pProperties) {
809 uint32_t count = std::min(
810 *pPropertyCount, static_cast<uint32_t>(loader_extensions.size()));
811
812 std::copy_n(loader_extensions.begin(), count, pProperties);
813
814 if (count < loader_extensions.size()) {
815 *pPropertyCount = count;
816 return VK_INCOMPLETE;
817 }
818
819 pProperties += count;
820 *pPropertyCount -= count;
821 }
Chia-I Wu01cf3052016-03-24 16:16:21 +0800822
823 VkResult result = data.driver.EnumerateDeviceExtensionProperties(
824 physicalDevice, pLayerName, pPropertyCount, pProperties);
Chia-I Wu01cf3052016-03-24 16:16:21 +0800825
Ian Elliottd4b50aa2017-01-09 16:21:36 -0700826 if (pProperties) {
827 // map VK_ANDROID_native_buffer to VK_KHR_swapchain
828 for (uint32_t i = 0; i < *pPropertyCount; i++) {
829 auto& prop = pProperties[i];
Chia-I Wu01cf3052016-03-24 16:16:21 +0800830
Ian Elliottd4b50aa2017-01-09 16:21:36 -0700831 if (strcmp(prop.extensionName,
832 VK_ANDROID_NATIVE_BUFFER_EXTENSION_NAME) != 0)
833 continue;
Chia-I Wu01cf3052016-03-24 16:16:21 +0800834
Ian Elliottd4b50aa2017-01-09 16:21:36 -0700835 memcpy(prop.extensionName, VK_KHR_SWAPCHAIN_EXTENSION_NAME,
836 sizeof(VK_KHR_SWAPCHAIN_EXTENSION_NAME));
837 prop.specVersion = VK_KHR_SWAPCHAIN_SPEC_VERSION;
838 }
839 }
Chia-I Wu01cf3052016-03-24 16:16:21 +0800840
Ian Elliottd4b50aa2017-01-09 16:21:36 -0700841 // restore loader extension count
842 if (!pLayerName && (result == VK_SUCCESS || result == VK_INCOMPLETE)) {
843 *pPropertyCount += loader_extensions.size();
Chia-I Wu01cf3052016-03-24 16:16:21 +0800844 }
845
846 return result;
847}
848
Chia-I Wuff4a6c72016-03-24 16:05:56 +0800849VkResult CreateInstance(const VkInstanceCreateInfo* pCreateInfo,
850 const VkAllocationCallbacks* pAllocator,
851 VkInstance* pInstance) {
852 const VkAllocationCallbacks& data_allocator =
853 (pAllocator) ? *pAllocator : GetDefaultAllocator();
854
Chia-I Wu31b2e4f2016-05-23 10:47:57 +0800855 CreateInfoWrapper wrapper(*pCreateInfo, data_allocator);
Chia-I Wu3e6c2d62016-04-11 13:55:56 +0800856 VkResult result = wrapper.Validate();
Chia-I Wuff4a6c72016-03-24 16:05:56 +0800857 if (result != VK_SUCCESS)
858 return result;
859
860 InstanceData* data = AllocateInstanceData(data_allocator);
861 if (!data)
862 return VK_ERROR_OUT_OF_HOST_MEMORY;
863
Chia-I Wu3e6c2d62016-04-11 13:55:56 +0800864 data->hook_extensions |= wrapper.GetHookExtensions();
Chia-I Wuff4a6c72016-03-24 16:05:56 +0800865
866 // call into the driver
867 VkInstance instance;
Chia-I Wu31b2e4f2016-05-23 10:47:57 +0800868 result = Hal::Device().CreateInstance(
Chia-I Wuff4a6c72016-03-24 16:05:56 +0800869 static_cast<const VkInstanceCreateInfo*>(wrapper), pAllocator,
870 &instance);
871 if (result != VK_SUCCESS) {
872 FreeInstanceData(data, data_allocator);
873 return result;
874 }
875
876 // initialize InstanceDriverTable
877 if (!SetData(instance, *data) ||
Chia-I Wu31b2e4f2016-05-23 10:47:57 +0800878 !InitDriverTable(instance, Hal::Device().GetInstanceProcAddr,
Chia-I Wucbe07ef2016-04-13 15:01:00 +0800879 wrapper.GetHalExtensions())) {
Chia-I Wuff4a6c72016-03-24 16:05:56 +0800880 data->driver.DestroyInstance = reinterpret_cast<PFN_vkDestroyInstance>(
Chia-I Wu31b2e4f2016-05-23 10:47:57 +0800881 Hal::Device().GetInstanceProcAddr(instance, "vkDestroyInstance"));
Chia-I Wuff4a6c72016-03-24 16:05:56 +0800882 if (data->driver.DestroyInstance)
883 data->driver.DestroyInstance(instance, pAllocator);
884
885 FreeInstanceData(data, data_allocator);
886
887 return VK_ERROR_INCOMPATIBLE_DRIVER;
888 }
889
890 data->get_device_proc_addr = reinterpret_cast<PFN_vkGetDeviceProcAddr>(
Chia-I Wu31b2e4f2016-05-23 10:47:57 +0800891 Hal::Device().GetInstanceProcAddr(instance, "vkGetDeviceProcAddr"));
Chia-I Wuff4a6c72016-03-24 16:05:56 +0800892 if (!data->get_device_proc_addr) {
893 data->driver.DestroyInstance(instance, pAllocator);
894 FreeInstanceData(data, data_allocator);
895
896 return VK_ERROR_INCOMPATIBLE_DRIVER;
897 }
898
899 *pInstance = instance;
900
901 return VK_SUCCESS;
902}
903
904void DestroyInstance(VkInstance instance,
905 const VkAllocationCallbacks* pAllocator) {
906 InstanceData& data = GetData(instance);
907 data.driver.DestroyInstance(instance, pAllocator);
908
909 VkAllocationCallbacks local_allocator;
910 if (!pAllocator) {
911 local_allocator = data.allocator;
912 pAllocator = &local_allocator;
913 }
914
915 FreeInstanceData(&data, *pAllocator);
916}
917
Chia-I Wu4901db72016-03-24 16:38:58 +0800918VkResult CreateDevice(VkPhysicalDevice physicalDevice,
919 const VkDeviceCreateInfo* pCreateInfo,
920 const VkAllocationCallbacks* pAllocator,
921 VkDevice* pDevice) {
922 const InstanceData& instance_data = GetData(physicalDevice);
923 const VkAllocationCallbacks& data_allocator =
924 (pAllocator) ? *pAllocator : instance_data.allocator;
925
926 CreateInfoWrapper wrapper(physicalDevice, *pCreateInfo, data_allocator);
Chia-I Wu3e6c2d62016-04-11 13:55:56 +0800927 VkResult result = wrapper.Validate();
Chia-I Wu4901db72016-03-24 16:38:58 +0800928 if (result != VK_SUCCESS)
929 return result;
930
Chia-I Wu950d6e12016-05-03 09:12:35 +0800931 DeviceData* data = AllocateDeviceData(data_allocator,
932 instance_data.debug_report_callbacks);
Chia-I Wu4901db72016-03-24 16:38:58 +0800933 if (!data)
934 return VK_ERROR_OUT_OF_HOST_MEMORY;
935
Chia-I Wu3e6c2d62016-04-11 13:55:56 +0800936 data->hook_extensions |= wrapper.GetHookExtensions();
Chia-I Wu4901db72016-03-24 16:38:58 +0800937
938 // call into the driver
939 VkDevice dev;
940 result = instance_data.driver.CreateDevice(
941 physicalDevice, static_cast<const VkDeviceCreateInfo*>(wrapper),
942 pAllocator, &dev);
943 if (result != VK_SUCCESS) {
944 FreeDeviceData(data, data_allocator);
945 return result;
946 }
947
948 // initialize DeviceDriverTable
949 if (!SetData(dev, *data) ||
Chia-I Wucbe07ef2016-04-13 15:01:00 +0800950 !InitDriverTable(dev, instance_data.get_device_proc_addr,
951 wrapper.GetHalExtensions())) {
Chia-I Wu4901db72016-03-24 16:38:58 +0800952 data->driver.DestroyDevice = reinterpret_cast<PFN_vkDestroyDevice>(
953 instance_data.get_device_proc_addr(dev, "vkDestroyDevice"));
954 if (data->driver.DestroyDevice)
955 data->driver.DestroyDevice(dev, pAllocator);
956
957 FreeDeviceData(data, data_allocator);
958
959 return VK_ERROR_INCOMPATIBLE_DRIVER;
960 }
Chris Forbesd8277912017-02-10 14:59:59 +1300961
962 // sanity check ANDROID_native_buffer implementation, whose set of
963 // entrypoints varies according to the spec version.
964 if ((wrapper.GetHalExtensions()[ProcHook::ANDROID_native_buffer]) &&
965 !data->driver.GetSwapchainGrallocUsageANDROID &&
966 !data->driver.GetSwapchainGrallocUsage2ANDROID) {
967 ALOGE("Driver's implementation of ANDROID_native_buffer is broken;"
968 " must expose at least one of "
969 "vkGetSwapchainGrallocUsageANDROID or "
970 "vkGetSwapchainGrallocUsage2ANDROID");
971
972 data->driver.DestroyDevice(dev, pAllocator);
973 FreeDeviceData(data, data_allocator);
974
975 return VK_ERROR_INCOMPATIBLE_DRIVER;
976 }
977
Jesse Hall85bb0c52017-02-09 22:13:02 -0800978 VkPhysicalDeviceProperties properties;
979 instance_data.driver.GetPhysicalDeviceProperties(physicalDevice,
980 &properties);
981
Jesse Halldc225072016-05-30 22:40:14 -0700982 data->driver_device = dev;
Jesse Hall85bb0c52017-02-09 22:13:02 -0800983 data->driver_version = properties.driverVersion;
Chia-I Wu4901db72016-03-24 16:38:58 +0800984
985 *pDevice = dev;
986
987 return VK_SUCCESS;
988}
989
990void DestroyDevice(VkDevice device, const VkAllocationCallbacks* pAllocator) {
991 DeviceData& data = GetData(device);
992 data.driver.DestroyDevice(device, pAllocator);
993
994 VkAllocationCallbacks local_allocator;
995 if (!pAllocator) {
996 local_allocator = data.allocator;
997 pAllocator = &local_allocator;
998 }
999
1000 FreeDeviceData(&data, *pAllocator);
1001}
1002
Chia-I Wuff4a6c72016-03-24 16:05:56 +08001003VkResult EnumeratePhysicalDevices(VkInstance instance,
1004 uint32_t* pPhysicalDeviceCount,
1005 VkPhysicalDevice* pPhysicalDevices) {
1006 const auto& data = GetData(instance);
1007
1008 VkResult result = data.driver.EnumeratePhysicalDevices(
1009 instance, pPhysicalDeviceCount, pPhysicalDevices);
1010 if ((result == VK_SUCCESS || result == VK_INCOMPLETE) && pPhysicalDevices) {
1011 for (uint32_t i = 0; i < *pPhysicalDeviceCount; i++)
1012 SetData(pPhysicalDevices[i], data);
1013 }
1014
1015 return result;
1016}
1017
Chia-I Wuba0be412016-03-24 16:24:40 +08001018void GetDeviceQueue(VkDevice device,
1019 uint32_t queueFamilyIndex,
1020 uint32_t queueIndex,
1021 VkQueue* pQueue) {
1022 const auto& data = GetData(device);
1023
1024 data.driver.GetDeviceQueue(device, queueFamilyIndex, queueIndex, pQueue);
1025 SetData(*pQueue, data);
1026}
1027
Chia-I Wu6a58a8a2016-03-24 16:29:51 +08001028VKAPI_ATTR VkResult
1029AllocateCommandBuffers(VkDevice device,
1030 const VkCommandBufferAllocateInfo* pAllocateInfo,
1031 VkCommandBuffer* pCommandBuffers) {
1032 const auto& data = GetData(device);
1033
1034 VkResult result = data.driver.AllocateCommandBuffers(device, pAllocateInfo,
1035 pCommandBuffers);
1036 if (result == VK_SUCCESS) {
1037 for (uint32_t i = 0; i < pAllocateInfo->commandBufferCount; i++)
1038 SetData(pCommandBuffers[i], data);
1039 }
1040
1041 return result;
1042}
1043
Chia-I Wu9d518162016-03-24 14:55:27 +08001044} // namespace driver
1045} // namespace vulkan