与另一个单独的进程共享来自交换链后台缓冲区的 direct3d11 渲染帧作为纹理

Posted

技术标签:

【中文标题】与另一个单独的进程共享来自交换链后台缓冲区的 direct3d11 渲染帧作为纹理【英文标题】:Share direct3d11 rendered frame from swapchain backbuffer as texture with another separate process 【发布时间】:2021-12-30 18:01:48 【问题描述】:

所以我会详细说明标题

我想要完成的是在一个进程中完成所有计算和渲染,然后从另一个进程中读取结果帧(在所有计算完成后,我将在出现之前使用交换链后台缓冲区)并将其显示在显示器上。基本上我想在两个单独的进程之间共享视频内存(不是整个屏幕,只是应用程序窗口)。

我正在使用带有 DirectXTK 的 direct3d11。我的笔记本电脑有 NVIDIA gpu 和 intel UHD 620 graphics 。 以管理员权限打开了 Visual Studio。

这是我尝试创建缓冲区共享句柄的代码

    auto swapChain = m_deviceResources->GetSwapChain();

    /*ComPtr< ID3D11Resource> backbuffer;*/
    /*swapChain->GetBuffer(0, __uuidof(ID3D11Resource),
    (void **) backbuffer.GetAddressOf());*/

    swapChain->GetBuffer(0, __uuidof(ID3D11Texture2D),(void **)tex_shared.GetAddressOf());

    D3D11_TEXTURE2D_DESC tex_2d_desc;
    tex_shared->GetDesc(&tex_2d_desc);
    tex_2d_desc.MiscFlags = D3D11_RESOURCE_MISC_SHARED_KEYEDMUTEX | D3D11_RESOURCE_MISC_SHARED_NTHANDLE;
    tex_2d_desc.CPUAccessFlags = D3D11_CPU_ACCESS_READ | D3D11_CPU_ACCESS_WRITE;

    HANDLE sharedhandle=nullptr;
    IDXGIResource1* pOtherResource=nullptr;
    tex_shared->QueryInterface(__uuidof(IDXGIResource1), (void**)&pOtherResource);

    SECURITY_ATTRIBUTES sa;
    sa.bInheritHandle = FALSE;
    sa.nLength = sizeof(SECURITY_ATTRIBUTES);
    sa.lpSecurityDescriptor = NULL;

    pOtherResource->CreateSharedHandle(&sa,GENERIC_ALL,L"SharedTexture" ,&sharedhandle);

我尝试从另一个进程中使用此代码检索句柄

  ComPtr<IDXGIResource1> p_tex_shared;
  device->OpenSharedResourceByName(L"SharedTexture", 
    DXGI_SHARED_RESOURCE_READ ,
    __uuidof(IDXGIResource1), 
    (void**)p_tex_shared.GetAddressOf());

但我得到了这个错误

Exception thrown at 0x00007FF84751466C in SimpleTrianglePC.exe: Microsoft C++ exception: _com_error at memory location 0x000000139CEFF248.
D3D11 ERROR: ID3D11Device::OpenSharedResourceByName: Returning E_INVALIDARG, meaning 
invalid parameters were passed. [ STATE_CREATION ERROR #381: 
DEVICE_OPEN_SHARED_RESOURCE_INVALIDARG_RETURN]
D3D11: **BREAK** enabled for the previous message, which was: [ ERROR STATE_CREATION 
Exception thrown at 0x00007FF84751466C (KernelBase.dll) in SimpleTrianglePC.exe: 
0x0000087A (parameters: 0x0000000000000001, 0x000000139CEFC500, 0x000000139CEFE2D0).
Unhandled exception at 0x00007FF84751466C (KernelBase.dll) in SimpleTrianglePC.exe: 
0x0000087A (parameters: 0x0000000000000001, 0x000000139CEFC500, 0x000000139CEFE2D0).

我也尝试使用 OpenSharedResource1 而不是 OpenSharedResourceByName,但给出了同样的错误。

【问题讨论】:

您是否尝试为 CreateSharedHandle 的第一个参数 (sa) 和 DXGI_SHARED_RESOURCE_READ 而不是 GENERIC_ALL 传递 null 而不是某些东西? @SimonMourier 我刚刚尝试过,但报同样的错误。 【参考方案1】:

您无法修改 DXGI 交换链拥有的纹理表面来添加共享标志,就像您在上面尝试做的那样。您最好的选择是将后备缓冲区复制到可共享的纹理中。

    使用与交换链后台缓冲区相同的大小和格式创建可共享纹理。 获取 DXGI 后缓冲纹理 使用ID3D11DeviceContext::CopyResource 将上下文从后台缓冲区复制到每帧的可共享纹理。

见Microsoft Docs

【讨论】:

感谢@Chuck Walbourn。如何完成将后台缓冲区复制到可共享纹理。

以上是关于与另一个单独的进程共享来自交换链后台缓冲区的 direct3d11 渲染帧作为纹理的主要内容,如果未能解决你的问题,请参考以下文章

与另一个进程共享复杂对象

在 MPI 进程之间交换数据(晕)

如何在两个进程之间共享数据?

linux c编程:管道

linux进程间通信之管道

进程间通信之管道(pipefifo)