Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

关于UE Vulkan渲染管线的数据 传给 MNN Vulkan后端做推理? #3134

Open
Sodiride123 opened this issue Dec 21, 2024 · 6 comments
Open
Labels
User The user ask question about how to use. Or don't use MNN correctly and cause bug.

Comments

@Sodiride123
Copy link

您好,
我当前在UE里面用Vulkan做了一个渲染管线,现在想把每一帧的数据传给MNN做推理,我现在可以拿到UE侧VkBuffer相关数据,请问下如何正确的让MNN Vulkan后端 接收 将UE侧的数据。目前我理解的流程是:

  1. 在创建session的时候,我用的是UE渲染管线的那套Vulkan上下文,确保推理和渲染都在同一个vulkan实例里面。
  2. 从session拿到inputTensor。
  3. (问题在这一步)我的理解是拿到并且强转inputTensor里的deviceId()类型,例如MNN::VulkanBuffer* handle = (MNN::VulkanBuffer*)(inputTensor->deviceId()), 有点不太懂这一步之后怎么把UE那边的数据传进来?
@jxt1234
Copy link
Collaborator

jxt1234 commented Dec 22, 2024

基于 vulkan buffer (-DMNN_VULKAN_IMAGE=false)模式的话是支持传输的。需要加载如下头文件:

#define MNN_VULKAN
#include <MNN/MNNSharedContext.h>
  1. 创建 MNN Module 或 Session 时传入 DeviceContext :
        MNN::ScheduleConfig config;
        MNN::BackendConfig bnConfig;
        MNNVulkanContext mShareContext;
        mShareContext.iQueueFamilyIndex = mDevice->queueFamilyIndex();
        mShareContext.pDevice = mDevice->get();
        mShareContext.pInstance = mInstance->get();
        mShareContext.pPhysicalDevice = mDevice->physicalDevice();
        mShareContext.pQueue = mDevice->queue();
        bnConfig.sharedContext = &mShareContext;
        config.backendConfig = &bnConfig;
        /*创建 session 或者 module */
  1. 获取 vulkan 内存,然后用 vulkan 的API复制数据过去,或者直接使用输出的数据
MNNVulkanTensorContent dst;
tensor->getDeviceInfo(&dst, MNN_FORWARD_VULKAN);

3.同步(获取的Vulkan内存有可能并没有计算完成,此时需要先同步 )

tensor->wait

@jxt1234 jxt1234 added the User The user ask question about how to use. Or don't use MNN correctly and cause bug. label Dec 22, 2024
@Sodiride123
Copy link
Author

多谢回复,这里还有几个小问题想请教:

  1. 目前如果想在渲染管线和推理之间传输数据(都在GPU上),是不是基于VkBuffer的类型会更方便一点?
  2. 我看您回复的第2步里面,应该是用getDeviceInfo把InputTensor相关的Vulkan资源填充到了MNNVulkanTensorContent结构体里面是吧,后面我就可以用vkCmdCopyBuffer()把渲染管线那边的VkBuffer拷贝到MNN这边对吧?或者是不是可以把dst里面的句柄直接指向渲染管线的Vk数据,省略拷贝?
  3. 推理之后,我用auto outputTensor = net->getSessionOutput(session, NULL)得到输出数据,是不是也是需要用您在第2步的方法,反向操作一下,把VkBuffer传回渲染管线?

@jxt1234
Copy link
Collaborator

jxt1234 commented Dec 24, 2024

  1. 是的;
  2. 可以用 CopyBuffer ,也可以直接指向。不过需要用 barrier 或者调 tensor->wait() 保证同步。
  3. 是的

@Sodiride123
Copy link
Author

感谢答复,
有一个GPU内数据拷贝的问题想请教下,我现在UE渲染管线那边的图像API用的是Vulkan,MNN这边的后端也是Vulkan,那么自然是用类似vkCmdCopyBuffer的接口进行GPU上的数据拷贝。 我在想一旦我将MNN推理这边的后端更换成不和渲染那边一致,比如OpenCL或者Cuda,那么渲染与推理之间的数据传输和同步的工作量就会变得很大,因为涉及到跨API之间的适配和互操作。

有没有那种针对GPU上的比较通用的拷贝接口,类似copy_n或者memcpy这种;就哪怕我渲染和推理使用的后端不一样,还是能直接在GPU上进行直接的数据拷贝。还是说当前如果想在GPU内实现memory的拷贝,只能是通过特殊的 API(比如 CUDA、Vulkan、OpenCL)来管理?

@jxt1234
Copy link
Collaborator

jxt1234 commented Jan 3, 2025

  1. 这个是没有的,和操作系统及API相关,Android 可以用 HardwardBuffer 。
  2. 可以用 mnn 的 tensor->map / unmap ,在后端支持的情况下会使用共享内存,不过不能保持免拷贝。

@Sodiride123
Copy link
Author

您好我遇到一个问题,就是我在把inputTensor里的Vk资源直接指向渲染管线的Vk数据之后推理的问题:
MNN::Tensor* inputTensor = interpreter->getSessionInput(session, nullptr);
MNN::Tensor* outputTensor = interpreter->getSessionOutput(session, nullptr);
此时的inputTensor 对应的Vulkan句柄为000005B6AB7C0DD0,outputTensor 为000005B6AB7C16D0。

当我把inputTensor 对应的vkbuffer,offset和size改成指向UE渲染的当前帧的相关Vulkan资源,然后查看inputTensor(此时是更改过后的句柄),当前帧数据确实成功地得到了。但是运行interpreter->runSession(session)之后我发现,推理框架还是再拿inputTensor 一开始的句柄(000005B6AB7C0DD0)对应的资源做推理,并没有用更改过后的inputTensor做推理。

目前发现interpreter->runSession(session)这里他只会认 创建inputTensor 时的最初对应的句柄,怎么能彻底更改呢?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
User The user ask question about how to use. Or don't use MNN correctly and cause bug.
Projects
None yet
Development

No branches or pull requests

2 participants