使用NvPipe编码桌面复制API ID3D11Texture2D框架

时间:2019-05-30 10:06:47

标签: c++ encoding nvidia desktop-duplication

我正在尝试使用桌面复制API捕获桌面框架,并立即使用NvPipe对其进行编码,而无需通过CPU访问像素。

是否有任何方法可以将ID3D11Texture2D数据作为NvPipe的输入,或采取其他一些有效的方法?我正在开发一种VR解决方案,该解决方案需要尽可能低的延迟,因此即使节省1毫秒也很重要。

编辑:在遵循@Soonts的建议之后,我最终得到了似乎无效的代码:

    cudaArray *array;
    m_DeviceContext->CopySubresourceRegion(CopyBuffer, 0, 0, 0, 0, m_SharedSurf, 0, Box);
    cudaError_t err = cudaGraphicsD3D11RegisterResource(&_cudaResource, CopyBuffer, cudaGraphicsRegisterFlagsNone);
    err = cudaGraphicsResourceSetMapFlags(_cudaResource, cudaGraphicsMapFlagsReadOnly);
    cudaStream_t cuda_stream;
    cudaStreamCreate(&cuda_stream);
    err = cudaGraphicsMapResources(1, &_cudaResource, cuda_stream);
    err = cudaGraphicsSubResourceGetMappedArray(&array, _cudaResource, 0, 0);
    uint64_t compressedSize = NvPipe_Encode(encoder, array, dataPitch, buffer.data(), buffer.size(), width, height, false);

NvPipe_Encode导致内存访问冲突,并且不执行任何操作。我不知道我要搞错哪一步,因为我似乎无法在线找到有关任何函数或变量/结构的任何文档,并且对变量进行监视不会显示有价值的信息,除了它们在内存中的地址。

1 个答案:

答案 0 :(得分:1)

我没有尝试过,但我认为应该可以与CUDA互操作。

调用cudaGraphicsD3D11RegisterResource为CUDA互操作注册纹理。不确定是否可以注册从DD获得的DWM拥有的纹理。如果不能,请再创建一个(在默认池中),注册该一个,然后使用ID3D11DeviceContext :: CopyResource更新每个帧。

调用cudaGraphicsResourceSetMapFlags,以指定要从互操作的CUDA一侧进行只读访问。

调用cudaGraphicsMapResources以允许CUDA访问纹理。

致电cudaGraphicsSubResourceGetMappedArray。现在,您有了一个设备指针,其中包含可以提供给NvPipe的帧数据。

P.S。另一种选择是使用媒体基础而不是NvPipe。 MF不仅可以在nVidia上支持所有GPU,而且在大多数系统上也可以使用硬件编码器。我不确定延迟,从不使用MF对它太敏感,也从不使用NvPipe,不知道它们如何比较。