blob: e8a2fb74f5a0c8102b9bd3db352b9cb0517c7567 [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,
79 HostVisibleMemoryVirtualizationInfo* info_out) {
80
81 info_out->supported =
82 canFitVirtualHostVisibleMemoryInfo(memoryProperties);
83
84 if (!info_out->supported) return;
85
86 uint32_t typeCount =
87 memoryProperties->memoryTypeCount;
88 uint32_t heapCount =
89 memoryProperties->memoryHeapCount;
90
91 info_out->physicalDevice = physicalDevice;
92 info_out->hostMemoryProperties = *memoryProperties;
93 info_out->guestMemoryProperties = *memoryProperties;
94
95 uint32_t firstFreeTypeIndex = typeCount;
96 uint32_t firstFreeHeapIndex = heapCount;
97 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];
110 if (type.propertyFlags & VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT) {
111
112 auto& guestMemoryType =
113 info_out->guestMemoryProperties.memoryTypes[i];
114
115 auto& newVirtualMemoryType =
116 info_out->guestMemoryProperties.memoryTypes[firstFreeTypeIndex];
117
118 auto& newVirtualMemoryHeap =
119 info_out->guestMemoryProperties.memoryHeaps[firstFreeHeapIndex];
120
121 newVirtualMemoryType = type;
122
123 // Set this memory type to have a separate heap.
124 newVirtualMemoryType.heapIndex = firstFreeHeapIndex;
125
126 // Remove all references to host visible in the guest memory type at
127 // index i, while transferring them to the new virtual memory type.
128 guestMemoryType.propertyFlags =
129 type.propertyFlags & \
130 ~(VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT |
131 VK_MEMORY_PROPERTY_HOST_COHERENT_BIT |
132 VK_MEMORY_PROPERTY_HOST_CACHED_BIT);
133
134 // Remove device local from the new virtual memory type.
135 newVirtualMemoryType.propertyFlags =
136 guestMemoryType.propertyFlags &
137 ~(VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT);
138
139 // In the corresponding new memory heap, copy the information over,
140 // remove device local flags, and resize it based on what is
141 // supported by the PCI device.
142 newVirtualMemoryHeap.flags =
143 newVirtualMemoryHeap.flags &
144 ~(VK_MEMORY_HEAP_DEVICE_LOCAL_BIT);
145
146 // TODO: Figure out how to support bigger sizes
147 newVirtualMemoryHeap.size = 512ULL * 1048576ULL; // 512 MB
148
149 info_out->memoryTypeIndexMappingToHost[firstFreeTypeIndex] = i;
150 info_out->memoryHeapIndexMappingToHost[firstFreeHeapIndex] = i;
151
152 info_out->memoryTypeIndexMappingFromHost[i] = firstFreeTypeIndex;
153 info_out->memoryHeapIndexMappingFromHost[i] = firstFreeHeapIndex;
154
155 // Was the original memory type also a device local type? If so,
156 // advertise both types in resulting type bits.
157 info_out->memoryTypeBitsShouldAdvertiseBoth[i] =
158 type.propertyFlags & VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT;
159
160 ++firstFreeTypeIndex;
161 ++firstFreeHeapIndex;
162 }
163 }
164}
165
166} // namespace goldfish_vk