blob: 8b9b9d2aa13c35c66a6bf5ef9acd9fcdacff24fc [file] [log] [blame]
Chia-I Wu9d518162016-03-24 14:55:27 +08001/*
2 * Copyright 2016 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
Chia-I Wudbb7e9c2016-03-24 15:09:38 +080017#include <stdlib.h>
18#include <string.h>
19#include <algorithm>
Chia-I Wuff4a6c72016-03-24 16:05:56 +080020#include <array>
Chia-I Wu4901db72016-03-24 16:38:58 +080021#include <new>
Chia-I Wudbb7e9c2016-03-24 15:09:38 +080022#include <malloc.h>
Chia-I Wu9d518162016-03-24 14:55:27 +080023#include <sys/prctl.h>
24
25#include "driver.h"
Jesse Hallb7c4e3b2016-04-11 13:51:38 -070026#include "stubhal.h"
Chia-I Wu9d518162016-03-24 14:55:27 +080027
Chia-I Wudbb7e9c2016-03-24 15:09:38 +080028// #define ENABLE_ALLOC_CALLSTACKS 1
29#if ENABLE_ALLOC_CALLSTACKS
30#include <utils/CallStack.h>
31#define ALOGD_CALLSTACK(...) \
32 do { \
33 ALOGD(__VA_ARGS__); \
34 android::CallStack callstack; \
35 callstack.update(); \
36 callstack.log(LOG_TAG, ANDROID_LOG_DEBUG, " "); \
37 } while (false)
38#else
39#define ALOGD_CALLSTACK(...) \
40 do { \
41 } while (false)
42#endif
43
Chia-I Wu9d518162016-03-24 14:55:27 +080044namespace vulkan {
45namespace driver {
46
Chia-I Wu136b8eb2016-03-24 15:01:52 +080047namespace {
48
Chia-I Wu31b2e4f2016-05-23 10:47:57 +080049class Hal {
50 public:
51 static bool Open();
52
53 static const Hal& Get() { return hal_; }
54 static const hwvulkan_device_t& Device() { return *Get().dev_; }
55
Chia-I Wu31938252016-05-23 15:31:02 +080056 int GetDebugReportIndex() const { return debug_report_index_; }
57
Chia-I Wu31b2e4f2016-05-23 10:47:57 +080058 private:
Chia-I Wu31938252016-05-23 15:31:02 +080059 Hal() : dev_(nullptr), debug_report_index_(-1) {}
Chia-I Wu31b2e4f2016-05-23 10:47:57 +080060 Hal(const Hal&) = delete;
61 Hal& operator=(const Hal&) = delete;
62
Chia-I Wu31938252016-05-23 15:31:02 +080063 bool InitDebugReportIndex();
64
Chia-I Wu31b2e4f2016-05-23 10:47:57 +080065 static Hal hal_;
66
67 const hwvulkan_device_t* dev_;
Chia-I Wu31938252016-05-23 15:31:02 +080068 int debug_report_index_;
Chia-I Wu31b2e4f2016-05-23 10:47:57 +080069};
70
Chia-I Wu4901db72016-03-24 16:38:58 +080071class CreateInfoWrapper {
72 public:
Chia-I Wu31b2e4f2016-05-23 10:47:57 +080073 CreateInfoWrapper(const VkInstanceCreateInfo& create_info,
Chia-I Wuff4a6c72016-03-24 16:05:56 +080074 const VkAllocationCallbacks& allocator);
Chia-I Wu4901db72016-03-24 16:38:58 +080075 CreateInfoWrapper(VkPhysicalDevice physical_dev,
76 const VkDeviceCreateInfo& create_info,
77 const VkAllocationCallbacks& allocator);
78 ~CreateInfoWrapper();
79
Chia-I Wu3e6c2d62016-04-11 13:55:56 +080080 VkResult Validate();
Chia-I Wu4901db72016-03-24 16:38:58 +080081
Chia-I Wu3e6c2d62016-04-11 13:55:56 +080082 const std::bitset<ProcHook::EXTENSION_COUNT>& GetHookExtensions() const;
83 const std::bitset<ProcHook::EXTENSION_COUNT>& GetHalExtensions() const;
Chia-I Wu4901db72016-03-24 16:38:58 +080084
Chia-I Wuff4a6c72016-03-24 16:05:56 +080085 explicit operator const VkInstanceCreateInfo*() const;
Chia-I Wu4901db72016-03-24 16:38:58 +080086 explicit operator const VkDeviceCreateInfo*() const;
87
88 private:
89 struct ExtensionFilter {
90 VkExtensionProperties* exts;
91 uint32_t ext_count;
92
93 const char** names;
94 uint32_t name_count;
95 };
96
Chia-I Wu3e6c2d62016-04-11 13:55:56 +080097 VkResult SanitizePNext();
Chia-I Wu4901db72016-03-24 16:38:58 +080098
Chia-I Wu3e6c2d62016-04-11 13:55:56 +080099 VkResult SanitizeLayers();
100 VkResult SanitizeExtensions();
Chia-I Wu4901db72016-03-24 16:38:58 +0800101
Chia-I Wu3e6c2d62016-04-11 13:55:56 +0800102 VkResult QueryExtensionCount(uint32_t& count) const;
103 VkResult EnumerateExtensions(uint32_t& count,
104 VkExtensionProperties* props) const;
105 VkResult InitExtensionFilter();
106 void FilterExtension(const char* name);
Chia-I Wu4901db72016-03-24 16:38:58 +0800107
108 const bool is_instance_;
109 const VkAllocationCallbacks& allocator_;
110
Chia-I Wu31b2e4f2016-05-23 10:47:57 +0800111 VkPhysicalDevice physical_dev_;
Chia-I Wu4901db72016-03-24 16:38:58 +0800112
113 union {
114 VkInstanceCreateInfo instance_info_;
115 VkDeviceCreateInfo dev_info_;
116 };
117
118 ExtensionFilter extension_filter_;
119
120 std::bitset<ProcHook::EXTENSION_COUNT> hook_extensions_;
121 std::bitset<ProcHook::EXTENSION_COUNT> hal_extensions_;
122};
123
Chia-I Wu31b2e4f2016-05-23 10:47:57 +0800124Hal Hal::hal_;
125
126bool Hal::Open() {
Jesse Halldc225072016-05-30 22:40:14 -0700127 ALOG_ASSERT(!hal_.dev_, "OpenHAL called more than once");
Chia-I Wu31b2e4f2016-05-23 10:47:57 +0800128
129 // Use a stub device unless we successfully open a real HAL device.
130 hal_.dev_ = &stubhal::kDevice;
131
132 const hwvulkan_module_t* module;
133 int result =
134 hw_get_module("vulkan", reinterpret_cast<const hw_module_t**>(&module));
135 if (result != 0) {
136 ALOGI("no Vulkan HAL present, using stub HAL");
137 return true;
138 }
139
140 hwvulkan_device_t* device;
141 result =
142 module->common.methods->open(&module->common, HWVULKAN_DEVICE_0,
143 reinterpret_cast<hw_device_t**>(&device));
144 if (result != 0) {
145 // Any device with a Vulkan HAL should be able to open the device.
146 ALOGE("failed to open Vulkan HAL device: %s (%d)", strerror(-result),
147 result);
148 return false;
149 }
150
151 hal_.dev_ = device;
152
Chia-I Wu31938252016-05-23 15:31:02 +0800153 hal_.InitDebugReportIndex();
154
155 return true;
156}
157
158bool Hal::InitDebugReportIndex() {
159 uint32_t count;
160 if (dev_->EnumerateInstanceExtensionProperties(nullptr, &count, nullptr) !=
161 VK_SUCCESS) {
162 ALOGE("failed to get HAL instance extension count");
163 return false;
164 }
165
166 VkExtensionProperties* exts = reinterpret_cast<VkExtensionProperties*>(
167 malloc(sizeof(VkExtensionProperties) * count));
168 if (!exts) {
169 ALOGE("failed to allocate HAL instance extension array");
170 return false;
171 }
172
173 if (dev_->EnumerateInstanceExtensionProperties(nullptr, &count, exts) !=
174 VK_SUCCESS) {
175 ALOGE("failed to enumerate HAL instance extensions");
176 free(exts);
177 return false;
178 }
179
180 for (uint32_t i = 0; i < count; i++) {
181 if (strcmp(exts[i].extensionName, VK_EXT_DEBUG_REPORT_EXTENSION_NAME) ==
182 0) {
183 debug_report_index_ = static_cast<int>(i);
184 break;
185 }
186 }
187
188 free(exts);
189
Chia-I Wu31b2e4f2016-05-23 10:47:57 +0800190 return true;
191}
192
193CreateInfoWrapper::CreateInfoWrapper(const VkInstanceCreateInfo& create_info,
Chia-I Wuff4a6c72016-03-24 16:05:56 +0800194 const VkAllocationCallbacks& allocator)
195 : is_instance_(true),
196 allocator_(allocator),
Chia-I Wu31b2e4f2016-05-23 10:47:57 +0800197 physical_dev_(VK_NULL_HANDLE),
Chia-I Wuff4a6c72016-03-24 16:05:56 +0800198 instance_info_(create_info),
199 extension_filter_() {
200 hook_extensions_.set(ProcHook::EXTENSION_CORE);
201 hal_extensions_.set(ProcHook::EXTENSION_CORE);
202}
203
Chia-I Wu4901db72016-03-24 16:38:58 +0800204CreateInfoWrapper::CreateInfoWrapper(VkPhysicalDevice physical_dev,
205 const VkDeviceCreateInfo& create_info,
206 const VkAllocationCallbacks& allocator)
207 : is_instance_(false),
208 allocator_(allocator),
209 physical_dev_(physical_dev),
210 dev_info_(create_info),
211 extension_filter_() {
212 hook_extensions_.set(ProcHook::EXTENSION_CORE);
213 hal_extensions_.set(ProcHook::EXTENSION_CORE);
214}
215
216CreateInfoWrapper::~CreateInfoWrapper() {
217 allocator_.pfnFree(allocator_.pUserData, extension_filter_.exts);
218 allocator_.pfnFree(allocator_.pUserData, extension_filter_.names);
219}
220
Chia-I Wu3e6c2d62016-04-11 13:55:56 +0800221VkResult CreateInfoWrapper::Validate() {
222 VkResult result = SanitizePNext();
Chia-I Wu4901db72016-03-24 16:38:58 +0800223 if (result == VK_SUCCESS)
Chia-I Wu3e6c2d62016-04-11 13:55:56 +0800224 result = SanitizeLayers();
Chia-I Wu4901db72016-03-24 16:38:58 +0800225 if (result == VK_SUCCESS)
Chia-I Wu3e6c2d62016-04-11 13:55:56 +0800226 result = SanitizeExtensions();
Chia-I Wu4901db72016-03-24 16:38:58 +0800227
228 return result;
229}
230
231const std::bitset<ProcHook::EXTENSION_COUNT>&
Chia-I Wu3e6c2d62016-04-11 13:55:56 +0800232CreateInfoWrapper::GetHookExtensions() const {
Chia-I Wu4901db72016-03-24 16:38:58 +0800233 return hook_extensions_;
234}
235
236const std::bitset<ProcHook::EXTENSION_COUNT>&
Chia-I Wu3e6c2d62016-04-11 13:55:56 +0800237CreateInfoWrapper::GetHalExtensions() const {
Chia-I Wu4901db72016-03-24 16:38:58 +0800238 return hal_extensions_;
239}
240
Chia-I Wuff4a6c72016-03-24 16:05:56 +0800241CreateInfoWrapper::operator const VkInstanceCreateInfo*() const {
242 return &instance_info_;
243}
244
Chia-I Wu4901db72016-03-24 16:38:58 +0800245CreateInfoWrapper::operator const VkDeviceCreateInfo*() const {
246 return &dev_info_;
247}
248
Chia-I Wu3e6c2d62016-04-11 13:55:56 +0800249VkResult CreateInfoWrapper::SanitizePNext() {
Chia-I Wu4901db72016-03-24 16:38:58 +0800250 const struct StructHeader {
251 VkStructureType type;
252 const void* next;
253 } * header;
254
255 if (is_instance_) {
256 header = reinterpret_cast<const StructHeader*>(instance_info_.pNext);
257
258 // skip leading VK_STRUCTURE_TYPE_LOADER_INSTANCE_CREATE_INFOs
259 while (header &&
260 header->type == VK_STRUCTURE_TYPE_LOADER_INSTANCE_CREATE_INFO)
261 header = reinterpret_cast<const StructHeader*>(header->next);
262
263 instance_info_.pNext = header;
264 } else {
265 header = reinterpret_cast<const StructHeader*>(dev_info_.pNext);
266
267 // skip leading VK_STRUCTURE_TYPE_LOADER_DEVICE_CREATE_INFOs
268 while (header &&
269 header->type == VK_STRUCTURE_TYPE_LOADER_DEVICE_CREATE_INFO)
270 header = reinterpret_cast<const StructHeader*>(header->next);
271
272 dev_info_.pNext = header;
273 }
274
275 return VK_SUCCESS;
276}
277
Chia-I Wu3e6c2d62016-04-11 13:55:56 +0800278VkResult CreateInfoWrapper::SanitizeLayers() {
Chia-I Wu4901db72016-03-24 16:38:58 +0800279 auto& layer_names = (is_instance_) ? instance_info_.ppEnabledLayerNames
280 : dev_info_.ppEnabledLayerNames;
281 auto& layer_count = (is_instance_) ? instance_info_.enabledLayerCount
282 : dev_info_.enabledLayerCount;
283
284 // remove all layers
285 layer_names = nullptr;
286 layer_count = 0;
287
288 return VK_SUCCESS;
289}
290
Chia-I Wu3e6c2d62016-04-11 13:55:56 +0800291VkResult CreateInfoWrapper::SanitizeExtensions() {
Chia-I Wu4901db72016-03-24 16:38:58 +0800292 auto& ext_names = (is_instance_) ? instance_info_.ppEnabledExtensionNames
293 : dev_info_.ppEnabledExtensionNames;
294 auto& ext_count = (is_instance_) ? instance_info_.enabledExtensionCount
295 : dev_info_.enabledExtensionCount;
296 if (!ext_count)
297 return VK_SUCCESS;
298
Chia-I Wu3e6c2d62016-04-11 13:55:56 +0800299 VkResult result = InitExtensionFilter();
Chia-I Wu4901db72016-03-24 16:38:58 +0800300 if (result != VK_SUCCESS)
301 return result;
302
303 for (uint32_t i = 0; i < ext_count; i++)
Chia-I Wu3e6c2d62016-04-11 13:55:56 +0800304 FilterExtension(ext_names[i]);
Chia-I Wu4901db72016-03-24 16:38:58 +0800305
306 ext_names = extension_filter_.names;
307 ext_count = extension_filter_.name_count;
308
309 return VK_SUCCESS;
310}
311
Chia-I Wu3e6c2d62016-04-11 13:55:56 +0800312VkResult CreateInfoWrapper::QueryExtensionCount(uint32_t& count) const {
Chia-I Wu4901db72016-03-24 16:38:58 +0800313 if (is_instance_) {
Chia-I Wu31b2e4f2016-05-23 10:47:57 +0800314 return Hal::Device().EnumerateInstanceExtensionProperties(
315 nullptr, &count, nullptr);
Chia-I Wu4901db72016-03-24 16:38:58 +0800316 } else {
317 const auto& driver = GetData(physical_dev_).driver;
318 return driver.EnumerateDeviceExtensionProperties(physical_dev_, nullptr,
319 &count, nullptr);
320 }
321}
322
Chia-I Wu3e6c2d62016-04-11 13:55:56 +0800323VkResult CreateInfoWrapper::EnumerateExtensions(
Chia-I Wu4901db72016-03-24 16:38:58 +0800324 uint32_t& count,
325 VkExtensionProperties* props) const {
326 if (is_instance_) {
Chia-I Wu31b2e4f2016-05-23 10:47:57 +0800327 return Hal::Device().EnumerateInstanceExtensionProperties(
328 nullptr, &count, props);
Chia-I Wu4901db72016-03-24 16:38:58 +0800329 } else {
330 const auto& driver = GetData(physical_dev_).driver;
331 return driver.EnumerateDeviceExtensionProperties(physical_dev_, nullptr,
332 &count, props);
333 }
334}
335
Chia-I Wu3e6c2d62016-04-11 13:55:56 +0800336VkResult CreateInfoWrapper::InitExtensionFilter() {
Chia-I Wu4901db72016-03-24 16:38:58 +0800337 // query extension count
338 uint32_t count;
Chia-I Wu3e6c2d62016-04-11 13:55:56 +0800339 VkResult result = QueryExtensionCount(count);
Chia-I Wu4901db72016-03-24 16:38:58 +0800340 if (result != VK_SUCCESS || count == 0)
341 return result;
342
343 auto& filter = extension_filter_;
344 filter.exts =
345 reinterpret_cast<VkExtensionProperties*>(allocator_.pfnAllocation(
346 allocator_.pUserData, sizeof(VkExtensionProperties) * count,
347 alignof(VkExtensionProperties),
348 VK_SYSTEM_ALLOCATION_SCOPE_COMMAND));
349 if (!filter.exts)
350 return VK_ERROR_OUT_OF_HOST_MEMORY;
351
352 // enumerate extensions
Chia-I Wu3e6c2d62016-04-11 13:55:56 +0800353 result = EnumerateExtensions(count, filter.exts);
Chia-I Wu4901db72016-03-24 16:38:58 +0800354 if (result != VK_SUCCESS && result != VK_INCOMPLETE)
355 return result;
356
357 if (!count)
358 return VK_SUCCESS;
359
360 filter.ext_count = count;
361
362 // allocate name array
363 uint32_t enabled_ext_count = (is_instance_)
364 ? instance_info_.enabledExtensionCount
365 : dev_info_.enabledExtensionCount;
366 count = std::min(filter.ext_count, enabled_ext_count);
367 filter.names = reinterpret_cast<const char**>(allocator_.pfnAllocation(
368 allocator_.pUserData, sizeof(const char*) * count, alignof(const char*),
369 VK_SYSTEM_ALLOCATION_SCOPE_COMMAND));
370 if (!filter.names)
371 return VK_ERROR_OUT_OF_HOST_MEMORY;
372
373 return VK_SUCCESS;
374}
375
Chia-I Wu3e6c2d62016-04-11 13:55:56 +0800376void CreateInfoWrapper::FilterExtension(const char* name) {
Chia-I Wu4901db72016-03-24 16:38:58 +0800377 auto& filter = extension_filter_;
378
379 ProcHook::Extension ext_bit = GetProcHookExtension(name);
380 if (is_instance_) {
381 switch (ext_bit) {
382 case ProcHook::KHR_android_surface:
383 case ProcHook::KHR_surface:
384 hook_extensions_.set(ext_bit);
385 // return now as these extensions do not require HAL support
386 return;
387 case ProcHook::EXT_debug_report:
388 // both we and HAL can take part in
389 hook_extensions_.set(ext_bit);
390 break;
391 case ProcHook::EXTENSION_UNKNOWN:
392 // HAL's extensions
393 break;
394 default:
395 ALOGW("Ignored invalid instance extension %s", name);
396 return;
397 }
398 } else {
399 switch (ext_bit) {
400 case ProcHook::KHR_swapchain:
401 // map VK_KHR_swapchain to VK_ANDROID_native_buffer
402 name = VK_ANDROID_NATIVE_BUFFER_EXTENSION_NAME;
403 ext_bit = ProcHook::ANDROID_native_buffer;
404 break;
405 case ProcHook::EXTENSION_UNKNOWN:
406 // HAL's extensions
407 break;
408 default:
409 ALOGW("Ignored invalid device extension %s", name);
410 return;
411 }
412 }
413
414 for (uint32_t i = 0; i < filter.ext_count; i++) {
415 const VkExtensionProperties& props = filter.exts[i];
416 // ignore unknown extensions
417 if (strcmp(name, props.extensionName) != 0)
418 continue;
419
Chia-I Wu4901db72016-03-24 16:38:58 +0800420 filter.names[filter.name_count++] = name;
Chia-I Wu1600e262016-04-12 09:40:06 +0800421 if (ext_bit != ProcHook::EXTENSION_UNKNOWN) {
422 if (ext_bit == ProcHook::ANDROID_native_buffer)
423 hook_extensions_.set(ProcHook::KHR_swapchain);
424
425 hal_extensions_.set(ext_bit);
426 }
Chia-I Wu4901db72016-03-24 16:38:58 +0800427
428 break;
429 }
430}
431
Chia-I Wudbb7e9c2016-03-24 15:09:38 +0800432VKAPI_ATTR void* DefaultAllocate(void*,
433 size_t size,
434 size_t alignment,
435 VkSystemAllocationScope) {
436 void* ptr = nullptr;
437 // Vulkan requires 'alignment' to be a power of two, but posix_memalign
438 // additionally requires that it be at least sizeof(void*).
439 int ret = posix_memalign(&ptr, std::max(alignment, sizeof(void*)), size);
440 ALOGD_CALLSTACK("Allocate: size=%zu align=%zu => (%d) %p", size, alignment,
441 ret, ptr);
442 return ret == 0 ? ptr : nullptr;
443}
444
445VKAPI_ATTR void* DefaultReallocate(void*,
446 void* ptr,
447 size_t size,
448 size_t alignment,
449 VkSystemAllocationScope) {
450 if (size == 0) {
451 free(ptr);
452 return nullptr;
453 }
454
455 // TODO(jessehall): Right now we never shrink allocations; if the new
456 // request is smaller than the existing chunk, we just continue using it.
457 // Right now the loader never reallocs, so this doesn't matter. If that
458 // changes, or if this code is copied into some other project, this should
459 // probably have a heuristic to allocate-copy-free when doing so will save
460 // "enough" space.
461 size_t old_size = ptr ? malloc_usable_size(ptr) : 0;
462 if (size <= old_size)
463 return ptr;
464
465 void* new_ptr = nullptr;
466 if (posix_memalign(&new_ptr, std::max(alignment, sizeof(void*)), size) != 0)
467 return nullptr;
468 if (ptr) {
469 memcpy(new_ptr, ptr, std::min(old_size, size));
470 free(ptr);
471 }
472 return new_ptr;
473}
474
475VKAPI_ATTR void DefaultFree(void*, void* ptr) {
476 ALOGD_CALLSTACK("Free: %p", ptr);
477 free(ptr);
478}
479
Chia-I Wuff4a6c72016-03-24 16:05:56 +0800480InstanceData* AllocateInstanceData(const VkAllocationCallbacks& allocator) {
481 void* data_mem = allocator.pfnAllocation(
482 allocator.pUserData, sizeof(InstanceData), alignof(InstanceData),
483 VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
484 if (!data_mem)
485 return nullptr;
486
487 return new (data_mem) InstanceData(allocator);
488}
489
490void FreeInstanceData(InstanceData* data,
491 const VkAllocationCallbacks& allocator) {
492 data->~InstanceData();
493 allocator.pfnFree(allocator.pUserData, data);
494}
495
Chia-I Wu950d6e12016-05-03 09:12:35 +0800496DeviceData* AllocateDeviceData(
497 const VkAllocationCallbacks& allocator,
498 const DebugReportCallbackList& debug_report_callbacks) {
Chia-I Wu4901db72016-03-24 16:38:58 +0800499 void* data_mem = allocator.pfnAllocation(
500 allocator.pUserData, sizeof(DeviceData), alignof(DeviceData),
501 VK_SYSTEM_ALLOCATION_SCOPE_DEVICE);
502 if (!data_mem)
503 return nullptr;
504
Chia-I Wu950d6e12016-05-03 09:12:35 +0800505 return new (data_mem) DeviceData(allocator, debug_report_callbacks);
Chia-I Wu4901db72016-03-24 16:38:58 +0800506}
507
508void FreeDeviceData(DeviceData* data, const VkAllocationCallbacks& allocator) {
509 data->~DeviceData();
510 allocator.pfnFree(allocator.pUserData, data);
511}
512
Chia-I Wu136b8eb2016-03-24 15:01:52 +0800513} // anonymous namespace
514
Chia-I Wu9d518162016-03-24 14:55:27 +0800515bool Debuggable() {
516 return (prctl(PR_GET_DUMPABLE, 0, 0, 0, 0) >= 0);
517}
518
Chia-I Wu136b8eb2016-03-24 15:01:52 +0800519bool OpenHAL() {
Chia-I Wu31b2e4f2016-05-23 10:47:57 +0800520 return Hal::Open();
Chia-I Wu136b8eb2016-03-24 15:01:52 +0800521}
522
Chia-I Wudbb7e9c2016-03-24 15:09:38 +0800523const VkAllocationCallbacks& GetDefaultAllocator() {
524 static const VkAllocationCallbacks kDefaultAllocCallbacks = {
525 .pUserData = nullptr,
526 .pfnAllocation = DefaultAllocate,
527 .pfnReallocation = DefaultReallocate,
528 .pfnFree = DefaultFree,
529 };
530
531 return kDefaultAllocCallbacks;
532}
533
Chia-I Wueb7db122016-03-24 09:11:06 +0800534PFN_vkVoidFunction GetInstanceProcAddr(VkInstance instance, const char* pName) {
535 const ProcHook* hook = GetProcHook(pName);
536 if (!hook)
Chia-I Wu31b2e4f2016-05-23 10:47:57 +0800537 return Hal::Device().GetInstanceProcAddr(instance, pName);
Chia-I Wueb7db122016-03-24 09:11:06 +0800538
539 if (!instance) {
540 if (hook->type == ProcHook::GLOBAL)
541 return hook->proc;
542
Chia-I Wu109f8982016-04-22 06:40:40 +0800543 // v0 layers expect
544 //
545 // vkGetInstanceProcAddr(VK_NULL_HANDLE, "vkCreateDevice");
546 //
547 // to work.
548 if (strcmp(pName, "vkCreateDevice") == 0)
549 return hook->proc;
550
Chia-I Wueb7db122016-03-24 09:11:06 +0800551 ALOGE(
Chia-I Wue201c3f2016-05-03 13:26:08 +0800552 "internal vkGetInstanceProcAddr called for %s without an instance",
Chia-I Wueb7db122016-03-24 09:11:06 +0800553 pName);
554
Chia-I Wu109f8982016-04-22 06:40:40 +0800555 return nullptr;
Chia-I Wueb7db122016-03-24 09:11:06 +0800556 }
557
558 PFN_vkVoidFunction proc;
559
560 switch (hook->type) {
561 case ProcHook::INSTANCE:
562 proc = (GetData(instance).hook_extensions[hook->extension])
563 ? hook->proc
Chia-I Wu36cc00a2016-04-13 16:52:06 +0800564 : nullptr;
Chia-I Wueb7db122016-03-24 09:11:06 +0800565 break;
566 case ProcHook::DEVICE:
567 proc = (hook->extension == ProcHook::EXTENSION_CORE)
568 ? hook->proc
569 : hook->checked_proc;
570 break;
571 default:
572 ALOGE(
Chia-I Wue201c3f2016-05-03 13:26:08 +0800573 "internal vkGetInstanceProcAddr called for %s with an instance",
Chia-I Wueb7db122016-03-24 09:11:06 +0800574 pName);
575 proc = nullptr;
576 break;
577 }
578
579 return proc;
580}
581
582PFN_vkVoidFunction GetDeviceProcAddr(VkDevice device, const char* pName) {
583 const ProcHook* hook = GetProcHook(pName);
584 if (!hook)
Chia-I Wucc5e2762016-03-24 13:01:16 +0800585 return GetData(device).driver.GetDeviceProcAddr(device, pName);
Chia-I Wueb7db122016-03-24 09:11:06 +0800586
587 if (hook->type != ProcHook::DEVICE) {
Chia-I Wue201c3f2016-05-03 13:26:08 +0800588 ALOGE("internal vkGetDeviceProcAddr called for %s", pName);
Chia-I Wueb7db122016-03-24 09:11:06 +0800589 return nullptr;
590 }
591
Chia-I Wu36cc00a2016-04-13 16:52:06 +0800592 return (GetData(device).hook_extensions[hook->extension]) ? hook->proc
593 : nullptr;
Chia-I Wueb7db122016-03-24 09:11:06 +0800594}
595
Chia-I Wuff4a6c72016-03-24 16:05:56 +0800596VkResult EnumerateInstanceExtensionProperties(
597 const char* pLayerName,
598 uint32_t* pPropertyCount,
599 VkExtensionProperties* pProperties) {
600 static const std::array<VkExtensionProperties, 2> loader_extensions = {{
601 // WSI extensions
602 {VK_KHR_SURFACE_EXTENSION_NAME, VK_KHR_SURFACE_SPEC_VERSION},
603 {VK_KHR_ANDROID_SURFACE_EXTENSION_NAME,
604 VK_KHR_ANDROID_SURFACE_SPEC_VERSION},
605 }};
Chia-I Wu31938252016-05-23 15:31:02 +0800606 static const VkExtensionProperties loader_debug_report_extension = {
607 VK_EXT_DEBUG_REPORT_EXTENSION_NAME, VK_EXT_DEBUG_REPORT_SPEC_VERSION,
608 };
Chia-I Wuff4a6c72016-03-24 16:05:56 +0800609
610 // enumerate our extensions first
611 if (!pLayerName && pProperties) {
612 uint32_t count = std::min(
613 *pPropertyCount, static_cast<uint32_t>(loader_extensions.size()));
614
615 std::copy_n(loader_extensions.begin(), count, pProperties);
616
617 if (count < loader_extensions.size()) {
618 *pPropertyCount = count;
619 return VK_INCOMPLETE;
620 }
621
622 pProperties += count;
623 *pPropertyCount -= count;
Chia-I Wu31938252016-05-23 15:31:02 +0800624
625 if (Hal::Get().GetDebugReportIndex() < 0) {
626 if (!*pPropertyCount) {
627 *pPropertyCount = count;
628 return VK_INCOMPLETE;
629 }
630
631 pProperties[0] = loader_debug_report_extension;
632 pProperties += 1;
633 *pPropertyCount -= 1;
634 }
Chia-I Wuff4a6c72016-03-24 16:05:56 +0800635 }
636
Chia-I Wu31b2e4f2016-05-23 10:47:57 +0800637 VkResult result = Hal::Device().EnumerateInstanceExtensionProperties(
Chia-I Wuff4a6c72016-03-24 16:05:56 +0800638 pLayerName, pPropertyCount, pProperties);
639
Chia-I Wu31938252016-05-23 15:31:02 +0800640 if (!pLayerName && (result == VK_SUCCESS || result == VK_INCOMPLETE)) {
641 int idx = Hal::Get().GetDebugReportIndex();
642 if (idx < 0) {
643 *pPropertyCount += 1;
644 } else if (pProperties &&
645 static_cast<uint32_t>(idx) < *pPropertyCount) {
646 pProperties[idx].specVersion =
647 std::min(pProperties[idx].specVersion,
648 loader_debug_report_extension.specVersion);
649 }
650
Chia-I Wuff4a6c72016-03-24 16:05:56 +0800651 *pPropertyCount += loader_extensions.size();
Chia-I Wu31938252016-05-23 15:31:02 +0800652 }
Chia-I Wuff4a6c72016-03-24 16:05:56 +0800653
654 return result;
655}
656
Chia-I Wu01cf3052016-03-24 16:16:21 +0800657VkResult EnumerateDeviceExtensionProperties(
658 VkPhysicalDevice physicalDevice,
659 const char* pLayerName,
660 uint32_t* pPropertyCount,
661 VkExtensionProperties* pProperties) {
662 const InstanceData& data = GetData(physicalDevice);
Ian Elliottd4b50aa2017-01-09 16:21:36 -0700663 static const std::array<VkExtensionProperties, 1> loader_extensions = {{
664 // WSI extensions
665 {VK_KHR_INCREMENTAL_PRESENT_EXTENSION_NAME,
666 VK_KHR_INCREMENTAL_PRESENT_SPEC_VERSION},
667 }};
668
669 // enumerate our extensions first
670 if (!pLayerName && pProperties) {
671 uint32_t count = std::min(
672 *pPropertyCount, static_cast<uint32_t>(loader_extensions.size()));
673
674 std::copy_n(loader_extensions.begin(), count, pProperties);
675
676 if (count < loader_extensions.size()) {
677 *pPropertyCount = count;
678 return VK_INCOMPLETE;
679 }
680
681 pProperties += count;
682 *pPropertyCount -= count;
683 }
Chia-I Wu01cf3052016-03-24 16:16:21 +0800684
685 VkResult result = data.driver.EnumerateDeviceExtensionProperties(
686 physicalDevice, pLayerName, pPropertyCount, pProperties);
Chia-I Wu01cf3052016-03-24 16:16:21 +0800687
Ian Elliottd4b50aa2017-01-09 16:21:36 -0700688 if (pProperties) {
689 // map VK_ANDROID_native_buffer to VK_KHR_swapchain
690 for (uint32_t i = 0; i < *pPropertyCount; i++) {
691 auto& prop = pProperties[i];
Chia-I Wu01cf3052016-03-24 16:16:21 +0800692
Ian Elliottd4b50aa2017-01-09 16:21:36 -0700693 if (strcmp(prop.extensionName,
694 VK_ANDROID_NATIVE_BUFFER_EXTENSION_NAME) != 0)
695 continue;
Chia-I Wu01cf3052016-03-24 16:16:21 +0800696
Ian Elliottd4b50aa2017-01-09 16:21:36 -0700697 memcpy(prop.extensionName, VK_KHR_SWAPCHAIN_EXTENSION_NAME,
698 sizeof(VK_KHR_SWAPCHAIN_EXTENSION_NAME));
699 prop.specVersion = VK_KHR_SWAPCHAIN_SPEC_VERSION;
700 }
701 }
Chia-I Wu01cf3052016-03-24 16:16:21 +0800702
Ian Elliottd4b50aa2017-01-09 16:21:36 -0700703 // restore loader extension count
704 if (!pLayerName && (result == VK_SUCCESS || result == VK_INCOMPLETE)) {
705 *pPropertyCount += loader_extensions.size();
Chia-I Wu01cf3052016-03-24 16:16:21 +0800706 }
707
708 return result;
709}
710
Chia-I Wuff4a6c72016-03-24 16:05:56 +0800711VkResult CreateInstance(const VkInstanceCreateInfo* pCreateInfo,
712 const VkAllocationCallbacks* pAllocator,
713 VkInstance* pInstance) {
714 const VkAllocationCallbacks& data_allocator =
715 (pAllocator) ? *pAllocator : GetDefaultAllocator();
716
Chia-I Wu31b2e4f2016-05-23 10:47:57 +0800717 CreateInfoWrapper wrapper(*pCreateInfo, data_allocator);
Chia-I Wu3e6c2d62016-04-11 13:55:56 +0800718 VkResult result = wrapper.Validate();
Chia-I Wuff4a6c72016-03-24 16:05:56 +0800719 if (result != VK_SUCCESS)
720 return result;
721
722 InstanceData* data = AllocateInstanceData(data_allocator);
723 if (!data)
724 return VK_ERROR_OUT_OF_HOST_MEMORY;
725
Chia-I Wu3e6c2d62016-04-11 13:55:56 +0800726 data->hook_extensions |= wrapper.GetHookExtensions();
Chia-I Wuff4a6c72016-03-24 16:05:56 +0800727
728 // call into the driver
729 VkInstance instance;
Chia-I Wu31b2e4f2016-05-23 10:47:57 +0800730 result = Hal::Device().CreateInstance(
Chia-I Wuff4a6c72016-03-24 16:05:56 +0800731 static_cast<const VkInstanceCreateInfo*>(wrapper), pAllocator,
732 &instance);
733 if (result != VK_SUCCESS) {
734 FreeInstanceData(data, data_allocator);
735 return result;
736 }
737
738 // initialize InstanceDriverTable
739 if (!SetData(instance, *data) ||
Chia-I Wu31b2e4f2016-05-23 10:47:57 +0800740 !InitDriverTable(instance, Hal::Device().GetInstanceProcAddr,
Chia-I Wucbe07ef2016-04-13 15:01:00 +0800741 wrapper.GetHalExtensions())) {
Chia-I Wuff4a6c72016-03-24 16:05:56 +0800742 data->driver.DestroyInstance = reinterpret_cast<PFN_vkDestroyInstance>(
Chia-I Wu31b2e4f2016-05-23 10:47:57 +0800743 Hal::Device().GetInstanceProcAddr(instance, "vkDestroyInstance"));
Chia-I Wuff4a6c72016-03-24 16:05:56 +0800744 if (data->driver.DestroyInstance)
745 data->driver.DestroyInstance(instance, pAllocator);
746
747 FreeInstanceData(data, data_allocator);
748
749 return VK_ERROR_INCOMPATIBLE_DRIVER;
750 }
751
752 data->get_device_proc_addr = reinterpret_cast<PFN_vkGetDeviceProcAddr>(
Chia-I Wu31b2e4f2016-05-23 10:47:57 +0800753 Hal::Device().GetInstanceProcAddr(instance, "vkGetDeviceProcAddr"));
Chia-I Wuff4a6c72016-03-24 16:05:56 +0800754 if (!data->get_device_proc_addr) {
755 data->driver.DestroyInstance(instance, pAllocator);
756 FreeInstanceData(data, data_allocator);
757
758 return VK_ERROR_INCOMPATIBLE_DRIVER;
759 }
760
761 *pInstance = instance;
762
763 return VK_SUCCESS;
764}
765
766void DestroyInstance(VkInstance instance,
767 const VkAllocationCallbacks* pAllocator) {
768 InstanceData& data = GetData(instance);
769 data.driver.DestroyInstance(instance, pAllocator);
770
771 VkAllocationCallbacks local_allocator;
772 if (!pAllocator) {
773 local_allocator = data.allocator;
774 pAllocator = &local_allocator;
775 }
776
777 FreeInstanceData(&data, *pAllocator);
778}
779
Chia-I Wu4901db72016-03-24 16:38:58 +0800780VkResult CreateDevice(VkPhysicalDevice physicalDevice,
781 const VkDeviceCreateInfo* pCreateInfo,
782 const VkAllocationCallbacks* pAllocator,
783 VkDevice* pDevice) {
784 const InstanceData& instance_data = GetData(physicalDevice);
785 const VkAllocationCallbacks& data_allocator =
786 (pAllocator) ? *pAllocator : instance_data.allocator;
787
788 CreateInfoWrapper wrapper(physicalDevice, *pCreateInfo, data_allocator);
Chia-I Wu3e6c2d62016-04-11 13:55:56 +0800789 VkResult result = wrapper.Validate();
Chia-I Wu4901db72016-03-24 16:38:58 +0800790 if (result != VK_SUCCESS)
791 return result;
792
Chia-I Wu950d6e12016-05-03 09:12:35 +0800793 DeviceData* data = AllocateDeviceData(data_allocator,
794 instance_data.debug_report_callbacks);
Chia-I Wu4901db72016-03-24 16:38:58 +0800795 if (!data)
796 return VK_ERROR_OUT_OF_HOST_MEMORY;
797
Chia-I Wu3e6c2d62016-04-11 13:55:56 +0800798 data->hook_extensions |= wrapper.GetHookExtensions();
Chia-I Wu4901db72016-03-24 16:38:58 +0800799
800 // call into the driver
801 VkDevice dev;
802 result = instance_data.driver.CreateDevice(
803 physicalDevice, static_cast<const VkDeviceCreateInfo*>(wrapper),
804 pAllocator, &dev);
805 if (result != VK_SUCCESS) {
806 FreeDeviceData(data, data_allocator);
807 return result;
808 }
809
810 // initialize DeviceDriverTable
811 if (!SetData(dev, *data) ||
Chia-I Wucbe07ef2016-04-13 15:01:00 +0800812 !InitDriverTable(dev, instance_data.get_device_proc_addr,
813 wrapper.GetHalExtensions())) {
Chia-I Wu4901db72016-03-24 16:38:58 +0800814 data->driver.DestroyDevice = reinterpret_cast<PFN_vkDestroyDevice>(
815 instance_data.get_device_proc_addr(dev, "vkDestroyDevice"));
816 if (data->driver.DestroyDevice)
817 data->driver.DestroyDevice(dev, pAllocator);
818
819 FreeDeviceData(data, data_allocator);
820
821 return VK_ERROR_INCOMPATIBLE_DRIVER;
822 }
Jesse Halldc225072016-05-30 22:40:14 -0700823 data->driver_device = dev;
Chia-I Wu4901db72016-03-24 16:38:58 +0800824
825 *pDevice = dev;
826
827 return VK_SUCCESS;
828}
829
830void DestroyDevice(VkDevice device, const VkAllocationCallbacks* pAllocator) {
831 DeviceData& data = GetData(device);
832 data.driver.DestroyDevice(device, pAllocator);
833
834 VkAllocationCallbacks local_allocator;
835 if (!pAllocator) {
836 local_allocator = data.allocator;
837 pAllocator = &local_allocator;
838 }
839
840 FreeDeviceData(&data, *pAllocator);
841}
842
Chia-I Wuff4a6c72016-03-24 16:05:56 +0800843VkResult EnumeratePhysicalDevices(VkInstance instance,
844 uint32_t* pPhysicalDeviceCount,
845 VkPhysicalDevice* pPhysicalDevices) {
846 const auto& data = GetData(instance);
847
848 VkResult result = data.driver.EnumeratePhysicalDevices(
849 instance, pPhysicalDeviceCount, pPhysicalDevices);
850 if ((result == VK_SUCCESS || result == VK_INCOMPLETE) && pPhysicalDevices) {
851 for (uint32_t i = 0; i < *pPhysicalDeviceCount; i++)
852 SetData(pPhysicalDevices[i], data);
853 }
854
855 return result;
856}
857
Chia-I Wuba0be412016-03-24 16:24:40 +0800858void GetDeviceQueue(VkDevice device,
859 uint32_t queueFamilyIndex,
860 uint32_t queueIndex,
861 VkQueue* pQueue) {
862 const auto& data = GetData(device);
863
864 data.driver.GetDeviceQueue(device, queueFamilyIndex, queueIndex, pQueue);
865 SetData(*pQueue, data);
866}
867
Chia-I Wu6a58a8a2016-03-24 16:29:51 +0800868VKAPI_ATTR VkResult
869AllocateCommandBuffers(VkDevice device,
870 const VkCommandBufferAllocateInfo* pAllocateInfo,
871 VkCommandBuffer* pCommandBuffers) {
872 const auto& data = GetData(device);
873
874 VkResult result = data.driver.AllocateCommandBuffers(device, pAllocateInfo,
875 pCommandBuffers);
876 if (result == VK_SUCCESS) {
877 for (uint32_t i = 0; i < pAllocateInfo->commandBufferCount; i++)
878 SetData(pCommandBuffers[i], data);
879 }
880
881 return result;
882}
883
Chia-I Wu9d518162016-03-24 14:55:27 +0800884} // namespace driver
885} // namespace vulkan