blob: c1495fb8618619789012bb38838e0807e9b3054a [file] [log] [blame]
Lingfeng Yang58b89c82018-12-25 11:23:21 -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#include "HostVisibleMemoryVirtualization.h"
16
Lingfeng Yang35e9c6a2018-12-25 17:13:36 -080017#include "android/base/SubAllocator.h"
18
19#include "Resources.h"
20#include "VkEncoder.h"
21
Lingfeng Yang58b89c82018-12-25 11:23:21 -080022#include <log/log.h>
23
24#include <set>
25
Lingfeng Yang35e9c6a2018-12-25 17:13:36 -080026using android::base::SubAllocator;
27
Lingfeng Yang58b89c82018-12-25 11:23:21 -080028namespace goldfish_vk {
29
30bool canFitVirtualHostVisibleMemoryInfo(
31 const VkPhysicalDeviceMemoryProperties* memoryProperties) {
32 uint32_t typeCount =
33 memoryProperties->memoryTypeCount;
34 uint32_t heapCount =
35 memoryProperties->memoryHeapCount;
36
37 bool canFit = true;
38
39 if (typeCount == VK_MAX_MEMORY_TYPES) {
40 canFit = false;
41 ALOGE("Underlying device has no free memory types");
42 }
43
44 if (heapCount == VK_MAX_MEMORY_HEAPS) {
45 canFit = false;
46 ALOGE("Underlying device has no free memory heaps");
47 }
48
49 uint32_t numFreeMemoryTypes = VK_MAX_MEMORY_TYPES - typeCount;
Lingfeng Yang58b89c82018-12-25 11:23:21 -080050 uint32_t hostVisibleMemoryTypeCount = 0;
Lingfeng Yang58b89c82018-12-25 11:23:21 -080051
52 if (hostVisibleMemoryTypeCount > numFreeMemoryTypes) {
53 ALOGE("Underlying device has too many host visible memory types (%u)"
54 "and not enough free types (%u)",
55 hostVisibleMemoryTypeCount, numFreeMemoryTypes);
56 canFit = false;
57 }
58
Lingfeng Yang58b89c82018-12-25 11:23:21 -080059 return canFit;
60}
61
62void initHostVisibleMemoryVirtualizationInfo(
63 VkPhysicalDevice physicalDevice,
64 const VkPhysicalDeviceMemoryProperties* memoryProperties,
Lingfeng Yangafe29d32018-12-25 13:01:52 -080065 bool hasDirectMem,
Lingfeng Yang58b89c82018-12-25 11:23:21 -080066 HostVisibleMemoryVirtualizationInfo* info_out) {
Lingfeng Yangafe29d32018-12-25 13:01:52 -080067
Lingfeng Yangdf173132018-12-25 13:30:57 -080068 if (info_out->initialized) return;
69
70 info_out->initialized = true;
71
Lingfeng Yangafe29d32018-12-25 13:01:52 -080072 info_out->memoryPropertiesSupported =
Lingfeng Yang58b89c82018-12-25 11:23:21 -080073 canFitVirtualHostVisibleMemoryInfo(memoryProperties);
74
Lingfeng Yangafe29d32018-12-25 13:01:52 -080075 info_out->directMemSupported = hasDirectMem;
76
77 if (!info_out->memoryPropertiesSupported ||
78 !info_out->directMemSupported) {
79 info_out->virtualizationSupported = false;
80 return;
81 }
82
83 info_out->virtualizationSupported = true;
Lingfeng Yang58b89c82018-12-25 11:23:21 -080084
Lingfeng Yangdf173132018-12-25 13:30:57 -080085 info_out->physicalDevice = physicalDevice;
86 info_out->hostMemoryProperties = *memoryProperties;
87 info_out->guestMemoryProperties = *memoryProperties;
88
Lingfeng Yang58b89c82018-12-25 11:23:21 -080089 uint32_t typeCount =
90 memoryProperties->memoryTypeCount;
91 uint32_t heapCount =
92 memoryProperties->memoryHeapCount;
93
Lingfeng Yang58b89c82018-12-25 11:23:21 -080094 uint32_t firstFreeTypeIndex = typeCount;
95 uint32_t firstFreeHeapIndex = heapCount;
Lingfeng Yangdf173132018-12-25 13:30:57 -080096
Lingfeng Yang58b89c82018-12-25 11:23:21 -080097 for (uint32_t i = 0; i < typeCount; ++i) {
98
99 // Set up identity mapping and not-both
100 // by default, to be edited later.
101 info_out->memoryTypeIndexMappingToHost[i] = i;
102 info_out->memoryHeapIndexMappingToHost[i] = i;
103
104 info_out->memoryTypeIndexMappingFromHost[i] = i;
105 info_out->memoryHeapIndexMappingFromHost[i] = i;
106
107 info_out->memoryTypeBitsShouldAdvertiseBoth[i] = false;
108
109 const auto& type = memoryProperties->memoryTypes[i];
Lingfeng Yangdf173132018-12-25 13:30:57 -0800110
Lingfeng Yang58b89c82018-12-25 11:23:21 -0800111 if (type.propertyFlags & VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT) {
Lingfeng Yangdf173132018-12-25 13:30:57 -0800112 uint32_t heapIndex = type.heapIndex;
Lingfeng Yang58b89c82018-12-25 11:23:21 -0800113
114 auto& guestMemoryType =
115 info_out->guestMemoryProperties.memoryTypes[i];
116
117 auto& newVirtualMemoryType =
118 info_out->guestMemoryProperties.memoryTypes[firstFreeTypeIndex];
119
120 auto& newVirtualMemoryHeap =
121 info_out->guestMemoryProperties.memoryHeaps[firstFreeHeapIndex];
122
Lingfeng Yangdf173132018-12-25 13:30:57 -0800123 // Remove all references to host visible in the guest memory type at
124 // index i, while transferring them to the new virtual memory type.
Lingfeng Yang58b89c82018-12-25 11:23:21 -0800125 newVirtualMemoryType = type;
126
127 // Set this memory type to have a separate heap.
128 newVirtualMemoryType.heapIndex = firstFreeHeapIndex;
129
Lingfeng Yangdf173132018-12-25 13:30:57 -0800130 newVirtualMemoryType.propertyFlags =
131 type.propertyFlags &
132 ~(VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT);
133
Lingfeng Yang58b89c82018-12-25 11:23:21 -0800134 guestMemoryType.propertyFlags =
135 type.propertyFlags & \
136 ~(VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT |
137 VK_MEMORY_PROPERTY_HOST_COHERENT_BIT |
138 VK_MEMORY_PROPERTY_HOST_CACHED_BIT);
139
Lingfeng Yang58b89c82018-12-25 11:23:21 -0800140 // In the corresponding new memory heap, copy the information over,
141 // remove device local flags, and resize it based on what is
142 // supported by the PCI device.
Lingfeng Yangdf173132018-12-25 13:30:57 -0800143 newVirtualMemoryHeap =
144 memoryProperties->memoryHeaps[heapIndex];
Lingfeng Yang58b89c82018-12-25 11:23:21 -0800145 newVirtualMemoryHeap.flags =
146 newVirtualMemoryHeap.flags &
147 ~(VK_MEMORY_HEAP_DEVICE_LOCAL_BIT);
148
149 // TODO: Figure out how to support bigger sizes
Lingfeng Yang35e9c6a2018-12-25 17:13:36 -0800150 newVirtualMemoryHeap.size = VIRTUAL_HOST_VISIBLE_HEAP_SIZE;
Lingfeng Yang58b89c82018-12-25 11:23:21 -0800151
152 info_out->memoryTypeIndexMappingToHost[firstFreeTypeIndex] = i;
153 info_out->memoryHeapIndexMappingToHost[firstFreeHeapIndex] = i;
154
155 info_out->memoryTypeIndexMappingFromHost[i] = firstFreeTypeIndex;
156 info_out->memoryHeapIndexMappingFromHost[i] = firstFreeHeapIndex;
157
158 // Was the original memory type also a device local type? If so,
159 // advertise both types in resulting type bits.
160 info_out->memoryTypeBitsShouldAdvertiseBoth[i] =
161 type.propertyFlags & VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT;
162
163 ++firstFreeTypeIndex;
Lingfeng Yang35e9c6a2018-12-25 17:13:36 -0800164
165 // Explicitly only create one new heap.
166 // ++firstFreeHeapIndex;
Lingfeng Yang58b89c82018-12-25 11:23:21 -0800167 }
168 }
Lingfeng Yangdf173132018-12-25 13:30:57 -0800169
170 info_out->guestMemoryProperties.memoryTypeCount = firstFreeTypeIndex;
Lingfeng Yang35e9c6a2018-12-25 17:13:36 -0800171 info_out->guestMemoryProperties.memoryHeapCount = firstFreeHeapIndex + 1;
Lingfeng Yangdf173132018-12-25 13:30:57 -0800172
173 for (uint32_t i = info_out->guestMemoryProperties.memoryTypeCount; i < VK_MAX_MEMORY_TYPES; ++i) {
174 memset(&info_out->guestMemoryProperties.memoryTypes[i],
175 0x0, sizeof(VkMemoryType));
176 }
Lingfeng Yang58b89c82018-12-25 11:23:21 -0800177}
178
Lingfeng Yang35e9c6a2018-12-25 17:13:36 -0800179bool isHostVisibleMemoryTypeIndexForGuest(
180 const HostVisibleMemoryVirtualizationInfo* info,
181 uint32_t index) {
182 return info->guestMemoryProperties.memoryTypes[index].propertyFlags &
183 VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT;
184}
185
186VkResult finishHostMemAllocInit(
187 VkEncoder* enc,
188 VkDevice device,
189 uint32_t memoryTypeIndex,
190 VkDeviceSize nonCoherentAtomSize,
191 VkDeviceSize allocSize,
192 VkDeviceSize mappedSize,
193 uint8_t* mappedPtr,
194 HostMemAlloc* out) {
195
196 out->enc = enc;
197 out->device = device;
198 out->memoryTypeIndex = memoryTypeIndex;
199 out->nonCoherentAtomSize = nonCoherentAtomSize;
200 out->allocSize = allocSize;
201 out->mappedSize = mappedSize;
202 out->mappedPtr = mappedPtr;
203
204 out->subAlloc = new
205 SubAllocator(
206 out->mappedPtr,
207 out->mappedSize,
208 out->nonCoherentAtomSize);
209
210 out->initialized = true;
211 out->initResult = VK_SUCCESS;
212 return VK_SUCCESS;
213}
214
215void destroyHostMemAlloc(
216 VkDevice device,
217 HostMemAlloc* toDestroy) {
218
219 if (toDestroy->initResult != VK_SUCCESS) return;
220 if (!toDestroy->initialized) return;
221
222 toDestroy->enc->vkFreeMemory(device, toDestroy->memory, nullptr);
223 delete toDestroy->subAlloc;
224}
225
226void subAllocHostMemory(
227 HostMemAlloc* alloc,
228 const VkMemoryAllocateInfo* pAllocateInfo,
229 SubAlloc* out) {
230
231 VkDeviceSize mappedSize =
232 alloc->nonCoherentAtomSize * (
233 (pAllocateInfo->allocationSize +
234 alloc->nonCoherentAtomSize - 1) /
235 alloc->nonCoherentAtomSize);
236
237 void* subMapped = alloc->subAlloc->alloc(mappedSize);
238 out->mappedPtr = (uint8_t*)subMapped;
239
240 out->subAllocSize = pAllocateInfo->allocationSize;
241 out->subMappedSize = mappedSize;
242
243 out->baseMemory = alloc->memory;
244 out->baseOffset = alloc->subAlloc->getOffset(subMapped);
245
246 out->subMemory = new_from_host_VkDeviceMemory(VK_NULL_HANDLE);
247 out->subAlloc = alloc->subAlloc;
248}
249
250void subFreeHostMemory(SubAlloc* toFree) {
251 delete_goldfish_VkDeviceMemory(toFree->subMemory);
252 toFree->subAlloc->free(toFree->mappedPtr);
253 memset(toFree, 0x0, sizeof(SubAlloc));
254}
255
Lingfeng Yangdf173132018-12-25 13:30:57 -0800256} // namespace goldfish_vk