我正在尝试使用桌面复制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导致内存访问冲突,并且不执行任何操作。我不知道我要搞错哪一步,因为我似乎无法在线找到有关任何函数或变量/结构的任何文档,并且对变量进行监视不会显示有价值的信息,除了它们在内存中的地址。
答案 0 :(得分:1)
我没有尝试过,但我认为应该可以与CUDA互操作。
调用cudaGraphicsD3D11RegisterResource
为CUDA互操作注册纹理。不确定是否可以注册从DD获得的DWM拥有的纹理。如果不能,请再创建一个(在默认池中),注册该一个,然后使用ID3D11DeviceContext :: CopyResource更新每个帧。
调用cudaGraphicsResourceSetMapFlags
,以指定要从互操作的CUDA一侧进行只读访问。
调用cudaGraphicsMapResources
以允许CUDA访问纹理。
致电cudaGraphicsSubResourceGetMappedArray
。现在,您有了一个设备指针,其中包含可以提供给NvPipe的帧数据。
P.S。另一种选择是使用媒体基础而不是NvPipe。 MF不仅可以在nVidia上支持所有GPU,而且在大多数系统上也可以使用硬件编码器。我不确定延迟,从不使用MF对它太敏感,也从不使用NvPipe,不知道它们如何比较。