blob: 38e7b4328c39616dfb7bfe472c6f4bb29a119fa8 [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>
Jesse Hall53457db2016-12-14 16:54:06 -080032
Chia-I Wu9d518162016-03-24 14:55:27 +080033#include "driver.h"
Jesse Hallb7c4e3b2016-04-11 13:51:38 -070034#include "stubhal.h"
Chia-I Wu9d518162016-03-24 14:55:27 +080035
Chia-I Wudbb7e9c2016-03-24 15:09:38 +080036// #define ENABLE_ALLOC_CALLSTACKS 1
37#if ENABLE_ALLOC_CALLSTACKS
38#include <utils/CallStack.h>
39#define ALOGD_CALLSTACK(...) \
40 do { \
41 ALOGD(__VA_ARGS__); \
42 android::CallStack callstack; \
43 callstack.update(); \
44 callstack.log(LOG_TAG, ANDROID_LOG_DEBUG, " "); \
45 } while (false)
46#else
47#define ALOGD_CALLSTACK(...) \
48 do { \
49 } while (false)
50#endif
51
Chia-I Wu9d518162016-03-24 14:55:27 +080052namespace vulkan {
53namespace driver {
54
Chia-I Wu136b8eb2016-03-24 15:01:52 +080055namespace {
56
Chia-I Wu31b2e4f2016-05-23 10:47:57 +080057class Hal {
58 public:
59 static bool Open();
60
61 static const Hal& Get() { return hal_; }
62 static const hwvulkan_device_t& Device() { return *Get().dev_; }
63
Chia-I Wu31938252016-05-23 15:31:02 +080064 int GetDebugReportIndex() const { return debug_report_index_; }
65
Chia-I Wu31b2e4f2016-05-23 10:47:57 +080066 private:
Chia-I Wu31938252016-05-23 15:31:02 +080067 Hal() : dev_(nullptr), debug_report_index_(-1) {}
Chia-I Wu31b2e4f2016-05-23 10:47:57 +080068 Hal(const Hal&) = delete;
69 Hal& operator=(const Hal&) = delete;
70
Chia-I Wu31938252016-05-23 15:31:02 +080071 bool InitDebugReportIndex();
72
Chia-I Wu31b2e4f2016-05-23 10:47:57 +080073 static Hal hal_;
74
75 const hwvulkan_device_t* dev_;
Chia-I Wu31938252016-05-23 15:31:02 +080076 int debug_report_index_;
Chia-I Wu31b2e4f2016-05-23 10:47:57 +080077};
78
Chia-I Wu4901db72016-03-24 16:38:58 +080079class CreateInfoWrapper {
80 public:
Chia-I Wu31b2e4f2016-05-23 10:47:57 +080081 CreateInfoWrapper(const VkInstanceCreateInfo& create_info,
Chia-I Wuff4a6c72016-03-24 16:05:56 +080082 const VkAllocationCallbacks& allocator);
Chia-I Wu4901db72016-03-24 16:38:58 +080083 CreateInfoWrapper(VkPhysicalDevice physical_dev,
84 const VkDeviceCreateInfo& create_info,
85 const VkAllocationCallbacks& allocator);
86 ~CreateInfoWrapper();
87
Chia-I Wu3e6c2d62016-04-11 13:55:56 +080088 VkResult Validate();
Chia-I Wu4901db72016-03-24 16:38:58 +080089
Chia-I Wu3e6c2d62016-04-11 13:55:56 +080090 const std::bitset<ProcHook::EXTENSION_COUNT>& GetHookExtensions() const;
91 const std::bitset<ProcHook::EXTENSION_COUNT>& GetHalExtensions() const;
Chia-I Wu4901db72016-03-24 16:38:58 +080092
Chia-I Wuff4a6c72016-03-24 16:05:56 +080093 explicit operator const VkInstanceCreateInfo*() const;
Chia-I Wu4901db72016-03-24 16:38:58 +080094 explicit operator const VkDeviceCreateInfo*() const;
95
96 private:
97 struct ExtensionFilter {
98 VkExtensionProperties* exts;
99 uint32_t ext_count;
100
101 const char** names;
102 uint32_t name_count;
103 };
104
Chia-I Wu3e6c2d62016-04-11 13:55:56 +0800105 VkResult SanitizePNext();
Chia-I Wu4901db72016-03-24 16:38:58 +0800106
Chia-I Wu3e6c2d62016-04-11 13:55:56 +0800107 VkResult SanitizeLayers();
108 VkResult SanitizeExtensions();
Chia-I Wu4901db72016-03-24 16:38:58 +0800109
Chia-I Wu3e6c2d62016-04-11 13:55:56 +0800110 VkResult QueryExtensionCount(uint32_t& count) const;
111 VkResult EnumerateExtensions(uint32_t& count,
112 VkExtensionProperties* props) const;
113 VkResult InitExtensionFilter();
114 void FilterExtension(const char* name);
Chia-I Wu4901db72016-03-24 16:38:58 +0800115
116 const bool is_instance_;
117 const VkAllocationCallbacks& allocator_;
118
Chia-I Wu31b2e4f2016-05-23 10:47:57 +0800119 VkPhysicalDevice physical_dev_;
Chia-I Wu4901db72016-03-24 16:38:58 +0800120
121 union {
122 VkInstanceCreateInfo instance_info_;
123 VkDeviceCreateInfo dev_info_;
124 };
125
126 ExtensionFilter extension_filter_;
127
128 std::bitset<ProcHook::EXTENSION_COUNT> hook_extensions_;
129 std::bitset<ProcHook::EXTENSION_COUNT> hal_extensions_;
130};
131
Chia-I Wu31b2e4f2016-05-23 10:47:57 +0800132Hal Hal::hal_;
133
Jesse Hall53457db2016-12-14 16:54:06 -0800134void* LoadLibrary(const android_dlextinfo& dlextinfo,
135 const char* subname,
136 int subname_len) {
137 const char kLibFormat[] = "vulkan.%*s.so";
138 char* name = static_cast<char*>(
139 alloca(sizeof(kLibFormat) + static_cast<size_t>(subname_len)));
140 sprintf(name, kLibFormat, subname_len, subname);
141 return android_dlopen_ext(name, RTLD_LOCAL | RTLD_NOW, &dlextinfo);
142}
143
144const std::array<const char*, 2> HAL_SUBNAME_KEY_PROPERTIES = {{
145 "ro.hardware." HWVULKAN_HARDWARE_MODULE_ID,
146 "ro.board.platform",
147}};
148
149int LoadUpdatedDriver(const hw_module_t** module) {
150 const android_dlextinfo dlextinfo = {
151 .flags = ANDROID_DLEXT_USE_NAMESPACE,
152 .library_namespace = android::GraphicsEnv::getInstance().getDriverNamespace(),
153 };
154 if (!dlextinfo.library_namespace)
155 return -ENOENT;
156
157 void* so = nullptr;
158 char prop[PROPERTY_VALUE_MAX];
159 for (auto key : HAL_SUBNAME_KEY_PROPERTIES) {
160 int prop_len = property_get(key, prop, nullptr);
161 if (prop_len > 0) {
162 so = LoadLibrary(dlextinfo, prop, prop_len);
163 if (so)
164 break;
165 }
166 }
167 if (!so)
168 return -ENOENT;
169
170 hw_module_t* hmi = static_cast<hw_module_t*>(dlsym(so, HAL_MODULE_INFO_SYM_AS_STR));
171 if (!hmi) {
172 ALOGE("couldn't find symbol '%s' in HAL library: %s", HAL_MODULE_INFO_SYM_AS_STR, dlerror());
173 dlclose(so);
174 return -EINVAL;
175 }
176 if (strcmp(hmi->id, HWVULKAN_HARDWARE_MODULE_ID) != 0) {
177 ALOGE("HAL id '%s' != '%s'", hmi->id, HWVULKAN_HARDWARE_MODULE_ID);
178 dlclose(so);
179 return -EINVAL;
180 }
181 hmi->dso = so;
182 *module = hmi;
183 ALOGD("loaded updated driver");
184 return 0;
185}
186
Chia-I Wu31b2e4f2016-05-23 10:47:57 +0800187bool Hal::Open() {
Jesse Halldc225072016-05-30 22:40:14 -0700188 ALOG_ASSERT(!hal_.dev_, "OpenHAL called more than once");
Chia-I Wu31b2e4f2016-05-23 10:47:57 +0800189
190 // Use a stub device unless we successfully open a real HAL device.
191 hal_.dev_ = &stubhal::kDevice;
192
Jesse Hall53457db2016-12-14 16:54:06 -0800193 int result;
194 const hwvulkan_module_t* module = nullptr;
195
196 result = LoadUpdatedDriver(reinterpret_cast<const hw_module_t**>(&module));
197 if (result == -ENOENT) {
198 result = hw_get_module(HWVULKAN_HARDWARE_MODULE_ID, reinterpret_cast<const hw_module_t**>(&module));
199 }
Chia-I Wu31b2e4f2016-05-23 10:47:57 +0800200 if (result != 0) {
Jesse Hall53457db2016-12-14 16:54:06 -0800201 ALOGV("unable to load Vulkan HAL, using stub HAL (result=%d)", result);
Chia-I Wu31b2e4f2016-05-23 10:47:57 +0800202 return true;
203 }
204
205 hwvulkan_device_t* device;
206 result =
207 module->common.methods->open(&module->common, HWVULKAN_DEVICE_0,
208 reinterpret_cast<hw_device_t**>(&device));
209 if (result != 0) {
210 // Any device with a Vulkan HAL should be able to open the device.
211 ALOGE("failed to open Vulkan HAL device: %s (%d)", strerror(-result),
212 result);
213 return false;
214 }
215
216 hal_.dev_ = device;
217
Chia-I Wu31938252016-05-23 15:31:02 +0800218 hal_.InitDebugReportIndex();
219
220 return true;
221}
222
223bool Hal::InitDebugReportIndex() {
224 uint32_t count;
225 if (dev_->EnumerateInstanceExtensionProperties(nullptr, &count, nullptr) !=
226 VK_SUCCESS) {
227 ALOGE("failed to get HAL instance extension count");
228 return false;
229 }
230
231 VkExtensionProperties* exts = reinterpret_cast<VkExtensionProperties*>(
232 malloc(sizeof(VkExtensionProperties) * count));
233 if (!exts) {
234 ALOGE("failed to allocate HAL instance extension array");
235 return false;
236 }
237
238 if (dev_->EnumerateInstanceExtensionProperties(nullptr, &count, exts) !=
239 VK_SUCCESS) {
240 ALOGE("failed to enumerate HAL instance extensions");
241 free(exts);
242 return false;
243 }
244
245 for (uint32_t i = 0; i < count; i++) {
246 if (strcmp(exts[i].extensionName, VK_EXT_DEBUG_REPORT_EXTENSION_NAME) ==
247 0) {
248 debug_report_index_ = static_cast<int>(i);
249 break;
250 }
251 }
252
253 free(exts);
254
Chia-I Wu31b2e4f2016-05-23 10:47:57 +0800255 return true;
256}
257
258CreateInfoWrapper::CreateInfoWrapper(const VkInstanceCreateInfo& create_info,
Chia-I Wuff4a6c72016-03-24 16:05:56 +0800259 const VkAllocationCallbacks& allocator)
260 : is_instance_(true),
261 allocator_(allocator),
Chia-I Wu31b2e4f2016-05-23 10:47:57 +0800262 physical_dev_(VK_NULL_HANDLE),
Chia-I Wuff4a6c72016-03-24 16:05:56 +0800263 instance_info_(create_info),
264 extension_filter_() {
265 hook_extensions_.set(ProcHook::EXTENSION_CORE);
266 hal_extensions_.set(ProcHook::EXTENSION_CORE);
267}
268
Chia-I Wu4901db72016-03-24 16:38:58 +0800269CreateInfoWrapper::CreateInfoWrapper(VkPhysicalDevice physical_dev,
270 const VkDeviceCreateInfo& create_info,
271 const VkAllocationCallbacks& allocator)
272 : is_instance_(false),
273 allocator_(allocator),
274 physical_dev_(physical_dev),
275 dev_info_(create_info),
276 extension_filter_() {
277 hook_extensions_.set(ProcHook::EXTENSION_CORE);
278 hal_extensions_.set(ProcHook::EXTENSION_CORE);
279}
280
281CreateInfoWrapper::~CreateInfoWrapper() {
282 allocator_.pfnFree(allocator_.pUserData, extension_filter_.exts);
283 allocator_.pfnFree(allocator_.pUserData, extension_filter_.names);
284}
285
Chia-I Wu3e6c2d62016-04-11 13:55:56 +0800286VkResult CreateInfoWrapper::Validate() {
287 VkResult result = SanitizePNext();
Chia-I Wu4901db72016-03-24 16:38:58 +0800288 if (result == VK_SUCCESS)
Chia-I Wu3e6c2d62016-04-11 13:55:56 +0800289 result = SanitizeLayers();
Chia-I Wu4901db72016-03-24 16:38:58 +0800290 if (result == VK_SUCCESS)
Chia-I Wu3e6c2d62016-04-11 13:55:56 +0800291 result = SanitizeExtensions();
Chia-I Wu4901db72016-03-24 16:38:58 +0800292
293 return result;
294}
295
296const std::bitset<ProcHook::EXTENSION_COUNT>&
Chia-I Wu3e6c2d62016-04-11 13:55:56 +0800297CreateInfoWrapper::GetHookExtensions() const {
Chia-I Wu4901db72016-03-24 16:38:58 +0800298 return hook_extensions_;
299}
300
301const std::bitset<ProcHook::EXTENSION_COUNT>&
Chia-I Wu3e6c2d62016-04-11 13:55:56 +0800302CreateInfoWrapper::GetHalExtensions() const {
Chia-I Wu4901db72016-03-24 16:38:58 +0800303 return hal_extensions_;
304}
305
Chia-I Wuff4a6c72016-03-24 16:05:56 +0800306CreateInfoWrapper::operator const VkInstanceCreateInfo*() const {
307 return &instance_info_;
308}
309
Chia-I Wu4901db72016-03-24 16:38:58 +0800310CreateInfoWrapper::operator const VkDeviceCreateInfo*() const {
311 return &dev_info_;
312}
313
Chia-I Wu3e6c2d62016-04-11 13:55:56 +0800314VkResult CreateInfoWrapper::SanitizePNext() {
Chia-I Wu4901db72016-03-24 16:38:58 +0800315 const struct StructHeader {
316 VkStructureType type;
317 const void* next;
318 } * header;
319
320 if (is_instance_) {
321 header = reinterpret_cast<const StructHeader*>(instance_info_.pNext);
322
323 // skip leading VK_STRUCTURE_TYPE_LOADER_INSTANCE_CREATE_INFOs
324 while (header &&
325 header->type == VK_STRUCTURE_TYPE_LOADER_INSTANCE_CREATE_INFO)
326 header = reinterpret_cast<const StructHeader*>(header->next);
327
328 instance_info_.pNext = header;
329 } else {
330 header = reinterpret_cast<const StructHeader*>(dev_info_.pNext);
331
332 // skip leading VK_STRUCTURE_TYPE_LOADER_DEVICE_CREATE_INFOs
333 while (header &&
334 header->type == VK_STRUCTURE_TYPE_LOADER_DEVICE_CREATE_INFO)
335 header = reinterpret_cast<const StructHeader*>(header->next);
336
337 dev_info_.pNext = header;
338 }
339
340 return VK_SUCCESS;
341}
342
Chia-I Wu3e6c2d62016-04-11 13:55:56 +0800343VkResult CreateInfoWrapper::SanitizeLayers() {
Chia-I Wu4901db72016-03-24 16:38:58 +0800344 auto& layer_names = (is_instance_) ? instance_info_.ppEnabledLayerNames
345 : dev_info_.ppEnabledLayerNames;
346 auto& layer_count = (is_instance_) ? instance_info_.enabledLayerCount
347 : dev_info_.enabledLayerCount;
348
349 // remove all layers
350 layer_names = nullptr;
351 layer_count = 0;
352
353 return VK_SUCCESS;
354}
355
Chia-I Wu3e6c2d62016-04-11 13:55:56 +0800356VkResult CreateInfoWrapper::SanitizeExtensions() {
Chia-I Wu4901db72016-03-24 16:38:58 +0800357 auto& ext_names = (is_instance_) ? instance_info_.ppEnabledExtensionNames
358 : dev_info_.ppEnabledExtensionNames;
359 auto& ext_count = (is_instance_) ? instance_info_.enabledExtensionCount
360 : dev_info_.enabledExtensionCount;
361 if (!ext_count)
362 return VK_SUCCESS;
363
Chia-I Wu3e6c2d62016-04-11 13:55:56 +0800364 VkResult result = InitExtensionFilter();
Chia-I Wu4901db72016-03-24 16:38:58 +0800365 if (result != VK_SUCCESS)
366 return result;
367
368 for (uint32_t i = 0; i < ext_count; i++)
Chia-I Wu3e6c2d62016-04-11 13:55:56 +0800369 FilterExtension(ext_names[i]);
Chia-I Wu4901db72016-03-24 16:38:58 +0800370
371 ext_names = extension_filter_.names;
372 ext_count = extension_filter_.name_count;
373
374 return VK_SUCCESS;
375}
376
Chia-I Wu3e6c2d62016-04-11 13:55:56 +0800377VkResult CreateInfoWrapper::QueryExtensionCount(uint32_t& count) const {
Chia-I Wu4901db72016-03-24 16:38:58 +0800378 if (is_instance_) {
Chia-I Wu31b2e4f2016-05-23 10:47:57 +0800379 return Hal::Device().EnumerateInstanceExtensionProperties(
380 nullptr, &count, nullptr);
Chia-I Wu4901db72016-03-24 16:38:58 +0800381 } else {
382 const auto& driver = GetData(physical_dev_).driver;
383 return driver.EnumerateDeviceExtensionProperties(physical_dev_, nullptr,
384 &count, nullptr);
385 }
386}
387
Chia-I Wu3e6c2d62016-04-11 13:55:56 +0800388VkResult CreateInfoWrapper::EnumerateExtensions(
Chia-I Wu4901db72016-03-24 16:38:58 +0800389 uint32_t& count,
390 VkExtensionProperties* props) const {
391 if (is_instance_) {
Chia-I Wu31b2e4f2016-05-23 10:47:57 +0800392 return Hal::Device().EnumerateInstanceExtensionProperties(
393 nullptr, &count, props);
Chia-I Wu4901db72016-03-24 16:38:58 +0800394 } else {
395 const auto& driver = GetData(physical_dev_).driver;
396 return driver.EnumerateDeviceExtensionProperties(physical_dev_, nullptr,
397 &count, props);
398 }
399}
400
Chia-I Wu3e6c2d62016-04-11 13:55:56 +0800401VkResult CreateInfoWrapper::InitExtensionFilter() {
Chia-I Wu4901db72016-03-24 16:38:58 +0800402 // query extension count
403 uint32_t count;
Chia-I Wu3e6c2d62016-04-11 13:55:56 +0800404 VkResult result = QueryExtensionCount(count);
Chia-I Wu4901db72016-03-24 16:38:58 +0800405 if (result != VK_SUCCESS || count == 0)
406 return result;
407
408 auto& filter = extension_filter_;
409 filter.exts =
410 reinterpret_cast<VkExtensionProperties*>(allocator_.pfnAllocation(
411 allocator_.pUserData, sizeof(VkExtensionProperties) * count,
412 alignof(VkExtensionProperties),
413 VK_SYSTEM_ALLOCATION_SCOPE_COMMAND));
414 if (!filter.exts)
415 return VK_ERROR_OUT_OF_HOST_MEMORY;
416
417 // enumerate extensions
Chia-I Wu3e6c2d62016-04-11 13:55:56 +0800418 result = EnumerateExtensions(count, filter.exts);
Chia-I Wu4901db72016-03-24 16:38:58 +0800419 if (result != VK_SUCCESS && result != VK_INCOMPLETE)
420 return result;
421
422 if (!count)
423 return VK_SUCCESS;
424
425 filter.ext_count = count;
426
427 // allocate name array
428 uint32_t enabled_ext_count = (is_instance_)
429 ? instance_info_.enabledExtensionCount
430 : dev_info_.enabledExtensionCount;
431 count = std::min(filter.ext_count, enabled_ext_count);
432 filter.names = reinterpret_cast<const char**>(allocator_.pfnAllocation(
433 allocator_.pUserData, sizeof(const char*) * count, alignof(const char*),
434 VK_SYSTEM_ALLOCATION_SCOPE_COMMAND));
435 if (!filter.names)
436 return VK_ERROR_OUT_OF_HOST_MEMORY;
437
438 return VK_SUCCESS;
439}
440
Chia-I Wu3e6c2d62016-04-11 13:55:56 +0800441void CreateInfoWrapper::FilterExtension(const char* name) {
Chia-I Wu4901db72016-03-24 16:38:58 +0800442 auto& filter = extension_filter_;
443
444 ProcHook::Extension ext_bit = GetProcHookExtension(name);
445 if (is_instance_) {
446 switch (ext_bit) {
447 case ProcHook::KHR_android_surface:
448 case ProcHook::KHR_surface:
449 hook_extensions_.set(ext_bit);
450 // return now as these extensions do not require HAL support
451 return;
452 case ProcHook::EXT_debug_report:
453 // both we and HAL can take part in
454 hook_extensions_.set(ext_bit);
455 break;
456 case ProcHook::EXTENSION_UNKNOWN:
Chris Forbes6aa30db2017-02-20 17:12:53 +1300457 case ProcHook::KHR_get_physical_device_properties2:
Chia-I Wu4901db72016-03-24 16:38:58 +0800458 // HAL's extensions
459 break;
460 default:
461 ALOGW("Ignored invalid instance extension %s", name);
462 return;
463 }
464 } else {
465 switch (ext_bit) {
466 case ProcHook::KHR_swapchain:
467 // map VK_KHR_swapchain to VK_ANDROID_native_buffer
468 name = VK_ANDROID_NATIVE_BUFFER_EXTENSION_NAME;
469 ext_bit = ProcHook::ANDROID_native_buffer;
470 break;
Ian Elliott9e853732017-02-03 11:24:07 -0700471 case ProcHook::KHR_incremental_present:
Ian Elliott8a977262017-01-19 09:05:58 -0700472 case ProcHook::GOOGLE_display_timing:
473 hook_extensions_.set(ext_bit);
474 // return now as these extensions do not require HAL support
475 return;
Courtney Goeltzenleuchterd634c482017-01-05 15:55:31 -0700476 case ProcHook::EXT_hdr_metadata:
477 hook_extensions_.set(ext_bit);
478 break;
Chia-I Wu4901db72016-03-24 16:38:58 +0800479 case ProcHook::EXTENSION_UNKNOWN:
480 // HAL's extensions
481 break;
Chris Forbes1d5f68c2017-01-31 10:17:01 +1300482 case ProcHook::KHR_shared_presentable_image:
Chris Forbes4a832c72017-01-24 10:16:48 +1300483 // Exposed by HAL, but API surface is all in the loader
484 break;
Chia-I Wu4901db72016-03-24 16:38:58 +0800485 default:
486 ALOGW("Ignored invalid device extension %s", name);
487 return;
488 }
489 }
490
491 for (uint32_t i = 0; i < filter.ext_count; i++) {
492 const VkExtensionProperties& props = filter.exts[i];
493 // ignore unknown extensions
494 if (strcmp(name, props.extensionName) != 0)
495 continue;
496
Chia-I Wu4901db72016-03-24 16:38:58 +0800497 filter.names[filter.name_count++] = name;
Chia-I Wu1600e262016-04-12 09:40:06 +0800498 if (ext_bit != ProcHook::EXTENSION_UNKNOWN) {
499 if (ext_bit == ProcHook::ANDROID_native_buffer)
500 hook_extensions_.set(ProcHook::KHR_swapchain);
501
Chris Forbes4a832c72017-01-24 10:16:48 +1300502 // Exposed by HAL, but API surface is all in the loader
Chris Forbes1d5f68c2017-01-31 10:17:01 +1300503 if (ext_bit == ProcHook::KHR_shared_presentable_image)
Chris Forbes4a832c72017-01-24 10:16:48 +1300504 hook_extensions_.set(ext_bit);
505
Chia-I Wu1600e262016-04-12 09:40:06 +0800506 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) {
681 static const std::array<VkExtensionProperties, 2> loader_extensions = {{
682 // WSI extensions
683 {VK_KHR_SURFACE_EXTENSION_NAME, VK_KHR_SURFACE_SPEC_VERSION},
684 {VK_KHR_ANDROID_SURFACE_EXTENSION_NAME,
685 VK_KHR_ANDROID_SURFACE_SPEC_VERSION},
686 }};
Chia-I Wu31938252016-05-23 15:31:02 +0800687 static const VkExtensionProperties loader_debug_report_extension = {
688 VK_EXT_DEBUG_REPORT_EXTENSION_NAME, VK_EXT_DEBUG_REPORT_SPEC_VERSION,
689 };
Chia-I Wuff4a6c72016-03-24 16:05:56 +0800690
691 // enumerate our extensions first
692 if (!pLayerName && pProperties) {
693 uint32_t count = std::min(
694 *pPropertyCount, static_cast<uint32_t>(loader_extensions.size()));
695
696 std::copy_n(loader_extensions.begin(), count, pProperties);
697
698 if (count < loader_extensions.size()) {
699 *pPropertyCount = count;
700 return VK_INCOMPLETE;
701 }
702
703 pProperties += count;
704 *pPropertyCount -= count;
Chia-I Wu31938252016-05-23 15:31:02 +0800705
706 if (Hal::Get().GetDebugReportIndex() < 0) {
707 if (!*pPropertyCount) {
708 *pPropertyCount = count;
709 return VK_INCOMPLETE;
710 }
711
712 pProperties[0] = loader_debug_report_extension;
713 pProperties += 1;
714 *pPropertyCount -= 1;
715 }
Chia-I Wuff4a6c72016-03-24 16:05:56 +0800716 }
717
Chia-I Wu31b2e4f2016-05-23 10:47:57 +0800718 VkResult result = Hal::Device().EnumerateInstanceExtensionProperties(
Chia-I Wuff4a6c72016-03-24 16:05:56 +0800719 pLayerName, pPropertyCount, pProperties);
720
Chia-I Wu31938252016-05-23 15:31:02 +0800721 if (!pLayerName && (result == VK_SUCCESS || result == VK_INCOMPLETE)) {
722 int idx = Hal::Get().GetDebugReportIndex();
723 if (idx < 0) {
724 *pPropertyCount += 1;
725 } else if (pProperties &&
726 static_cast<uint32_t>(idx) < *pPropertyCount) {
727 pProperties[idx].specVersion =
728 std::min(pProperties[idx].specVersion,
729 loader_debug_report_extension.specVersion);
730 }
731
Chia-I Wuff4a6c72016-03-24 16:05:56 +0800732 *pPropertyCount += loader_extensions.size();
Chia-I Wu31938252016-05-23 15:31:02 +0800733 }
Chia-I Wuff4a6c72016-03-24 16:05:56 +0800734
735 return result;
736}
737
Chia-I Wu01cf3052016-03-24 16:16:21 +0800738VkResult EnumerateDeviceExtensionProperties(
739 VkPhysicalDevice physicalDevice,
740 const char* pLayerName,
741 uint32_t* pPropertyCount,
742 VkExtensionProperties* pProperties) {
743 const InstanceData& data = GetData(physicalDevice);
Courtney Goeltzenleuchterd634c482017-01-05 15:55:31 -0700744 static const std::array<VkExtensionProperties, 3> loader_extensions = {{
Ian Elliottd4b50aa2017-01-09 16:21:36 -0700745 // WSI extensions
746 {VK_KHR_INCREMENTAL_PRESENT_EXTENSION_NAME,
747 VK_KHR_INCREMENTAL_PRESENT_SPEC_VERSION},
Ian Elliott8a977262017-01-19 09:05:58 -0700748 {VK_GOOGLE_DISPLAY_TIMING_EXTENSION_NAME,
749 VK_GOOGLE_DISPLAY_TIMING_SPEC_VERSION},
Courtney Goeltzenleuchterd634c482017-01-05 15:55:31 -0700750 {VK_EXT_HDR_METADATA_EXTENSION_NAME,
751 VK_EXT_HDR_METADATA_SPEC_VERSION},
Ian Elliottd4b50aa2017-01-09 16:21:36 -0700752 }};
753
754 // enumerate our extensions first
755 if (!pLayerName && pProperties) {
756 uint32_t count = std::min(
757 *pPropertyCount, static_cast<uint32_t>(loader_extensions.size()));
758
759 std::copy_n(loader_extensions.begin(), count, pProperties);
760
761 if (count < loader_extensions.size()) {
762 *pPropertyCount = count;
763 return VK_INCOMPLETE;
764 }
765
766 pProperties += count;
767 *pPropertyCount -= count;
768 }
Chia-I Wu01cf3052016-03-24 16:16:21 +0800769
770 VkResult result = data.driver.EnumerateDeviceExtensionProperties(
771 physicalDevice, pLayerName, pPropertyCount, pProperties);
Chia-I Wu01cf3052016-03-24 16:16:21 +0800772
Ian Elliottd4b50aa2017-01-09 16:21:36 -0700773 if (pProperties) {
774 // map VK_ANDROID_native_buffer to VK_KHR_swapchain
775 for (uint32_t i = 0; i < *pPropertyCount; i++) {
776 auto& prop = pProperties[i];
Chia-I Wu01cf3052016-03-24 16:16:21 +0800777
Ian Elliottd4b50aa2017-01-09 16:21:36 -0700778 if (strcmp(prop.extensionName,
779 VK_ANDROID_NATIVE_BUFFER_EXTENSION_NAME) != 0)
780 continue;
Chia-I Wu01cf3052016-03-24 16:16:21 +0800781
Ian Elliottd4b50aa2017-01-09 16:21:36 -0700782 memcpy(prop.extensionName, VK_KHR_SWAPCHAIN_EXTENSION_NAME,
783 sizeof(VK_KHR_SWAPCHAIN_EXTENSION_NAME));
784 prop.specVersion = VK_KHR_SWAPCHAIN_SPEC_VERSION;
785 }
786 }
Chia-I Wu01cf3052016-03-24 16:16:21 +0800787
Ian Elliottd4b50aa2017-01-09 16:21:36 -0700788 // restore loader extension count
789 if (!pLayerName && (result == VK_SUCCESS || result == VK_INCOMPLETE)) {
790 *pPropertyCount += loader_extensions.size();
Chia-I Wu01cf3052016-03-24 16:16:21 +0800791 }
792
793 return result;
794}
795
Chia-I Wuff4a6c72016-03-24 16:05:56 +0800796VkResult CreateInstance(const VkInstanceCreateInfo* pCreateInfo,
797 const VkAllocationCallbacks* pAllocator,
798 VkInstance* pInstance) {
799 const VkAllocationCallbacks& data_allocator =
800 (pAllocator) ? *pAllocator : GetDefaultAllocator();
801
Chia-I Wu31b2e4f2016-05-23 10:47:57 +0800802 CreateInfoWrapper wrapper(*pCreateInfo, data_allocator);
Chia-I Wu3e6c2d62016-04-11 13:55:56 +0800803 VkResult result = wrapper.Validate();
Chia-I Wuff4a6c72016-03-24 16:05:56 +0800804 if (result != VK_SUCCESS)
805 return result;
806
807 InstanceData* data = AllocateInstanceData(data_allocator);
808 if (!data)
809 return VK_ERROR_OUT_OF_HOST_MEMORY;
810
Chia-I Wu3e6c2d62016-04-11 13:55:56 +0800811 data->hook_extensions |= wrapper.GetHookExtensions();
Chia-I Wuff4a6c72016-03-24 16:05:56 +0800812
813 // call into the driver
814 VkInstance instance;
Chia-I Wu31b2e4f2016-05-23 10:47:57 +0800815 result = Hal::Device().CreateInstance(
Chia-I Wuff4a6c72016-03-24 16:05:56 +0800816 static_cast<const VkInstanceCreateInfo*>(wrapper), pAllocator,
817 &instance);
818 if (result != VK_SUCCESS) {
819 FreeInstanceData(data, data_allocator);
820 return result;
821 }
822
823 // initialize InstanceDriverTable
824 if (!SetData(instance, *data) ||
Chia-I Wu31b2e4f2016-05-23 10:47:57 +0800825 !InitDriverTable(instance, Hal::Device().GetInstanceProcAddr,
Chia-I Wucbe07ef2016-04-13 15:01:00 +0800826 wrapper.GetHalExtensions())) {
Chia-I Wuff4a6c72016-03-24 16:05:56 +0800827 data->driver.DestroyInstance = reinterpret_cast<PFN_vkDestroyInstance>(
Chia-I Wu31b2e4f2016-05-23 10:47:57 +0800828 Hal::Device().GetInstanceProcAddr(instance, "vkDestroyInstance"));
Chia-I Wuff4a6c72016-03-24 16:05:56 +0800829 if (data->driver.DestroyInstance)
830 data->driver.DestroyInstance(instance, pAllocator);
831
832 FreeInstanceData(data, data_allocator);
833
834 return VK_ERROR_INCOMPATIBLE_DRIVER;
835 }
836
837 data->get_device_proc_addr = reinterpret_cast<PFN_vkGetDeviceProcAddr>(
Chia-I Wu31b2e4f2016-05-23 10:47:57 +0800838 Hal::Device().GetInstanceProcAddr(instance, "vkGetDeviceProcAddr"));
Chia-I Wuff4a6c72016-03-24 16:05:56 +0800839 if (!data->get_device_proc_addr) {
840 data->driver.DestroyInstance(instance, pAllocator);
841 FreeInstanceData(data, data_allocator);
842
843 return VK_ERROR_INCOMPATIBLE_DRIVER;
844 }
845
846 *pInstance = instance;
847
848 return VK_SUCCESS;
849}
850
851void DestroyInstance(VkInstance instance,
852 const VkAllocationCallbacks* pAllocator) {
853 InstanceData& data = GetData(instance);
854 data.driver.DestroyInstance(instance, pAllocator);
855
856 VkAllocationCallbacks local_allocator;
857 if (!pAllocator) {
858 local_allocator = data.allocator;
859 pAllocator = &local_allocator;
860 }
861
862 FreeInstanceData(&data, *pAllocator);
863}
864
Chia-I Wu4901db72016-03-24 16:38:58 +0800865VkResult CreateDevice(VkPhysicalDevice physicalDevice,
866 const VkDeviceCreateInfo* pCreateInfo,
867 const VkAllocationCallbacks* pAllocator,
868 VkDevice* pDevice) {
869 const InstanceData& instance_data = GetData(physicalDevice);
870 const VkAllocationCallbacks& data_allocator =
871 (pAllocator) ? *pAllocator : instance_data.allocator;
872
873 CreateInfoWrapper wrapper(physicalDevice, *pCreateInfo, data_allocator);
Chia-I Wu3e6c2d62016-04-11 13:55:56 +0800874 VkResult result = wrapper.Validate();
Chia-I Wu4901db72016-03-24 16:38:58 +0800875 if (result != VK_SUCCESS)
876 return result;
877
Chia-I Wu950d6e12016-05-03 09:12:35 +0800878 DeviceData* data = AllocateDeviceData(data_allocator,
879 instance_data.debug_report_callbacks);
Chia-I Wu4901db72016-03-24 16:38:58 +0800880 if (!data)
881 return VK_ERROR_OUT_OF_HOST_MEMORY;
882
Chia-I Wu3e6c2d62016-04-11 13:55:56 +0800883 data->hook_extensions |= wrapper.GetHookExtensions();
Chia-I Wu4901db72016-03-24 16:38:58 +0800884
885 // call into the driver
886 VkDevice dev;
887 result = instance_data.driver.CreateDevice(
888 physicalDevice, static_cast<const VkDeviceCreateInfo*>(wrapper),
889 pAllocator, &dev);
890 if (result != VK_SUCCESS) {
891 FreeDeviceData(data, data_allocator);
892 return result;
893 }
894
895 // initialize DeviceDriverTable
896 if (!SetData(dev, *data) ||
Chia-I Wucbe07ef2016-04-13 15:01:00 +0800897 !InitDriverTable(dev, instance_data.get_device_proc_addr,
898 wrapper.GetHalExtensions())) {
Chia-I Wu4901db72016-03-24 16:38:58 +0800899 data->driver.DestroyDevice = reinterpret_cast<PFN_vkDestroyDevice>(
900 instance_data.get_device_proc_addr(dev, "vkDestroyDevice"));
901 if (data->driver.DestroyDevice)
902 data->driver.DestroyDevice(dev, pAllocator);
903
904 FreeDeviceData(data, data_allocator);
905
906 return VK_ERROR_INCOMPATIBLE_DRIVER;
907 }
Chris Forbesd8277912017-02-10 14:59:59 +1300908
909 // sanity check ANDROID_native_buffer implementation, whose set of
910 // entrypoints varies according to the spec version.
911 if ((wrapper.GetHalExtensions()[ProcHook::ANDROID_native_buffer]) &&
912 !data->driver.GetSwapchainGrallocUsageANDROID &&
913 !data->driver.GetSwapchainGrallocUsage2ANDROID) {
914 ALOGE("Driver's implementation of ANDROID_native_buffer is broken;"
915 " must expose at least one of "
916 "vkGetSwapchainGrallocUsageANDROID or "
917 "vkGetSwapchainGrallocUsage2ANDROID");
918
919 data->driver.DestroyDevice(dev, pAllocator);
920 FreeDeviceData(data, data_allocator);
921
922 return VK_ERROR_INCOMPATIBLE_DRIVER;
923 }
924
Jesse Hall85bb0c52017-02-09 22:13:02 -0800925 VkPhysicalDeviceProperties properties;
926 instance_data.driver.GetPhysicalDeviceProperties(physicalDevice,
927 &properties);
928
Jesse Halldc225072016-05-30 22:40:14 -0700929 data->driver_device = dev;
Jesse Hall85bb0c52017-02-09 22:13:02 -0800930 data->driver_version = properties.driverVersion;
Chia-I Wu4901db72016-03-24 16:38:58 +0800931
932 *pDevice = dev;
933
934 return VK_SUCCESS;
935}
936
937void DestroyDevice(VkDevice device, const VkAllocationCallbacks* pAllocator) {
938 DeviceData& data = GetData(device);
939 data.driver.DestroyDevice(device, pAllocator);
940
941 VkAllocationCallbacks local_allocator;
942 if (!pAllocator) {
943 local_allocator = data.allocator;
944 pAllocator = &local_allocator;
945 }
946
947 FreeDeviceData(&data, *pAllocator);
948}
949
Chia-I Wuff4a6c72016-03-24 16:05:56 +0800950VkResult EnumeratePhysicalDevices(VkInstance instance,
951 uint32_t* pPhysicalDeviceCount,
952 VkPhysicalDevice* pPhysicalDevices) {
953 const auto& data = GetData(instance);
954
955 VkResult result = data.driver.EnumeratePhysicalDevices(
956 instance, pPhysicalDeviceCount, pPhysicalDevices);
957 if ((result == VK_SUCCESS || result == VK_INCOMPLETE) && pPhysicalDevices) {
958 for (uint32_t i = 0; i < *pPhysicalDeviceCount; i++)
959 SetData(pPhysicalDevices[i], data);
960 }
961
962 return result;
963}
964
Chia-I Wuba0be412016-03-24 16:24:40 +0800965void GetDeviceQueue(VkDevice device,
966 uint32_t queueFamilyIndex,
967 uint32_t queueIndex,
968 VkQueue* pQueue) {
969 const auto& data = GetData(device);
970
971 data.driver.GetDeviceQueue(device, queueFamilyIndex, queueIndex, pQueue);
972 SetData(*pQueue, data);
973}
974
Chia-I Wu6a58a8a2016-03-24 16:29:51 +0800975VKAPI_ATTR VkResult
976AllocateCommandBuffers(VkDevice device,
977 const VkCommandBufferAllocateInfo* pAllocateInfo,
978 VkCommandBuffer* pCommandBuffers) {
979 const auto& data = GetData(device);
980
981 VkResult result = data.driver.AllocateCommandBuffers(device, pAllocateInfo,
982 pCommandBuffers);
983 if (result == VK_SUCCESS) {
984 for (uint32_t i = 0; i < pAllocateInfo->commandBufferCount; i++)
985 SetData(pCommandBuffers[i], data);
986 }
987
988 return result;
989}
990
Chia-I Wu9d518162016-03-24 14:55:27 +0800991} // namespace driver
992} // namespace vulkan