topbanner_forum
  *

avatar image

Welcome, Guest. Please login or register.
Did you miss your activation email?

Login with username, password and session length
  • Monday May 6, 2024, 9:35 pm
  • Proudly celebrating 15+ years online.
  • Donate now to become a lifetime supporting member of the site and get a non-expiring license key for all of our programs.
  • donate

Recent Posts

Pages: [1] 2 3 4 5 6 ... 10next
1
The Direct3DHook code is now hosted on GitHub : https://github.com/s...zzarama/Direct3DHook

Still have to make some changes for you mouser - I have released an alpha of the EasyHook library that has the required changes to continue with the GAC'less injection process.

Time is of course a little short so it's taking me a little longer that I would like to get around to it all :)

Cheers,
J

If anyone wants to try the new screenshot captor addon for capturing DirectX full screen images, I have uploaded it here:


You will need to install the new screenshot captor release, and then the addon.  The addon will also make you install the SlimDx runtimes, and you will have to reboot your pc after the install.

Then you can set a hotkey for DirectX full screen capture (may default to Ctrl+Alt+Shift+X).



How well does it work?

Well.. It's a bit hit or miss at this point -- and I have to warn you that there is a fairly good chance it will crash your directX application when invoked.

If your directx game has its own way to take screenshots, that will without a doubt be a better solution than trying to use SC to take them.

So this is only for people who really like testing stuff early.  But I would like to hear reports of whether it works for you.



Thanks to Justin S, who's code powers this addon.  See this thread for a more discussion of the issues involved: https://www.donation...ex.php?topic=29890.0
2
Worked for Battlefield 3 and World of Tanks (both D3D 10 I think)

Didn't work for Global Agenda (I think it is D3D10), AV in presenthook (something to do with that game it would seem)

Battlefield3_Screenshot.png
WorldOfTanks_Screenshot.png
3
Interesting.. Well it shouldnt be invoking more than one at a time, so I'm not sure why it would make a difference how rapidly you *try* to capture from the directx window -- it should only be doing one attempt at a time.

However it's possible that the code to unhook is not being given enough time to do its thing before the commandline tool exits?

Also, given my testing which shows that success is a bit random -- it may not have to do with trying to do lots of captures in a row -- and more to do with simply an X% probability of failing to capture on any given request?

Yeah I don't know how reliably EasyHook cleans up the hooks after itself... I haven't experienced any issues with a percentage of injections failing - generally once it works on my system I'm good to go.

Btw - I will give your screenshot application a try soon, just haven't had time :)
4
(see attachment in previous post)
I am able to get captures of "The Ball" and "Counterstrike:Source" but not Crysis2 or Skyrim. Rapid shots crashed Counterstirke. I pressed the key about 2 time a second. (see attachment in previous post)

I think because it is running a command line to do the inject and copy multiple screenshots are likely to be a bit buggy in the same app.

Mouser - it is probably worth investigating the reverse p/invoke method so you can communicate to the .NET assemblies directly. This can be done in C++ .NET using some attributes, or via a custom build process with C# (decompile to MSIL, edit, recompile -> also known as creative roundtripping).
5
It works!
Wonderful.

[i can't say for sure why kind of effects on stability that it might have on the target app as ive seen an occasional issue but it works!!!]

Great work Justin!!!!  :Thmbsup: :Thmbsup: :Thmbsup:

Great stuff!
6
I'll recheck the D3D10 one

Working fine here, my creation code for D3D10 looks like this:

   using (SlimDX.Direct3D10.Device device = new Device(factory.GetAdapter(0), DriverType.Hardware, DeviceCreationFlags.None))
    {
        this.DebugMessage("Hook: Device created");
        _d3d10VTblAddresses.AddRange(GetVTblAddresses(device.ComPointer, D3D10_DEVICE_METHOD_COUNT));

        using (SlimDX.Windows.RenderForm renderForm = new SlimDX.Windows.RenderForm())
        {
            using (SlimDX.DXGI.SwapChain sc = new SlimDX.DXGI.SwapChain(factory, device, DXGI.CreateSwapChainDescription(renderForm.Handle)))
            {
                _dxgiSwapChainVTblAddresses.AddRange(GetVTblAddresses(sc.ComPointer, DXGI.DXGI_SWAPCHAIN_METHOD_COUNT));
            }
        }
    }

I'm not sure if you are using the TestScreenshot or not, or whether you are logging the debug messages, but do you see the debug message: "1612:DXHookD3D10: Hook: Device created" ?

Cheers,
J
7
I'll recheck the D3D10 one
8
Good luck - I also switched to a non-GAC setup for testing purposes, for this I would run the D3D10/11 sample direct from my application directory.

The "EmptyProject10" and "EmptyProject11" are perfect for this as they have no dependencies (although on my machine getting them to fullscreen and then capturing was a pain at times - one of my screens would sometimes go black so would have to Alt+Enter a few times before I was ready to try the capture).

This might help you out in future for debugging:
To debug  I set the ScreenshotInject project as my startup project in VS2010, and edited the build settings so that it started the appropriate D3D sample app on Debug. Then externally I would run the screenshottest to do the injection etc... All your breakpoints will be hit nicely (although fullscreen apps are not so easy to debug, well especially with only one screen hehe)

Cheers,
J
9
Well good news mouser.

The errors with capturing in D3D10/11 were a different problem, you should leave both D3D10/11 as DriverType.Hardware in the device creation, and instead fix a different problem as outlined in the code below. D3D9 needs to still have the DriverType.None for it to work in fullscreen.

The problem is actually within the PresentHook where SlimDX is giving us some grief over disposing of its reference to the SwapChain - which cannot be done while in Fullscreen window mode - therefore we just have to keep a reference to the same SwapChain.

The bad news (for me) was that I didn't bother testing the original code until after half a day of stuffing around with it LOL!!! I just assumed it was a problem with the device creation :-[... It's times like these I wish I followed in my fathers footsteps and became a carpenter or maybe an electrician :P. Anyway I think SlimDX might have something to do with it - and I'm in the process of switching to SharpDX, but that is a ways off for the moment.

Here is a snippet that will get it working for you, enjoy!

DXHookD3D10.cs:
       private SwapChain _swapChain;
        private IntPtr _swapChainPointer;

        /// <summary>
        /// Our present hook that will grab a copy of the backbuffer when requested. Note: this supports multi-sampling (anti-aliasing)
        /// </summary>
        /// <param name="swapChainPtr"></param>
        /// <param name="syncInterval"></param>
        /// <param name="flags"></param>
        /// <returns>The HRESULT of the original method</returns>
        int PresentHook(IntPtr swapChainPtr, int syncInterval, SlimDX.DXGI.PresentFlags flags)
        {
            if (swapChainPtr != _swapChainPointer)
            {
                _swapChain = SlimDX.DXGI.SwapChain.FromPointer(swapChainPtr);
            }
            SwapChain swapChain = _swapChain;
            //using (SlimDX.DXGI.SwapChain swapChain = SlimDX.DXGI.SwapChain.FromPointer(swapChainPtr))
            {

DXHookD3D11.cs:
       private SwapChain _swapChain;
        private IntPtr _swapChainPointer;


        /// <summary>
        /// Our present hook that will grab a copy of the backbuffer when requested. Note: this supports multi-sampling (anti-aliasing)
        /// </summary>
        /// <param name="swapChainPtr"></param>
        /// <param name="syncInterval"></param>
        /// <param name="flags"></param>
        /// <returns>The HRESULT of the original method</returns>
        int PresentHook(IntPtr swapChainPtr, int syncInterval, SlimDX.DXGI.PresentFlags flags)
        {
            if (swapChainPtr != _swapChainPointer)
            {
                _swapChain = SlimDX.DXGI.SwapChain.FromPointer(swapChainPtr);
            }
            SwapChain swapChain = _swapChain;

            //using (SlimDX.DXGI.SwapChain swapChain = SlimDX.DXGI.SwapChain.FromPointer(swapChainPtr))
            {
10
And what I have done is shamelessly taken Justin's code and modified it slightly to make it a commandline non-interactive directx screenshot taker, and then added code to Screenshot Captor that will invoke it on a target window and grab the resulting screenshot as if it was taken from within the app itself.  I'm just waiting for Justin to hopefully succeed in the hard work of getting it to work on full screen dx10 and dx11, and it will be ready for testing.

That's what it is there for :P (he did donate tho guys which was much appreciated but not necessary :)
11
Fantastic to see you posting, Justin -- welcome! It's an honor to have you stop by.

My hat is off to you with this process injection/hook stuff -- it's way over my head and *very* impressive work.

And I apologize for the over-the-top ranting on my part -- It's well known I have a very low tolerance for frustration and no one is as good at pushing my buttons as microsoft is :)

I'm really looking forward to adapting your code to provide a directx capture option for Screenshot Captor -- so i'll be following your work closely, and look forward to hearing about your other projects.

I'm hoping in the end i'll be able to build a little installer that will take care of the GAC stuff for the directx capture, and make that an optional install for users who need directx capture.

Once again, welcome   :up:

Thanks mouser, I know the pain don't worry!! Will definitely keep you posted on changes - I'll probably move the project source so that it is in code.google or github which will make it easier for it to be worked upon by others too - at the moment the project itself is really only a demonstration of the technique and requires a bit of tweaking for any real world usage.

Happy to be here

Cheers,
J
12
The problem with the technique I use in the code mouser has been using is that it uses process injection. Unfortunately this complicated approach was the only reliable way I could determine to capture at a reasonable speed from the DirectX application, and especially from a full screen one. I'm happy to elaborate on this, so if someone wants to know more about it just let me know.

I'm certainly interested in the dark arts! :)

Feel free to elaborate! (Here at DC or a blog post -- whatever works for you -- just post here if you do a blog post so I and others know.)


There's basically three techniques that I'm familiar with Renegade:

1) Proxy DLL (don't think this works on Vista up anymore) where you create a DLL that implements the same interfaces as the library you are attempting to intercept, and rename the original - with yours doing what you need to before passing the call on to the original - then all applications using the library will call your DLL instead
2) Hooking + Interface Wrapping (see the link below)
3) Hook the virtual function addresses of the COM object in question (this is the one I use as its less work, and I also describe this in the link below)

You will find a good description of the last two and how I learnt about them here: http://spazzarama.wo...-direct3d-api-hooks/

Cheers,
J
13
Hehehe, I'm glad to see you got it working in the end mouser, and thanks for the invite to the forums. I'm sorry you had to go through so much pain to get it up and running :-[

For those that don't know me (I'm brand new to these forums) I am the author of the blog @ http://spazzarama.wordpress.com/ and have felt the significant amount of pain and frustration that I'm sure mouser has endured when dealing with capturing images from DirectX applications. I maintain that site in the hope that what I learn from difficult problems I run across in my travels as a programmer can in turn help others. I experience great joy when people find it useful.

The problem with the technique I use in the code mouser has been using is that it uses process injection. Unfortunately this complicated approach was the only reliable way I could determine to capture at a reasonable speed from the DirectX application, and especially from a full screen one. I'm happy to elaborate on this, so if someone wants to know more about it just let me know.

Good luck with the next release of the screencapture app mouser - I hope that you've found that DirectX project helpful :) As discussed separately there are a few enhancements I have planned that will hopefully improve things a little - but it is still a complicated process, and there's no real way around it :(. If you are keen to exclude the GAC from the equation it might be possible to use the PATH environment variable but I haven't tried it to date...

I'll post about another opensource project currently in progress in the near future once bare bones are in place. I hope to find people that will find it useful and perhaps want to join in with the development fun :D - a hint is it involves pretty flashing lights (come on, everyone loves those!!)

Cheers,
Justin
Pages: [1] 2 3 4 5 6 ... 10next