blob: 800e474e8af093f1e43ba6dbf16d8b1995431aa5 [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);
Ian Elliottd4b50aa2017-01-09 16:21:36 -0700666 static const std::array<VkExtensionProperties, 1> loader_extensions = {{
667 // WSI extensions
668 {VK_KHR_INCREMENTAL_PRESENT_EXTENSION_NAME,
669 VK_KHR_INCREMENTAL_PRESENT_SPEC_VERSION},
670 }};
671
672 // enumerate our extensions first
673 if (!pLayerName && pProperties) {
674 uint32_t count = std::min(
675 *pPropertyCount, static_cast<uint32_t>(loader_extensions.size()));
676
677 std::copy_n(loader_extensions.begin(), count, pProperties);
678
679 if (count < loader_extensions.size()) {
680 *pPropertyCount = count;
681 return VK_INCOMPLETE;
682 }
683
684 pProperties += count;
685 *pPropertyCount -= count;
686 }
Chia-I Wu01cf3052016-03-24 16:16:21 +0800687
688 VkResult result = data.driver.EnumerateDeviceExtensionProperties(
689 physicalDevice, pLayerName, pPropertyCount, pProperties);
Chia-I Wu01cf3052016-03-24 16:16:21 +0800690
Ian Elliottd4b50aa2017-01-09 16:21:36 -0700691 if (pProperties) {
692 // map VK_ANDROID_native_buffer to VK_KHR_swapchain
693 for (uint32_t i = 0; i < *pPropertyCount; i++) {
694 auto& prop = pProperties[i];
Chia-I Wu01cf3052016-03-24 16:16:21 +0800695
Ian Elliottd4b50aa2017-01-09 16:21:36 -0700696 if (strcmp(prop.extensionName,
697 VK_ANDROID_NATIVE_BUFFER_EXTENSION_NAME) != 0)
698 continue;
Chia-I Wu01cf3052016-03-24 16:16:21 +0800699
Ian Elliottd4b50aa2017-01-09 16:21:36 -0700700 memcpy(prop.extensionName, VK_KHR_SWAPCHAIN_EXTENSION_NAME,
701 sizeof(VK_KHR_SWAPCHAIN_EXTENSION_NAME));
702 prop.specVersion = VK_KHR_SWAPCHAIN_SPEC_VERSION;
703 }
704 }
Chia-I Wu01cf3052016-03-24 16:16:21 +0800705
Ian Elliottd4b50aa2017-01-09 16:21:36 -0700706 // restore loader extension count
707 if (!pLayerName && (result == VK_SUCCESS || result == VK_INCOMPLETE)) {
708 *pPropertyCount += loader_extensions.size();
Chia-I Wu01cf3052016-03-24 16:16:21 +0800709 }
710
711 return result;
712}
713
Chia-I Wuff4a6c72016-03-24 16:05:56 +0800714VkResult CreateInstance(const VkInstanceCreateInfo* pCreateInfo,
715 const VkAllocationCallbacks* pAllocator,
716 VkInstance* pInstance) {
717 const VkAllocationCallbacks& data_allocator =
718 (pAllocator) ? *pAllocator : GetDefaultAllocator();
719
Chia-I Wu31b2e4f2016-05-23 10:47:57 +0800720 CreateInfoWrapper wrapper(*pCreateInfo, data_allocator);
Chia-I Wu3e6c2d62016-04-11 13:55:56 +0800721 VkResult result = wrapper.Validate();
Chia-I Wuff4a6c72016-03-24 16:05:56 +0800722 if (result != VK_SUCCESS)
723 return result;
724
725 InstanceData* data = AllocateInstanceData(data_allocator);
726 if (!data)
727 return VK_ERROR_OUT_OF_HOST_MEMORY;
728
Chia-I Wu3e6c2d62016-04-11 13:55:56 +0800729 data->hook_extensions |= wrapper.GetHookExtensions();
Chia-I Wuff4a6c72016-03-24 16:05:56 +0800730
731 // call into the driver
732 VkInstance instance;
Chia-I Wu31b2e4f2016-05-23 10:47:57 +0800733 result = Hal::Device().CreateInstance(
Chia-I Wuff4a6c72016-03-24 16:05:56 +0800734 static_cast<const VkInstanceCreateInfo*>(wrapper), pAllocator,
735 &instance);
736 if (result != VK_SUCCESS) {
737 FreeInstanceData(data, data_allocator);
738 return result;
739 }
740
741 // initialize InstanceDriverTable
742 if (!SetData(instance, *data) ||
Chia-I Wu31b2e4f2016-05-23 10:47:57 +0800743 !InitDriverTable(instance, Hal::Device().GetInstanceProcAddr,
Chia-I Wucbe07ef2016-04-13 15:01:00 +0800744 wrapper.GetHalExtensions())) {
Chia-I Wuff4a6c72016-03-24 16:05:56 +0800745 data->driver.DestroyInstance = reinterpret_cast<PFN_vkDestroyInstance>(
Chia-I Wu31b2e4f2016-05-23 10:47:57 +0800746 Hal::Device().GetInstanceProcAddr(instance, "vkDestroyInstance"));
Chia-I Wuff4a6c72016-03-24 16:05:56 +0800747 if (data->driver.DestroyInstance)
748 data->driver.DestroyInstance(instance, pAllocator);
749
750 FreeInstanceData(data, data_allocator);
751
752 return VK_ERROR_INCOMPATIBLE_DRIVER;
753 }
754
755 data->get_device_proc_addr = reinterpret_cast<PFN_vkGetDeviceProcAddr>(
Chia-I Wu31b2e4f2016-05-23 10:47:57 +0800756 Hal::Device().GetInstanceProcAddr(instance, "vkGetDeviceProcAddr"));
Chia-I Wuff4a6c72016-03-24 16:05:56 +0800757 if (!data->get_device_proc_addr) {
758 data->driver.DestroyInstance(instance, pAllocator);
759 FreeInstanceData(data, data_allocator);
760
761 return VK_ERROR_INCOMPATIBLE_DRIVER;
762 }
763
764 *pInstance = instance;
765
766 return VK_SUCCESS;
767}
768
769void DestroyInstance(VkInstance instance,
770 const VkAllocationCallbacks* pAllocator) {
771 InstanceData& data = GetData(instance);
772 data.driver.DestroyInstance(instance, pAllocator);
773
774 VkAllocationCallbacks local_allocator;
775 if (!pAllocator) {
776 local_allocator = data.allocator;
777 pAllocator = &local_allocator;
778 }
779
780 FreeInstanceData(&data, *pAllocator);
781}
782
Chia-I Wu4901db72016-03-24 16:38:58 +0800783VkResult CreateDevice(VkPhysicalDevice physicalDevice,
784 const VkDeviceCreateInfo* pCreateInfo,
785 const VkAllocationCallbacks* pAllocator,
786 VkDevice* pDevice) {
787 const InstanceData& instance_data = GetData(physicalDevice);
788 const VkAllocationCallbacks& data_allocator =
789 (pAllocator) ? *pAllocator : instance_data.allocator;
790
791 CreateInfoWrapper wrapper(physicalDevice, *pCreateInfo, data_allocator);
Chia-I Wu3e6c2d62016-04-11 13:55:56 +0800792 VkResult result = wrapper.Validate();
Chia-I Wu4901db72016-03-24 16:38:58 +0800793 if (result != VK_SUCCESS)
794 return result;
795
Chia-I Wu950d6e12016-05-03 09:12:35 +0800796 DeviceData* data = AllocateDeviceData(data_allocator,
797 instance_data.debug_report_callbacks);
Chia-I Wu4901db72016-03-24 16:38:58 +0800798 if (!data)
799 return VK_ERROR_OUT_OF_HOST_MEMORY;
800
Chia-I Wu3e6c2d62016-04-11 13:55:56 +0800801 data->hook_extensions |= wrapper.GetHookExtensions();
Chia-I Wu4901db72016-03-24 16:38:58 +0800802
803 // call into the driver
804 VkDevice dev;
805 result = instance_data.driver.CreateDevice(
806 physicalDevice, static_cast<const VkDeviceCreateInfo*>(wrapper),
807 pAllocator, &dev);
808 if (result != VK_SUCCESS) {
809 FreeDeviceData(data, data_allocator);
810 return result;
811 }
812
813 // initialize DeviceDriverTable
814 if (!SetData(dev, *data) ||
Chia-I Wucbe07ef2016-04-13 15:01:00 +0800815 !InitDriverTable(dev, instance_data.get_device_proc_addr,
816 wrapper.GetHalExtensions())) {
Chia-I Wu4901db72016-03-24 16:38:58 +0800817 data->driver.DestroyDevice = reinterpret_cast<PFN_vkDestroyDevice>(
818 instance_data.get_device_proc_addr(dev, "vkDestroyDevice"));
819 if (data->driver.DestroyDevice)
820 data->driver.DestroyDevice(dev, pAllocator);
821
822 FreeDeviceData(data, data_allocator);
823
824 return VK_ERROR_INCOMPATIBLE_DRIVER;
825 }
Jesse Halldc225072016-05-30 22:40:14 -0700826 data->driver_device = dev;
Chia-I Wu4901db72016-03-24 16:38:58 +0800827
828 *pDevice = dev;
829
830 return VK_SUCCESS;
831}
832
833void DestroyDevice(VkDevice device, const VkAllocationCallbacks* pAllocator) {
834 DeviceData& data = GetData(device);
835 data.driver.DestroyDevice(device, pAllocator);
836
837 VkAllocationCallbacks local_allocator;
838 if (!pAllocator) {
839 local_allocator = data.allocator;
840 pAllocator = &local_allocator;
841 }
842
843 FreeDeviceData(&data, *pAllocator);
844}
845
Chia-I Wuff4a6c72016-03-24 16:05:56 +0800846VkResult EnumeratePhysicalDevices(VkInstance instance,
847 uint32_t* pPhysicalDeviceCount,
848 VkPhysicalDevice* pPhysicalDevices) {
849 const auto& data = GetData(instance);
850
851 VkResult result = data.driver.EnumeratePhysicalDevices(
852 instance, pPhysicalDeviceCount, pPhysicalDevices);
853 if ((result == VK_SUCCESS || result == VK_INCOMPLETE) && pPhysicalDevices) {
854 for (uint32_t i = 0; i < *pPhysicalDeviceCount; i++)
855 SetData(pPhysicalDevices[i], data);
856 }
857
858 return result;
859}
860
Chia-I Wuba0be412016-03-24 16:24:40 +0800861void GetDeviceQueue(VkDevice device,
862 uint32_t queueFamilyIndex,
863 uint32_t queueIndex,
864 VkQueue* pQueue) {
865 const auto& data = GetData(device);
866
867 data.driver.GetDeviceQueue(device, queueFamilyIndex, queueIndex, pQueue);
868 SetData(*pQueue, data);
869}
870
Chia-I Wu6a58a8a2016-03-24 16:29:51 +0800871VKAPI_ATTR VkResult
872AllocateCommandBuffers(VkDevice device,
873 const VkCommandBufferAllocateInfo* pAllocateInfo,
874 VkCommandBuffer* pCommandBuffers) {
875 const auto& data = GetData(device);
876
877 VkResult result = data.driver.AllocateCommandBuffers(device, pAllocateInfo,
878 pCommandBuffers);
879 if (result == VK_SUCCESS) {
880 for (uint32_t i = 0; i < pAllocateInfo->commandBufferCount; i++)
881 SetData(pCommandBuffers[i], data);
882 }
883
884 return result;
885}
886
Chia-I Wu9d518162016-03-24 14:55:27 +0800887} // namespace driver
888} // namespace vulkan