| Lingfeng Yang | 71b596b | 2018-11-07 18:03:25 -0800 | [diff] [blame] | 1 | // Copyright (C) 2018 The Android Open Source Project |
| 2 | // Copyright (C) 2018 Google Inc. |
| 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 | |
| Lingfeng Yang | 71b596b | 2018-11-07 18:03:25 -0800 | [diff] [blame] | 16 | #include "ResourceTracker.h" |
| 17 | |
| Lingfeng Yang | 71b596b | 2018-11-07 18:03:25 -0800 | [diff] [blame] | 18 | #include "Resources.h" |
| Lingfeng Yang | 131d5a4 | 2018-11-30 12:00:33 -0800 | [diff] [blame^] | 19 | #include "VkEncoder.h" |
| Lingfeng Yang | 71b596b | 2018-11-07 18:03:25 -0800 | [diff] [blame] | 20 | |
| Lingfeng Yang | 131d5a4 | 2018-11-30 12:00:33 -0800 | [diff] [blame^] | 21 | #include "android/base/AlignedBuf.h" |
| Lingfeng Yang | 6ab1b0d | 2018-11-27 23:36:03 -0800 | [diff] [blame] | 22 | #include "android/base/synchronization/AndroidLock.h" |
| 23 | |
| 24 | #include <unordered_map> |
| 25 | |
| Lingfeng Yang | 131d5a4 | 2018-11-30 12:00:33 -0800 | [diff] [blame^] | 26 | #include <log/log.h> |
| 27 | |
| 28 | #define RESOURCE_TRACKER_DEBUG 0 |
| 29 | |
| 30 | #if RESOURCE_TRACKER_DEBUG |
| 31 | #define D(fmt,...) ALOGD("%s: " fmt, __func__, ##__VA_ARGS__); |
| 32 | #else |
| 33 | #ifndef D |
| 34 | #define D(fmt,...) |
| 35 | #endif |
| 36 | #endif |
| 37 | |
| 38 | using android::aligned_buf_alloc; |
| 39 | using android::aligned_buf_free; |
| Lingfeng Yang | 6ab1b0d | 2018-11-27 23:36:03 -0800 | [diff] [blame] | 40 | using android::base::guest::AutoLock; |
| 41 | using android::base::guest::Lock; |
| 42 | |
| Lingfeng Yang | 71b596b | 2018-11-07 18:03:25 -0800 | [diff] [blame] | 43 | namespace goldfish_vk { |
| 44 | |
| Lingfeng Yang | 2285df1 | 2018-11-17 16:25:11 -0800 | [diff] [blame] | 45 | #define MAKE_HANDLE_MAPPING_FOREACH(type_name, map_impl, map_to_u64_impl, map_from_u64_impl) \ |
| 46 | void mapHandles_##type_name(type_name* handles, size_t count) override { \ |
| 47 | for (size_t i = 0; i < count; ++i) { \ |
| 48 | map_impl; \ |
| 49 | } \ |
| 50 | } \ |
| 51 | void mapHandles_##type_name##_u64(const type_name* handles, uint64_t* handle_u64s, size_t count) override { \ |
| 52 | for (size_t i = 0; i < count; ++i) { \ |
| 53 | map_to_u64_impl; \ |
| 54 | } \ |
| 55 | } \ |
| 56 | void mapHandles_u64_##type_name(const uint64_t* handle_u64s, type_name* handles, size_t count) override { \ |
| 57 | for (size_t i = 0; i < count; ++i) { \ |
| 58 | map_from_u64_impl; \ |
| 59 | } \ |
| 60 | } \ |
| 61 | |
| 62 | #define DEFINE_RESOURCE_TRACKING_CLASS(class_name, impl) \ |
| 63 | class class_name : public VulkanHandleMapping { \ |
| 64 | public: \ |
| 65 | virtual ~class_name() { } \ |
| 66 | GOLDFISH_VK_LIST_HANDLE_TYPES(impl) \ |
| 67 | }; \ |
| 68 | |
| 69 | #define CREATE_MAPPING_IMPL_FOR_TYPE(type_name) \ |
| 70 | MAKE_HANDLE_MAPPING_FOREACH(type_name, \ |
| Lingfeng Yang | 6ab1b0d | 2018-11-27 23:36:03 -0800 | [diff] [blame] | 71 | handles[i] = new_from_host_##type_name(handles[i]); ResourceTracker::get()->register_##type_name(handles[i]);, \ |
| Lingfeng Yang | 2285df1 | 2018-11-17 16:25:11 -0800 | [diff] [blame] | 72 | handle_u64s[i] = (uint64_t)(uintptr_t)new_from_host_##type_name(handles[i]), \ |
| Lingfeng Yang | 6ab1b0d | 2018-11-27 23:36:03 -0800 | [diff] [blame] | 73 | handles[i] = (type_name)(uintptr_t)new_from_host_u64_##type_name(handle_u64s[i]); ResourceTracker::get()->register_##type_name(handles[i]);) |
| Lingfeng Yang | 2285df1 | 2018-11-17 16:25:11 -0800 | [diff] [blame] | 74 | |
| 75 | #define UNWRAP_MAPPING_IMPL_FOR_TYPE(type_name) \ |
| 76 | MAKE_HANDLE_MAPPING_FOREACH(type_name, \ |
| 77 | handles[i] = get_host_##type_name(handles[i]), \ |
| Lingfeng Yang | e4008a0 | 2018-11-18 12:22:48 -0800 | [diff] [blame] | 78 | handle_u64s[i] = (uint64_t)(uintptr_t)get_host_u64_##type_name(handles[i]), \ |
| Lingfeng Yang | 2285df1 | 2018-11-17 16:25:11 -0800 | [diff] [blame] | 79 | handles[i] = (type_name)(uintptr_t)get_host_##type_name((type_name)(uintptr_t)handle_u64s[i])) |
| 80 | |
| 81 | #define DESTROY_MAPPING_IMPL_FOR_TYPE(type_name) \ |
| 82 | MAKE_HANDLE_MAPPING_FOREACH(type_name, \ |
| Lingfeng Yang | 6ab1b0d | 2018-11-27 23:36:03 -0800 | [diff] [blame] | 83 | ResourceTracker::get()->unregister_##type_name(handles[i]); delete_goldfish_##type_name(handles[i]), \ |
| Lingfeng Yang | 2285df1 | 2018-11-17 16:25:11 -0800 | [diff] [blame] | 84 | (void)handle_u64s[i]; delete_goldfish_##type_name(handles[i]), \ |
| 85 | (void)handles[i]; delete_goldfish_##type_name((type_name)(uintptr_t)handle_u64s[i])) |
| 86 | |
| 87 | DEFINE_RESOURCE_TRACKING_CLASS(CreateMapping, CREATE_MAPPING_IMPL_FOR_TYPE) |
| 88 | DEFINE_RESOURCE_TRACKING_CLASS(UnwrapMapping, UNWRAP_MAPPING_IMPL_FOR_TYPE) |
| 89 | DEFINE_RESOURCE_TRACKING_CLASS(DestroyMapping, DESTROY_MAPPING_IMPL_FOR_TYPE) |
| Lingfeng Yang | 71b596b | 2018-11-07 18:03:25 -0800 | [diff] [blame] | 90 | |
| 91 | class ResourceTracker::Impl { |
| 92 | public: |
| 93 | Impl() = default; |
| 94 | CreateMapping createMapping; |
| 95 | UnwrapMapping unwrapMapping; |
| 96 | DestroyMapping destroyMapping; |
| Lingfeng Yang | 2285df1 | 2018-11-17 16:25:11 -0800 | [diff] [blame] | 97 | DefaultHandleMapping defaultMapping; |
| Lingfeng Yang | 6ab1b0d | 2018-11-27 23:36:03 -0800 | [diff] [blame] | 98 | |
| 99 | #define HANDLE_DEFINE_TRIVIAL_INFO_STRUCT(type) \ |
| 100 | struct type##_Info { \ |
| 101 | uint32_t unused; \ |
| 102 | }; \ |
| 103 | |
| 104 | GOLDFISH_VK_LIST_TRIVIAL_HANDLE_TYPES(HANDLE_DEFINE_TRIVIAL_INFO_STRUCT) |
| 105 | |
| 106 | struct VkDevice_Info { |
| 107 | VkPhysicalDevice physdev; |
| 108 | VkPhysicalDeviceProperties props; |
| 109 | VkPhysicalDeviceMemoryProperties memProps; |
| 110 | }; |
| 111 | |
| 112 | struct VkDeviceMemory_Info { |
| 113 | VkDeviceSize allocationSize; |
| 114 | uint32_t memoryTypeIndex; |
| 115 | }; |
| 116 | |
| 117 | #define HANDLE_REGISTER_IMPL_IMPL(type) \ |
| 118 | std::unordered_map<type, type##_Info> info_##type; \ |
| 119 | void register_##type(type obj) { \ |
| 120 | AutoLock lock(mLock); \ |
| 121 | info_##type[obj] = type##_Info(); \ |
| 122 | } \ |
| 123 | void unregister_##type(type obj) { \ |
| 124 | AutoLock lock(mLock); \ |
| 125 | info_##type.erase(obj); \ |
| 126 | } \ |
| 127 | |
| 128 | GOLDFISH_VK_LIST_HANDLE_TYPES(HANDLE_REGISTER_IMPL_IMPL) |
| 129 | |
| 130 | void setDeviceInfo(VkDevice device, |
| 131 | VkPhysicalDevice physdev, |
| 132 | VkPhysicalDeviceProperties props, |
| 133 | VkPhysicalDeviceMemoryProperties memProps) { |
| 134 | AutoLock lock(mLock); |
| 135 | auto& info = info_VkDevice[device]; |
| 136 | info.physdev = physdev; |
| 137 | info.props = props; |
| 138 | info.memProps = memProps; |
| 139 | } |
| 140 | |
| 141 | bool isMemoryTypeHostVisible(VkDevice device, uint32_t typeIndex) const { |
| 142 | AutoLock lock(mLock); |
| 143 | const auto it = info_VkDevice.find(device); |
| 144 | |
| 145 | if (it == info_VkDevice.end()) return false; |
| 146 | |
| 147 | const auto& info = it->second; |
| 148 | return info.memProps.memoryTypes[typeIndex].propertyFlags & |
| 149 | VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT; |
| 150 | } |
| 151 | |
| 152 | VkDeviceSize getNonCoherentExtendedSize(VkDevice device, VkDeviceSize basicSize) const { |
| 153 | AutoLock lock(mLock); |
| 154 | const auto it = info_VkDevice.find(device); |
| 155 | if (it == info_VkDevice.end()) return basicSize; |
| 156 | const auto& info = it->second; |
| 157 | |
| 158 | VkDeviceSize nonCoherentAtomSize = |
| 159 | info.props.limits.nonCoherentAtomSize; |
| 160 | VkDeviceSize atoms = |
| 161 | (basicSize + nonCoherentAtomSize - 1) / nonCoherentAtomSize; |
| 162 | return atoms * nonCoherentAtomSize; |
| 163 | } |
| 164 | |
| Lingfeng Yang | 131d5a4 | 2018-11-30 12:00:33 -0800 | [diff] [blame^] | 165 | VkResult on_vkCreateDevice( |
| 166 | void* context, |
| 167 | VkResult input_result, |
| 168 | VkPhysicalDevice physicalDevice, |
| 169 | const VkDeviceCreateInfo*, |
| 170 | const VkAllocationCallbacks*, |
| 171 | VkDevice* pDevice) { |
| 172 | |
| 173 | if (input_result != VK_SUCCESS) return input_result; |
| 174 | |
| 175 | VkEncoder* enc = (VkEncoder*)context; |
| 176 | |
| 177 | VkPhysicalDeviceProperties props; |
| 178 | VkPhysicalDeviceMemoryProperties memProps; |
| 179 | enc->vkGetPhysicalDeviceProperties(physicalDevice, &props); |
| 180 | enc->vkGetPhysicalDeviceMemoryProperties(physicalDevice, &memProps); |
| 181 | |
| 182 | setDeviceInfo(*pDevice, physicalDevice, props, memProps); |
| 183 | |
| 184 | return input_result; |
| 185 | } |
| 186 | |
| 187 | VkResult on_vkAllocateMemory( |
| 188 | void*, |
| 189 | VkResult input_result, |
| 190 | VkDevice device, |
| 191 | const VkMemoryAllocateInfo* pAllocateInfo, |
| 192 | const VkAllocationCallbacks*, |
| 193 | VkDeviceMemory* pMemory) { |
| 194 | |
| 195 | if (input_result != VK_SUCCESS) return input_result; |
| 196 | |
| 197 | // Assumes pMemory has already been allocated. |
| 198 | goldfish_VkDeviceMemory* mem = as_goldfish_VkDeviceMemory(*pMemory); |
| 199 | VkDeviceSize size = pAllocateInfo->allocationSize; |
| 200 | |
| 201 | // assume memory is not host visible. |
| 202 | mem->ptr = nullptr; |
| 203 | mem->size = size; |
| 204 | mem->mappedSize = getNonCoherentExtendedSize(device, size); |
| 205 | |
| 206 | if (!isMemoryTypeHostVisible(device, pAllocateInfo->memoryTypeIndex)) { |
| 207 | return input_result; |
| 208 | } |
| 209 | |
| 210 | // This is a strict alignment; we do not expect any |
| 211 | // actual device to have more stringent requirements |
| 212 | // than this. |
| 213 | mem->ptr = (uint8_t*)aligned_buf_alloc(4096, mem->mappedSize); |
| 214 | D("host visible alloc: size 0x%llx host ptr %p mapped size 0x%llx", |
| 215 | (unsigned long long)size, mem->ptr, |
| 216 | (unsigned long long)mem->mappedSize); |
| 217 | |
| 218 | return input_result; |
| 219 | } |
| 220 | |
| Lingfeng Yang | 6ab1b0d | 2018-11-27 23:36:03 -0800 | [diff] [blame] | 221 | private: |
| 222 | mutable Lock mLock; |
| 223 | |
| Lingfeng Yang | 71b596b | 2018-11-07 18:03:25 -0800 | [diff] [blame] | 224 | }; |
| Lingfeng Yang | 71b596b | 2018-11-07 18:03:25 -0800 | [diff] [blame] | 225 | ResourceTracker::ResourceTracker() : mImpl(new ResourceTracker::Impl()) { } |
| 226 | ResourceTracker::~ResourceTracker() { } |
| Lingfeng Yang | 71b596b | 2018-11-07 18:03:25 -0800 | [diff] [blame] | 227 | VulkanHandleMapping* ResourceTracker::createMapping() { |
| 228 | return &mImpl->createMapping; |
| 229 | } |
| Lingfeng Yang | 71b596b | 2018-11-07 18:03:25 -0800 | [diff] [blame] | 230 | VulkanHandleMapping* ResourceTracker::unwrapMapping() { |
| 231 | return &mImpl->unwrapMapping; |
| 232 | } |
| Lingfeng Yang | 71b596b | 2018-11-07 18:03:25 -0800 | [diff] [blame] | 233 | VulkanHandleMapping* ResourceTracker::destroyMapping() { |
| 234 | return &mImpl->destroyMapping; |
| 235 | } |
| Lingfeng Yang | 2285df1 | 2018-11-17 16:25:11 -0800 | [diff] [blame] | 236 | VulkanHandleMapping* ResourceTracker::defaultMapping() { |
| 237 | return &mImpl->defaultMapping; |
| 238 | } |
| Lingfeng Yang | 71b596b | 2018-11-07 18:03:25 -0800 | [diff] [blame] | 239 | static ResourceTracker* sTracker = nullptr; |
| Lingfeng Yang | 71b596b | 2018-11-07 18:03:25 -0800 | [diff] [blame] | 240 | // static |
| 241 | ResourceTracker* ResourceTracker::get() { |
| 242 | if (!sTracker) { |
| 243 | // To be initialized once on vulkan device open. |
| 244 | sTracker = new ResourceTracker; |
| 245 | } |
| 246 | return sTracker; |
| 247 | } |
| Lingfeng Yang | 71b596b | 2018-11-07 18:03:25 -0800 | [diff] [blame] | 248 | |
| Lingfeng Yang | 6ab1b0d | 2018-11-27 23:36:03 -0800 | [diff] [blame] | 249 | #define HANDLE_REGISTER_IMPL(type) \ |
| 250 | void ResourceTracker::register_##type(type obj) { \ |
| 251 | mImpl->register_##type(obj); \ |
| 252 | } \ |
| 253 | void ResourceTracker::unregister_##type(type obj) { \ |
| 254 | mImpl->unregister_##type(obj); \ |
| 255 | } \ |
| 256 | |
| 257 | GOLDFISH_VK_LIST_HANDLE_TYPES(HANDLE_REGISTER_IMPL) |
| 258 | |
| 259 | void ResourceTracker::setDeviceInfo( |
| 260 | VkDevice device, |
| 261 | VkPhysicalDevice physdev, |
| 262 | VkPhysicalDeviceProperties props, |
| 263 | VkPhysicalDeviceMemoryProperties memProps) { |
| 264 | mImpl->setDeviceInfo(device, physdev, props, memProps); |
| 265 | } |
| 266 | |
| 267 | bool ResourceTracker::isMemoryTypeHostVisible( |
| 268 | VkDevice device, uint32_t typeIndex) const { |
| 269 | return mImpl->isMemoryTypeHostVisible(device, typeIndex); |
| 270 | } |
| 271 | |
| 272 | VkDeviceSize ResourceTracker::getNonCoherentExtendedSize(VkDevice device, VkDeviceSize basicSize) const { |
| 273 | return mImpl->getNonCoherentExtendedSize(device, basicSize); |
| 274 | } |
| 275 | |
| Lingfeng Yang | 131d5a4 | 2018-11-30 12:00:33 -0800 | [diff] [blame^] | 276 | VkResult ResourceTracker::on_vkCreateDevice( |
| 277 | void* context, |
| 278 | VkResult input_result, |
| 279 | VkPhysicalDevice physicalDevice, |
| 280 | const VkDeviceCreateInfo* pCreateInfo, |
| 281 | const VkAllocationCallbacks* pAllocator, |
| 282 | VkDevice* pDevice) { |
| 283 | return mImpl->on_vkCreateDevice( |
| 284 | context, input_result, physicalDevice, pCreateInfo, pAllocator, pDevice); |
| 285 | } |
| 286 | |
| 287 | VkResult ResourceTracker::on_vkAllocateMemory( |
| 288 | void* context, |
| 289 | VkResult input_result, |
| 290 | VkDevice device, |
| 291 | const VkMemoryAllocateInfo* pAllocateInfo, |
| 292 | const VkAllocationCallbacks* pAllocator, |
| 293 | VkDeviceMemory* pMemory) { |
| 294 | return mImpl->on_vkAllocateMemory( |
| 295 | context, input_result, device, pAllocateInfo, pAllocator, pMemory); |
| 296 | } |
| 297 | |
| Lingfeng Yang | 71b596b | 2018-11-07 18:03:25 -0800 | [diff] [blame] | 298 | } // namespace goldfish_vk |