blob: 88fbc6e588dd2761725012d761da2537c563fb2a [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
17#include <log/log.h>
18
19#include <set>
20
21namespace goldfish_vk {
22
23bool canFitVirtualHostVisibleMemoryInfo(
24 const VkPhysicalDeviceMemoryProperties* memoryProperties) {
25 uint32_t typeCount =
26 memoryProperties->memoryTypeCount;
27 uint32_t heapCount =
28 memoryProperties->memoryHeapCount;
29
30 bool canFit = true;
31
32 if (typeCount == VK_MAX_MEMORY_TYPES) {
33 canFit = false;
34 ALOGE("Underlying device has no free memory types");
35 }
36
37 if (heapCount == VK_MAX_MEMORY_HEAPS) {
38 canFit = false;
39 ALOGE("Underlying device has no free memory heaps");
40 }
41
42 uint32_t numFreeMemoryTypes = VK_MAX_MEMORY_TYPES - typeCount;
43 uint32_t numFreeMemoryHeaps = VK_MAX_MEMORY_HEAPS - heapCount;
44
45 uint32_t hostVisibleMemoryTypeCount = 0;
46 uint32_t hostVisibleMemoryHeapCount = 0;
47 std::set<uint32_t> hostVisibleMemoryHeaps;
48
49 for (uint32_t i = 0; i < typeCount; ++i) {
50 const auto& type = memoryProperties->memoryTypes[i];
51 if (type.propertyFlags & VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT) {
52 ++hostVisibleMemoryTypeCount;
53 hostVisibleMemoryHeaps.insert(type.heapIndex);
54 }
55 }
56 hostVisibleMemoryHeapCount =
57 (uint32_t)hostVisibleMemoryHeaps.size();
58
59 if (hostVisibleMemoryTypeCount > numFreeMemoryTypes) {
60 ALOGE("Underlying device has too many host visible memory types (%u)"
61 "and not enough free types (%u)",
62 hostVisibleMemoryTypeCount, numFreeMemoryTypes);
63 canFit = false;
64 }
65
66 if (hostVisibleMemoryHeapCount > numFreeMemoryHeaps) {
67 ALOGE("Underlying device has too many host visible memory types (%u)"
68 "and not enough free types (%u)",
69 hostVisibleMemoryHeapCount, numFreeMemoryHeaps);
70 canFit = false;
71 }
72
73 return canFit;
74}
75
76void initHostVisibleMemoryVirtualizationInfo(
77 VkPhysicalDevice physicalDevice,
78 const VkPhysicalDeviceMemoryProperties* memoryProperties,
Lingfeng Yangafe29d32018-12-25 13:01:52 -080079 bool hasDirectMem,
Lingfeng Yang58b89c82018-12-25 11:23:21 -080080 HostVisibleMemoryVirtualizationInfo* info_out) {
Lingfeng Yangafe29d32018-12-25 13:01:52 -080081
Lingfeng Yangdf173132018-12-25 13:30:57 -080082 if (info_out->initialized) return;
83
84 info_out->initialized = true;
85
Lingfeng Yangafe29d32018-12-25 13:01:52 -080086 info_out->memoryPropertiesSupported =
Lingfeng Yang58b89c82018-12-25 11:23:21 -080087 canFitVirtualHostVisibleMemoryInfo(memoryProperties);
88
Lingfeng Yangafe29d32018-12-25 13:01:52 -080089 info_out->directMemSupported = hasDirectMem;
90
91 if (!info_out->memoryPropertiesSupported ||
92 !info_out->directMemSupported) {
93 info_out->virtualizationSupported = false;
94 return;
95 }
96
97 info_out->virtualizationSupported = true;
Lingfeng Yang58b89c82018-12-25 11:23:21 -080098
Lingfeng Yangdf173132018-12-25 13:30:57 -080099 info_out->physicalDevice = physicalDevice;
100 info_out->hostMemoryProperties = *memoryProperties;
101 info_out->guestMemoryProperties = *memoryProperties;
102
Lingfeng Yang58b89c82018-12-25 11:23:21 -0800103 uint32_t typeCount =
104 memoryProperties->memoryTypeCount;
105 uint32_t heapCount =
106 memoryProperties->memoryHeapCount;
107
Lingfeng Yang58b89c82018-12-25 11:23:21 -0800108 uint32_t firstFreeTypeIndex = typeCount;
109 uint32_t firstFreeHeapIndex = heapCount;
Lingfeng Yangdf173132018-12-25 13:30:57 -0800110
Lingfeng Yang58b89c82018-12-25 11:23:21 -0800111 for (uint32_t i = 0; i < typeCount; ++i) {
112
113 // Set up identity mapping and not-both
114 // by default, to be edited later.
115 info_out->memoryTypeIndexMappingToHost[i] = i;
116 info_out->memoryHeapIndexMappingToHost[i] = i;
117
118 info_out->memoryTypeIndexMappingFromHost[i] = i;
119 info_out->memoryHeapIndexMappingFromHost[i] = i;
120
121 info_out->memoryTypeBitsShouldAdvertiseBoth[i] = false;
122
123 const auto& type = memoryProperties->memoryTypes[i];
Lingfeng Yangdf173132018-12-25 13:30:57 -0800124
Lingfeng Yang58b89c82018-12-25 11:23:21 -0800125 if (type.propertyFlags & VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT) {
Lingfeng Yangdf173132018-12-25 13:30:57 -0800126 uint32_t heapIndex = type.heapIndex;
Lingfeng Yang58b89c82018-12-25 11:23:21 -0800127
128 auto& guestMemoryType =
129 info_out->guestMemoryProperties.memoryTypes[i];
130
131 auto& newVirtualMemoryType =
132 info_out->guestMemoryProperties.memoryTypes[firstFreeTypeIndex];
133
134 auto& newVirtualMemoryHeap =
135 info_out->guestMemoryProperties.memoryHeaps[firstFreeHeapIndex];
136
Lingfeng Yangdf173132018-12-25 13:30:57 -0800137 // Remove all references to host visible in the guest memory type at
138 // index i, while transferring them to the new virtual memory type.
Lingfeng Yang58b89c82018-12-25 11:23:21 -0800139 newVirtualMemoryType = type;
140
141 // Set this memory type to have a separate heap.
142 newVirtualMemoryType.heapIndex = firstFreeHeapIndex;
143
Lingfeng Yangdf173132018-12-25 13:30:57 -0800144 newVirtualMemoryType.propertyFlags =
145 type.propertyFlags &
146 ~(VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT);
147
Lingfeng Yang58b89c82018-12-25 11:23:21 -0800148 guestMemoryType.propertyFlags =
149 type.propertyFlags & \
150 ~(VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT |
151 VK_MEMORY_PROPERTY_HOST_COHERENT_BIT |
152 VK_MEMORY_PROPERTY_HOST_CACHED_BIT);
153
Lingfeng Yang58b89c82018-12-25 11:23:21 -0800154 // In the corresponding new memory heap, copy the information over,
155 // remove device local flags, and resize it based on what is
156 // supported by the PCI device.
Lingfeng Yangdf173132018-12-25 13:30:57 -0800157 newVirtualMemoryHeap =
158 memoryProperties->memoryHeaps[heapIndex];
Lingfeng Yang58b89c82018-12-25 11:23:21 -0800159 newVirtualMemoryHeap.flags =
160 newVirtualMemoryHeap.flags &
161 ~(VK_MEMORY_HEAP_DEVICE_LOCAL_BIT);
162
163 // TODO: Figure out how to support bigger sizes
164 newVirtualMemoryHeap.size = 512ULL * 1048576ULL; // 512 MB
165
166 info_out->memoryTypeIndexMappingToHost[firstFreeTypeIndex] = i;
167 info_out->memoryHeapIndexMappingToHost[firstFreeHeapIndex] = i;
168
169 info_out->memoryTypeIndexMappingFromHost[i] = firstFreeTypeIndex;
170 info_out->memoryHeapIndexMappingFromHost[i] = firstFreeHeapIndex;
171
172 // Was the original memory type also a device local type? If so,
173 // advertise both types in resulting type bits.
174 info_out->memoryTypeBitsShouldAdvertiseBoth[i] =
175 type.propertyFlags & VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT;
176
177 ++firstFreeTypeIndex;
178 ++firstFreeHeapIndex;
179 }
180 }
Lingfeng Yangdf173132018-12-25 13:30:57 -0800181
182 info_out->guestMemoryProperties.memoryTypeCount = firstFreeTypeIndex;
183 info_out->guestMemoryProperties.memoryHeapCount = firstFreeHeapIndex;
184
185 for (uint32_t i = info_out->guestMemoryProperties.memoryTypeCount; i < VK_MAX_MEMORY_TYPES; ++i) {
186 memset(&info_out->guestMemoryProperties.memoryTypes[i],
187 0x0, sizeof(VkMemoryType));
188 }
Lingfeng Yang58b89c82018-12-25 11:23:21 -0800189}
190
Lingfeng Yangdf173132018-12-25 13:30:57 -0800191} // namespace goldfish_vk