blob: 0bb42b248727f8150b46fbfda748452633a61876 [file] [log] [blame]
Lingfeng Yang71b596b2018-11-07 18:03:25 -08001// 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 Yang71b596b2018-11-07 18:03:25 -080016#include "ResourceTracker.h"
17
Lingfeng Yang71b596b2018-11-07 18:03:25 -080018#include "Resources.h"
Lingfeng Yang131d5a42018-11-30 12:00:33 -080019#include "VkEncoder.h"
Lingfeng Yang71b596b2018-11-07 18:03:25 -080020
Lingfeng Yang131d5a42018-11-30 12:00:33 -080021#include "android/base/AlignedBuf.h"
Lingfeng Yang6ab1b0d2018-11-27 23:36:03 -080022#include "android/base/synchronization/AndroidLock.h"
23
24#include <unordered_map>
25
Lingfeng Yang131d5a42018-11-30 12:00:33 -080026#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
38using android::aligned_buf_alloc;
39using android::aligned_buf_free;
Lingfeng Yang6ab1b0d2018-11-27 23:36:03 -080040using android::base::guest::AutoLock;
41using android::base::guest::Lock;
42
Lingfeng Yang71b596b2018-11-07 18:03:25 -080043namespace goldfish_vk {
44
Lingfeng Yang2285df12018-11-17 16:25:11 -080045#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) \
63class class_name : public VulkanHandleMapping { \
64public: \
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 Yang6ab1b0d2018-11-27 23:36:03 -080071 handles[i] = new_from_host_##type_name(handles[i]); ResourceTracker::get()->register_##type_name(handles[i]);, \
Lingfeng Yang2285df12018-11-17 16:25:11 -080072 handle_u64s[i] = (uint64_t)(uintptr_t)new_from_host_##type_name(handles[i]), \
Lingfeng Yang6ab1b0d2018-11-27 23:36:03 -080073 handles[i] = (type_name)(uintptr_t)new_from_host_u64_##type_name(handle_u64s[i]); ResourceTracker::get()->register_##type_name(handles[i]);)
Lingfeng Yang2285df12018-11-17 16:25:11 -080074
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 Yange4008a02018-11-18 12:22:48 -080078 handle_u64s[i] = (uint64_t)(uintptr_t)get_host_u64_##type_name(handles[i]), \
Lingfeng Yang2285df12018-11-17 16:25:11 -080079 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 Yang6ab1b0d2018-11-27 23:36:03 -080083 ResourceTracker::get()->unregister_##type_name(handles[i]); delete_goldfish_##type_name(handles[i]), \
Lingfeng Yang2285df12018-11-17 16:25:11 -080084 (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
87DEFINE_RESOURCE_TRACKING_CLASS(CreateMapping, CREATE_MAPPING_IMPL_FOR_TYPE)
88DEFINE_RESOURCE_TRACKING_CLASS(UnwrapMapping, UNWRAP_MAPPING_IMPL_FOR_TYPE)
89DEFINE_RESOURCE_TRACKING_CLASS(DestroyMapping, DESTROY_MAPPING_IMPL_FOR_TYPE)
Lingfeng Yang71b596b2018-11-07 18:03:25 -080090
91class ResourceTracker::Impl {
92public:
93 Impl() = default;
94 CreateMapping createMapping;
95 UnwrapMapping unwrapMapping;
96 DestroyMapping destroyMapping;
Lingfeng Yang2285df12018-11-17 16:25:11 -080097 DefaultHandleMapping defaultMapping;
Lingfeng Yang6ab1b0d2018-11-27 23:36:03 -080098
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 Yang131d5a42018-11-30 12:00:33 -0800165 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 Yang6ab1b0d2018-11-27 23:36:03 -0800221private:
222 mutable Lock mLock;
223
Lingfeng Yang71b596b2018-11-07 18:03:25 -0800224};
Lingfeng Yang71b596b2018-11-07 18:03:25 -0800225ResourceTracker::ResourceTracker() : mImpl(new ResourceTracker::Impl()) { }
226ResourceTracker::~ResourceTracker() { }
Lingfeng Yang71b596b2018-11-07 18:03:25 -0800227VulkanHandleMapping* ResourceTracker::createMapping() {
228 return &mImpl->createMapping;
229}
Lingfeng Yang71b596b2018-11-07 18:03:25 -0800230VulkanHandleMapping* ResourceTracker::unwrapMapping() {
231 return &mImpl->unwrapMapping;
232}
Lingfeng Yang71b596b2018-11-07 18:03:25 -0800233VulkanHandleMapping* ResourceTracker::destroyMapping() {
234 return &mImpl->destroyMapping;
235}
Lingfeng Yang2285df12018-11-17 16:25:11 -0800236VulkanHandleMapping* ResourceTracker::defaultMapping() {
237 return &mImpl->defaultMapping;
238}
Lingfeng Yang71b596b2018-11-07 18:03:25 -0800239static ResourceTracker* sTracker = nullptr;
Lingfeng Yang71b596b2018-11-07 18:03:25 -0800240// static
241ResourceTracker* ResourceTracker::get() {
242 if (!sTracker) {
243 // To be initialized once on vulkan device open.
244 sTracker = new ResourceTracker;
245 }
246 return sTracker;
247}
Lingfeng Yang71b596b2018-11-07 18:03:25 -0800248
Lingfeng Yang6ab1b0d2018-11-27 23:36:03 -0800249#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
257GOLDFISH_VK_LIST_HANDLE_TYPES(HANDLE_REGISTER_IMPL)
258
259void ResourceTracker::setDeviceInfo(
260 VkDevice device,
261 VkPhysicalDevice physdev,
262 VkPhysicalDeviceProperties props,
263 VkPhysicalDeviceMemoryProperties memProps) {
264 mImpl->setDeviceInfo(device, physdev, props, memProps);
265}
266
267bool ResourceTracker::isMemoryTypeHostVisible(
268 VkDevice device, uint32_t typeIndex) const {
269 return mImpl->isMemoryTypeHostVisible(device, typeIndex);
270}
271
272VkDeviceSize ResourceTracker::getNonCoherentExtendedSize(VkDevice device, VkDeviceSize basicSize) const {
273 return mImpl->getNonCoherentExtendedSize(device, basicSize);
274}
275
Lingfeng Yang131d5a42018-11-30 12:00:33 -0800276VkResult 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
287VkResult 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 Yang71b596b2018-11-07 18:03:25 -0800298} // namespace goldfish_vk