@@ -91,7 +91,7 @@ public DXHookD3D11(CaptureInterface ssInterface)
9191 SharpDX . Windows . RenderForm _renderForm ;
9292 Texture2D _resolvedRTShared ;
9393 SharpDX . DXGI . KeyedMutex _resolvedRTSharedKeyedMutex ;
94- ShaderResourceView _resolvedSharedSRV ;
94+ ShaderResourceView _resolvedSRV ;
9595 Capture . Hook . DX11 . ScreenAlignedQuadRenderer _saQuad ;
9696 Texture2D _finalRT ;
9797 Texture2D _resizedRT ;
@@ -107,7 +107,6 @@ public DXHookD3D11(CaptureInterface ssInterface)
107107 Texture2D _resolvedRT ;
108108 SharpDX . DXGI . KeyedMutex _resolvedRTKeyedMutex ;
109109 SharpDX . DXGI . KeyedMutex _resolvedRTKeyedMutex_Dev2 ;
110- //ShaderResourceView _resolvedSRV;
111110 #endregion
112111
113112 protected override string HookName
@@ -228,16 +227,111 @@ int ResizeTargetHook(IntPtr swapChainPtr, ref ModeDescription newTargetParameter
228227 return DXGISwapChain_ResizeTargetHook . Original ( swapChainPtr , ref newTargetParameters ) ;
229228 }
230229
231- void EnsureResources ( SharpDX . Direct3D11 . Device device , Texture2DDescription description , Rectangle captureRegion , ScreenshotRequest request )
230+ void EnsureResources ( SharpDX . Direct3D11 . Device device , Texture2DDescription description , Rectangle captureRegion , ScreenshotRequest request , bool useSameDeviceForResize = false )
232231 {
233- if ( _device != null && request . Resize != null && ( _resizedRT == null || ( _resizedRT . Device . NativePointer != _device . NativePointer || _resizedRT . Description . Width != request . Resize . Value . Width || _resizedRT . Description . Height != request . Resize . Value . Height ) ) )
232+ var resizeDevice = useSameDeviceForResize ? device : _device ;
233+
234+ // Check if _resolvedRT or _finalRT require creation
235+ if ( _finalRT != null && ( _finalRT . Device . NativePointer == device . NativePointer || _finalRT . Device . NativePointer == _device . NativePointer ) &&
236+ _finalRT . Description . Height == captureRegion . Height && _finalRT . Description . Width == captureRegion . Width &&
237+ _resolvedRT != null && _resolvedRT . Description . Height == description . Height && _resolvedRT . Description . Width == description . Width &&
238+ ( _resolvedRT . Device . NativePointer == device . NativePointer || _resolvedRT . Device . NativePointer == _device . NativePointer ) && _resolvedRT . Description . Format == description . Format
239+ )
240+ {
241+
242+ }
243+ else
244+ {
245+ RemoveAndDispose ( ref _query ) ;
246+ RemoveAndDispose ( ref _resolvedRT ) ;
247+ RemoveAndDispose ( ref _resolvedSRV ) ;
248+ RemoveAndDispose ( ref _finalRT ) ;
249+ RemoveAndDispose ( ref _resolvedRTShared ) ;
250+ RemoveAndDispose ( ref _resolvedRTKeyedMutex ) ;
251+ RemoveAndDispose ( ref _resolvedRTKeyedMutex_Dev2 ) ;
252+
253+ _query = new Query ( resizeDevice , new QueryDescription ( )
254+ {
255+ Flags = QueryFlags . None ,
256+ Type = QueryType . Event
257+ } ) ;
258+ _queryIssued = false ;
259+
260+ try
261+ {
262+ ResourceOptionFlags resolvedRTOptionFlags = ResourceOptionFlags . None ;
263+
264+ if ( device != resizeDevice )
265+ resolvedRTOptionFlags |= ResourceOptionFlags . SharedKeyedmutex ;
266+
267+ _resolvedRT = ToDispose ( new Texture2D ( device , new Texture2DDescription ( )
268+ {
269+ CpuAccessFlags = CpuAccessFlags . None ,
270+ Format = description . Format , // for multisampled backbuffer, this must be same format
271+ Height = description . Height ,
272+ Usage = ResourceUsage . Default ,
273+ Width = description . Width ,
274+ ArraySize = 1 ,
275+ SampleDescription = new SharpDX . DXGI . SampleDescription ( 1 , 0 ) , // Ensure single sample
276+ BindFlags = BindFlags . ShaderResource ,
277+ MipLevels = 1 ,
278+ OptionFlags = resolvedRTOptionFlags
279+ } ) ) ;
280+ }
281+ catch
282+ {
283+ // Failed to create the shared resource, try again using the same device as game for resize
284+ EnsureResources ( device , description , captureRegion , request , true ) ;
285+ return ;
286+ }
287+
288+ // Retrieve reference to the keyed mutex
289+ _resolvedRTKeyedMutex = ToDispose ( _resolvedRT . QueryInterfaceOrNull < SharpDX . DXGI . KeyedMutex > ( ) ) ;
290+
291+ // If the resolvedRT is a shared resource _resolvedRTKeyedMutex will not be null
292+ if ( _resolvedRTKeyedMutex != null )
293+ {
294+ using ( var resource = _resolvedRT . QueryInterface < SharpDX . DXGI . Resource > ( ) )
295+ {
296+ _resolvedRTShared = ToDispose ( resizeDevice . OpenSharedResource < Texture2D > ( resource . SharedHandle ) ) ;
297+ _resolvedRTKeyedMutex_Dev2 = ToDispose ( _resolvedRTShared . QueryInterfaceOrNull < SharpDX . DXGI . KeyedMutex > ( ) ) ;
298+ }
299+ // SRV for use if resizing
300+ _resolvedSRV = ToDispose ( new ShaderResourceView ( resizeDevice , _resolvedRTShared ) ) ;
301+ }
302+ else
303+ {
304+ _resolvedSRV = ToDispose ( new ShaderResourceView ( resizeDevice , _resolvedRT ) ) ;
305+ }
306+
307+ _finalRT = ToDispose ( new Texture2D ( resizeDevice , new Texture2DDescription ( )
308+ {
309+ CpuAccessFlags = CpuAccessFlags . Read ,
310+ Format = description . Format ,
311+ Height = captureRegion . Height ,
312+ Usage = ResourceUsage . Staging ,
313+ Width = captureRegion . Width ,
314+ ArraySize = 1 ,
315+ SampleDescription = new SharpDX . DXGI . SampleDescription ( 1 , 0 ) ,
316+ BindFlags = BindFlags . None ,
317+ MipLevels = 1 ,
318+ OptionFlags = ResourceOptionFlags . None
319+ } ) ) ;
320+ _finalRTMapped = false ;
321+ }
322+
323+ if ( _resolvedRT != null && _resolvedRTKeyedMutex_Dev2 == null && resizeDevice == _device )
324+ resizeDevice = device ;
325+
326+ if ( resizeDevice != null && request . Resize != null && ( _resizedRT == null || ( _resizedRT . Device . NativePointer != resizeDevice . NativePointer || _resizedRT . Description . Width != request . Resize . Value . Width || _resizedRT . Description . Height != request . Resize . Value . Height ) ) )
234327 {
235328 // Create/Recreate resources for resizing
236329 RemoveAndDispose ( ref _resizedRT ) ;
237330 RemoveAndDispose ( ref _resizedRTV ) ;
238331 RemoveAndDispose ( ref _saQuad ) ;
239332
240- _resizedRT = ToDispose ( new Texture2D ( _device , new Texture2DDescription ( ) {
333+ _resizedRT = ToDispose ( new Texture2D ( resizeDevice , new Texture2DDescription ( )
334+ {
241335 Format = SharpDX . DXGI . Format . R8G8B8A8_UNorm , // Supports BMP/PNG/etc
242336 Height = request . Resize . Value . Height ,
243337 Width = request . Resize . Value . Width ,
@@ -249,74 +343,11 @@ void EnsureResources(SharpDX.Direct3D11.Device device, Texture2DDescription desc
249343 OptionFlags = ResourceOptionFlags . None
250344 } ) ) ;
251345
252- _resizedRTV = ToDispose ( new RenderTargetView ( _device , _resizedRT ) ) ;
346+ _resizedRTV = ToDispose ( new RenderTargetView ( resizeDevice , _resizedRT ) ) ;
253347
254348 _saQuad = ToDispose ( new DX11 . ScreenAlignedQuadRenderer ( ) ) ;
255- _saQuad . Initialize ( new DX11 . DeviceManager ( _device ) ) ;
256- }
257-
258- // Check if _resolvedRT or _finalRT require creation
259- if ( _finalRT != null && _finalRT . Device . NativePointer == _device . NativePointer &&
260- _finalRT . Description . Height == captureRegion . Height && _finalRT . Description . Width == captureRegion . Width &&
261- _resolvedRT != null && _resolvedRT . Description . Height == description . Height && _resolvedRT . Description . Width == description . Width &&
262- _resolvedRT . Device . NativePointer == device . NativePointer && _resolvedRT . Description . Format == description . Format
263- )
264- {
265- return ;
266- }
267-
268- RemoveAndDispose ( ref _query ) ;
269- RemoveAndDispose ( ref _resolvedRT ) ;
270- RemoveAndDispose ( ref _resolvedSharedSRV ) ;
271- RemoveAndDispose ( ref _finalRT ) ;
272- RemoveAndDispose ( ref _resolvedRTShared ) ;
273-
274- _query = new Query ( _device , new QueryDescription ( )
275- {
276- Flags = QueryFlags . None ,
277- Type = QueryType . Event
278- } ) ;
279- _queryIssued = false ;
280-
281- _resolvedRT = ToDispose ( new Texture2D ( device , new Texture2DDescription ( ) {
282- CpuAccessFlags = CpuAccessFlags . None ,
283- Format = description . Format , // for multisampled backbuffer, this must be same format
284- Height = description . Height ,
285- Usage = ResourceUsage . Default ,
286- Width = description . Width ,
287- ArraySize = 1 ,
288- SampleDescription = new SharpDX . DXGI . SampleDescription ( 1 , 0 ) , // Ensure single sample
289- BindFlags = BindFlags . ShaderResource ,
290- MipLevels = 1 ,
291- OptionFlags = ResourceOptionFlags . SharedKeyedmutex
292- } ) ) ;
293-
294- // Retrieve reference to the keyed mutex
295- _resolvedRTKeyedMutex = ToDispose ( _resolvedRT . QueryInterfaceOrNull < SharpDX . DXGI . KeyedMutex > ( ) ) ;
296-
297- using ( var resource = _resolvedRT . QueryInterface < SharpDX . DXGI . Resource > ( ) )
298- {
299- _resolvedRTShared = ToDispose ( _device . OpenSharedResource < Texture2D > ( resource . SharedHandle ) ) ;
300- _resolvedRTKeyedMutex_Dev2 = ToDispose ( _resolvedRTShared . QueryInterfaceOrNull < SharpDX . DXGI . KeyedMutex > ( ) ) ;
349+ _saQuad . Initialize ( new DX11 . DeviceManager ( resizeDevice ) ) ;
301350 }
302-
303- // SRV for use if resizing
304- _resolvedSharedSRV = ToDispose ( new ShaderResourceView ( _device , _resolvedRTShared ) ) ;
305-
306- _finalRT = ToDispose ( new Texture2D ( _device , new Texture2DDescription ( )
307- {
308- CpuAccessFlags = CpuAccessFlags . Read ,
309- Format = description . Format ,
310- Height = captureRegion . Height ,
311- Usage = ResourceUsage . Staging ,
312- Width = captureRegion . Width ,
313- ArraySize = 1 ,
314- SampleDescription = new SharpDX . DXGI . SampleDescription ( 1 , 0 ) ,
315- BindFlags = BindFlags . None ,
316- MipLevels = 1 ,
317- OptionFlags = ResourceOptionFlags . None
318- } ) ) ;
319- _finalRTMapped = false ;
320351 }
321352
322353 /// <summary>
@@ -378,7 +409,7 @@ int PresentHook(IntPtr swapChainPtr, int syncInterval, SharpDX.DXGI.PresentFlags
378409 {
379410 if ( _resolvedRTKeyedMutex_Dev2 != null )
380411 _resolvedRTKeyedMutex_Dev2 . Acquire ( 1 , int . MaxValue ) ;
381- _saQuad . ShaderResource = _resolvedSharedSRV ;
412+ _saQuad . ShaderResource = _resolvedSRV ;
382413 _saQuad . RenderTargetView = _resizedRTV ;
383414 _saQuad . RenderTarget = _resizedRT ;
384415 _saQuad . Render ( ) ;
@@ -392,7 +423,10 @@ int PresentHook(IntPtr swapChainPtr, int syncInterval, SharpDX.DXGI.PresentFlags
392423 else
393424 {
394425 // Make sourceTexture be the resolved texture
395- sourceTexture = _resolvedRTShared ;
426+ if ( _resolvedRTShared != null )
427+ sourceTexture = _resolvedRTShared ;
428+ else
429+ sourceTexture = _resolvedRT ;
396430 }
397431 }
398432 else
@@ -401,7 +435,11 @@ int PresentHook(IntPtr swapChainPtr, int syncInterval, SharpDX.DXGI.PresentFlags
401435 if ( _resolvedRTKeyedMutex != null ) _resolvedRTKeyedMutex . Acquire ( 0 , int . MaxValue ) ;
402436 currentRT . Device . ImmediateContext . CopySubresourceRegion ( currentRT , 0 , null , _resolvedRT , 0 ) ;
403437 if ( _resolvedRTKeyedMutex != null ) _resolvedRTKeyedMutex . Release ( 1 ) ;
404- sourceTexture = _resolvedRTShared ;
438+
439+ if ( _resolvedRTShared != null )
440+ sourceTexture = _resolvedRTShared ;
441+ else
442+ sourceTexture = _resolvedRT ;
405443 }
406444
407445 // Copy to memory and send back to host process on a background thread so that we do not cause any delay in the rendering pipeline
@@ -412,6 +450,7 @@ int PresentHook(IntPtr swapChainPtr, int syncInterval, SharpDX.DXGI.PresentFlags
412450
413451 bool acquireLock = sourceTexture == _resolvedRTShared ;
414452
453+
415454 ThreadPool . QueueUserWorkItem ( new WaitCallback ( ( o ) =>
416455 {
417456 // Acquire lock on second device
0 commit comments