1 /*
2 * Copyright (c) 2023 Huawei Device Co., Ltd.
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 <chrono>
16 #include <thread>
17 #include <unistd.h>
18 #include <window.h>
19 #include <gtest/gtest.h>
20 #include <dlfcn.h>
21 #include <iostream>
22 #include <string>
23 #include <vector>
24
25 #include "refbase.h"
26 #include "surface.h"
27 #include "vulkan/vulkan.h"
28 #include "render_context/render_context.h"
29 #include "transaction/rs_transaction.h"
30 #include "ui/rs_surface_extractor.h"
31 #include "ui/rs_surface_node.h"
32
33 using namespace testing;
34 using namespace testing::ext;
35 using namespace OHOS::Rosen;
36
37 namespace vulkan::loader {
38 class VulkanLoaderSystemTest : public testing::Test {
39 public:
SetUpTestCase()40 static void SetUpTestCase() {}
TearDownTestCase()41 static void TearDownTestCase()
42 {
43 if (libVulkan_ != nullptr) {
44 dlclose(libVulkan_);
45 libVulkan_ = nullptr;
46 }
47 }
48 static inline void DLOpenLibVulkan();
49 static inline void TrytoCreateVkInstance();
50
51 static inline PFN_vkCreateInstance vkCreateInstance;
52 static inline PFN_vkDestroySurfaceKHR vkDestroySurfaceKHR;
53 static inline PFN_vkCreateDevice vkCreateDevice;
54 static inline PFN_vkEnumerateInstanceExtensionProperties vkEnumerateInstanceExtensionProperties;
55 static inline PFN_vkEnumerateInstanceLayerProperties vkEnumerateInstanceLayerProperties;
56 static inline PFN_vkGetDeviceProcAddr vkGetDeviceProcAddr;
57 static inline PFN_vkGetInstanceProcAddr vkGetInstanceProcAddr;
58 static inline PFN_vkEnumeratePhysicalDevices vkEnumeratePhysicalDevices;
59 static inline PFN_vkCreateSurfaceOHOS vkCreateSurfaceOHOS;
60 static inline PFN_vkGetPhysicalDeviceSurfaceSupportKHR fpGetPhysicalDeviceSurfaceSupportKHR;
61 static inline PFN_vkGetPhysicalDeviceSurfaceCapabilitiesKHR fpGetPhysicalDeviceSurfaceCapabilitiesKHR;
62 static inline PFN_vkGetPhysicalDeviceSurfaceFormatsKHR fpGetPhysicalDeviceSurfaceFormatsKHR;
63 static inline PFN_vkGetPhysicalDeviceSurfacePresentModesKHR fpGetPhysicalDeviceSurfacePresentModesKHR;
64 static inline PFN_vkCreateSwapchainKHR fpCreateSwapchainKHR;
65 static inline PFN_vkDestroySwapchainKHR fpDestroySwapchainKHR;
66 static inline PFN_vkGetSwapchainImagesKHR fpGetSwapchainImagesKHR;
67 static inline PFN_vkAcquireNextImageKHR fpAcquireNextImageKHR;
68 static inline PFN_vkQueuePresentKHR fpQueuePresentKHR;
69
70 static inline void *libVulkan_ = nullptr;
71 static inline VkInstance instance_ = nullptr;
72 static inline VkSurfaceKHR surface_ = VK_NULL_HANDLE;
73 static inline VkPhysicalDevice physicalDevice_ = nullptr;
74 static inline VkDevice device_ = nullptr;
75 static inline VkSwapchainKHR swapChain_ = VK_NULL_HANDLE;
76 static inline bool isSupportedVulkan_ = false;
77 };
78
DLOpenLibVulkan()79 void VulkanLoaderSystemTest::DLOpenLibVulkan()
80 {
81 #ifdef __aarch64__
82 const char *path = "/system/lib64/libvulkan.so";
83 #else
84 const char *path = "/system/lib/libvulkan.so";
85 #endif
86 libVulkan_ = dlopen(path, RTLD_NOW | RTLD_LOCAL);
87 if (libVulkan_ == nullptr) {
88 std::cout << "dlerror: " << dlerror() << std::endl;
89 isSupportedVulkan_ = false;
90 return;
91 }
92 isSupportedVulkan_ = true;
93 }
94
TrytoCreateVkInstance()95 void VulkanLoaderSystemTest::TrytoCreateVkInstance()
96 {
97 VkApplicationInfo appInfo = {};
98 appInfo.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO;
99 appInfo.pApplicationName = "pApplicationName";
100 appInfo.pEngineName = "pEngineName";
101 appInfo.apiVersion = VK_API_VERSION_1_0;
102
103 std::vector<const char*> instanceExtensions = {
104 VK_KHR_SURFACE_EXTENSION_NAME,
105 VK_OHOS_SURFACE_EXTENSION_NAME
106 };
107
108 VkInstanceCreateInfo instanceCreateInfo = {};
109 instanceCreateInfo.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO;
110 instanceCreateInfo.pNext = NULL;
111 instanceCreateInfo.pApplicationInfo = &appInfo;
112
113 instanceCreateInfo.enabledExtensionCount = static_cast<uint32_t>(instanceExtensions.size());
114 instanceCreateInfo.ppEnabledExtensionNames = instanceExtensions.data();
115
116 VkResult result = vkCreateInstance(&instanceCreateInfo, nullptr, &instance_);
117 if (result == VK_ERROR_INCOMPATIBLE_DRIVER) {
118 isSupportedVulkan_ = false;
119 } else {
120 isSupportedVulkan_ = true;
121 }
122 std::cout << "TrytoCreateVkInstance result: " << result << std::endl;
123 }
124
125 /**
126 * @tc.name: Load base Vulkan functions
127 * @tc.desc: Load base Vulkan functions
128 * @tc.type: FUNC
129 * @tc.require: issueI6SKRO
130 */
131 HWTEST_F(VulkanLoaderSystemTest, LoadBaseFuncPtr, TestSize.Level1)
132 {
133 DLOpenLibVulkan();
134 if (isSupportedVulkan_) {
135 EXPECT_NE(libVulkan_, nullptr);
136
137 // Load base functions
138 vkEnumerateInstanceExtensionProperties = reinterpret_cast<PFN_vkEnumerateInstanceExtensionProperties>(
139 dlsym(libVulkan_, "vkEnumerateInstanceExtensionProperties"));
140 EXPECT_NE(vkEnumerateInstanceExtensionProperties, nullptr);
141 vkEnumerateInstanceLayerProperties = reinterpret_cast<PFN_vkEnumerateInstanceLayerProperties>(
142 dlsym(libVulkan_, "vkEnumerateInstanceLayerProperties"));
143 EXPECT_NE(vkEnumerateInstanceLayerProperties, nullptr);
144 vkCreateInstance = reinterpret_cast<PFN_vkCreateInstance>(dlsym(libVulkan_, "vkCreateInstance"));
145 EXPECT_NE(vkCreateInstance, nullptr);
146 vkGetInstanceProcAddr = reinterpret_cast<PFN_vkGetInstanceProcAddr>(dlsym(libVulkan_, "vkGetInstanceProcAddr"));
147 EXPECT_NE(vkGetInstanceProcAddr, nullptr);
148 vkGetDeviceProcAddr = reinterpret_cast<PFN_vkGetDeviceProcAddr>(dlsym(libVulkan_, "vkGetDeviceProcAddr"));
149 EXPECT_NE(vkGetDeviceProcAddr, nullptr);
150 TrytoCreateVkInstance();
151 }
152 }
153
154 /**
155 * @tc.name: Load instance based Vulkan function pointers
156 * @tc.desc: Load instance based Vulkan function pointers
157 * @tc.type: FUNC
158 * @tc.require: issueI6SKRO
159 */
160 HWTEST_F(VulkanLoaderSystemTest, LoadInstanceFuncPtr, TestSize.Level1)
161 {
162 if (isSupportedVulkan_) {
163 vkEnumeratePhysicalDevices = reinterpret_cast<PFN_vkEnumeratePhysicalDevices>(
164 vkGetInstanceProcAddr(instance_, "vkEnumeratePhysicalDevices"));
165 EXPECT_NE(vkEnumeratePhysicalDevices, nullptr);
166 vkCreateDevice = reinterpret_cast<PFN_vkCreateDevice>(
167 vkGetInstanceProcAddr(instance_, "vkCreateDevice"));
168 EXPECT_NE(vkCreateDevice, nullptr);
169 vkCreateSurfaceOHOS = reinterpret_cast<PFN_vkCreateSurfaceOHOS>(
170 vkGetInstanceProcAddr(instance_, "vkCreateSurfaceOHOS"));
171 EXPECT_NE(vkCreateSurfaceOHOS, nullptr);
172 vkDestroySurfaceKHR = reinterpret_cast<PFN_vkDestroySurfaceKHR>(
173 vkGetInstanceProcAddr(instance_, "vkDestroySurfaceKHR"));
174 EXPECT_NE(vkDestroySurfaceKHR, nullptr);
175 fpGetPhysicalDeviceSurfaceSupportKHR = reinterpret_cast<PFN_vkGetPhysicalDeviceSurfaceSupportKHR>(
176 vkGetInstanceProcAddr(instance_, "vkGetPhysicalDeviceSurfaceSupportKHR"));
177 EXPECT_NE(fpGetPhysicalDeviceSurfaceSupportKHR, nullptr);
178 fpGetPhysicalDeviceSurfaceCapabilitiesKHR = reinterpret_cast<PFN_vkGetPhysicalDeviceSurfaceCapabilitiesKHR>(
179 vkGetInstanceProcAddr(instance_, "vkGetPhysicalDeviceSurfaceCapabilitiesKHR"));
180 EXPECT_NE(fpGetPhysicalDeviceSurfaceCapabilitiesKHR, nullptr);
181 fpGetPhysicalDeviceSurfaceFormatsKHR = reinterpret_cast<PFN_vkGetPhysicalDeviceSurfaceFormatsKHR>(
182 vkGetInstanceProcAddr(instance_, "vkGetPhysicalDeviceSurfaceFormatsKHR"));
183 EXPECT_NE(fpGetPhysicalDeviceSurfaceFormatsKHR, nullptr);
184 fpGetPhysicalDeviceSurfacePresentModesKHR = reinterpret_cast<PFN_vkGetPhysicalDeviceSurfacePresentModesKHR>(
185 vkGetInstanceProcAddr(instance_, "vkGetPhysicalDeviceSurfacePresentModesKHR"));
186 EXPECT_NE(fpGetPhysicalDeviceSurfacePresentModesKHR, nullptr);
187 }
188 }
189
190 /**
191 * @tc.name: create device
192 * @tc.desc: create device
193 * @tc.type: FUNC
194 * @tc.require: issueI6SKRO
195 */
196 HWTEST_F(VulkanLoaderSystemTest, createDevice_Test, TestSize.Level1)
197 {
198 if (isSupportedVulkan_) {
199 uint32_t gpuCount = 0;
200 VkResult err = vkEnumeratePhysicalDevices(instance_, &gpuCount, nullptr);
201 EXPECT_EQ(err, VK_SUCCESS);
202 EXPECT_NE(gpuCount, 0);
203 std::vector<VkPhysicalDevice> physicalDevices(gpuCount);
204 err = vkEnumeratePhysicalDevices(instance_, &gpuCount, physicalDevices.data());
205 EXPECT_EQ(err, VK_SUCCESS);
206 physicalDevice_ = physicalDevices[0];
207
208 std::vector<const char*> deviceExtensions;
209 deviceExtensions.push_back(VK_KHR_SWAPCHAIN_EXTENSION_NAME);
210 VkDeviceCreateInfo deviceCreateInfo = {};
211 deviceCreateInfo.enabledExtensionCount = (uint32_t)deviceExtensions.size();
212 deviceCreateInfo.ppEnabledExtensionNames = deviceExtensions.data();
213
214 VkDevice logicalDevice;
215 err = vkCreateDevice(physicalDevice_, &deviceCreateInfo, nullptr, &logicalDevice);
216 EXPECT_EQ(err, VK_SUCCESS);
217 EXPECT_NE(logicalDevice, nullptr);
218 device_ = logicalDevice;
219 }
220 }
221
222 /**
223 * @tc.name: Load device based Vulkan function pointers
224 * @tc.desc: Load device based Vulkan function pointers
225 * @tc.type: FUNC
226 * @tc.require: issueI6SKRO
227 */
228 HWTEST_F(VulkanLoaderSystemTest, LoadDeviceFuncPtr, TestSize.Level1)
229 {
230 if (isSupportedVulkan_) {
231 fpCreateSwapchainKHR = reinterpret_cast<PFN_vkCreateSwapchainKHR>(
232 vkGetDeviceProcAddr(device_, "vkCreateSwapchainKHR"));
233 EXPECT_NE(fpCreateSwapchainKHR, nullptr);
234 fpDestroySwapchainKHR = reinterpret_cast<PFN_vkDestroySwapchainKHR>(
235 vkGetDeviceProcAddr(device_, "vkDestroySwapchainKHR"));
236 EXPECT_NE(fpDestroySwapchainKHR, nullptr);
237 fpGetSwapchainImagesKHR = reinterpret_cast<PFN_vkGetSwapchainImagesKHR>(
238 vkGetDeviceProcAddr(device_, "vkGetSwapchainImagesKHR"));
239 EXPECT_NE(fpGetSwapchainImagesKHR, nullptr);
240 fpAcquireNextImageKHR = reinterpret_cast<PFN_vkAcquireNextImageKHR>(
241 vkGetDeviceProcAddr(device_, "vkAcquireNextImageKHR"));
242 EXPECT_NE(fpAcquireNextImageKHR, nullptr);
243 fpQueuePresentKHR = reinterpret_cast<PFN_vkQueuePresentKHR>(vkGetDeviceProcAddr(device_, "vkQueuePresentKHR"));
244 EXPECT_NE(fpQueuePresentKHR, nullptr);
245 }
246 }
247
248 /**
249 * @tc.name: create surface
250 * @tc.desc: create surface
251 * @tc.type: FUNC
252 * @tc.require: issueI6SKRO
253 */
254 HWTEST_F(VulkanLoaderSystemTest, createSurface_Test, TestSize.Level1)
255 {
256 if (isSupportedVulkan_) {
257 struct RSSurfaceNodeConfig rsSurfaceNodeConfig;
258 rsSurfaceNodeConfig.SurfaceNodeName = "createSurface_test";
259 auto surfaceNode = RSSurfaceNode::Create(rsSurfaceNodeConfig, RSSurfaceNodeType::DEFAULT);
260 OHOS::sptr<OHOS::Surface> surf = surfaceNode->GetSurface();
261 OHNativeWindow* nativeWindow = CreateNativeWindowFromSurface(&surf);
262 EXPECT_NE(nativeWindow, nullptr);
263 VkSurfaceCreateInfoOHOS surfaceCreateInfo = {};
264 surfaceCreateInfo.sType = VK_STRUCTURE_TYPE_SURFACE_CREATE_INFO_OHOS;
265 surfaceCreateInfo.window = nativeWindow;
266 VkResult err = vkCreateSurfaceOHOS(instance_, &surfaceCreateInfo, NULL, &surface_);
267 EXPECT_EQ(err, VK_SUCCESS);
268 EXPECT_NE(surface_, VK_NULL_HANDLE);
269 }
270 }
271
272 /**
273 * @tc.name: create swapChain
274 * @tc.desc: create swapChain
275 * @tc.type: FUNC
276 * @tc.require: issueI6SKRO
277 */
278 HWTEST_F(VulkanLoaderSystemTest, createSwapChain_Test, TestSize.Level1)
279 {
280 if (isSupportedVulkan_) {
281 VkSwapchainKHR oldSwapchain = swapChain_;
282 VkSwapchainCreateInfoKHR swapchainCI = {};
283 swapchainCI.sType = VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR;
284 swapchainCI.surface = surface_;
285 VkSurfaceCapabilitiesKHR surfCaps;
286 VkResult err = fpGetPhysicalDeviceSurfaceCapabilitiesKHR(physicalDevice_, surface_, &surfCaps);
287 EXPECT_EQ(err, VK_SUCCESS);
288 uint32_t desiredNumberOfSwapchainImages = surfCaps.minImageCount + 1;
289 swapchainCI.minImageCount = desiredNumberOfSwapchainImages;
290 swapchainCI.imageFormat = VK_FORMAT_B8G8R8A8_UNORM;
291 uint32_t formatCount;
292 err = fpGetPhysicalDeviceSurfaceFormatsKHR(physicalDevice_, surface_, &formatCount, NULL);
293 EXPECT_EQ(err, VK_SUCCESS);
294 EXPECT_GT(formatCount, 0);
295 std::vector<VkSurfaceFormatKHR> surfaceFormats(formatCount);
296 err = fpGetPhysicalDeviceSurfaceFormatsKHR(physicalDevice_, surface_, &formatCount, surfaceFormats.data());
297 EXPECT_EQ(err, VK_SUCCESS);
298 swapchainCI.imageColorSpace = surfaceFormats[0].colorSpace;
299 uint32_t width = 1280;
300 uint32_t height = 720;
301 swapchainCI.imageExtent = { width, height };
302 swapchainCI.imageUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
303 swapchainCI.preTransform = (VkSurfaceTransformFlagBitsKHR)VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR;
304 swapchainCI.imageArrayLayers = 1;
305 swapchainCI.imageSharingMode = VK_SHARING_MODE_EXCLUSIVE;
306 swapchainCI.queueFamilyIndexCount = 0;
307 swapchainCI.presentMode = VK_PRESENT_MODE_MAILBOX_KHR;
308 swapchainCI.oldSwapchain = oldSwapchain;
309 swapchainCI.clipped = VK_TRUE;
310 swapchainCI.compositeAlpha = VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR;
311
312 err = fpCreateSwapchainKHR(device_, &swapchainCI, nullptr, &swapChain_);
313 EXPECT_EQ(err, VK_SUCCESS);
314 EXPECT_NE(swapChain_, VK_NULL_HANDLE);
315 }
316 }
317 }