blob: 1641e31bc36e25a0b3e6e87a779a347097628f09 [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>
20#include <malloc.h>
Chia-I Wu9d518162016-03-24 14:55:27 +080021#include <sys/prctl.h>
22
23#include "driver.h"
Chia-I Wu136b8eb2016-03-24 15:01:52 +080024#include "loader.h"
Chia-I Wu9d518162016-03-24 14:55:27 +080025
Chia-I Wudbb7e9c2016-03-24 15:09:38 +080026// #define ENABLE_ALLOC_CALLSTACKS 1
27#if ENABLE_ALLOC_CALLSTACKS
28#include <utils/CallStack.h>
29#define ALOGD_CALLSTACK(...) \
30 do { \
31 ALOGD(__VA_ARGS__); \
32 android::CallStack callstack; \
33 callstack.update(); \
34 callstack.log(LOG_TAG, ANDROID_LOG_DEBUG, " "); \
35 } while (false)
36#else
37#define ALOGD_CALLSTACK(...) \
38 do { \
39 } while (false)
40#endif
41
Chia-I Wu9d518162016-03-24 14:55:27 +080042namespace vulkan {
43namespace driver {
44
Chia-I Wu136b8eb2016-03-24 15:01:52 +080045namespace {
46
47hwvulkan_device_t* g_hwdevice = nullptr;
48
Chia-I Wudbb7e9c2016-03-24 15:09:38 +080049VKAPI_ATTR void* DefaultAllocate(void*,
50 size_t size,
51 size_t alignment,
52 VkSystemAllocationScope) {
53 void* ptr = nullptr;
54 // Vulkan requires 'alignment' to be a power of two, but posix_memalign
55 // additionally requires that it be at least sizeof(void*).
56 int ret = posix_memalign(&ptr, std::max(alignment, sizeof(void*)), size);
57 ALOGD_CALLSTACK("Allocate: size=%zu align=%zu => (%d) %p", size, alignment,
58 ret, ptr);
59 return ret == 0 ? ptr : nullptr;
60}
61
62VKAPI_ATTR void* DefaultReallocate(void*,
63 void* ptr,
64 size_t size,
65 size_t alignment,
66 VkSystemAllocationScope) {
67 if (size == 0) {
68 free(ptr);
69 return nullptr;
70 }
71
72 // TODO(jessehall): Right now we never shrink allocations; if the new
73 // request is smaller than the existing chunk, we just continue using it.
74 // Right now the loader never reallocs, so this doesn't matter. If that
75 // changes, or if this code is copied into some other project, this should
76 // probably have a heuristic to allocate-copy-free when doing so will save
77 // "enough" space.
78 size_t old_size = ptr ? malloc_usable_size(ptr) : 0;
79 if (size <= old_size)
80 return ptr;
81
82 void* new_ptr = nullptr;
83 if (posix_memalign(&new_ptr, std::max(alignment, sizeof(void*)), size) != 0)
84 return nullptr;
85 if (ptr) {
86 memcpy(new_ptr, ptr, std::min(old_size, size));
87 free(ptr);
88 }
89 return new_ptr;
90}
91
92VKAPI_ATTR void DefaultFree(void*, void* ptr) {
93 ALOGD_CALLSTACK("Free: %p", ptr);
94 free(ptr);
95}
96
Chia-I Wu136b8eb2016-03-24 15:01:52 +080097} // anonymous namespace
98
Chia-I Wu9d518162016-03-24 14:55:27 +080099bool Debuggable() {
100 return (prctl(PR_GET_DUMPABLE, 0, 0, 0, 0) >= 0);
101}
102
Chia-I Wu136b8eb2016-03-24 15:01:52 +0800103bool OpenHAL() {
104 if (g_hwdevice)
105 return true;
106
107 const hwvulkan_module_t* module;
108 int result =
109 hw_get_module("vulkan", reinterpret_cast<const hw_module_t**>(&module));
110 if (result != 0) {
111 ALOGE("failed to load vulkan hal: %s (%d)", strerror(-result), result);
112 return false;
113 }
114
115 hwvulkan_device_t* device;
116 result =
117 module->common.methods->open(&module->common, HWVULKAN_DEVICE_0,
118 reinterpret_cast<hw_device_t**>(&device));
119 if (result != 0) {
120 ALOGE("failed to open vulkan driver: %s (%d)", strerror(-result),
121 result);
122 return false;
123 }
124
125 if (!InitLoader(device)) {
126 device->common.close(&device->common);
127 return false;
128 }
129
130 g_hwdevice = device;
131
132 return true;
133}
134
Chia-I Wudbb7e9c2016-03-24 15:09:38 +0800135const VkAllocationCallbacks& GetDefaultAllocator() {
136 static const VkAllocationCallbacks kDefaultAllocCallbacks = {
137 .pUserData = nullptr,
138 .pfnAllocation = DefaultAllocate,
139 .pfnReallocation = DefaultReallocate,
140 .pfnFree = DefaultFree,
141 };
142
143 return kDefaultAllocCallbacks;
144}
145
Chia-I Wueb7db122016-03-24 09:11:06 +0800146PFN_vkVoidFunction GetInstanceProcAddr(VkInstance instance, const char* pName) {
147 const ProcHook* hook = GetProcHook(pName);
148 if (!hook)
149 return g_hwdevice->GetInstanceProcAddr(instance, pName);
150
151 if (!instance) {
152 if (hook->type == ProcHook::GLOBAL)
153 return hook->proc;
154
155 ALOGE(
156 "Invalid use of vkGetInstanceProcAddr to query %s without an "
157 "instance",
158 pName);
159
160 // Some naughty layers expect
161 //
162 // vkGetInstanceProcAddr(VK_NULL_HANDLE, "vkCreateDevice");
163 //
164 // to work.
165 return (strcmp(pName, "vkCreateDevice") == 0) ? hook->proc : nullptr;
166 }
167
168 PFN_vkVoidFunction proc;
169
170 switch (hook->type) {
171 case ProcHook::INSTANCE:
172 proc = (GetData(instance).hook_extensions[hook->extension])
173 ? hook->proc
174 : hook->disabled_proc;
175 break;
176 case ProcHook::DEVICE:
177 proc = (hook->extension == ProcHook::EXTENSION_CORE)
178 ? hook->proc
179 : hook->checked_proc;
180 break;
181 default:
182 ALOGE(
183 "Invalid use of vkGetInstanceProcAddr to query %s with an "
184 "instance",
185 pName);
186 proc = nullptr;
187 break;
188 }
189
190 return proc;
191}
192
193PFN_vkVoidFunction GetDeviceProcAddr(VkDevice device, const char* pName) {
194 const ProcHook* hook = GetProcHook(pName);
195 if (!hook)
Chia-I Wucc5e2762016-03-24 13:01:16 +0800196 return GetData(device).driver.GetDeviceProcAddr(device, pName);
Chia-I Wueb7db122016-03-24 09:11:06 +0800197
198 if (hook->type != ProcHook::DEVICE) {
199 ALOGE("Invalid use of vkGetDeviceProcAddr to query %s", pName);
200 return nullptr;
201 }
202
203 return (GetData(device).hook_extensions[hook->extension])
204 ? hook->proc
205 : hook->disabled_proc;
206}
207
Chia-I Wuba0be412016-03-24 16:24:40 +0800208void GetDeviceQueue(VkDevice device,
209 uint32_t queueFamilyIndex,
210 uint32_t queueIndex,
211 VkQueue* pQueue) {
212 const auto& data = GetData(device);
213
214 data.driver.GetDeviceQueue(device, queueFamilyIndex, queueIndex, pQueue);
215 SetData(*pQueue, data);
216}
217
Chia-I Wu9d518162016-03-24 14:55:27 +0800218} // namespace driver
219} // namespace vulkan