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