22
33bool VCD3D11Manager::Init () {
44 this ->ISys ()
5- .SubscribeSync (" Hook/Present/Fisrt" , [this ](MulNX::Message& msg) {this ->OnPresentFirst (msg);});
6-
5+ .SubscribeSync (" Hook/Present/Fisrt" , [this ](MulNX::Message& msg) {this ->OnPresentFirst (msg);})
6+ . SubscribeSync ( " Hook/BeforePresent " , [ this ](MulNX::Message& msg) { this -> CopyTexture ();});
77 return true ;
88}
99
1010void VCD3D11Manager::OnPresentFirst (MulNX::Message& msg) {
1111 // 1. 创建我们的 D3D11 设备(与原设备同一级别)
12- D3D_FEATURE_LEVEL originalLevel = pGraphicsManager->pd3dDevice ->GetFeatureLevel ();
13- D3D11CreateDevice (
14- pGraphicsManager->D3D11Cfg .pAdapter ,
15- pGraphicsManager->D3D11Cfg .DriverType ,
16- pGraphicsManager->D3D11Cfg .Software ,
17- pGraphicsManager->D3D11Cfg .Flags ,
12+ D3D_FEATURE_LEVEL originalLevel = this -> pGraphicsManager ->pd3dDevice ->GetFeatureLevel ();
13+ HRESULT hr = D3D11CreateDevice (
14+ this -> pGraphicsManager ->D3D11Cfg .pAdapter ,
15+ this -> pGraphicsManager ->D3D11Cfg .DriverType ,
16+ this -> pGraphicsManager ->D3D11Cfg .Software ,
17+ this -> pGraphicsManager ->D3D11Cfg .Flags ,
1818 &originalLevel, 1 ,
19- pGraphicsManager->D3D11Cfg .SDKVersion ,
20- &this -> pDevice , nullptr , &this -> pContext
19+ this -> pGraphicsManager ->D3D11Cfg .SDKVersion ,
20+ &pDevice, nullptr , &pContext
2121 );
22+ if (FAILED (hr)) {
23+ this ->ISys ().LogError (" 捕获用D3D11设备创建失败" );
24+ return ;
25+ }
26+ this ->ISys ().LogSucc (" 捕获用D3D11设备创建成功" );
2227
2328 // 2. 获取原设备后台缓冲区描述(只需尺寸/格式,不持有资源)
24- ID3D11DeviceContext* origCtx = pGraphicsManager->pd3dContext ;
25- ID3D11RenderTargetView* pRTV = nullptr ;
26- origCtx->OMGetRenderTargets (1 , &pRTV, nullptr );
27- if (!pRTV) return ;
29+ ComPtr<ID3D11RenderTargetView> pRTV;
30+ this ->pGraphicsManager ->pd3dContext ->OMGetRenderTargets (1 , pRTV.GetAddressOf (), nullptr );
31+ if (!pRTV) {
32+ this ->ISys ().LogError (" 无法获取原设备渲染目标" );
33+ return ;
34+ }
2835
29- ID3D11Resource* pBBRes = nullptr ;
36+ ComPtr< ID3D11Resource> pBBRes;
3037 pRTV->GetResource (&pBBRes);
31- pRTV->Release ();
38+ if (!pBBRes) {
39+ this ->ISys ().LogError (" 无法获取后台缓冲区资源" );
40+ return ;
41+ }
3242
3343 D3D11_TEXTURE2D_DESC bbDesc;
34- static_cast <ID3D11Texture2D*>(pBBRes)->GetDesc (&bbDesc);
35- pBBRes->Release ();
44+ static_cast <ID3D11Texture2D*>(pBBRes.Get ())->GetDesc (&bbDesc);
3645
3746 // 3. 在原设备上创建共享纹理(格式/尺寸与后台缓冲一致)
3847 D3D11_TEXTURE2D_DESC sharedDesc = bbDesc;
3948 sharedDesc.MipLevels = 1 ;
4049 sharedDesc.ArraySize = 1 ;
41- sharedDesc.MiscFlags = D3D11_RESOURCE_MISC_SHARED ; // 关键
42- sharedDesc.BindFlags = D3D11_BIND_SHADER_RESOURCE ; // 或按需
50+ sharedDesc.MiscFlags = D3D11_RESOURCE_MISC_SHARED_KEYEDMUTEX ;
51+ sharedDesc.BindFlags = D3D11_BIND_SHADER_RESOURCE ;
4352 sharedDesc.CPUAccessFlags = 0 ;
4453 sharedDesc.Usage = D3D11_USAGE_DEFAULT ;
4554
46- ID3D11Device* origDevice = pGraphicsManager->pd3dDevice ;
47- origDevice->CreateTexture2D (&sharedDesc, nullptr , &pSharedTex);
55+ hr = this ->pGraphicsManager ->pd3dDevice ->CreateTexture2D (&sharedDesc, nullptr , &this ->buffer1 .srcTex .pTex );
56+ if (FAILED (hr)) {
57+ this ->ISys ().LogError (" 共享纹理创建失败" );
58+ return ;
59+ }
60+ this ->ISys ().LogSucc (" 共享纹理创建成功" );
4861
62+ HANDLE hSharedHandle = nullptr ;
4963 // 4. 获取共享句柄,并在我们自己的设备上打开
50- IDXGIResource* pDXGIRes = nullptr ;
51- pSharedTex->QueryInterface (IID_PPV_ARGS (&pDXGIRes));
52- pDXGIRes->GetSharedHandle (&hSharedHandle);
53- pDXGIRes->Release ();
54-
55- // pSharedTex 由原设备持有,后续每帧拷贝后会再次共享(无需每次打开)
56- // 我们设备打开一次即可(除非缓冲描述变化,基本不会)
57- this ->pDevice ->OpenSharedResource (hSharedHandle, IID_PPV_ARGS (&pRemoteTex));
64+ ComPtr<IDXGIResource> pDXGIRes;
65+ hr = this ->buffer1 .srcTex .pTex .As (&pDXGIRes);
66+ if (FAILED (hr)) {
67+ this ->ISys ().LogError (" 获取IDXGIResource失败" );
68+ return ;
69+ }
70+ hr = pDXGIRes->GetSharedHandle (&hSharedHandle);
71+ if (FAILED (hr)) {
72+ this ->ISys ().LogError (" 获取共享句柄失败" );
73+ return ;
74+ }
75+ this ->ISys ().LogSucc (" 共享句柄获取成功" );
76+
77+ hr = pDevice->OpenSharedResource (hSharedHandle, IID_PPV_ARGS (&this ->buffer1 .dstTex .pTex ));
78+ if (FAILED (hr)) {
79+ this ->ISys ().LogError (" 在捕获设备上打开共享资源失败" );
80+ return ;
81+ }
82+ this ->ISys ().LogSucc (" 共享资源在捕获设备上打开成功" );
83+
84+ // 5. 获取两端的 Keyed Mutex 接口
85+ hr = this ->buffer1 .srcTex .pTex .As (&this ->buffer1 .srcTex .pMutex );
86+ if (FAILED (hr)) {
87+ this ->ISys ().LogError (" 原设备获取KeyedMutex失败" );
88+ return ;
89+ }
90+ hr = this ->buffer1 .dstTex .pTex .As (&this ->buffer1 .dstTex .pMutex );
91+ if (FAILED (hr)) {
92+ this ->ISys ().LogError (" 录制设备获取KeyedMutex失败" );
93+ return ;
94+ }
95+ this ->ISys ().LogSucc (" Keyed Mutex初始化完成" );
96+ }
97+
98+ void VCD3D11Manager::CopyTexture () {
99+ ComPtr<ID3D11Texture2D> backBuffer;
100+ HRESULT hr = pGraphicsManager->pSwapChain ->GetBuffer (0 , IID_PPV_ARGS (&backBuffer));
101+ if (FAILED (hr)) return ;
102+
103+ // 等待录制端完成上一帧读取(key = 0 表示资源可写)
104+ hr = this ->buffer1 .srcTex .pMutex ->AcquireSync (0 , INFINITE );
105+ if (FAILED (hr)) {
106+ this ->ISys ().LogError (" AcquireSync(0) 失败" );
107+ return ;
108+ }
109+
110+ // 执行拷贝
111+ pGraphicsManager->pd3dContext ->CopyResource (this ->buffer1 .srcTex .pTex .Get (), backBuffer.Get ());
112+
113+ // 通知录制端新帧已就绪(key = 1)
114+ hr = this ->buffer1 .srcTex .pMutex ->ReleaseSync (1 );
115+ if (FAILED (hr)) {
116+ this ->ISys ().LogError (" ReleaseSync(1) 失败" );
117+ }
58118}
0 commit comments