I was relieved when the comments on my earlier post about backward compatibility agreed with the approach we chose for XNA Game Studio 4.0. Banjobeni summed up the general sentiment:
"If you break it, break it good."
The initial motivation for breaking changes in XNA GS 4.0 was the addition of Windows Phone, but this is about more than any one platform. A quick history lesson:
Version 1.0 of the XNA Framework was designed around DirectX 9 on Windows. We had little time to create an enormous API, so had to move fast and decisively. In retrospect I think we did a great job choosing the right places to concentrate our design efforts, and I’m proud of what we built, but there were many areas where we decided “hey, we don’t have time to agonize over this detail, so let’s just copy whatever native DirectX 9 does, and move on”.
When we started work on Xbox 360 in the second half of the 1.0 development schedule, some of these hasty decisions needed to be revised (and some were revised further in our 2.0 release), but many were left alone. Even when things didn’t exactly fit the Xbox, they were similar enough that we could squint and say “yeah, that’s close enough to get the job done”.
When we looked at the new phone platform, we found more things that did not work quite the same as on Windows. Had we tried to squint until they looked the same, we would have ended up with our eyes screwed most of the way shut! I’m a perfectionist, and that just didn’t feel good enough.
Ok, let’s change our API in the places necessary to make the phone consistent with our other platforms.
But breaking changes are expensive. Having gone three years without any major breaks, we felt this was a good time to introduce an inflection point, cleaning up our act and setting ourselves up for the future. But we also felt it was important that this be a one time thing. Breaking changes every three years may be ok, but every year, or every six months, most certainly would not. If we’re going to break it, let’s break it good, taking all the pain in one go so we don’t have to break again for many years to come.
So, we took the opportunity provided by the phone to also reduce those nagging Windows vs. Xbox inconsistencies.
We also used this opportunity to improve usability, applying our three years of experience to look at which things cause the most confusion for our customers, and tweaking these APIs to reduce the chance of error.
Finally, we gazed deep into our crystal ball in an attempt to predict the future. This failed miserably (sadly, it turns out I am not psychic at all so instead I made some guesses. XNA Game Studio 4.0 sits on top of DirectX 9 on both Windows and Xbox 360, and we have no immediate plans to move to DirectX 10 or 11, but looking years into the future, it seems at least possible we might someday want to do that. DirectX 11 adds some things that are not in DirectX 9, but it also changes and in some cases removes features. Adding features is relatively painless from a compatibility perspective (it’s easy to imagine how a third profile could someday sit alongside Reach and HiDef) but taking things away hurts deep (it would suck if any such third profile could not be a strict superset of HiDef, in the same way that HiDef is a superset of Reach). So we looked at what it would take to implement our API using DirectX 11, and made sure we didn’t include anything that would make this excessively difficult. I am not promising we will ever support DirectX 11, just saying we did some thinking about this and laid some groundwork so if we ever do want it, we can go there without having to break backward compatibility.
An overarching goal of these API tweaks was that even though we are breaking things, we still want the new API to feel like the XNA Framework you know and love. Some of the details may be different, but existing developer knowledge and design patterns should be easy to move across.
Another goal was to prefer simplicity over complexity. I am a big believer in minimalist design. It’s easy to add new things each time we encounter a new problem, but I think more valuable to hone them down to their core essence, trying to find the minimum surface area necessary to communicate between developer and runtime. It makes me happy that the XNA Framework 4.0 API surface is significantly smaller than the 3.1 version.
I’ll be writing more about these changes and the reasons behind them over the coming weeks, but here is a quick summary of the more significant breaking changes:
- Replaced StorageContainer.TitleLocation with a new OpenStream API
- Replaced individual graphics renderstates with a new state objects API
- Premultiplied alpha is now enabled by default
- Made it easier to use SpriteBatch with custom renderstates and custom shaders
- No more SpriteBatch vertex shader magic, so you can easily position SpriteBatch text in a 3D world using BasicEffect
- Vertex buffers are now strongly typed, each one having an associated VertexDeclaration
- You no longer need to specify a VertexDeclaration before drawing, because this is implicit in your choice of vertex buffer
- Vertex buffer sizes are now specified as number of vertices rather than bytes
- Replaced GraphicsDevice.Vertices with a new SetVertexBuffer API
- Each rendertarget now has an associated depth buffer: no more DepthStencilBuffer type
- RenderTarget2D now inherits Texture2D: no more GetTexture method
- SetRenderTarget atomically sets all rendertargets, rather than changing just one layer
- Replaced Effect.Begin and End with a new EffectPass.Apply method
- Removed the low level shader APIs (VertexShader, PixelShader, Set*ShaderConstant)
- Removed EffectPool, StateBlock, GammaRamp, ClipPlane
- Removed triangle fans
- Removed point sprites
- Changed the Color type from BGRA to RGBA byte ordering
I suspect some of you will have concerns about some of these removals. Don’t panic! This article is already too long, and I’m running out of time to write more, but I am confident once I explain the why, how, and wheretofore of these changes, you will agree they are good and sensible. If there are specific things you would like me to write about first, please let me know via the comments below.