1# Vulkan开发指导 2 3<!--Kit: ArkGraphics 2D--> 4<!--Subsystem: Graphic--> 5<!--Owner: @andrew1993--> 6<!--Designer: @ext4FAT1--> 7<!--Tester: @nobuggers--> 8<!--Adviser: @ge-yafang--> 9 10## 场景介绍 11 12Vulkan是一套用来做2D和3D渲染的图形应用程序接口,其中创建VkSurfaceKHR对象是一个非常关键的步骤,在OpenHarmony中,VkSurfaceKHR会对接到OHNativeWindow模块功能,实现Buffer轮转。 13 14在OpenHarmony中,需要通过OHNativeWindow来创建VkSurfaceKHR对象,而OHNativeWindow需要从XComponent中获取,所以此场景下需要配合XComponent模块和NativeWindow模块一起使用。 15 16## 接口说明 17 18| 接口名 | 描述 | 19| ------------------------------------------------------------ | ---------------------- | 20| vkCreateSurfaceOHOS (VkInstance instance, const VkSurfaceCreateInfoOHOS\* pCreateInfo, const VkAllocationCallbacks\* pAllocator, VkSurfaceKHR\* pSurface) | 创建VkSurfaceKHR对象。 | 21 22更多的接口说明请参考[Vulkan](vulkan.md)。 23 24## 开发步骤 25 26以下步骤说明了如何创建一个VkSurfaceKHR对象。 27 28首先,使用平台扩展的接口,需要定义一个宏`VK_USE_PLATFORM_OHOS`,我们在CMakeLists.txt定义这个宏。 29 30```txt 31ADD_DEFINITIONS(-DVK_USE_PLATFORM_OHOS=1) 32``` 33 34**添加动态链接库** 35 36CMakeLists.txt中添加以下lib。 37 38```txt 39libace_ndk.z.so 40libnative_window.so 41libvulkan.so 42``` 43 44> **说明:** 45> 46> 在程序中通过dlopen函数链接libvulkan.so动态库时不需要在CMake中增加依赖,否则会导致符号冲突。 47 48**头文件** 49 50```c++ 51#include <ace/xcomponent/native_interface_xcomponent.h> 52#include <native_window/external_window.h> 53#include <vulkan/vulkan.h> 54``` 55 561. **首先需要创建一个Vulkan实例**。 57 58 ```c++ 59 VkInstance instance = VK_NULL_HANDLE; 60 61 VkApplicationInfo appInfo = {}; 62 appInfo.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO; 63 appInfo.pApplicationName = "vulkanExample"; 64 appInfo.pEngineName = "vulkanExample"; 65 appInfo.apiVersion = VK_API_VERSION_1_3; 66 67 VkInstanceCreateInfo instanceCreateInfo = {}; 68 instanceCreateInfo.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO; 69 instanceCreateInfo.pNext = NULL; 70 instanceCreateInfo.pApplicationInfo = &appInfo; 71 72 std::vector<const char *> instanceExtensions = { 73 VK_KHR_SURFACE_EXTENSION_NAME, 74 VK_OHOS_SURFACE_EXTENSION_NAME // Surface扩展 75 }; 76 instanceCreateInfo.enabledExtensionCount = static_cast<uint32_t>(instanceExtensions.size()); 77 instanceCreateInfo.ppEnabledExtensionNames = instanceExtensions.data(); 78 79 vkCreateInstance(&instanceCreateInfo, nullptr, &instance); 80 ``` 81 822. **获取OHNativeWindow**。 83 84 OHNativeWindow需要从XComponent组件中获取,下面提供一份从XComponent组件中获取OHNativeWindow的代码示例,XComponent模块的具体使用方法请参考[XComponent模块的介绍文档](../../ui/napi-xcomponent-guidelines.md)。 85 86 1. ets/pages/Index.ets中增加一个XComponent组件。 87 88 ```ts 89 XComponent({ 90 id: 'xcomponentId', 91 type: 'surface', 92 libraryname: 'entry' 93 }) 94 .margin({ bottom: 20 }) 95 .width(360) 96 .height(360) 97 ``` 98 99 2. 从XComponent组件中获取OHNativeWindow。 100 101 ```c++ 102 // XComponent在创建Suface时的回调函数 103 void OnSurfaceCreatedCB(OH_NativeXComponent *component, void *window) { 104 // 在回调函数里可以拿到OHNativeWindow 105 OHNativeWindow *nativeWindow = static_cast<OHNativeWindow *>(window); 106 } 107 108 static napi_value Init(napi_env env, napi_value exports) { 109 napi_property_descriptor desc[] = {{"add", nullptr, Add, nullptr, nullptr, nullptr, napi_default, nullptr}}; 110 napi_define_properties(env, exports, sizeof(desc) / sizeof(desc[0]), desc); 111 112 napi_value exportInstance = nullptr; 113 OH_NativeXComponent *nativeXComponent = nullptr; 114 // 获取nativeXComponent 115 napi_get_named_property(env, exports, OH_NATIVE_XCOMPONENT_OBJ, &exportInstance); 116 napi_unwrap(env, exportInstance, reinterpret_cast<void **>(&nativeXComponent)); 117 // 获取XComponentId 118 char idStr[OH_XCOMPONENT_ID_LEN_MAX + 1] = {}; 119 uint64_t idSize = OH_XCOMPONENT_ID_LEN_MAX + 1; 120 OH_NativeXComponent_GetXComponentId(nativeXComponent, idStr, &idSize); 121 122 // 声明一个XComponent的Callback 123 OH_NativeXComponent_Callback callback; 124 // 注册OnSurfaceCreated回调函数 125 callback.OnSurfaceCreated = OnSurfaceCreatedCB; 126 // 将callback注册给nativeXComponent 127 OH_NativeXComponent_RegisterCallback(nativeXComponent, &callback); 128 129 return exports; 130 } 131 ``` 132 1333. **创建VkSurfaceKHR对象**。 134 135 ```c++ 136 VkSurfaceKHR surface = VK_NULL_HANDLE; 137 VkSurfaceCreateInfoOHOS surfaceCreateInfo = {}; 138 surfaceCreateInfo.sType = VK_STRUCTURE_TYPE_SURFACE_CREATE_INFO_OHOS; 139 surfaceCreateInfo.window = nativeWindow; // 这里的nativeWindow就是从上一步骤OnSurfaceCreatedCB回调函数中拿到的 140 int err = vkCreateSurfaceOHOS(instance, &surfaceCreateInfo, NULL, &surface); 141 if (err != VK_SUCCESS) { 142 // Create Surface Failed. 143 } 144 ``` 145 146## 相关实例 147 148针对Vulkan的使用,具体可见以下相关实例: 149 150- [XComponent组件对接Vulkan(API11)](https://gitcode.com/openharmony/applications_app_samples/tree/master/code/BasicFeature/Native/NdkVulkan) 151 152后续更多vulkan的用法请参考[Vulkan官方网站](https://www.vulkan.org/)。