同一进程内跨线程传递ID3D11Texture2D是否需要CreateSharedHandle?
嘿,这个问题我太熟了——结论很明确:完全不需要用CreateSharedHandle,这个API是给跨进程共享资源准备的,对你这种同一进程、多线程各持同一适配器设备的场景来说根本用不上。
具体该怎么做?
创建纹理时加个共享标志
你在第一个线程的设备上创建ID3D11Texture2D的时候,记得在D3D11_TEXTURE2D_DESC的MiscFlags里加上D3D11_RESOURCE_MISC_SHARED。这个标志就是告诉D3D11:“嘿,这个资源要给同一适配器上的其他设备用哈”。给你个代码片段参考:
D3D11_TEXTURE2D_DESC texDesc = {}; // 先把宽度、高度、格式这些必要参数填好 texDesc.MiscFlags = D3D11_RESOURCE_MISC_SHARED; // 这行是关键 ID3D11Texture2D* pTexture = nullptr; hr = pDevice1->CreateTexture2D(&texDesc, nullptr, &pTexture);其他线程的设备直接打开共享资源
纹理创建好之后,其他线程的设备不用绕弯子,直接调用ID3D11Device::OpenSharedResource就能拿到这个纹理在当前设备下可用的接口。全程不需要CreateSharedHandle,毕竟同一进程里内存空间本来就是共享的,D3D11已经帮你搞定了轻量的内部共享机制。示例代码:
ID3D11Texture2D* pSharedTexture = nullptr; hr = pDevice2->OpenSharedResource(pTexture, __uuidof(ID3D11Texture2D), (void**)&pSharedTexture);同步工作千万别忘!
不管是不是跨设备,跨线程访问D3D11资源一定要做好同步。比如用ID3D11Fence(D3D11.1及以上版本支持)、临界区或者事件对象,确保一个线程在读写资源的时候,另一个线程不会凑过来捣乱,不然很容易出现资源状态冲突或者数据损坏的问题。
再啰嗦一句为啥不用CreateSharedHandle?
CreateSharedHandle的核心作用是生成一个操作系统级别的句柄,让资源能在不同进程之间传递访问。而你这是同一进程内的操作,内存空间本来就是通的,D3D11提供的同一适配器多设备共享机制已经足够高效,完全没必要多此一举去生成跨进程句柄。
内容的提问来源于stack exchange,提问作者Dean

