1 // Copyright (C) 2024 The Android Open Source Project
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14
15 #include <gmock/gmock.h>
16 #include <gtest/gtest.h>
17
18 #include <vector>
19
20 #include "VkEmulatedPhysicalDeviceMemory.h"
21 #include "gfxstream/host/Features.h"
22
23 namespace gfxstream {
24 namespace vk {
25 namespace {
26
27 using ::testing::AllOf;
28 using ::testing::ElementsAreArray;
29 using ::testing::Eq;
30 using ::testing::ExplainMatchResult;
31 using ::testing::Field;
32 using ::testing::Matcher;
33 using ::testing::Optional;
34
35 MATCHER_P(EqsVkMemoryHeap, expected, "") {
36 return ExplainMatchResult(AllOf(Field("size", &VkMemoryHeap::size, Eq(expected.size)),
37 Field("flags", &VkMemoryHeap::flags, Eq(expected.flags))),
38 arg, result_listener);
39 }
40
41 MATCHER_P(EqsVkMemoryType, expected, "") {
42 return ExplainMatchResult(
43 AllOf(Field("propertyFlags", &VkMemoryType::propertyFlags, Eq(expected.propertyFlags)),
44 Field("heapIndex", &VkMemoryType::heapIndex, Eq(expected.heapIndex))),
45 arg, result_listener);
46 }
47
48 MATCHER_P(EqsHostMemoryInfo, expected, "") {
49 return ExplainMatchResult(
50 AllOf(
51 Field("index", &EmulatedPhysicalDeviceMemoryProperties::HostMemoryInfo::index,
52 Eq(expected.index)),
53 Field("memoryType", &EmulatedPhysicalDeviceMemoryProperties::HostMemoryInfo::memoryType,
54 EqsVkMemoryType(expected.memoryType))),
55 arg, result_listener);
56 }
57
58 MATCHER_P(EqsVkPhysicalDeviceMemoryProperties, expected, "") {
59 std::vector<Matcher<VkMemoryHeap>> memoryHeapsMatchers;
60 for (uint32_t i = 0; i < VK_MAX_MEMORY_HEAPS; i++) {
61 memoryHeapsMatchers.push_back(EqsVkMemoryHeap(expected.memoryHeaps[i]));
62 }
63
64 std::vector<Matcher<VkMemoryType>> memoryTypesMatchers;
65 for (uint32_t i = 0; i < VK_MAX_MEMORY_TYPES; i++) {
66 memoryTypesMatchers.push_back(EqsVkMemoryType(expected.memoryTypes[i]));
67 }
68
69 return ExplainMatchResult(
70 AllOf(Field("memoryTypeCount", &VkPhysicalDeviceMemoryProperties::memoryTypeCount,
71 Eq(expected.memoryTypeCount)),
72 Field("memoryTypes", &VkPhysicalDeviceMemoryProperties::memoryTypes,
73 ElementsAreArray(memoryTypesMatchers)),
74 Field("memoryHeapCount", &VkPhysicalDeviceMemoryProperties::memoryHeapCount,
75 Eq(expected.memoryHeapCount)),
76 Field("memoryHeaps", &VkPhysicalDeviceMemoryProperties::memoryHeaps,
77 ElementsAreArray(memoryHeapsMatchers))),
78 arg, result_listener);
79 }
80
TEST(VkGuestMemoryUtilsTest,Passthrough)81 TEST(VkGuestMemoryUtilsTest, Passthrough) {
82 const VkPhysicalDeviceMemoryProperties hostMemoryProperties = {
83 .memoryTypeCount = 2,
84 .memoryTypes =
85 {
86 {
87 .propertyFlags = VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT,
88 .heapIndex = 0,
89 },
90 {
91 .propertyFlags = VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT,
92 .heapIndex = 1,
93 },
94 },
95 .memoryHeapCount = 2,
96 .memoryHeaps =
97 {
98 {
99 .size = 0x1000000,
100 .flags = 0,
101 },
102 {
103 .size = 0x200000,
104 .flags = VK_MEMORY_HEAP_DEVICE_LOCAL_BIT,
105 },
106 },
107 };
108
109 gfxstream::host::FeatureSet features;
110 EmulatedPhysicalDeviceMemoryProperties helper(hostMemoryProperties, 1, features);
111
112 // Passthrough when no features enabled:
113 const auto actualGuestMemoryProperties = helper.getGuestMemoryProperties();
114 EXPECT_THAT(actualGuestMemoryProperties,
115 EqsVkPhysicalDeviceMemoryProperties(hostMemoryProperties));
116 }
117
TEST(VkGuestMemoryUtilsTest,ReserveAHardwareBuffer)118 TEST(VkGuestMemoryUtilsTest, ReserveAHardwareBuffer) {
119 const VkPhysicalDeviceMemoryProperties hostMemoryProperties = {
120 .memoryTypeCount = 2,
121 .memoryTypes =
122 {
123 {
124 .propertyFlags = VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT,
125 .heapIndex = 0,
126 },
127 {
128 .propertyFlags = VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT,
129 .heapIndex = 1,
130 },
131 },
132 .memoryHeapCount = 2,
133 .memoryHeaps =
134 {
135 {
136 .size = 0x1000000,
137 .flags = 0,
138 },
139 {
140 .size = 0x200000,
141 .flags = VK_MEMORY_HEAP_DEVICE_LOCAL_BIT,
142 },
143 },
144 };
145
146 gfxstream::host::FeatureSet features;
147 features.VulkanUseDedicatedAhbMemoryType.enabled = true;
148
149 const uint32_t kHostColorBufferIndex = 1;
150 EmulatedPhysicalDeviceMemoryProperties helper(hostMemoryProperties, kHostColorBufferIndex,
151 features);
152
153 const VkPhysicalDeviceMemoryProperties expectedGuestMemoryProperties = {
154 .memoryTypeCount = 3,
155 .memoryTypes =
156 {
157 {
158 .propertyFlags = VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT,
159 .heapIndex = 0,
160 },
161 {
162 .propertyFlags = VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT,
163 .heapIndex = 1,
164 },
165 // Note: extra memory type here:
166 {
167 .propertyFlags = VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT,
168 .heapIndex = 1,
169 },
170 },
171 .memoryHeapCount = 2,
172 .memoryHeaps =
173 {
174 {
175 .size = 0x1000000,
176 .flags = 0,
177 },
178 {
179 .size = 0x200000,
180 .flags = VK_MEMORY_HEAP_DEVICE_LOCAL_BIT,
181 },
182 },
183 };
184
185 const auto actualGuestMemoryProperties = helper.getGuestMemoryProperties();
186 EXPECT_THAT(actualGuestMemoryProperties,
187 EqsVkPhysicalDeviceMemoryProperties(expectedGuestMemoryProperties));
188
189 const auto mappedHostMemoryInfo = helper.getHostMemoryInfoFromGuestMemoryTypeIndex(2);
190 EXPECT_THAT(mappedHostMemoryInfo,
191 Optional(EqsHostMemoryInfo(EmulatedPhysicalDeviceMemoryProperties::HostMemoryInfo{
192 .index = kHostColorBufferIndex,
193 .memoryType = hostMemoryProperties.memoryTypes[kHostColorBufferIndex],
194 })));
195 }
196
TEST(VkGuestMemoryUtilsTest,VulkanAllocateDeviceMemoryOnly)197 TEST(VkGuestMemoryUtilsTest, VulkanAllocateDeviceMemoryOnly) {
198 const VkPhysicalDeviceMemoryProperties hostMemoryProperties = {
199 .memoryTypeCount = 3,
200 .memoryTypes =
201 {
202 {
203 .propertyFlags = VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT,
204 .heapIndex = 0,
205 },
206 {
207 .propertyFlags = VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT,
208 .heapIndex = 1,
209 },
210 },
211 .memoryHeapCount = 2,
212 .memoryHeaps =
213 {
214 {
215 .size = 0x1000000,
216 .flags = 0,
217 },
218 {
219 .size = 0x200000,
220 .flags = VK_MEMORY_HEAP_DEVICE_LOCAL_BIT,
221 },
222 },
223 };
224
225 gfxstream::host::FeatureSet features;
226 features.VulkanAllocateDeviceMemoryOnly.enabled = true;
227
228 EmulatedPhysicalDeviceMemoryProperties helper(hostMemoryProperties, 1, features);
229
230 const VkPhysicalDeviceMemoryProperties expectedGuestMemoryProperties = {
231 .memoryTypeCount = 3,
232 .memoryTypes =
233 {
234 {
235 .propertyFlags = 0,
236 .heapIndex = 0,
237 },
238 {
239 .propertyFlags = VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT,
240 .heapIndex = 1,
241 },
242 },
243 .memoryHeapCount = 2,
244 .memoryHeaps =
245 {
246 {
247 .size = 0x1000000,
248 .flags = 0,
249 },
250 {
251 .size = 0x200000,
252 .flags = VK_MEMORY_HEAP_DEVICE_LOCAL_BIT,
253 },
254 },
255 };
256
257 const auto actualGuestMemoryProperties = helper.getGuestMemoryProperties();
258 EXPECT_THAT(actualGuestMemoryProperties,
259 EqsVkPhysicalDeviceMemoryProperties(expectedGuestMemoryProperties));
260 }
261
262 } // namespace
263 } // namespace vk
264 } // namespace gfxstream