Hi! I am Amit Mohindra, a Program Manager on the Visual C++ team.
We believe Metro style games and graphics-intensive apps present a huge opportunity for developers on new devices such as tablets. The primary API for accessing the full power of the underlying graphics hardware on Windows is DirectX 11 (including Direct3D and Direct2D).
One of the most significant innovations we have brought to Visual Studio 11 is a series of tools for assisting you in developing Direct3D games. We made a quick video of some of these features on Channel9 (link). In this post, I will walk through our debugging & diagnostics support for D3D.
The new Graphics Debugger in Visual Studio is a debugging and analysis tool that captures detailed information from a Direct3D application as it executes. You can use it to:
Let’s try to hypothetically solve a simple problem step by step using the graphics debugger. For this blog the game we’re working on is a rotating Die game. Here is what it should look like.
However, when we run the application we find out that the Die does not get rendered in the game.
To start debugging this game, right-click on the project in Solution Explorer and set “Enable Graphics Capture” to “Yes” in the Debugging node.
Now, F5 to start debugging your application and you will notice that the game now has some fundamental statistics displayed in the top left corner. This indicates that VS is ready to capture diagnostic information from the game for you to investigate the rendering issues.
In order to capture a frame, just hit the “Print Screen” key. You can repeat this as often as you like; each frame will show up in Visual Studio as part of the “Graphics Experiment.vsglog” file. The log file contains all the information required for you to debug the rendering issues. The file by default is located in a temporary location, but you can choose to save the file and share it with other developers.
Let’s dig further into what’s going on by analyzing the captured frame in Visual Studio. To understand it better I want to know what got drawn when I called the “DrawIndexed” API in my code.
To inspect the “DrawIndexed” call right-click on the frame thumbnail and select “Events List” from the context menu to bring up the events list window.
The Graphics Event List window lists all the DirectX events captured by running a program under the VS debugger. It also simulates the events under the graphics debugger, re-running the commands using the same inputs as used by the running program. In the search box you could type “Draw” to filter the list to show the DirectX draw calls. Clicking through the draw calls you will be able to see in the frame window (on the right) how that frame was drawn piece by piece.
In the search box in this window type “Draw”, this will filter the list to show the draw calls made by the game. Select the “DrawIndexed” call in the events list and check to see in the frame window if something gets rendered.
Unfortunately in this scenario as seen above nothing is rendered so we need to continue our debugging process. A draw API (DrawIndexed) submits work to the rendering pipeline. So let’s inspect the rendering pipeline to see if something was submitted as part of the “DrawIndexed” call. In order to see what was going on in the graphics pipeline when the draw call was executed, right-click on the call in the events list and bring up the pipeline viewer by selecting “Pipeline Viewer” from the context menu.
The Graphics pipeline viewer shows the different stages in the graphics pipeline and how those stages modify your model.
The viewer shows four different views of the mesh data; these correspond to four different stages in the pipeline
Note there are other stages in the graphics pipeline which are not represented in this view. For more on the new graphics pipeline stages in DirectX 11, see here.
In the graphics pipeline view you can see that something is being drawn that looks like the Die that the application wanted to render. It seems from the figure above that the “Die” (cube) structure is going through the graphics pipeline correctly indicating that the shaders are functioning correctly (they aren’t modifying the original structure in a way that would prevent them from being rendered).
At this point we need to continue debugging and take a look elsewhere. It could be that the pixels being overwritten or discarded. To verify this hypothesis lets go take a look at the pixels in the center of the frame (where the Die is supposed to be rendered). In the frame buffer window click in the center to first select a pixel and then right click and choose “Pixel History” from the context menu.
The Graphics Pixel History window displays the activities that contribute to the color of the selected pixel in the current frame. It contains information about how the pixel was modified by each DirectX event in the pixel history window. This includes the initial frame buffer state, followed by the intermediate draw events of rendering and the final result.
We can see from the “Pixel History” window that the frame buffer color for the pixel was blue, and then the pixel shader applied a different color (grey) to the pixel. However, the final color is still blue. The desired pixel color being rendered is not getting applied at all. This is an indication that the blend state might not be set correctly. Blend state controls how color and alpha values are blended when combining rendered data with existing render target data. To inspect the blend state, right click on the pixel and choose “Object Table” from the context menu. This will pop up the “Graphics Object Table” window.
The Graphics Object Table displays Direct3D objects created by the target program. Any object that contains state information can be viewed by double clicking on the object in the table.
Sort the object table (by “Type”) and then scroll to the list of “D3D11 Blend State” object. Double click on the “D3D11 Blend State” object will the lowest valid (not N/A) “Usage Age”. “Usage Age” helps scope the object to investigate in relation to the selected draw call, lower the usage age the more relevant it is. Double click on the blend state object with the lowest usage age and it will open a document with details of the object inside Visual Studio.
From the picture above we can see:
We can see from this that the blend state for the source is being masked since it is set to zero (D3D11_BLEND_ZERO) and the blend state for the destination is set to one (D3D11_BLEND_ONE). This causes the background color to come out as the primary color after blending thus we don’t see the Die being rendered. The values should be switched such that the output of the pixel shader is primary output of the blending operation.
To find out where the blend state is being set we can go back to the event list window and filter the event list to look for “blendstate” since the event list lists all the DirectX events that transpired for the captured frame. Once you filter you can see calls to “OMSetBlendState”. “OMSetBlendState” is the call that sets the blend state. To get to the source code where this call is being made right click on the “OMSetBlendState” call and chose “Call Stack” from the context menu to bring up the “Graphics Call Stack” window
The Graphics Event Callstack window ties the DirectX events to the C++ source code being debugged.
Double click on the first call in the call stack and it takes you to the “OMSetBlendState” call in the code. A few lines above the “OMBlendState” call and you will notice the lines of code where source and destination blend values are set.
Switch the two states by changing the code to reflect the following:
Build and Run.
Game development isn’t easy and we think tools should help you make use of the underlying DirectX platform. In this release, we are excited to bring this new type of diagnostics experience directly into Visual Studio. These features are still under development and could potentially change or not even be included in our final product. These features are only available of Visual Studio Professional and above SKU’s.
Is it possible to use this debugging feature for managed projects (I did not find a way, but maybe there is one)? If not, it is planned for release? From the looks of it the experience is better than with PIX, it would be great if this is available for .NET - as far as I understand, this only affects launching the executable, everything else is more or less agnostic wrt .NET/native.
How about shader debugging, will you support stepping through HLSL?
I really wish I could use this, but the VS11 preview build borked my DirectX install, so directx won't load in debug (either 9 or 10+, which is weird). I should probably just wipe my machine at this point though...
@Brad: They've mentioned shader stepping for AMP compiled shaders, but that's C++ implemented shaders. I don't remember HLSL stepping being mentioned....
What editions of VS will support this? And does it let us use the D3DPERF API to name and group events? The graphics event list pane could be a tree, perfect for representing nested named events. And how about the profiling angle, can we see draw call durations in this mode? Or is there some other bit of VS for that now?
Fundamentally, I can't see how this is more useful than PIX. You haven't shown anything we couldn't already do. I'd have preferred the engineering effort to have been put into improving PIX for Windows, bringing it up to the standard of the 360 version. Bringing it inside VS doesn't seem any different from what NVIDIA's Parallel nSight already does.
@Arseny, this would work with.NET applications as well, that is ability to capture Direct3D calls made by the application. In the current builds that are publically avaible to get around it you could create an exe project and set the settings to enable capture. We are working on improving the experience and will have a much better experience in the next public release of Visual Studio.
@Brad, that certainly something which would provide value if integrated inside Visual Studio and is on our list of things to do for a future release.
I encourage you to try these features in Visual Studio and share feedback.
@Andrew, I posted an answer yesterday but somehow it seems it did not get published.
I mentioned in the blog earlier that this functionality will be suppored for VS Pro and above SKU's. Yes you can still use D3DPERF API to name and group events. Its hard to see from the screen shots but the event list is a tree view.
Game development is becoming increasingly important on a wide variety of devices of different form factors. To help Game developers be more productive, we have introduced new tooling support inside Visual Studio. What I have talked about is just a part of whole end-to-end experience, there is more tooling support, for e.g. you can now directly interact with meshes and texture used in your games inside Visual Studio and able to compile HLSL shaders inside Visual Studio with full coloring support for HLSL in VS IDE. More details on what else introduced in terms of tooling look here: channel9.msdn.com/.../Visual-Studio-vNext-DirectX-11-Development-Experience
We want to tie the end-to-end experience for game developers inside Visual Studio. In the future we do see improving the edit, build, debug and analyze cycle for game developers. In this release we have concentrated on parts of the edit, build and debug cycle and not so much on the analyze part of the development cycle (profiling support). We do see this an important aspect of game debugging and have it on the list of things to do in the future.
Please do share feedback about the things you would like to see and things you would like improved in the current experience.
Hi Amit, thanks for the reply! I've also experienced problems posting comments on MSDN blogs recently; I spoke with the support team and they're apparently aware of the issue.
I guess in general my feedback is that these changes just won't improve my productivity in the way Microsoft seems to think they will. I watched that video and didn't see anything that would help me more than the tools Microsoft and others already make. The node-based shader editing is cool to look at, but looks the same as already available elsewhere, and if it's restricted to the Pro version of Visual Studio it's not going to get deployed to artists (what company would spend hundreds on extra VS licenses just for them to use a shader editor?)
I've never felt the need to open meshes or textures in Visual Studio: there are already dedicated tools that do the job fine. Why didn't you just improve PIX so it could show you the meshes in this way?
I've always compiled shaders from within Visual Studio anyway, using custom build rules (which was made *less* productive in VS2010/11 due to the removal of the UI for editing those rules.) The rule pointed at fxc.exe and I manually set up all the command-line flags so the interface was as easy as changing C++ compilation options.
I've also always had syntax highlighting for them by setting my shader file extensions to a "C++ editing experience" and adding the extra HLSL keywords to UserType.dat.
What I actually want to see is what I've badgered anyone at Microsoft who'll listen about for the last few years: PIX for Xbox 360 for Windows. This just seems to be yet another interface for the same basic debugging process. We've already got AMD GPUPS, Intel GPA, NVIDIA NVPerfHUD and Parallel nSight, PIX, gDebugger etc...
Will that support Vertex debugging? Didn't find it in current preview version. And your example happened to be solving problem with per-pixel stage, but what if the culling is incorrect, the vertex shader constants is incorrect and so on, so that there are no pixels out?
Is there work being put into making the output more concise? Looking at the blend state dump, I would rather see "One" rather than "D3D11_BLEND_ONE," and "RGBA (15)" instead of "00001111" for the write mask.