blob: 28428732c974292972f3bcef4a7aa954fcfbfe1b [file] [log] [blame]
Jason Macnak741afe72022-04-14 08:19:52 -07001// Note: needs to be included before DisplayVk to avoid conflicts
2// between gtest and x11 headers.
Kaiyi Liea146f72021-02-03 12:52:23 -08003#include <gtest/gtest.h>
4
Kaiyi Li9b3a0d82021-02-06 13:03:16 -08005#include "DisplayVk.h"
6
Jason Macnak741afe72022-04-14 08:19:52 -07007#include "BorrowedImageVk.h"
Kaiyi Liea146f72021-02-03 12:52:23 -08008#include "Standalone.h"
Joshua Duongef2bbc22022-10-05 11:59:15 -07009#include "aemu/base/synchronization/Lock.h"
Kaiyi Liea146f72021-02-03 12:52:23 -080010#include "tests/VkTestUtils.h"
11#include "vulkan/VulkanDispatch.h"
12
Jason Macnak32281f72022-10-12 13:00:36 -070013using gfxstream::DisplaySurface;
14
Jason Macnaked0c9e62023-03-30 15:58:24 -070015namespace gfxstream {
16namespace vk {
17namespace {
18
Kaiyi Liea146f72021-02-03 12:52:23 -080019class DisplayVkTest : public ::testing::Test {
20 protected:
Jason Macnaked0c9e62023-03-30 15:58:24 -070021 using RenderTexture = RenderTextureVk;
Jason Macnak741afe72022-04-14 08:19:52 -070022
Jason Macnaked0c9e62023-03-30 15:58:24 -070023 static void SetUpTestCase() { k_vk = vkDispatch(false); }
Kaiyi Liea146f72021-02-03 12:52:23 -080024
25 void SetUp() override {
26 // skip the test when testing without a window
Jason Macnaked0c9e62023-03-30 15:58:24 -070027 if (!shouldUseWindow()) {
Kaiyi Liea146f72021-02-03 12:52:23 -080028 GTEST_SKIP();
29 }
30 ASSERT_NE(k_vk, nullptr);
31
32 createInstance();
33 createWindowAndSurface();
Jason Macnaked0c9e62023-03-30 15:58:24 -070034 m_window = createOrGetTestWindow(0, 0, k_width, k_height);
Kaiyi Liea146f72021-02-03 12:52:23 -080035 pickPhysicalDevice();
36 createLogicalDevice();
Kaiyi Lic701d662021-10-15 13:15:07 -070037 k_vk->vkGetDeviceQueue(m_vkDevice, m_compositorQueueFamilyIndex, 0, &m_compositorVkQueue);
Lingfeng Yang30dafd62021-09-13 17:33:38 -070038 m_compositorVkQueueLock = std::make_shared<android::base::Lock>();
Kaiyi Lic701d662021-10-15 13:15:07 -070039 k_vk->vkGetDeviceQueue(m_vkDevice, m_swapChainQueueFamilyIndex, 0, &m_swapChainVkQueue);
Lingfeng Yang30dafd62021-09-13 17:33:38 -070040 m_swapChainVkQueueLock = std::make_shared<android::base::Lock>();
Kaiyi Lided6ac82021-02-06 13:17:26 -080041 VkCommandPoolCreateInfo commandPoolCi = {
42 .sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO,
43 .queueFamilyIndex = m_compositorQueueFamilyIndex};
Kaiyi Lic701d662021-10-15 13:15:07 -070044 ASSERT_EQ(k_vk->vkCreateCommandPool(m_vkDevice, &commandPoolCi, nullptr, &m_vkCommandPool),
Kaiyi Liea146f72021-02-03 12:52:23 -080045 VK_SUCCESS);
46 m_displayVk = std::make_unique<DisplayVk>(
Kaiyi Lic701d662021-10-15 13:15:07 -070047 *k_vk, m_vkPhysicalDevice, m_swapChainQueueFamilyIndex, m_compositorQueueFamilyIndex,
48 m_vkDevice, m_compositorVkQueue, m_compositorVkQueueLock, m_swapChainVkQueue,
Lingfeng Yang30dafd62021-09-13 17:33:38 -070049 m_swapChainVkQueueLock);
Jason Macnak32281f72022-10-12 13:00:36 -070050 m_displaySurface = std::make_unique<gfxstream::DisplaySurface>(
51 k_width, k_height,
52 DisplaySurfaceVk::create(*k_vk, m_vkInstance, m_window->getNativeWindow()));
53 ASSERT_NE(m_displaySurface, nullptr);
54 m_displayVk->bindToSurface(m_displaySurface.get());
Kaiyi Liea146f72021-02-03 12:52:23 -080055 }
56
57 void TearDown() override {
Jason Macnaked0c9e62023-03-30 15:58:24 -070058 if (shouldUseWindow()) {
Kaiyi Liea146f72021-02-03 12:52:23 -080059 ASSERT_EQ(k_vk->vkQueueWaitIdle(m_compositorVkQueue), VK_SUCCESS);
60 ASSERT_EQ(k_vk->vkQueueWaitIdle(m_swapChainVkQueue), VK_SUCCESS);
61
62 m_displayVk.reset();
63 k_vk->vkDestroyCommandPool(m_vkDevice, m_vkCommandPool, nullptr);
64 k_vk->vkDestroyDevice(m_vkDevice, nullptr);
65 k_vk->vkDestroySurfaceKHR(m_vkInstance, m_vkSurface, nullptr);
66 k_vk->vkDestroyInstance(m_vkInstance, nullptr);
67 }
68 }
69
Jason Macnak741afe72022-04-14 08:19:52 -070070 std::unique_ptr<BorrowedImageInfoVk> createBorrowedImageInfo(
71 const std::unique_ptr<const RenderTexture>& texture) {
72 static uint32_t sTextureId = 0;
73
74 auto info = std::make_unique<BorrowedImageInfoVk>();
75 info->id = sTextureId++;
76 info->width = texture->m_vkImageCreateInfo.extent.width;
77 info->height = texture->m_vkImageCreateInfo.extent.height;
78 info->image = texture->m_vkImage;
79 info->imageCreateInfo = texture->m_vkImageCreateInfo;
80 info->preBorrowLayout = RenderTexture::k_vkImageLayout;
81 info->preBorrowQueueFamilyIndex = m_compositorQueueFamilyIndex;
82 info->postBorrowLayout = RenderTexture::k_vkImageLayout;
83 info->postBorrowQueueFamilyIndex = m_compositorQueueFamilyIndex;
84 return info;
85 }
Kaiyi Liea146f72021-02-03 12:52:23 -080086
Jason Macnaked0c9e62023-03-30 15:58:24 -070087 static const VulkanDispatch* k_vk;
Joshua Duong86ae80a2023-01-17 10:23:36 -080088 static constexpr uint32_t k_width = 0x100;
89 static constexpr uint32_t k_height = 0x100;
Kaiyi Liea146f72021-02-03 12:52:23 -080090
91 OSWindow *m_window;
92 VkInstance m_vkInstance = VK_NULL_HANDLE;
93 VkSurfaceKHR m_vkSurface = VK_NULL_HANDLE;
94 VkPhysicalDevice m_vkPhysicalDevice = VK_NULL_HANDLE;
95 uint32_t m_swapChainQueueFamilyIndex = 0;
96 uint32_t m_compositorQueueFamilyIndex = 0;
97 VkDevice m_vkDevice = VK_NULL_HANDLE;
98 VkQueue m_compositorVkQueue = VK_NULL_HANDLE;
Lingfeng Yang30dafd62021-09-13 17:33:38 -070099 std::shared_ptr<android::base::Lock> m_compositorVkQueueLock;
Kaiyi Liea146f72021-02-03 12:52:23 -0800100 VkQueue m_swapChainVkQueue = VK_NULL_HANDLE;
Lingfeng Yang30dafd62021-09-13 17:33:38 -0700101 std::shared_ptr<android::base::Lock> m_swapChainVkQueueLock;
Kaiyi Liea146f72021-02-03 12:52:23 -0800102 VkCommandPool m_vkCommandPool = VK_NULL_HANDLE;
103 std::unique_ptr<DisplayVk> m_displayVk = nullptr;
Jason Macnak32281f72022-10-12 13:00:36 -0700104 std::unique_ptr<DisplaySurface> m_displaySurface = nullptr;
Kaiyi Liea146f72021-02-03 12:52:23 -0800105
106 private:
107 void createInstance() {
Kaiyi Lic701d662021-10-15 13:15:07 -0700108 VkApplicationInfo appInfo = {.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO,
109 .pNext = nullptr,
110 .pApplicationName = "emulator SwapChainStateVk unittest",
111 .applicationVersion = VK_MAKE_VERSION(1, 0, 0),
112 .pEngineName = "No Engine",
113 .engineVersion = VK_MAKE_VERSION(1, 0, 0),
114 .apiVersion = VK_API_VERSION_1_1};
Kaiyi Liea146f72021-02-03 12:52:23 -0800115 auto extensions = SwapChainStateVk::getRequiredInstanceExtensions();
Kaiyi Lided6ac82021-02-06 13:17:26 -0800116 VkInstanceCreateInfo instanceCi = {
117 .sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO,
118 .pApplicationInfo = &appInfo,
119 .enabledExtensionCount = static_cast<uint32_t>(extensions.size()),
120 .ppEnabledExtensionNames = extensions.data()};
Kaiyi Lic701d662021-10-15 13:15:07 -0700121 ASSERT_EQ(k_vk->vkCreateInstance(&instanceCi, nullptr, &m_vkInstance), VK_SUCCESS);
Kaiyi Liea146f72021-02-03 12:52:23 -0800122 ASSERT_TRUE(m_vkInstance != VK_NULL_HANDLE);
123 }
124
125 void createWindowAndSurface() {
Jason Macnaked0c9e62023-03-30 15:58:24 -0700126 m_window = createOrGetTestWindow(0, 0, k_width, k_height);
Kaiyi Liea146f72021-02-03 12:52:23 -0800127 ASSERT_NE(m_window, nullptr);
Kaiyi Lieac86a72021-02-04 08:09:41 -0800128 // TODO(kaiyili, b/179477624): add support for other platforms
Kaiyi Liea146f72021-02-03 12:52:23 -0800129#ifdef _WIN32
Kaiyi Lided6ac82021-02-06 13:17:26 -0800130 VkWin32SurfaceCreateInfoKHR surfaceCi = {
131 .sType = VK_STRUCTURE_TYPE_WIN32_SURFACE_CREATE_INFO_KHR,
132 .hinstance = GetModuleHandle(nullptr),
133 .hwnd = m_window->getNativeWindow()};
Kaiyi Lic701d662021-10-15 13:15:07 -0700134 ASSERT_EQ(k_vk->vkCreateWin32SurfaceKHR(m_vkInstance, &surfaceCi, nullptr, &m_vkSurface),
Kaiyi Liea146f72021-02-03 12:52:23 -0800135 VK_SUCCESS);
136#endif
137 }
138
139 void pickPhysicalDevice() {
140 uint32_t physicalDeviceCount = 0;
Kaiyi Lic701d662021-10-15 13:15:07 -0700141 ASSERT_EQ(k_vk->vkEnumeratePhysicalDevices(m_vkInstance, &physicalDeviceCount, nullptr),
Kaiyi Liea146f72021-02-03 12:52:23 -0800142 VK_SUCCESS);
143 ASSERT_GT(physicalDeviceCount, 0);
144 std::vector<VkPhysicalDevice> physicalDevices(physicalDeviceCount);
Kaiyi Lic701d662021-10-15 13:15:07 -0700145 ASSERT_EQ(k_vk->vkEnumeratePhysicalDevices(m_vkInstance, &physicalDeviceCount,
146 physicalDevices.data()),
147 VK_SUCCESS);
Kaiyi Liea146f72021-02-03 12:52:23 -0800148 for (const auto &device : physicalDevices) {
Kaiyi Liea146f72021-02-03 12:52:23 -0800149 uint32_t queueFamilyCount = 0;
Kaiyi Lic701d662021-10-15 13:15:07 -0700150 k_vk->vkGetPhysicalDeviceQueueFamilyProperties(device, &queueFamilyCount, nullptr);
Kaiyi Liea146f72021-02-03 12:52:23 -0800151 ASSERT_GT(queueFamilyCount, 0);
152 std::vector<VkQueueFamilyProperties> queueProps(queueFamilyCount);
Kaiyi Lic701d662021-10-15 13:15:07 -0700153 k_vk->vkGetPhysicalDeviceQueueFamilyProperties(device, &queueFamilyCount,
154 queueProps.data());
155 std::optional<uint32_t> maybeSwapChainQueueFamilyIndex = std::nullopt;
156 std::optional<uint32_t> maybeCompositorQueueFamilyIndex = std::nullopt;
157 for (uint32_t queueFamilyIndex = 0; queueFamilyIndex < queueFamilyCount;
158 queueFamilyIndex++) {
Kaiyi Liea146f72021-02-03 12:52:23 -0800159 if (!maybeSwapChainQueueFamilyIndex.has_value() &&
Kaiyi Lic701d662021-10-15 13:15:07 -0700160 SwapChainStateVk::validateQueueFamilyProperties(*k_vk, device, m_vkSurface,
161 queueFamilyIndex) &&
162 SwapChainStateVk::createSwapChainCi(*k_vk, m_vkSurface, device, k_width,
Kaiyi Lie31de802022-03-23 10:23:48 -0700163 k_height, {queueFamilyIndex})) {
Kaiyi Liea146f72021-02-03 12:52:23 -0800164 maybeSwapChainQueueFamilyIndex = queueFamilyIndex;
165 }
166 if (!maybeCompositorQueueFamilyIndex.has_value() &&
Jason Macnak741afe72022-04-14 08:19:52 -0700167 CompositorVk::queueSupportsComposition(queueProps[queueFamilyIndex])) {
Kaiyi Liea146f72021-02-03 12:52:23 -0800168 maybeCompositorQueueFamilyIndex = queueFamilyIndex;
169 }
170 }
171 if (!maybeSwapChainQueueFamilyIndex.has_value() ||
172 !maybeCompositorQueueFamilyIndex.has_value()) {
173 continue;
174 }
Kaiyi Lic701d662021-10-15 13:15:07 -0700175 m_swapChainQueueFamilyIndex = maybeSwapChainQueueFamilyIndex.value();
176 m_compositorQueueFamilyIndex = maybeCompositorQueueFamilyIndex.value();
Kaiyi Liea146f72021-02-03 12:52:23 -0800177 m_vkPhysicalDevice = device;
178 return;
179 }
180 FAIL() << "Can't find a suitable VkPhysicalDevice.";
181 }
182
183 void createLogicalDevice() {
184 const float queuePriority = 1.0f;
185 std::vector<VkDeviceQueueCreateInfo> queueCis(0);
Gurchetan Singh2947cf32021-10-11 17:43:34 -0700186 for (auto queueFamilyIndex : std::unordered_set<uint32_t>(
Kaiyi Liea146f72021-02-03 12:52:23 -0800187 {m_swapChainQueueFamilyIndex, m_compositorQueueFamilyIndex})) {
Kaiyi Lic701d662021-10-15 13:15:07 -0700188 VkDeviceQueueCreateInfo queueCi = {.sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO,
189 .queueFamilyIndex = queueFamilyIndex,
190 .queueCount = 1,
191 .pQueuePriorities = &queuePriority};
Kaiyi Liea146f72021-02-03 12:52:23 -0800192 queueCis.push_back(queueCi);
193 }
Kaiyi Lic701d662021-10-15 13:15:07 -0700194 VkPhysicalDeviceFeatures2 features = {.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2,
Kaiyi Li9aac1f82021-10-04 10:53:01 -0700195 .pNext = nullptr};
Kaiyi Liea146f72021-02-03 12:52:23 -0800196 auto extensions = SwapChainStateVk::getRequiredDeviceExtensions();
Kaiyi Lided6ac82021-02-06 13:17:26 -0800197 VkDeviceCreateInfo deviceCi = {
198 .sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO,
199 .pNext = &features,
200 .queueCreateInfoCount = static_cast<uint32_t>(queueCis.size()),
201 .pQueueCreateInfos = queueCis.data(),
202 .enabledLayerCount = 0,
203 .enabledExtensionCount = static_cast<uint32_t>(extensions.size()),
204 .ppEnabledExtensionNames = extensions.data(),
205 .pEnabledFeatures = nullptr};
Kaiyi Lic701d662021-10-15 13:15:07 -0700206 ASSERT_EQ(k_vk->vkCreateDevice(m_vkPhysicalDevice, &deviceCi, nullptr, &m_vkDevice),
Kaiyi Liea146f72021-02-03 12:52:23 -0800207 VK_SUCCESS);
208 ASSERT_TRUE(m_vkDevice != VK_NULL_HANDLE);
209 }
210};
211
Jason Macnaked0c9e62023-03-30 15:58:24 -0700212const VulkanDispatch* DisplayVkTest::k_vk = nullptr;
Kaiyi Liea146f72021-02-03 12:52:23 -0800213
214TEST_F(DisplayVkTest, Init) {}
215
216TEST_F(DisplayVkTest, PostWithoutSurfaceShouldntCrash) {
217 uint32_t textureWidth = 20;
218 uint32_t textureHeight = 40;
219 DisplayVk displayVk(*k_vk, m_vkPhysicalDevice, m_swapChainQueueFamilyIndex,
Kaiyi Lic701d662021-10-15 13:15:07 -0700220 m_compositorQueueFamilyIndex, m_vkDevice, m_compositorVkQueue,
221 m_compositorVkQueueLock, m_swapChainVkQueue, m_swapChainVkQueueLock);
222 auto texture = RenderTexture::create(*k_vk, m_vkDevice, m_vkPhysicalDevice, m_compositorVkQueue,
223 m_vkCommandPool, textureWidth, textureHeight);
Kaiyi Liea146f72021-02-03 12:52:23 -0800224 std::vector<uint32_t> pixels(textureWidth * textureHeight, 0);
225 ASSERT_TRUE(texture->write(pixels));
Jason Macnak741afe72022-04-14 08:19:52 -0700226 const auto imageInfo = createBorrowedImageInfo(texture);
Jason Macnak32281f72022-10-12 13:00:36 -0700227 displayVk.post(imageInfo.get());
Kaiyi Liea146f72021-02-03 12:52:23 -0800228}
229
230TEST_F(DisplayVkTest, SimplePost) {
231 uint32_t textureWidth = 20;
232 uint32_t textureHeight = 40;
Kaiyi Lic701d662021-10-15 13:15:07 -0700233 auto texture = RenderTexture::create(*k_vk, m_vkDevice, m_vkPhysicalDevice, m_compositorVkQueue,
234 m_vkCommandPool, textureWidth, textureHeight);
Kaiyi Liea146f72021-02-03 12:52:23 -0800235 std::vector<uint32_t> pixels(textureWidth * textureHeight);
236 for (int i = 0; i < textureHeight; i++) {
237 for (int j = 0; j < textureWidth; j++) {
Kaiyi Lic701d662021-10-15 13:15:07 -0700238 uint8_t *pixel = reinterpret_cast<uint8_t *>(&pixels[i * textureWidth + j]);
Kaiyi Liea146f72021-02-03 12:52:23 -0800239 pixel[0] = static_cast<uint8_t>((i * 0xff / textureHeight) & 0xff);
240 pixel[1] = static_cast<uint8_t>((j * 0xff / textureWidth) & 0xff);
241 pixel[2] = 0;
242 pixel[3] = 0xff;
243 }
244 }
245 ASSERT_TRUE(texture->write(pixels));
Kaiyi Li9aac1f82021-10-04 10:53:01 -0700246 std::vector<std::shared_future<void>> waitForGpuFutures;
Kaiyi Liea146f72021-02-03 12:52:23 -0800247 for (uint32_t i = 0; i < 10; i++) {
Kaiyi Lif0a12762022-08-22 12:16:33 -0700248 const auto imageInfo = createBorrowedImageInfo(texture);
Jason Macnak32281f72022-10-12 13:00:36 -0700249 auto postResult = m_displayVk->post(imageInfo.get());
250 ASSERT_TRUE(postResult.success);
251 waitForGpuFutures.emplace_back(std::move(postResult.postCompletedWaitable));
Kaiyi Li9aac1f82021-10-04 10:53:01 -0700252 }
253 for (auto &waitForGpuFuture : waitForGpuFutures) {
254 waitForGpuFuture.wait();
Kaiyi Liea146f72021-02-03 12:52:23 -0800255 }
Kaiyi Liea146f72021-02-03 12:52:23 -0800256}
257
258TEST_F(DisplayVkTest, PostTwoColorBuffers) {
259 uint32_t textureWidth = 20;
260 uint32_t textureHeight = 40;
Kaiyi Lic701d662021-10-15 13:15:07 -0700261 auto redTexture =
262 RenderTexture::create(*k_vk, m_vkDevice, m_vkPhysicalDevice, m_compositorVkQueue,
263 m_vkCommandPool, textureWidth, textureHeight);
264 auto greenTexture =
265 RenderTexture::create(*k_vk, m_vkDevice, m_vkPhysicalDevice, m_compositorVkQueue,
266 m_vkCommandPool, textureWidth, textureHeight);
Kaiyi Liea146f72021-02-03 12:52:23 -0800267 uint32_t red = 0xff0000ff;
268 uint32_t green = 0xff00ff00;
269 std::vector<uint32_t> redPixels(textureWidth * textureHeight, red);
270 std::vector<uint32_t> greenPixels(textureWidth * textureHeight, green);
271 ASSERT_TRUE(redTexture->write(redPixels));
272 ASSERT_TRUE(greenTexture->write(greenPixels));
Kaiyi Li9aac1f82021-10-04 10:53:01 -0700273 std::vector<std::shared_future<void>> waitForGpuFutures;
Kaiyi Liea146f72021-02-03 12:52:23 -0800274 for (uint32_t i = 0; i < 10; i++) {
Kaiyi Lif0a12762022-08-22 12:16:33 -0700275 const auto redImageInfo = createBorrowedImageInfo(redTexture);
276 const auto greenImageInfo = createBorrowedImageInfo(greenTexture);
Jason Macnak32281f72022-10-12 13:00:36 -0700277 auto redPostResult = m_displayVk->post(redImageInfo.get());
278 ASSERT_TRUE(redPostResult.success);
279 waitForGpuFutures.emplace_back(std::move(redPostResult.postCompletedWaitable));
280
281 auto greenPostResult = m_displayVk->post(greenImageInfo.get());
282 ASSERT_TRUE(greenPostResult.success);
283 waitForGpuFutures.emplace_back(std::move(greenPostResult.postCompletedWaitable));
Kaiyi Li9aac1f82021-10-04 10:53:01 -0700284 }
285 for (auto &waitForGpuFuture : waitForGpuFutures) {
286 waitForGpuFuture.wait();
Kaiyi Liea146f72021-02-03 12:52:23 -0800287 }
Lingfeng Yang30dafd62021-09-13 17:33:38 -0700288}
Jason Macnaked0c9e62023-03-30 15:58:24 -0700289
290} // namespace
291} // namespace vk
292} // namespace gfxstream