Sign in to follow this  
alexisgreene

VS2012 Graphics Debugger

Recommended Posts

I have ran into a major problem while  rewriting my rendering code to take advantage of the mutithreading features of D3D11. I fired up the graphics debugger to see what is going on. Everything works fine with it except for the graphics pipeline stages viewer. When I click on it, the loading indicator shows up and never goes away. Has anyone else run into this problem?

Share this post


Link to post
Share on other sites

The support for multithreaded rendering is (very) likely to be improved in future iterations of the debugger.  I know that doesn't help you now, but at least there will be some help coming down the road...

Share this post


Link to post
Share on other sites

Well I took the advice you gave me when I began rewriting my rendering code and made the engine able to hot swap between multi-threaded rendering with deferred contexts and single threaded rendering using only the immediate context. Turns out using the graphics pipeline viewer was no help at all to me... I was accidentally swapping the stride and offset values when I set the vertex buffer for the input assembler. I had to compare IDeviceContext states of the new build and a build before the rewrite in order to catch that mistake.

Share this post


Link to post
Share on other sites

Nice - and how do you like the system with swappable threading?  When I implemented the one for Hieroglyph 3, I found that it helps you get a much better feel for what your algorithms are doing and where you are making assumptions (i.e. relying on a previously set state) and what you are spending your API calls on.

 

Do you have any debugging tips or experience that you can share?

Share this post


Link to post
Share on other sites

Having swappable threading is amazing because it forces you to truly understand what is going on under the hood and gives you an amazing debugging tool at the same time. This new and basic understanding of the pipeline stages and immediate vs deferred contexts made me realize how sloppy and inefficient my previous rendering code was. My laptop (a.k.a. development rig) has a really crappy Intel graphics card (DX10 - limited multi-threading) and a pretty beefy (at least for a laptop) nVidia graphics card (DX11). It is really nice to see my engine run optimally on each graphics card.

 

Tip #1

State management was, or rather still is, a huge challenge. In order to avoid unnecessary state changes (single-threaded) I came up with a somewhat simple approach. Every state change function (ex. IASetIndexBuffer()) will set a "desired" variable if it differs from a "current" variable, as well as pushing a function pointer (ex. ApplyIASetIndexBuffer()) to a vector named "m_PendingStateChanges". The variables I just mentioned are simply the variables that I would pass to the actual API function.

 

ApplyState() just iterates though the vector, utilizing all function pointers it contains to call only the necessary Apply*() functions. Those Apply*() functions simply submit the state change to the API and then update the "current" and "desired" variabes. This system of handling state changes eliminates unnecessary stage changes as well as eliminating having to test each individual pipeline state once ApplyState() is called.

 

Currently I do this on a per context basis, passing "true" to FinishCommandList() in order for all the deferred contexts to behave nicely with each other. The D3D11 docs explicitly state that this is inefficient. I am currently trying to find a way to pull state changing away from the context level and closer to the device level. In theory, there is only one immediate context so there should only be one "pipeline state manager". Finding a way for this to play nice with multiple contexts in a multi-threaded scenario, as well as not breaking hot swapping, is the challenge.

 

Tip #2

When things work good, fire up the graphics debugger and save a snapshot. Clicking the device context of a good draw call will give you detailed information of the entire pipeline. Since you have no visual pipeline stages while using deferred contexts, having a snapshot of what the device contexts should look like (state-wise) is the next best thing. Even without a good snapshot saved, you can scan over the values and possibly spot the problem.

 

Tip #3

Consider using http://threadingbuildingblocks.org/ over managing threads manually. This book http://www.amazon.com/Intel-Threading-Building-Blocks-Parallelism/dp/0596514808/ref=sr_1_1?ie=UTF8&qid=1334719817&sr=8-1 is a must have should you choose to use TBB. Scalable, automatic (and even manual) task dispatching, and concurrent safe containers and allocators are just a few of the things this library offers.

 

These are just the top 3 I could come up with off the top of my head.

Share this post


Link to post
Share on other sites

I'm glad you've found the source of your problems Deortuka, but as a follow up to your original question and to help others in the future, I'd like to share that Visual Studio Update 2 was made available today, with enhanced support for multithreaded rendering.

 

The following describes the process that should make Graphics Diagnostics more helpful in Multithreaded scenarios in the future:

 

 

1) After capturing graphics information from a multithreaded renderer, in the Event List, expand the command list to see the draw calls. For example:
        1 :: DeviceContext::Draw(foo)
        2 :: DeviceContext::IASetBlahBlah
        3 :: DeviceContext::ExecuteCommandList
                4 :: DeviceContext::Draw(foo)

2) The Pipeline Stages window will work when a Draw call under ExecuteCommandList is chosen, because these Draw events represent execution of the draw call.

3) With that Draw call (event 4 in this example) selected, things should work normally.

 

When the first Draw call (event 1) is selected, you should see this message in the Pipeline Stages window “Pipeline stages are not computable for deferred context draws/dispatches. Please examine the children of ExecuteCommandList instead.” This message is meant to direct you to the right place.

 

Good luck with your renderer!

Share this post


Link to post
Share on other sites

Thanks for sharing your tips - I haven't checked into the TBB library yet, so maybe that will be a good project for my next block of free time (whenever that may be...).  Do you notice a significant FPS change (increase or decrease) when running in either single or multi threaded mode?  I'm just curious what your experience is there too.

Share this post


Link to post
Share on other sites

I have been just rendering my user interface over a cube in order to test the new rendering code. I am also rewriting my map handling code in order to work better with the new renderer. Before the rewrite, I averaged roughly 260 fps while hosting a multi-player game (just me and one friend of mine) on a small map with full physics simulation enabled. Once I have the new map code done, I will be sure to let you know the change in performance.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this