vulkan-guidelines.md 4.6 KB
Newer Older
S
shegangbin 已提交
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
# Vulkan开发指导

## 场景介绍

Vulkan是一套用来做2D和3D渲染的图形应用程序接口,其中创建VkSurfaceKHR对象是一个非常关键的步骤,在OpenHarmony中,VkSurfaceKHR会对接到OHNativeWindow模块功能,实现Buffer轮转。

在OpenHarmony中,需要通过OHNativeWindow来创建VkSurfaceKHR对象,而OHNativeWindow需要从XComponent中获取,所以此场景下需要配合XComponent模块和NativeWindow模块一起使用。

## 接口说明

| 接口名 | 描述 | 
| -------- | -------- |
| vkCreateSurfaceOHOS (VkInstance instance, const VkSurfaceCreateInfoOHOS\* pCreateInfo, const VkAllocationCallbacks\* pAllocator, VkSurfaceKHR\* pSurface) | 创建VkSurfaceKHR对象。 | 

更多的接口说明请参考[Vulkan](../reference/native-lib/third_party_vulkan/vulkan-symbol.md)

## 开发步骤

以下步骤说明了如何在OpenHarmony平台创建一个VkSurfaceKHR对象。

**头文件**
```c++
#include <ace/xcomponent/native_interface_xcomponent.h>
#include <native_window/external_window.h>
#include <vulkan/vulkan.h>
```

1. **首先需要创建一个Vulkan实例**
    ```c++
    VkInstance instance = VK_NULL_HANDLE;

S
shegangbin 已提交
32 33 34 35 36
    VkApplicationInfo appInfo = {};
    appInfo.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO;
    appInfo.pApplicationName = "vulkanExample";
    appInfo.pEngineName = "vulkanExample";
    appInfo.apiVersion = VK_API_VERSION_1_3;
S
shegangbin 已提交
37
    
S
shegangbin 已提交
38 39 40 41
    VkInstanceCreateInfo instanceCreateInfo = {};
    instanceCreateInfo.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO;
    instanceCreateInfo.pNext = NULL;
    instanceCreateInfo.pApplicationInfo = &appInfo;
S
shegangbin 已提交
42

S
shegangbin 已提交
43
    std::vector<const char*> instanceExtensions = {
S
shegangbin 已提交
44
        VK_KHR_SURFACE_EXTENSION_NAME,
S
shegangbin 已提交
45
        VK_OHOS_SURFACE_EXTENSION_NAME // OpenHarmony平台的Surface扩展
S
shegangbin 已提交
46
    };
S
shegangbin 已提交
47
    instanceCreateInfo.enabledExtensionCount = static_cast<uint32_t>(instanceExtensions.size());
S
shegangbin 已提交
48 49 50 51 52 53
    instanceCreateInfo.ppEnabledExtensionNames = instanceExtensions.data();

    vkCreateInstance(&instanceCreateInfo, nullptr, &instance);
    ```

2. **获取OHNativeWindow**
S
shegangbin 已提交
54
    OHNativeWindow需要从XComponent组件中获取,下面提供一份从XComponent组件中获取OHNativeWindow的代码示例,XComponent模块的具体使用方法请参考[XComponent模块的介绍文档](../ui/arkts-common-components-xcomponent.md)[XComponent开发指导](xcomponent-guidelines.md)
S
shegangbin 已提交
55 56 57 58 59 60 61
    1. ets/pages/Index.ets中增加一个XComponent组件
    ```ts
    XComponent({
        id: 'xcomponentId',
        type: 'surface',
        libraryname: 'entry'
    })
S
shegangbin 已提交
62 63 64
    .margin({ bottom: 20 })
    .width(360)
    .height(360)
S
shegangbin 已提交
65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102
    ```
    2. 从XComponent组件中获取OHNativeWindow
    ```c++
    // XComponent在创建Suface时的回调函数
    void OnSurfaceCreatedCB(OH_NativeXComponent *component, void *window) {
        // 在回调函数里可以拿到OHNativeWindow
        OHNativeWindow* nativeWindow = static_cast<OHNativeWindow*>(window);
    }

    EXTERN_C_START
    static napi_value Init(napi_env env, napi_value exports)
    {
        napi_property_descriptor desc[] = {
            { "add", nullptr, Add, nullptr, nullptr, nullptr, napi_default, nullptr }
        };
        napi_define_properties(env, exports, sizeof(desc) / sizeof(desc[0]), desc);

        // 声明一个XComponent的Callback
        OH_NativeXComponent_Callback callback;
        // 注册OnSurfaceCreated回调函数
        callback.OnSurfaceCreated = OnSurfaceCreatedCB;
        
        char idStr[OH_XCOMPONENT_ID_LEN_MAX + 1] = {};
        uint64_t idSize = OH_XCOMPONENT_ID_LEN_MAX + 1;
        napi_value exportInstance = nullptr;
        OH_NativeXComponent *nativeXComponent = nullptr;
        // 获取nativeXComponent
        napi_get_named_property(env, exports, OH_NATIVE_XCOMPONENT_OBJ, &exportInstance);
        napi_unwrap(env, exportInstance, reinterpret_cast<void **>(&nativeXComponent));
        // 将callback注册给nativeXComponent
        OH_NativeXComponent_RegisterCallback(nativeXComponent, &callback);
        
        return exports;
    }
    ```

3. **创建VkSurfaceKHR对象**
    ```c++
S
shegangbin 已提交
103 104 105 106 107 108 109 110
    VkSurfaceKHR surface = VK_NULL_HANDLE;
    VkSurfaceCreateInfoOHOS surfaceCreateInfo = {};
    surfaceCreateInfo.sType = VK_STRUCTURE_TYPE_SURFACE_CREATE_INFO_OHOS;
    surfaceCreateInfo.window = nativeWindow; // 这里的nativeWindow就是从上一步骤OnSurfaceCreatedCB回调函数中拿到的
    int err = vkCreateSurfaceOHOS(instance, &surfaceCreateInfo, NULL, &surface);
    if (err != VK_SUCCESS) {
        std::cout << "Could not create surface!" << std::endl;
    }
S
shegangbin 已提交
111 112
    ```
后续更多vulkan的用法请参考[Vulkan官方网站](https://www.vulkan.org/)