A little more than three months ago, Microsoft hosted the //build/ conference at which they unveiled the upcoming version of Windows (commonly called Windows 8, though I don’t know if the marketing folks have accepted the fact that that is the name most of us are expecting for it yet). They released to the developer world a build of it called the Windows Developer Preview (and Windows Server Developer Preview) along with various tools for creating the new “Metro style” apps. I wasn’t able to make it to //build/ but I’ve watched a lot of the sessions in the past few months (53h43m04s and counting) and I’ve been running the developer preview a lot both on a developer machine and on a Samsung Series 7 Slate that I bought for testing and development.
So far I’m very impressed. As far as UI, there are some small changes I’d like to see. I wish the mouse would work more like touch input; having mouse and touch be different isn’t intuitive (for me) and the touch scheme has a very well-designed flow so I really don’t think it makes sense to keep the mouse in a bizarro legacy interaction style (scroll bars were always a kludge and the metro system bar should be on the right for all input interfaces in my opinion; let people who want the current Metro mouse style select it as a legacy option in Control Panel or at least give those of us who want the mouse to work like touch the option to enable that in Control Panel). But it’s a “developer preview” (i.e. pre-Beta) so such things may change in the beta (expected in late February) and/or in subsequent pre-RTM releases.
I really like the new Metro programming model (with one exception*). And since that’s what this post is about, let me explain it a bit. I want to clear up some misconceptions to begin with.
First, Metro style apps share some design elements (e.g. active tiles rather than dead icons) with Windows Phone but are an evolution from Windows Phone and differ in certain areas, sometimes significantly. If you think it’s all just colored boxes and black backgrounds, then I encourage you to watch Sam Moreau’s talk, Designing Metro style: principles and personality (and also to revisit Windows Phone since it’s evolved quite a bit from its RTM release). I am by no means a designer, but I found it fascinating. I also highly recommend watching Jensen Harris’ talk, 8 traits of great Metro style apps.
Second, Metro style apps don’t replace .NET (or Win32 or Web Applications). You can continue writing .NET apps (including XNA games) and expect them to run without any compatibility problems in Windows 8 Desktop style. Right now it’s not clear whether Desktop style apps will be supported on ARM-based tablets, but if you’re looking to create tablet apps, you really should be using Metro style, not Desktop style, since design of the Windows Runtime (more about that shortly) makes creating touch-friendly apps really easy. If you do any XAML development (WPF, Silverlight) then your XAML skills and even much of your XAML markup will translate directly into the world of Metro style apps. Much of your .NET code will translate directly as well, though there are some differences (and if you’re looking to create WinRT components that can be used in other languages/runtimes then there are some significant differences in order to meet ABI-compatibility requirements that will allow your component to be projected into those other languages in a way that meets the expectations of developers who use those languages. One thing you’ll notice is that .NET 4.5 maintains the same 4.0.30319 version number as .NET 4.0. This is intentional, not an oversight. .NET 4.5 is a superset of .NET 4.0 and the .NET teams at Microsoft have spent a lot of time and effort to make it so that existing .NET 4.0 apps can take advantage of the (in some places huge) performance increases in .NET 4.5 without any changes. There are new APIs (including new APIs for WPF) but backwards compatibility was one of the design goals so you should expect your existing Desktop apps to just work. If you’ve looked at anything about Metro, you’ve undoubtedly seen the (infamous) chart which was designed to highlight aspects of the Windows Runtime and wound up confusing people into thinking that Microsoft lost its mind and threw away decades of work and compatibility. Remember that Microsoft is a company that has built its reputation on backwards compatibility (to the point where they’re still maintaining bug-level compatibility for old 16-bit Windows 3.1 and earlier APIs (with due consideration given to security issues, of course) in order to let companies continue using applications they rely on in the latest versions of Windows.
The takeaway from the above is that WinRT is an OS interface (under the hood it’s design is based on COM with a lot of improvements and advances), just like .NET and Win32. It’s projected into different languages in ways that are natural for that language. Where it makes sense, those projections are done via existing things such as .NET classes. But it doesn’t eliminate the Desktop style version of those models. Just provides a new, clean, modern OS interface that will likely supplant Win32 and .NET within the next 10-15 years for most use cases.
Which gets us to Metro style presentation layers. As of the developer preview, your Microsoft provided options are:
- XAML with C#/VB/C++ (native, not the .NET CLI version); or
- Raw Direct3D (including Direct2D and DirectWrite) with C++.
For high performance game development, Microsoft recommends using Direct3D (and other DirectX APIs) with C++. This gets me to my * above. They haven’t announced a new version of XNA for Metro style apps and the existing XNA, being based on DirectX 9, can’t be used for Metro style apps. This has been a difficult thing to come to terms with. XNA completely changed my life. I’m a better, happier person than I was before I found it. XNA is still the way to go for XBLIG and Windows Phone game development. And you can continue using it to create Desktop style games (it’ll run just like it was Windows 7). But I’m quite sad that they haven’t announced a Metro style version of XNA, though it would certainly be a massive undertaking due to the sea change between DirectX 9 and DirectX 10 (continued in DirectX 11). For those looking for .NET solutions that’ll work in Metro style apps, have a look at SharpDX, (possibly) SlimDX (I believe a Metro-style port is in the works but am not sure), and (possibly) projects like ANX.Framework (not currently targeting Metro style but may in the future).
And thus we arrive at getting started with Metro style DirectX. I’m really excited about the new Windows and about Metro style and the Windows Runtime. I’ve been learning DirectX programming for a while, but it’s taken on a new urgency so the last few months have been a bit of an unexpected cram course for me. But I do believe that I grok it now (or much of it anyway). And I’ve decided to help those of you who are, like myself, XNA/.NET developers who have decided to take the plunge into the world of Metro DX with C++.
Some good news first. If the last time you looked at C++ was around the turn of the millennium, it has become much better. The C++11 (formerly called C++0x) additions make it a much nicer language and the new Windows Runtime stuff that replaces the old C-style Win32 core APIs (no more WndProc and other dark incantations; it’s real objects with events and everything now) is a huge improvement. The improvements to C++ IntelliSense in VS11 are huge and Visual C++ now supports code snippets and other productivity features.
None of this changes the fact that it’s still C++ though. It still has separate header files and code files which makes for a lot of minor annoyances. It still requires you to tell it which libraries to link against (which you do by viewing the project’s properties and then under “Configuration Properties” in “Linking” under “Input” adding them to the “Additional Dependencies” property) and throws compilation hissy fits with horrifying error messages if you make some minor mistake like try to call a static method via, e.g., ThreadPoolTimer.CreatePeriodicTimer(…) rather than ThreadPoolTimer::CreatePeriodicTimer(…) (a thousand apologies oh great compiler for daring to offend you with syntax that you clearly understand but nonetheless consider an abomination). (Yes, me and C++ have a long, at times ugly, history, but with age I’ve learned to mostly just accept it for what it is rather than pointlessly cast aspersions upon it.) Personally, I’d say that I’m now about 75% as efficient in C++ as I am in C# and I don’t really expect that to ever improve since C++ is just more verbose and demanding than C# is and improving it would require changes that would break the language and cause its diehard fans to rise up with torches and pitchforks.
This isn’t a one-off post. I’m planning a series of articles to help relate DirectX 11 to XNA and the C++ Standard Library to the .NET Framework. I can’t commit to a particular schedule but I’m hoping for a cadence of approximately a post a week.
Though I still haven’t actually told you how to get started so I can’t quite wrap up this post. You need a copy of the Windows Developer Preview and VS11 Express for Windows Metro style or VS11 Ultimate. The preview versions of VS11 won’t install on earlier versions of Windows. Note that installing the Windows Developer Preview is a one-way operation; you have to pave and reinstall if you want to go back to Windows 7/Vista/XP. I bought a separate hard drive and installed it to that. Others have used Virtual Machines. Search around; there’s a lot of good advice. For the developer tools version of WDP, you’ll need either a dual layer DVD+/-R or a thumb drive that is at least 8 GB.
Once you have everything installed, you’re ready to begin. I recommend reading Chuck Walbourn’s Getting Started with Direct3D 11 and the materials he links to. I especially recommend reading “Introduction to Direct3D 10” (SIGGRAPH 2007) since Direct3D 11 builds on the huge changes that were introduced in Direct3D 10. One of those changes was to scrap the old caps (capabilities) system that D3D 9 used and replace it with a bucketing system that is now known as feature levels. D3D10 hardware has to implement almost the entire spec (there are only 2-3 things that are optional); the same is true for D3D11 hardware and the D3D11 spec (which is, itself, a superset of D3D10, which is a superset of the capabilities in D3D9). The feature levels allow you to use D3D11 to target most D3D9 GPUs in code (along with D3D10 and 11 GPUs, of course). Rather than build a completely separate rendering pipeline for older cards, you can now just build one base rendering pipeline that works for all hardware and add in more advanced features (like geometry shaders and tessellation) to your graphics pipeline based on the feature level you get back when creating the device along with some performance checks to account for different hardware levels. (An entry level DX11 card may implement all the same things as a high end DX11 card, but it has less ALUs, fewer shader units, a lower clock speed, and slower RAM, all of which combine to produce a distinct difference in performance (and power usage, which is important for laptops and tablets)). The other big change in D3D10 was to change how resources (e.g. textures and vertex buffers) are created such that they are now validated at creation time rather than every time they are bound to the pipeline (as in D3D9). This creates a big performance gain.
The big change in Direct3D 11 was the separation of the graphics device into a device and one (or more) device contexts in order to make multithreading much better. A game will still have one ID3D11Device which is used for things like resource creation (including shaders) but it now will have one ID3D11DeviceContext which serves as the immediate context (i.e. it renders to the back buffer) and zero or more device contexts which are deferred contexts (they render to a command list that the immediate context can then take and execute exceedingly fast). On multicore machines, it can make sense to split off certain rendering operations onto a separate thread in order to perform the CPU side of rendering in parallel (one example being a particle system).
The big change in Metro style DirectX is that D3DX is gone. Desktop apps can still make use of it, but Metro style apps need to use other APIs (e.g. the D3DCompiler_xx.DLL APIs - http://blogs.msdn.com/b/chuckw/archive/2010/04/22/what-s-up-with-d3dcompiler-xx-dll.aspx).
One of the best ways to learn DirectX is with code samples. The samples provided for the Windows Developer Preview are all pretty good and this explanation of the Marble Maze sample does a particularly good job of explaining how a simple 3D game comes together. Much of the code can easily be reused with little-to-no modification for your own games. There’s code that simplifies loading everything from textures to audio to 3D models. I also strongly recommend the //build/ videos about DirectX. They demonstrate a lot of the really neat features that have been added to DirectX and to Visual Studio (PIX is now integrated into Visual Studio, for instance, and you can now do code analysis for C++ (even in the Express version!).
Happy new year to all!