1 #include <gtest/gtest.h>
2
3 #include "SwapChainStateVk.h"
4
5 #include "Standalone.h"
6 #include "vulkan/VulkanDispatch.h"
7
8 class SwapChainStateVkTest : public ::testing::Test {
9 protected:
SetUpTestCase()10 static void SetUpTestCase() { k_vk = emugl::vkDispatch(false); }
11
SetUp()12 void SetUp() override {
13 // skip the test when testing without a window
14 if (!emugl::shouldUseWindow()) {
15 GTEST_SKIP();
16 }
17 ASSERT_NE(k_vk, nullptr);
18
19 createInstance();
20 createWindowAndSurface();
21 pickPhysicalDevice();
22 createLogicalDevice();
23 }
24
TearDown()25 void TearDown() override {
26 if (emugl::shouldUseWindow()) {
27 k_vk->vkDestroyDevice(m_vkDevice, nullptr);
28 k_vk->vkDestroySurfaceKHR(m_vkInstance, m_vkSurface, nullptr);
29 k_vk->vkDestroyInstance(m_vkInstance, nullptr);
30 }
31 }
32
33 static goldfish_vk::VulkanDispatch *k_vk;
34 static const uint32_t k_width = 0x100;
35 static const uint32_t k_height = 0x100;
36
37 OSWindow *m_window;
38 VkInstance m_vkInstance = VK_NULL_HANDLE;
39 VkSurfaceKHR m_vkSurface = VK_NULL_HANDLE;
40 VkPhysicalDevice m_vkPhysicalDevice = VK_NULL_HANDLE;
41 uint32_t m_swapChainQueueFamilyIndex = 0;
42 VkDevice m_vkDevice = VK_NULL_HANDLE;
43
44 private:
createInstance()45 void createInstance() {
46 VkApplicationInfo appInfo = {
47 .sType = VK_STRUCTURE_TYPE_APPLICATION_INFO,
48 .pNext = nullptr,
49 .pApplicationName = "emulator SwapChainStateVk unittest",
50 .applicationVersion = VK_MAKE_VERSION(1, 0, 0),
51 .pEngineName = "No Engine",
52 .engineVersion = VK_MAKE_VERSION(1, 0, 0),
53 .apiVersion = VK_API_VERSION_1_1};
54 auto extensions = SwapChainStateVk::getRequiredInstanceExtensions();
55 VkInstanceCreateInfo instanceCi = {
56 .sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO,
57 .pApplicationInfo = &appInfo,
58 .enabledExtensionCount = static_cast<uint32_t>(extensions.size()),
59 .ppEnabledExtensionNames = extensions.data()};
60 ASSERT_EQ(k_vk->vkCreateInstance(&instanceCi, nullptr, &m_vkInstance),
61 VK_SUCCESS);
62 ASSERT_TRUE(m_vkInstance != VK_NULL_HANDLE);
63 }
64
createWindowAndSurface()65 void createWindowAndSurface() {
66 m_window = emugl::createOrGetTestWindow(0, 0, k_width, k_height);
67 ASSERT_NE(m_window, nullptr);
68 // TODO(kaiyili, b/179477624): add support for other platforms
69 #ifdef _WIN32
70 VkWin32SurfaceCreateInfoKHR surfaceCi = {
71 .sType = VK_STRUCTURE_TYPE_WIN32_SURFACE_CREATE_INFO_KHR,
72 .hinstance = GetModuleHandle(nullptr),
73 .hwnd = m_window->getNativeWindow()};
74 ASSERT_EQ(k_vk->vkCreateWin32SurfaceKHR(m_vkInstance, &surfaceCi,
75 nullptr, &m_vkSurface),
76 VK_SUCCESS);
77 #endif
78 }
79
pickPhysicalDevice()80 void pickPhysicalDevice() {
81 uint32_t physicalDeviceCount = 0;
82 ASSERT_EQ(k_vk->vkEnumeratePhysicalDevices(
83 m_vkInstance, &physicalDeviceCount, nullptr),
84 VK_SUCCESS);
85 ASSERT_GT(physicalDeviceCount, 0);
86 std::vector<VkPhysicalDevice> physicalDevices(physicalDeviceCount);
87 ASSERT_EQ(
88 k_vk->vkEnumeratePhysicalDevices(m_vkInstance, &physicalDeviceCount,
89 physicalDevices.data()),
90 VK_SUCCESS);
91 for (const auto &device : physicalDevices) {
92 uint32_t queueFamilyCount = 0;
93 k_vk->vkGetPhysicalDeviceQueueFamilyProperties(
94 device, &queueFamilyCount, nullptr);
95 ASSERT_GT(queueFamilyCount, 0);
96 uint32_t queueFamilyIndex = 0;
97 for (; queueFamilyIndex < queueFamilyCount; queueFamilyIndex++) {
98 if (!SwapChainStateVk::validateQueueFamilyProperties(
99 *k_vk, device, m_vkSurface, queueFamilyIndex)) {
100 continue;
101 }
102 if (SwapChainStateVk::createSwapChainCi(
103 *k_vk, m_vkSurface, device, k_width, k_height,
104 {queueFamilyIndex}) == nullptr) {
105 continue;
106 }
107 break;
108 }
109 if (queueFamilyIndex == queueFamilyCount) {
110 continue;
111 }
112
113 m_swapChainQueueFamilyIndex = queueFamilyIndex;
114 m_vkPhysicalDevice = device;
115 return;
116 }
117 FAIL() << "Can't find a suitable VkPhysicalDevice.";
118 }
119
createLogicalDevice()120 void createLogicalDevice() {
121 const float queuePriority = 1.0f;
122 VkDeviceQueueCreateInfo queueCi = {
123 .sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO,
124 .queueFamilyIndex = m_swapChainQueueFamilyIndex,
125 .queueCount = 1,
126 .pQueuePriorities = &queuePriority};
127 VkPhysicalDeviceFeatures features = {};
128 const std::vector<const char *> enabledDeviceExtensions =
129 SwapChainStateVk::getRequiredDeviceExtensions();
130 VkDeviceCreateInfo deviceCi = {
131 .sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO,
132 .queueCreateInfoCount = 1,
133 .pQueueCreateInfos = &queueCi,
134 .enabledLayerCount = 0,
135 .enabledExtensionCount =
136 static_cast<uint32_t>(enabledDeviceExtensions.size()),
137 .ppEnabledExtensionNames = enabledDeviceExtensions.data(),
138 .pEnabledFeatures = &features};
139 ASSERT_EQ(k_vk->vkCreateDevice(m_vkPhysicalDevice, &deviceCi, nullptr,
140 &m_vkDevice),
141 VK_SUCCESS);
142 ASSERT_TRUE(m_vkDevice != VK_NULL_HANDLE);
143 }
144 };
145
146 goldfish_vk::VulkanDispatch *SwapChainStateVkTest::k_vk = nullptr;
147
TEST_F(SwapChainStateVkTest,init)148 TEST_F(SwapChainStateVkTest, init) {
149 auto swapChainCi = SwapChainStateVk::createSwapChainCi(
150 *k_vk, m_vkSurface, m_vkPhysicalDevice, k_width, k_height,
151 {m_swapChainQueueFamilyIndex});
152 ASSERT_NE(swapChainCi, nullptr);
153 SwapChainStateVk swapChainState(*k_vk, m_vkDevice, *swapChainCi);
154 }