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