justinstenning / Direct3DHook

DirectX Capture and Overlays by using Direct3D API hooks
http://spazzarama.com/2011/03/14/c-screen-capture-and-overlays-for-direct3d-9-10-and-11-using-api-hooks
MIT License
580 stars 178 forks source link

Error with TestScreenshot app - support fallback to non-shared texture in D3D 11 if fails #58

Closed arvitaly closed 1 year ago

arvitaly commented 6 years ago

When request capture


Debug: DXHookD3D11: PresentHook: Request Start
Debug: Disposing of hooks...
Debug: DXHookD3D11: PresentHook: Exeception: SharpDX.SharpDXException: SharpDX.SharpDXException: HRESULT: [0x80070057], Module: [General], ApiCode: [E_INVALIDARG/Invalid Arguments], Message: The parameter is incorrect.

   at SharpDX.Result.CheckError()
   at SharpDX.Direct3D11.Device.CreateTexture2D(Texture2DDescription& descRef, DataBox[] initialDataRef, Texture2D texture2DOut)
   at SharpDX.Direct3D11.Texture2D..ctor(Device device, Texture2DDescription description)
   at Capture.Hook.DXHookD3D11.EnsureResources(Device device, Texture2DDescription description, Rectangle captureRegion, ScreenshotRequest request) in C:\Users\Administrator\Downloads\Direct3DHook-master\Capture\Hook\DXHookD3D11.cs:line 280
   at Capture.Hook.DXHookD3D11.PresentHook(IntPtr swapChainPtr, Int32 syncInterval, PresentFlags flags) in C:\Users\Administrator\Downloads\Direct3DHook-master\Capture\Hook\DXHookD3D11.cs:line 355
arvitaly commented 6 years ago

Now, when i select Direct3D 9 instead AutoDetect, there is not error. But, screenshot = null

Screenshot screenshot = _captureProcess.CaptureInterface.EndGetScreenshot(result)
justinstenning commented 6 years ago

What is the target you are capturing a screenshot from?

Do you know what Direct3D version it uses?

arvitaly commented 6 years ago

I think, it is answer This application requires Direct3D 11 installed

arvitaly commented 6 years ago

Please, look error in first post!

justinstenning commented 6 years ago

Parameter is incorrect means that something is incompatible with what is taking place. Either format of texture or some device setting etc.

What application does it fail in?

justinstenning commented 6 years ago

Hmm it is failing to create the texture, so that could also mean that the texture description is incompatible with your 3D graphics card etc.

What graphics card are you using?

arvitaly commented 6 years ago

11111111

justinstenning commented 6 years ago

Does it work for another game? Also again, what game is it failing on?

FYI it is failing when creating the shared texture here. You could test this in a test SharpDX app if you have the time to see if something is incompatible here.

_resolvedRT = ToDispose(new Texture2D(device, new Texture2DDescription() {
    CpuAccessFlags = CpuAccessFlags.None,
    Format = description.Format, // for multisampled backbuffer, this must be same format
    Height = description.Height,
    Usage = ResourceUsage.Default,
    Width = description.Width,
    ArraySize = 1,
    SampleDescription = new SharpDX.DXGI.SampleDescription(1, 0), // Ensure single sample
    BindFlags = BindFlags.ShaderResource,
    MipLevels = 1,
    OptionFlags = ResourceOptionFlags.SharedKeyedmutex
}));
arvitaly commented 6 years ago

Yes, it works for another Directx9 32-bit game.

But, i see FPS

image

arvitaly commented 6 years ago

Any idea, what parameters i can to change? I already tried height and width.

justinstenning commented 6 years ago

Try removing the last property. It will fail in code later on but worth checking if it gets past that one.

hanrelan commented 6 years ago

I'm having the same issue. This is with Dota 2 running in DX11 mode. The overlay works but screenshotting fails with the error:

Debug: DXHookD3D11: PresentHook: Exeception: SharpDX.SharpDXException: SharpDX.SharpDXException: HRESULT: [0x80070057], Module: [General], ApiCode: [E_INVALIDARG/Invalid Arguments], Message: The parameter is incorrect.

   at SharpDX.Result.CheckError()
   at SharpDX.Direct3D11.Device.CreateTexture2D(Texture2DDescription& descRef, DataBox[] initialDataRef, Texture2D texture2DOut)
   at SharpDX.Direct3D11.Texture2D..ctor(Device device, Texture2DDescription description)
   at Capture.Hook.DXHookD3D11.EnsureResources(Device device, Texture2DDescription description, Rectangle captureRegion, ScreenshotRequest request) in DXHookD3D11.cs:line 280
   at Capture.Hook.DXHookD3D11.PresentHook(IntPtr swapChainPtr, Int32 syncInterval, PresentFlags flags) in DXHookD3D11.cs:line 355
hanrelan commented 6 years ago

I changed OptionFlags from ResourceOptionFlags.SharedKeyedmutex to ResourceOptionFlags.None. Now it gets past that point but as you said it fails later. The new error is:

Debug: DXHookD3D11: PresentHook: Exeception: SharpDX.SharpDXException: SharpDX.SharpDXException: HRESULT: [0x80070057], Module: [General], ApiCode: [E_INVALIDARG/Invalid Arguments], Message: The parameter is incorrect.

   at SharpDX.Result.CheckError()
   at SharpDX.Direct3D11.Device.OpenSharedResource(IntPtr hResource, Guid returnedInterface, IntPtr& resourceOut)
   at SharpDX.Direct3D11.Device.OpenSharedResource[T](IntPtr resourceHandle)
   at Capture.Hook.DXHookD3D11.EnsureResources(Device device, Texture2DDescription description, Rectangle captureRegion, ScreenshotRequest request) in DXHookD3D11.cs:line 298
   at Capture.Hook.DXHookD3D11.PresentHook(IntPtr swapChainPtr, Int32 syncInterval, PresentFlags flags) in DXHookD3D11.cs:line 355
Information: Disconnecting from process 14012
justinstenning commented 6 years ago

@hanrelan thanks for checking.

Can you please setup a test using a SharedKeyedmutex texture in a standalone app? See if it works for your driver etc...

It sounds like we need to implement a non-shared texture fallback option. The old code that didn't use a shared texture will exist in the repository history, but it may be a little messy to put it back in place. Basically it means you would need to use the device that Dota2 creates to perform the operation rather than our own D3D device.

hanrelan commented 6 years ago

As another data point, I injected into the SharpDX MiniCube (DX11) sample and that worked. I also added print statements around the creation of the SharedKeyedmutex texture to make sure that code path was being executed and it was. So I don't think it's that my driver doesn't support this texture type.

EDIT: To add to this - I also modified the MiniCube sample and changed the ResourceOptionsFlags from None to SharedKeyedMutex. It didn't throw an error (I did get blank screen instead of rotating cube, but that's expected). So my driver seems to support this option

justinstenning commented 6 years ago

@hanrelan ok thanks, maybe its something to do with Dota 2.

hanrelan commented 6 years ago

If you want to reproduce it, you can download Dota for free from Steam and then set the -DX11 launch option as described here: https://dota2.gamepedia.com/Launch_Options

Is this something you're planning to look into? If not, any pointers on where to start looking or how to fix? I haven't done DX programming in a looong time but can run experiments and try to narrow down the issue.

Thanks!

justinstenning commented 6 years ago

@hanrelan I have reproduced the error here also. Understanding the cause would be ideal, but otherwise it will require retrofitting support for using the game's ID3D11Device for the frame capture instead of own new device.

justinstenning commented 6 years ago

@hanrelan I have a fix almost completed (i.e. revert to not using a shared texture if it fails to create). Just need to rework some of the resize logic first to fit the changes.

hanrelan commented 6 years ago

Cool thanks! Happy to test it out on Dota once it's ready

justinstenning commented 6 years ago

@hanrelan I still haven't got the resize code working, but feel free to try with the attached changes (DXHookD3D11.cs) to see if screen capture is working for you in dota2.

DXHookD3D11_cs.zip

hanrelan commented 6 years ago

Seems to work! Thanks!

hanrelan commented 6 years ago

Hmm maybe have spoken too soon. It does manage to grab some screenshots in the beginning, but as time goes on it stops grabbing the screenshots (keeps getting null). It may also be causing Dota in DX11 mode to freeze up or crash.

Haven't seen these issues with Dota in DX9, so something is different here. I'll keep testing to see what I can find (it's possible that some of these issues are due to Dota DX11 itself).

justinstenning commented 6 years ago

@hanrelan I did have an issue with it repeatedly reinitialising my DX resources for each capture, perhaps I didn't fix that correctly.

hanrelan commented 6 years ago

Also if I'm in Dota DX11 watching another game screen I see the following error:

Debug: DXHookD3D10_1: PresentHook: Exeception: SharpDX.SharpDXException: HRESULT: [0x8876086C], Module: [SharpDX.Direct3D9], ApiCode: [D3DERR_INVALIDCALL/InvalidCall], Message: Unknown

I believe this is an unrelated issue with the autodetect though. If I specify DX11 this doesn't happen (will open a separate issue)

hanrelan commented 6 years ago

Ok after a bunch of testing the screen capturing is definitely causing crashes. No reliable pattern to it so I'm not sure how to repro, but if I'm playing dota with DX11Hook screen capture it crashes several times a game. No crashes without the hook

justinstenning commented 6 years ago

@hanrelan do you mean within Dota? Or just in anything?

it crashes several times a game. No crashes without the hook

hanrelan commented 6 years ago

If Dota is hooked then Dota crashes several times in a game. I haven't tested hooking against other games so I'm not sure if this is true within other games as well.

justinstenning commented 6 years ago

@hanrelan I've tried again with the recent changes I've made to the overlay engine and updated SharpDX version and cannot reproduce the crash on screen capture (or display overlay). Please test the latest commit.