blob: 56396f467fef183809813cc25d3dd432ab8a1d93 [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>
Chia-I Wu4901db72016-03-24 16:38:58 +080024#include <new>
Mark Salyzyn7823e122016-09-29 08:08:05 -070025
26#include <log/log.h>
Chia-I Wu9d518162016-03-24 14:55:27 +080027
28#include "driver.h"
Jesse Hallb7c4e3b2016-04-11 13:51:38 -070029#include "stubhal.h"
Chia-I Wu9d518162016-03-24 14:55:27 +080030
Chia-I Wudbb7e9c2016-03-24 15:09:38 +080031// #define ENABLE_ALLOC_CALLSTACKS 1
32#if ENABLE_ALLOC_CALLSTACKS
33#include <utils/CallStack.h>
34#define ALOGD_CALLSTACK(...) \
35 do { \
36 ALOGD(__VA_ARGS__); \
37 android::CallStack callstack; \
38 callstack.update(); \
39 callstack.log(LOG_TAG, ANDROID_LOG_DEBUG, " "); \
40 } while (false)
41#else
42#define ALOGD_CALLSTACK(...) \
43 do { \
44 } while (false)
45#endif
46
Chia-I Wu9d518162016-03-24 14:55:27 +080047namespace vulkan {
48namespace driver {
49
Chia-I Wu136b8eb2016-03-24 15:01:52 +080050namespace {
51
Chia-I Wu31b2e4f2016-05-23 10:47:57 +080052class Hal {
53 public:
54 static bool Open();
55
56 static const Hal& Get() { return hal_; }
57 static const hwvulkan_device_t& Device() { return *Get().dev_; }
58
Chia-I Wu31938252016-05-23 15:31:02 +080059 int GetDebugReportIndex() const { return debug_report_index_; }
60
Chia-I Wu31b2e4f2016-05-23 10:47:57 +080061 private:
Chia-I Wu31938252016-05-23 15:31:02 +080062 Hal() : dev_(nullptr), debug_report_index_(-1) {}
Chia-I Wu31b2e4f2016-05-23 10:47:57 +080063 Hal(const Hal&) = delete;
64 Hal& operator=(const Hal&) = delete;
65
Chia-I Wu31938252016-05-23 15:31:02 +080066 bool InitDebugReportIndex();
67
Chia-I Wu31b2e4f2016-05-23 10:47:57 +080068 static Hal hal_;
69
70 const hwvulkan_device_t* dev_;
Chia-I Wu31938252016-05-23 15:31:02 +080071 int debug_report_index_;
Chia-I Wu31b2e4f2016-05-23 10:47:57 +080072};
73
Chia-I Wu4901db72016-03-24 16:38:58 +080074class CreateInfoWrapper {
75 public:
Chia-I Wu31b2e4f2016-05-23 10:47:57 +080076 CreateInfoWrapper(const VkInstanceCreateInfo& create_info,
Chia-I Wuff4a6c72016-03-24 16:05:56 +080077 const VkAllocationCallbacks& allocator);
Chia-I Wu4901db72016-03-24 16:38:58 +080078 CreateInfoWrapper(VkPhysicalDevice physical_dev,
79 const VkDeviceCreateInfo& create_info,
80 const VkAllocationCallbacks& allocator);
81 ~CreateInfoWrapper();
82
Chia-I Wu3e6c2d62016-04-11 13:55:56 +080083 VkResult Validate();
Chia-I Wu4901db72016-03-24 16:38:58 +080084
Chia-I Wu3e6c2d62016-04-11 13:55:56 +080085 const std::bitset<ProcHook::EXTENSION_COUNT>& GetHookExtensions() const;
86 const std::bitset<ProcHook::EXTENSION_COUNT>& GetHalExtensions() const;
Chia-I Wu4901db72016-03-24 16:38:58 +080087
Chia-I Wuff4a6c72016-03-24 16:05:56 +080088 explicit operator const VkInstanceCreateInfo*() const;
Chia-I Wu4901db72016-03-24 16:38:58 +080089 explicit operator const VkDeviceCreateInfo*() const;
90
91 private:
92 struct ExtensionFilter {
93 VkExtensionProperties* exts;
94 uint32_t ext_count;
95
96 const char** names;
97 uint32_t name_count;
98 };
99
Chia-I Wu3e6c2d62016-04-11 13:55:56 +0800100 VkResult SanitizePNext();
Chia-I Wu4901db72016-03-24 16:38:58 +0800101
Chia-I Wu3e6c2d62016-04-11 13:55:56 +0800102 VkResult SanitizeLayers();
103 VkResult SanitizeExtensions();
Chia-I Wu4901db72016-03-24 16:38:58 +0800104
Chia-I Wu3e6c2d62016-04-11 13:55:56 +0800105 VkResult QueryExtensionCount(uint32_t& count) const;
106 VkResult EnumerateExtensions(uint32_t& count,
107 VkExtensionProperties* props) const;
108 VkResult InitExtensionFilter();
109 void FilterExtension(const char* name);
Chia-I Wu4901db72016-03-24 16:38:58 +0800110
111 const bool is_instance_;
112 const VkAllocationCallbacks& allocator_;
113
Chia-I Wu31b2e4f2016-05-23 10:47:57 +0800114 VkPhysicalDevice physical_dev_;
Chia-I Wu4901db72016-03-24 16:38:58 +0800115
116 union {
117 VkInstanceCreateInfo instance_info_;
118 VkDeviceCreateInfo dev_info_;
119 };
120
121 ExtensionFilter extension_filter_;
122
123 std::bitset<ProcHook::EXTENSION_COUNT> hook_extensions_;
124 std::bitset<ProcHook::EXTENSION_COUNT> hal_extensions_;
125};
126
Chia-I Wu31b2e4f2016-05-23 10:47:57 +0800127Hal Hal::hal_;
128
129bool Hal::Open() {
Jesse Halldc225072016-05-30 22:40:14 -0700130 ALOG_ASSERT(!hal_.dev_, "OpenHAL called more than once");
Chia-I Wu31b2e4f2016-05-23 10:47:57 +0800131
132 // Use a stub device unless we successfully open a real HAL device.
133 hal_.dev_ = &stubhal::kDevice;
134
135 const hwvulkan_module_t* module;
136 int result =
137 hw_get_module("vulkan", reinterpret_cast<const hw_module_t**>(&module));
138 if (result != 0) {
139 ALOGI("no Vulkan HAL present, using stub HAL");
140 return true;
141 }
142
143 hwvulkan_device_t* device;
144 result =
145 module->common.methods->open(&module->common, HWVULKAN_DEVICE_0,
146 reinterpret_cast<hw_device_t**>(&device));
147 if (result != 0) {
148 // Any device with a Vulkan HAL should be able to open the device.
149 ALOGE("failed to open Vulkan HAL device: %s (%d)", strerror(-result),
150 result);
151 return false;
152 }
153
154 hal_.dev_ = device;
155
Chia-I Wu31938252016-05-23 15:31:02 +0800156 hal_.InitDebugReportIndex();
157
158 return true;
159}
160
161bool Hal::InitDebugReportIndex() {
162 uint32_t count;
163 if (dev_->EnumerateInstanceExtensionProperties(nullptr, &count, nullptr) !=
164 VK_SUCCESS) {
165 ALOGE("failed to get HAL instance extension count");
166 return false;
167 }
168
169 VkExtensionProperties* exts = reinterpret_cast<VkExtensionProperties*>(
170 malloc(sizeof(VkExtensionProperties) * count));
171 if (!exts) {
172 ALOGE("failed to allocate HAL instance extension array");
173 return false;
174 }
175
176 if (dev_->EnumerateInstanceExtensionProperties(nullptr, &count, exts) !=
177 VK_SUCCESS) {
178 ALOGE("failed to enumerate HAL instance extensions");
179 free(exts);
180 return false;
181 }
182
183 for (uint32_t i = 0; i < count; i++) {
184 if (strcmp(exts[i].extensionName, VK_EXT_DEBUG_REPORT_EXTENSION_NAME) ==
185 0) {
186 debug_report_index_ = static_cast<int>(i);
187 break;
188 }
189 }
190
191 free(exts);
192
Chia-I Wu31b2e4f2016-05-23 10:47:57 +0800193 return true;
194}
195
196CreateInfoWrapper::CreateInfoWrapper(const VkInstanceCreateInfo& create_info,
Chia-I Wuff4a6c72016-03-24 16:05:56 +0800197 const VkAllocationCallbacks& allocator)
198 : is_instance_(true),
199 allocator_(allocator),
Chia-I Wu31b2e4f2016-05-23 10:47:57 +0800200 physical_dev_(VK_NULL_HANDLE),
Chia-I Wuff4a6c72016-03-24 16:05:56 +0800201 instance_info_(create_info),
202 extension_filter_() {
203 hook_extensions_.set(ProcHook::EXTENSION_CORE);
204 hal_extensions_.set(ProcHook::EXTENSION_CORE);
205}
206
Chia-I Wu4901db72016-03-24 16:38:58 +0800207CreateInfoWrapper::CreateInfoWrapper(VkPhysicalDevice physical_dev,
208 const VkDeviceCreateInfo& create_info,
209 const VkAllocationCallbacks& allocator)
210 : is_instance_(false),
211 allocator_(allocator),
212 physical_dev_(physical_dev),
213 dev_info_(create_info),
214 extension_filter_() {
215 hook_extensions_.set(ProcHook::EXTENSION_CORE);
216 hal_extensions_.set(ProcHook::EXTENSION_CORE);
217}
218
219CreateInfoWrapper::~CreateInfoWrapper() {
220 allocator_.pfnFree(allocator_.pUserData, extension_filter_.exts);
221 allocator_.pfnFree(allocator_.pUserData, extension_filter_.names);
222}
223
Chia-I Wu3e6c2d62016-04-11 13:55:56 +0800224VkResult CreateInfoWrapper::Validate() {
225 VkResult result = SanitizePNext();
Chia-I Wu4901db72016-03-24 16:38:58 +0800226 if (result == VK_SUCCESS)
Chia-I Wu3e6c2d62016-04-11 13:55:56 +0800227 result = SanitizeLayers();
Chia-I Wu4901db72016-03-24 16:38:58 +0800228 if (result == VK_SUCCESS)
Chia-I Wu3e6c2d62016-04-11 13:55:56 +0800229 result = SanitizeExtensions();
Chia-I Wu4901db72016-03-24 16:38:58 +0800230
231 return result;
232}
233
234const std::bitset<ProcHook::EXTENSION_COUNT>&
Chia-I Wu3e6c2d62016-04-11 13:55:56 +0800235CreateInfoWrapper::GetHookExtensions() const {
Chia-I Wu4901db72016-03-24 16:38:58 +0800236 return hook_extensions_;
237}
238
239const std::bitset<ProcHook::EXTENSION_COUNT>&
Chia-I Wu3e6c2d62016-04-11 13:55:56 +0800240CreateInfoWrapper::GetHalExtensions() const {
Chia-I Wu4901db72016-03-24 16:38:58 +0800241 return hal_extensions_;
242}
243
Chia-I Wuff4a6c72016-03-24 16:05:56 +0800244CreateInfoWrapper::operator const VkInstanceCreateInfo*() const {
245 return &instance_info_;
246}
247
Chia-I Wu4901db72016-03-24 16:38:58 +0800248CreateInfoWrapper::operator const VkDeviceCreateInfo*() const {
249 return &dev_info_;
250}
251
Chia-I Wu3e6c2d62016-04-11 13:55:56 +0800252VkResult CreateInfoWrapper::SanitizePNext() {
Chia-I Wu4901db72016-03-24 16:38:58 +0800253 const struct StructHeader {
254 VkStructureType type;
255 const void* next;
256 } * header;
257
258 if (is_instance_) {
259 header = reinterpret_cast<const StructHeader*>(instance_info_.pNext);
260
261 // skip leading VK_STRUCTURE_TYPE_LOADER_INSTANCE_CREATE_INFOs
262 while (header &&
263 header->type == VK_STRUCTURE_TYPE_LOADER_INSTANCE_CREATE_INFO)
264 header = reinterpret_cast<const StructHeader*>(header->next);
265
266 instance_info_.pNext = header;
267 } else {
268 header = reinterpret_cast<const StructHeader*>(dev_info_.pNext);
269
270 // skip leading VK_STRUCTURE_TYPE_LOADER_DEVICE_CREATE_INFOs
271 while (header &&
272 header->type == VK_STRUCTURE_TYPE_LOADER_DEVICE_CREATE_INFO)
273 header = reinterpret_cast<const StructHeader*>(header->next);
274
275 dev_info_.pNext = header;
276 }
277
278 return VK_SUCCESS;
279}
280
Chia-I Wu3e6c2d62016-04-11 13:55:56 +0800281VkResult CreateInfoWrapper::SanitizeLayers() {
Chia-I Wu4901db72016-03-24 16:38:58 +0800282 auto& layer_names = (is_instance_) ? instance_info_.ppEnabledLayerNames
283 : dev_info_.ppEnabledLayerNames;
284 auto& layer_count = (is_instance_) ? instance_info_.enabledLayerCount
285 : dev_info_.enabledLayerCount;
286
287 // remove all layers
288 layer_names = nullptr;
289 layer_count = 0;
290
291 return VK_SUCCESS;
292}
293
Chia-I Wu3e6c2d62016-04-11 13:55:56 +0800294VkResult CreateInfoWrapper::SanitizeExtensions() {
Chia-I Wu4901db72016-03-24 16:38:58 +0800295 auto& ext_names = (is_instance_) ? instance_info_.ppEnabledExtensionNames
296 : dev_info_.ppEnabledExtensionNames;
297 auto& ext_count = (is_instance_) ? instance_info_.enabledExtensionCount
298 : dev_info_.enabledExtensionCount;
299 if (!ext_count)
300 return VK_SUCCESS;
301
Chia-I Wu3e6c2d62016-04-11 13:55:56 +0800302 VkResult result = InitExtensionFilter();
Chia-I Wu4901db72016-03-24 16:38:58 +0800303 if (result != VK_SUCCESS)
304 return result;
305
306 for (uint32_t i = 0; i < ext_count; i++)
Chia-I Wu3e6c2d62016-04-11 13:55:56 +0800307 FilterExtension(ext_names[i]);
Chia-I Wu4901db72016-03-24 16:38:58 +0800308
309 ext_names = extension_filter_.names;
310 ext_count = extension_filter_.name_count;
311
312 return VK_SUCCESS;
313}
314
Chia-I Wu3e6c2d62016-04-11 13:55:56 +0800315VkResult CreateInfoWrapper::QueryExtensionCount(uint32_t& count) const {
Chia-I Wu4901db72016-03-24 16:38:58 +0800316 if (is_instance_) {
Chia-I Wu31b2e4f2016-05-23 10:47:57 +0800317 return Hal::Device().EnumerateInstanceExtensionProperties(
318 nullptr, &count, nullptr);
Chia-I Wu4901db72016-03-24 16:38:58 +0800319 } else {
320 const auto& driver = GetData(physical_dev_).driver;
321 return driver.EnumerateDeviceExtensionProperties(physical_dev_, nullptr,
322 &count, nullptr);
323 }
324}
325
Chia-I Wu3e6c2d62016-04-11 13:55:56 +0800326VkResult CreateInfoWrapper::EnumerateExtensions(
Chia-I Wu4901db72016-03-24 16:38:58 +0800327 uint32_t& count,
328 VkExtensionProperties* props) const {
329 if (is_instance_) {
Chia-I Wu31b2e4f2016-05-23 10:47:57 +0800330 return Hal::Device().EnumerateInstanceExtensionProperties(
331 nullptr, &count, props);
Chia-I Wu4901db72016-03-24 16:38:58 +0800332 } else {
333 const auto& driver = GetData(physical_dev_).driver;
334 return driver.EnumerateDeviceExtensionProperties(physical_dev_, nullptr,
335 &count, props);
336 }
337}
338
Chia-I Wu3e6c2d62016-04-11 13:55:56 +0800339VkResult CreateInfoWrapper::InitExtensionFilter() {
Chia-I Wu4901db72016-03-24 16:38:58 +0800340 // query extension count
341 uint32_t count;
Chia-I Wu3e6c2d62016-04-11 13:55:56 +0800342 VkResult result = QueryExtensionCount(count);
Chia-I Wu4901db72016-03-24 16:38:58 +0800343 if (result != VK_SUCCESS || count == 0)
344 return result;
345
346 auto& filter = extension_filter_;
347 filter.exts =
348 reinterpret_cast<VkExtensionProperties*>(allocator_.pfnAllocation(
349 allocator_.pUserData, sizeof(VkExtensionProperties) * count,
350 alignof(VkExtensionProperties),
351 VK_SYSTEM_ALLOCATION_SCOPE_COMMAND));
352 if (!filter.exts)
353 return VK_ERROR_OUT_OF_HOST_MEMORY;
354
355 // enumerate extensions
Chia-I Wu3e6c2d62016-04-11 13:55:56 +0800356 result = EnumerateExtensions(count, filter.exts);
Chia-I Wu4901db72016-03-24 16:38:58 +0800357 if (result != VK_SUCCESS && result != VK_INCOMPLETE)
358 return result;
359
360 if (!count)
361 return VK_SUCCESS;
362
363 filter.ext_count = count;
364
365 // allocate name array
366 uint32_t enabled_ext_count = (is_instance_)
367 ? instance_info_.enabledExtensionCount
368 : dev_info_.enabledExtensionCount;
369 count = std::min(filter.ext_count, enabled_ext_count);
370 filter.names = reinterpret_cast<const char**>(allocator_.pfnAllocation(
371 allocator_.pUserData, sizeof(const char*) * count, alignof(const char*),
372 VK_SYSTEM_ALLOCATION_SCOPE_COMMAND));
373 if (!filter.names)
374 return VK_ERROR_OUT_OF_HOST_MEMORY;
375
376 return VK_SUCCESS;
377}
378
Chia-I Wu3e6c2d62016-04-11 13:55:56 +0800379void CreateInfoWrapper::FilterExtension(const char* name) {
Chia-I Wu4901db72016-03-24 16:38:58 +0800380 auto& filter = extension_filter_;
381
382 ProcHook::Extension ext_bit = GetProcHookExtension(name);
383 if (is_instance_) {
384 switch (ext_bit) {
385 case ProcHook::KHR_android_surface:
386 case ProcHook::KHR_surface:
387 hook_extensions_.set(ext_bit);
388 // return now as these extensions do not require HAL support
389 return;
390 case ProcHook::EXT_debug_report:
391 // both we and HAL can take part in
392 hook_extensions_.set(ext_bit);
393 break;
394 case ProcHook::EXTENSION_UNKNOWN:
395 // HAL's extensions
396 break;
397 default:
398 ALOGW("Ignored invalid instance extension %s", name);
399 return;
400 }
401 } else {
402 switch (ext_bit) {
403 case ProcHook::KHR_swapchain:
404 // map VK_KHR_swapchain to VK_ANDROID_native_buffer
405 name = VK_ANDROID_NATIVE_BUFFER_EXTENSION_NAME;
406 ext_bit = ProcHook::ANDROID_native_buffer;
407 break;
408 case ProcHook::EXTENSION_UNKNOWN:
409 // HAL's extensions
410 break;
411 default:
412 ALOGW("Ignored invalid device extension %s", name);
413 return;
414 }
415 }
416
417 for (uint32_t i = 0; i < filter.ext_count; i++) {
418 const VkExtensionProperties& props = filter.exts[i];
419 // ignore unknown extensions
420 if (strcmp(name, props.extensionName) != 0)
421 continue;
422
Chia-I Wu4901db72016-03-24 16:38:58 +0800423 filter.names[filter.name_count++] = name;
Chia-I Wu1600e262016-04-12 09:40:06 +0800424 if (ext_bit != ProcHook::EXTENSION_UNKNOWN) {
425 if (ext_bit == ProcHook::ANDROID_native_buffer)
426 hook_extensions_.set(ProcHook::KHR_swapchain);
427
428 hal_extensions_.set(ext_bit);
429 }
Chia-I Wu4901db72016-03-24 16:38:58 +0800430
431 break;
432 }
433}
434
Chia-I Wudbb7e9c2016-03-24 15:09:38 +0800435VKAPI_ATTR void* DefaultAllocate(void*,
436 size_t size,
437 size_t alignment,
438 VkSystemAllocationScope) {
439 void* ptr = nullptr;
440 // Vulkan requires 'alignment' to be a power of two, but posix_memalign
441 // additionally requires that it be at least sizeof(void*).
442 int ret = posix_memalign(&ptr, std::max(alignment, sizeof(void*)), size);
443 ALOGD_CALLSTACK("Allocate: size=%zu align=%zu => (%d) %p", size, alignment,
444 ret, ptr);
445 return ret == 0 ? ptr : nullptr;
446}
447
448VKAPI_ATTR void* DefaultReallocate(void*,
449 void* ptr,
450 size_t size,
451 size_t alignment,
452 VkSystemAllocationScope) {
453 if (size == 0) {
454 free(ptr);
455 return nullptr;
456 }
457
458 // TODO(jessehall): Right now we never shrink allocations; if the new
459 // request is smaller than the existing chunk, we just continue using it.
460 // Right now the loader never reallocs, so this doesn't matter. If that
461 // changes, or if this code is copied into some other project, this should
462 // probably have a heuristic to allocate-copy-free when doing so will save
463 // "enough" space.
464 size_t old_size = ptr ? malloc_usable_size(ptr) : 0;
465 if (size <= old_size)
466 return ptr;
467
468 void* new_ptr = nullptr;
469 if (posix_memalign(&new_ptr, std::max(alignment, sizeof(void*)), size) != 0)
470 return nullptr;
471 if (ptr) {
472 memcpy(new_ptr, ptr, std::min(old_size, size));
473 free(ptr);
474 }
475 return new_ptr;
476}
477
478VKAPI_ATTR void DefaultFree(void*, void* ptr) {
479 ALOGD_CALLSTACK("Free: %p", ptr);
480 free(ptr);
481}
482
Chia-I Wuff4a6c72016-03-24 16:05:56 +0800483InstanceData* AllocateInstanceData(const VkAllocationCallbacks& allocator) {
484 void* data_mem = allocator.pfnAllocation(
485 allocator.pUserData, sizeof(InstanceData), alignof(InstanceData),
486 VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
487 if (!data_mem)
488 return nullptr;
489
490 return new (data_mem) InstanceData(allocator);
491}
492
493void FreeInstanceData(InstanceData* data,
494 const VkAllocationCallbacks& allocator) {
495 data->~InstanceData();
496 allocator.pfnFree(allocator.pUserData, data);
497}
498
Chia-I Wu950d6e12016-05-03 09:12:35 +0800499DeviceData* AllocateDeviceData(
500 const VkAllocationCallbacks& allocator,
501 const DebugReportCallbackList& debug_report_callbacks) {
Chia-I Wu4901db72016-03-24 16:38:58 +0800502 void* data_mem = allocator.pfnAllocation(
503 allocator.pUserData, sizeof(DeviceData), alignof(DeviceData),
504 VK_SYSTEM_ALLOCATION_SCOPE_DEVICE);
505 if (!data_mem)
506 return nullptr;
507
Chia-I Wu950d6e12016-05-03 09:12:35 +0800508 return new (data_mem) DeviceData(allocator, debug_report_callbacks);
Chia-I Wu4901db72016-03-24 16:38:58 +0800509}
510
511void FreeDeviceData(DeviceData* data, const VkAllocationCallbacks& allocator) {
512 data->~DeviceData();
513 allocator.pfnFree(allocator.pUserData, data);
514}
515
Chia-I Wu136b8eb2016-03-24 15:01:52 +0800516} // anonymous namespace
517
Chia-I Wu9d518162016-03-24 14:55:27 +0800518bool Debuggable() {
519 return (prctl(PR_GET_DUMPABLE, 0, 0, 0, 0) >= 0);
520}
521
Chia-I Wu136b8eb2016-03-24 15:01:52 +0800522bool OpenHAL() {
Chia-I Wu31b2e4f2016-05-23 10:47:57 +0800523 return Hal::Open();
Chia-I Wu136b8eb2016-03-24 15:01:52 +0800524}
525
Chia-I Wudbb7e9c2016-03-24 15:09:38 +0800526const VkAllocationCallbacks& GetDefaultAllocator() {
527 static const VkAllocationCallbacks kDefaultAllocCallbacks = {
528 .pUserData = nullptr,
529 .pfnAllocation = DefaultAllocate,
530 .pfnReallocation = DefaultReallocate,
531 .pfnFree = DefaultFree,
532 };
533
534 return kDefaultAllocCallbacks;
535}
536
Chia-I Wueb7db122016-03-24 09:11:06 +0800537PFN_vkVoidFunction GetInstanceProcAddr(VkInstance instance, const char* pName) {
538 const ProcHook* hook = GetProcHook(pName);
539 if (!hook)
Chia-I Wu31b2e4f2016-05-23 10:47:57 +0800540 return Hal::Device().GetInstanceProcAddr(instance, pName);
Chia-I Wueb7db122016-03-24 09:11:06 +0800541
542 if (!instance) {
543 if (hook->type == ProcHook::GLOBAL)
544 return hook->proc;
545
Chia-I Wu109f8982016-04-22 06:40:40 +0800546 // v0 layers expect
547 //
548 // vkGetInstanceProcAddr(VK_NULL_HANDLE, "vkCreateDevice");
549 //
550 // to work.
551 if (strcmp(pName, "vkCreateDevice") == 0)
552 return hook->proc;
553
Chia-I Wueb7db122016-03-24 09:11:06 +0800554 ALOGE(
Chia-I Wue201c3f2016-05-03 13:26:08 +0800555 "internal vkGetInstanceProcAddr called for %s without an instance",
Chia-I Wueb7db122016-03-24 09:11:06 +0800556 pName);
557
Chia-I Wu109f8982016-04-22 06:40:40 +0800558 return nullptr;
Chia-I Wueb7db122016-03-24 09:11:06 +0800559 }
560
561 PFN_vkVoidFunction proc;
562
563 switch (hook->type) {
564 case ProcHook::INSTANCE:
565 proc = (GetData(instance).hook_extensions[hook->extension])
566 ? hook->proc
Chia-I Wu36cc00a2016-04-13 16:52:06 +0800567 : nullptr;
Chia-I Wueb7db122016-03-24 09:11:06 +0800568 break;
569 case ProcHook::DEVICE:
570 proc = (hook->extension == ProcHook::EXTENSION_CORE)
571 ? hook->proc
572 : hook->checked_proc;
573 break;
574 default:
575 ALOGE(
Chia-I Wue201c3f2016-05-03 13:26:08 +0800576 "internal vkGetInstanceProcAddr called for %s with an instance",
Chia-I Wueb7db122016-03-24 09:11:06 +0800577 pName);
578 proc = nullptr;
579 break;
580 }
581
582 return proc;
583}
584
585PFN_vkVoidFunction GetDeviceProcAddr(VkDevice device, const char* pName) {
586 const ProcHook* hook = GetProcHook(pName);
587 if (!hook)
Chia-I Wucc5e2762016-03-24 13:01:16 +0800588 return GetData(device).driver.GetDeviceProcAddr(device, pName);
Chia-I Wueb7db122016-03-24 09:11:06 +0800589
590 if (hook->type != ProcHook::DEVICE) {
Chia-I Wue201c3f2016-05-03 13:26:08 +0800591 ALOGE("internal vkGetDeviceProcAddr called for %s", pName);
Chia-I Wueb7db122016-03-24 09:11:06 +0800592 return nullptr;
593 }
594
Chia-I Wu36cc00a2016-04-13 16:52:06 +0800595 return (GetData(device).hook_extensions[hook->extension]) ? hook->proc
596 : nullptr;
Chia-I Wueb7db122016-03-24 09:11:06 +0800597}
598
Chia-I Wuff4a6c72016-03-24 16:05:56 +0800599VkResult EnumerateInstanceExtensionProperties(
600 const char* pLayerName,
601 uint32_t* pPropertyCount,
602 VkExtensionProperties* pProperties) {
603 static const std::array<VkExtensionProperties, 2> loader_extensions = {{
604 // WSI extensions
605 {VK_KHR_SURFACE_EXTENSION_NAME, VK_KHR_SURFACE_SPEC_VERSION},
606 {VK_KHR_ANDROID_SURFACE_EXTENSION_NAME,
607 VK_KHR_ANDROID_SURFACE_SPEC_VERSION},
608 }};
Chia-I Wu31938252016-05-23 15:31:02 +0800609 static const VkExtensionProperties loader_debug_report_extension = {
610 VK_EXT_DEBUG_REPORT_EXTENSION_NAME, VK_EXT_DEBUG_REPORT_SPEC_VERSION,
611 };
Chia-I Wuff4a6c72016-03-24 16:05:56 +0800612
613 // enumerate our extensions first
614 if (!pLayerName && pProperties) {
615 uint32_t count = std::min(
616 *pPropertyCount, static_cast<uint32_t>(loader_extensions.size()));
617
618 std::copy_n(loader_extensions.begin(), count, pProperties);
619
620 if (count < loader_extensions.size()) {
621 *pPropertyCount = count;
622 return VK_INCOMPLETE;
623 }
624
625 pProperties += count;
626 *pPropertyCount -= count;
Chia-I Wu31938252016-05-23 15:31:02 +0800627
628 if (Hal::Get().GetDebugReportIndex() < 0) {
629 if (!*pPropertyCount) {
630 *pPropertyCount = count;
631 return VK_INCOMPLETE;
632 }
633
634 pProperties[0] = loader_debug_report_extension;
635 pProperties += 1;
636 *pPropertyCount -= 1;
637 }
Chia-I Wuff4a6c72016-03-24 16:05:56 +0800638 }
639
Chia-I Wu31b2e4f2016-05-23 10:47:57 +0800640 VkResult result = Hal::Device().EnumerateInstanceExtensionProperties(
Chia-I Wuff4a6c72016-03-24 16:05:56 +0800641 pLayerName, pPropertyCount, pProperties);
642
Chia-I Wu31938252016-05-23 15:31:02 +0800643 if (!pLayerName && (result == VK_SUCCESS || result == VK_INCOMPLETE)) {
644 int idx = Hal::Get().GetDebugReportIndex();
645 if (idx < 0) {
646 *pPropertyCount += 1;
647 } else if (pProperties &&
648 static_cast<uint32_t>(idx) < *pPropertyCount) {
649 pProperties[idx].specVersion =
650 std::min(pProperties[idx].specVersion,
651 loader_debug_report_extension.specVersion);
652 }
653
Chia-I Wuff4a6c72016-03-24 16:05:56 +0800654 *pPropertyCount += loader_extensions.size();
Chia-I Wu31938252016-05-23 15:31:02 +0800655 }
Chia-I Wuff4a6c72016-03-24 16:05:56 +0800656
657 return result;
658}
659
Chia-I Wu01cf3052016-03-24 16:16:21 +0800660VkResult EnumerateDeviceExtensionProperties(
661 VkPhysicalDevice physicalDevice,
662 const char* pLayerName,
663 uint32_t* pPropertyCount,
664 VkExtensionProperties* pProperties) {
665 const InstanceData& data = GetData(physicalDevice);
666
667 VkResult result = data.driver.EnumerateDeviceExtensionProperties(
668 physicalDevice, pLayerName, pPropertyCount, pProperties);
669 if (result != VK_SUCCESS && result != VK_INCOMPLETE)
670 return result;
671
672 if (!pProperties)
673 return result;
674
675 // map VK_ANDROID_native_buffer to VK_KHR_swapchain
676 for (uint32_t i = 0; i < *pPropertyCount; i++) {
677 auto& prop = pProperties[i];
678
679 if (strcmp(prop.extensionName,
680 VK_ANDROID_NATIVE_BUFFER_EXTENSION_NAME) != 0)
681 continue;
682
683 memcpy(prop.extensionName, VK_KHR_SWAPCHAIN_EXTENSION_NAME,
684 sizeof(VK_KHR_SWAPCHAIN_EXTENSION_NAME));
685 prop.specVersion = VK_KHR_SWAPCHAIN_SPEC_VERSION;
686 }
687
688 return result;
689}
690
Chia-I Wuff4a6c72016-03-24 16:05:56 +0800691VkResult CreateInstance(const VkInstanceCreateInfo* pCreateInfo,
692 const VkAllocationCallbacks* pAllocator,
693 VkInstance* pInstance) {
694 const VkAllocationCallbacks& data_allocator =
695 (pAllocator) ? *pAllocator : GetDefaultAllocator();
696
Chia-I Wu31b2e4f2016-05-23 10:47:57 +0800697 CreateInfoWrapper wrapper(*pCreateInfo, data_allocator);
Chia-I Wu3e6c2d62016-04-11 13:55:56 +0800698 VkResult result = wrapper.Validate();
Chia-I Wuff4a6c72016-03-24 16:05:56 +0800699 if (result != VK_SUCCESS)
700 return result;
701
702 InstanceData* data = AllocateInstanceData(data_allocator);
703 if (!data)
704 return VK_ERROR_OUT_OF_HOST_MEMORY;
705
Chia-I Wu3e6c2d62016-04-11 13:55:56 +0800706 data->hook_extensions |= wrapper.GetHookExtensions();
Chia-I Wuff4a6c72016-03-24 16:05:56 +0800707
708 // call into the driver
709 VkInstance instance;
Chia-I Wu31b2e4f2016-05-23 10:47:57 +0800710 result = Hal::Device().CreateInstance(
Chia-I Wuff4a6c72016-03-24 16:05:56 +0800711 static_cast<const VkInstanceCreateInfo*>(wrapper), pAllocator,
712 &instance);
713 if (result != VK_SUCCESS) {
714 FreeInstanceData(data, data_allocator);
715 return result;
716 }
717
718 // initialize InstanceDriverTable
719 if (!SetData(instance, *data) ||
Chia-I Wu31b2e4f2016-05-23 10:47:57 +0800720 !InitDriverTable(instance, Hal::Device().GetInstanceProcAddr,
Chia-I Wucbe07ef2016-04-13 15:01:00 +0800721 wrapper.GetHalExtensions())) {
Chia-I Wuff4a6c72016-03-24 16:05:56 +0800722 data->driver.DestroyInstance = reinterpret_cast<PFN_vkDestroyInstance>(
Chia-I Wu31b2e4f2016-05-23 10:47:57 +0800723 Hal::Device().GetInstanceProcAddr(instance, "vkDestroyInstance"));
Chia-I Wuff4a6c72016-03-24 16:05:56 +0800724 if (data->driver.DestroyInstance)
725 data->driver.DestroyInstance(instance, pAllocator);
726
727 FreeInstanceData(data, data_allocator);
728
729 return VK_ERROR_INCOMPATIBLE_DRIVER;
730 }
731
732 data->get_device_proc_addr = reinterpret_cast<PFN_vkGetDeviceProcAddr>(
Chia-I Wu31b2e4f2016-05-23 10:47:57 +0800733 Hal::Device().GetInstanceProcAddr(instance, "vkGetDeviceProcAddr"));
Chia-I Wuff4a6c72016-03-24 16:05:56 +0800734 if (!data->get_device_proc_addr) {
735 data->driver.DestroyInstance(instance, pAllocator);
736 FreeInstanceData(data, data_allocator);
737
738 return VK_ERROR_INCOMPATIBLE_DRIVER;
739 }
740
741 *pInstance = instance;
742
743 return VK_SUCCESS;
744}
745
746void DestroyInstance(VkInstance instance,
747 const VkAllocationCallbacks* pAllocator) {
748 InstanceData& data = GetData(instance);
749 data.driver.DestroyInstance(instance, pAllocator);
750
751 VkAllocationCallbacks local_allocator;
752 if (!pAllocator) {
753 local_allocator = data.allocator;
754 pAllocator = &local_allocator;
755 }
756
757 FreeInstanceData(&data, *pAllocator);
758}
759
Chia-I Wu4901db72016-03-24 16:38:58 +0800760VkResult CreateDevice(VkPhysicalDevice physicalDevice,
761 const VkDeviceCreateInfo* pCreateInfo,
762 const VkAllocationCallbacks* pAllocator,
763 VkDevice* pDevice) {
764 const InstanceData& instance_data = GetData(physicalDevice);
765 const VkAllocationCallbacks& data_allocator =
766 (pAllocator) ? *pAllocator : instance_data.allocator;
767
768 CreateInfoWrapper wrapper(physicalDevice, *pCreateInfo, data_allocator);
Chia-I Wu3e6c2d62016-04-11 13:55:56 +0800769 VkResult result = wrapper.Validate();
Chia-I Wu4901db72016-03-24 16:38:58 +0800770 if (result != VK_SUCCESS)
771 return result;
772
Chia-I Wu950d6e12016-05-03 09:12:35 +0800773 DeviceData* data = AllocateDeviceData(data_allocator,
774 instance_data.debug_report_callbacks);
Chia-I Wu4901db72016-03-24 16:38:58 +0800775 if (!data)
776 return VK_ERROR_OUT_OF_HOST_MEMORY;
777
Chia-I Wu3e6c2d62016-04-11 13:55:56 +0800778 data->hook_extensions |= wrapper.GetHookExtensions();
Chia-I Wu4901db72016-03-24 16:38:58 +0800779
780 // call into the driver
781 VkDevice dev;
782 result = instance_data.driver.CreateDevice(
783 physicalDevice, static_cast<const VkDeviceCreateInfo*>(wrapper),
784 pAllocator, &dev);
785 if (result != VK_SUCCESS) {
786 FreeDeviceData(data, data_allocator);
787 return result;
788 }
789
790 // initialize DeviceDriverTable
791 if (!SetData(dev, *data) ||
Chia-I Wucbe07ef2016-04-13 15:01:00 +0800792 !InitDriverTable(dev, instance_data.get_device_proc_addr,
793 wrapper.GetHalExtensions())) {
Chia-I Wu4901db72016-03-24 16:38:58 +0800794 data->driver.DestroyDevice = reinterpret_cast<PFN_vkDestroyDevice>(
795 instance_data.get_device_proc_addr(dev, "vkDestroyDevice"));
796 if (data->driver.DestroyDevice)
797 data->driver.DestroyDevice(dev, pAllocator);
798
799 FreeDeviceData(data, data_allocator);
800
801 return VK_ERROR_INCOMPATIBLE_DRIVER;
802 }
Jesse Halldc225072016-05-30 22:40:14 -0700803 data->driver_device = dev;
Chia-I Wu4901db72016-03-24 16:38:58 +0800804
805 *pDevice = dev;
806
807 return VK_SUCCESS;
808}
809
810void DestroyDevice(VkDevice device, const VkAllocationCallbacks* pAllocator) {
811 DeviceData& data = GetData(device);
812 data.driver.DestroyDevice(device, pAllocator);
813
814 VkAllocationCallbacks local_allocator;
815 if (!pAllocator) {
816 local_allocator = data.allocator;
817 pAllocator = &local_allocator;
818 }
819
820 FreeDeviceData(&data, *pAllocator);
821}
822
Chia-I Wuff4a6c72016-03-24 16:05:56 +0800823VkResult EnumeratePhysicalDevices(VkInstance instance,
824 uint32_t* pPhysicalDeviceCount,
825 VkPhysicalDevice* pPhysicalDevices) {
826 const auto& data = GetData(instance);
827
828 VkResult result = data.driver.EnumeratePhysicalDevices(
829 instance, pPhysicalDeviceCount, pPhysicalDevices);
830 if ((result == VK_SUCCESS || result == VK_INCOMPLETE) && pPhysicalDevices) {
831 for (uint32_t i = 0; i < *pPhysicalDeviceCount; i++)
832 SetData(pPhysicalDevices[i], data);
833 }
834
835 return result;
836}
837
Chia-I Wuba0be412016-03-24 16:24:40 +0800838void GetDeviceQueue(VkDevice device,
839 uint32_t queueFamilyIndex,
840 uint32_t queueIndex,
841 VkQueue* pQueue) {
842 const auto& data = GetData(device);
843
844 data.driver.GetDeviceQueue(device, queueFamilyIndex, queueIndex, pQueue);
845 SetData(*pQueue, data);
846}
847
Chia-I Wu6a58a8a2016-03-24 16:29:51 +0800848VKAPI_ATTR VkResult
849AllocateCommandBuffers(VkDevice device,
850 const VkCommandBufferAllocateInfo* pAllocateInfo,
851 VkCommandBuffer* pCommandBuffers) {
852 const auto& data = GetData(device);
853
854 VkResult result = data.driver.AllocateCommandBuffers(device, pAllocateInfo,
855 pCommandBuffers);
856 if (result == VK_SUCCESS) {
857 for (uint32_t i = 0; i < pAllocateInfo->commandBufferCount; i++)
858 SetData(pCommandBuffers[i], data);
859 }
860
861 return result;
862}
863
Chia-I Wu9d518162016-03-24 14:55:27 +0800864} // namespace driver
865} // namespace vulkan