I love it when people agree with me:
http://techreport.com/review/26239/a-closer-look-at-directx-12
The question, then, almost asks itself. Did AMD's work on Mantle motivate Microsoft to introduce a lower-level graphics API?
When I spoke to AMD people a few hours after the D3D12 reveal, I got a strong sense that that wasn't the case—and that it was developers, not AMD, who had spearheaded the push for a lower-level graphics API on Windows. Indeed, at the keynote, Microsoft's Development Manager for Graphics, Anuj Gosalia, made no mention of Mantle. He stated that "engineers at Microsoft and GPU manufacturers have been working at this for some time," and he added that D3D12 was "designed closely with game developers."
I then talked with Ritche Corpus, AMD's Software Alliances and Developer Relations Director. Corpus told me that AMD shared its work on Mantle with Microsoft "from day one" and that parts of Direct3D 12 are "very similar" to AMD's API. I asked if D3D12's development had begun before Mantle's. Corpus' answer: "Not that we know." Corpus explained that, when AMD was developing Mantle, it received no feedback from game developers that would suggest AMD was wasting its time because a similar project was underway at Microsoft. I recalled that, at AMD's APU13 event in November 2013, EA DICE's Johan Andersson expressed a desire to use Mantle "everywhere and on everything." Those are perhaps not the words I would have used if I had known D3D12 was right around the corner.
The day after the D3D12 keynote, I got on the phone with Tony Tamasi, Nvidia's Senior VP of Content and Technology. Tamasi painted a rather different picture than Corpus. He told me D3D12 had been in in the works for "more than three years" (longer than Mantle) and that "everyone" had been involved in its development. As he pointed out, people from AMD, Nvidia, Intel, and even Qualcomm stood on stage at the D3D12 reveal keynote. Those four companies' logos are also featured prominently on the current landing page for the official DirectX blog:
Tamasi went on to note that, since development cycles for new GPUs span "many years," there was "no possible way" Microsoft could have slapped together a new API within six months of Mantle's public debut.
Seen from that angle, it does seem quite far-fetched that Microsoft could have sprung a new graphics API on a major GPU vendor without giving them years to prepare—or, for that matter, requesting their input throughout the development process. AMD is hardly a bit player in the GPU market, and its silicon powers Microsoft's own Xbox One console, which will be one of the platforms supporting D3D12 next year. I'm not sure what Microsoft would stand to gain by keeping AMD out of the loop.
I think it's entirely possible AMD has known about D3D12 from the beginning, that it pushed ahead with Mantle anyhow in order to secure a temporary advantage over the competition, and that it's now seeking to embellish its part in D3D12's creation. It's equally possible AMD was entirely forthright with us, and that Nvidia is simply trying to downplay the extent of its competitor's influence.
So we're down to "he said, she said" on the timeline here, though I stand by my theory. There's no way AMD wasn't aware of DX12 cooking, and a three year lead time on the API is typical given the time it takes to develop the hardware built around it.
As for the actual API changes:
Direct3D 12 . . . [unifies] much of the pipeline state into immutable pipeline state objects (PSOs), which are finalized on creation. This allows hardware and drivers to immediately convert the PSO into whatever hardware native instructions and state are required to execute GPU work. Which PSO is in use can still be changed dynamically, but to do so the hardware only needs to copy the minimal amount of pre-computed state directly to the hardware registers, rather than computing the hardware state on the fly. This means significantly reduced draw call overhead, and many more draw calls per frame.
This is a huge biggie, and something I've been hoping for a while now. Moving on:
Direct3D 12 introduces a new model for work submission based on command lists that contain the entirety of information needed to execute a particular workload on the GPU. Each new command list contains information such as which PSO to use, what texture and buffer resources are needed, and the arguments to all draw calls. Because each command list is self-contained and inherits no state, the driver can pre-compute all necessary GPU commands up-front and in a free-threaded manner. The only serial process necessary is the final submission of command lists to the GPU via the command queue, which is a highly efficient process.
D3D12 takes things a step further with a construct called bundles, which lets developers re-use commands in order to further reduce driver overhead:
In addition to command lists, Direct3D 12 also introduces a second level of work pre-computation, bundles. Unlike command lists which are completely self-contained and typically constructed, submitted once, and discarded, bundles provide a form of state inheritance which permits reuse. For example, if a game wants to draw two character models with different textures, one approach is to record a command list with two sets of identical draw calls. But another approach is to "record" one bundle that draws a single character model, then "play back" the bundle twice on the command list using different resources. In the latter case, the driver only has to compute the appropriate instructions once, and creating the command list essentially amounts to two low-cost function calls.
So now instead of a massive command stream, we have both a state independent command list, and an easily reusable command list.
nstead of requiring standalone resource views and explicit mapping to slots, Direct3D 12 provides a descriptor heap into which games create their various resource views. This provides a mechanism for the GPU to directly write the hardware-native resource description (descriptor) to memory up-front. To declare which resources are to be used by the pipeline for a particular draw call, games specify one or more descriptor tables which represent sub-ranges of the full descriptor heap. As the descriptor heap has already been populated with the appropriate hardware-specific descriptor data, changing descriptor tables is an extremely low-cost operation.
In addition to the improved performance offered by descriptor heaps and tables, Direct3D 12 also allows resources to be dynamically indexed in shaders, providing unprecedented flexibility and unlocking new rendering techniques. As an example, modern deferred rendering engines typically encode a material or object identifier of some kind to the intermediate g-buffer. In Direct3D 11, these engines must be careful to avoid using too many materials, as including too many in one g-buffer can significantly slow down the final render pass. With dynamically indexable resources, a scene with a thousand materials can be finalized just as quickly as one with only ten.
Every engine that uses deferred rendering techniques just got a massive speed boost.
Think about memory management, for example. The way DirectX 11 works is, if you want to allocate a texture, before you can use it, the driver basically pre-validates that that memory is resident on the GPU. So, there's work going on in the driver and on the CPU to validate that that memory is resident. In a world where the developer controls memory allocation, they will already know whether they've allocated or de-allocated that memory. There's no check that has to happen. Now, if the developer screws up and tries to render from a texture that isn't resident, it's gonna break, right? But because they have control of that, there's no validation step that will need to take place in the driver, and so you save that CPU work.
A speed hack, but one that makes sense. That being said, I would expect more "game breaking" bugs to slip through to release as a result, since less stuff is going to get caught within the driver during development. Personally, I'd keep the validation around just for the debugging, but have a way to disable it for the release.
Overall, I'm liking the improvements on the DX front, though its clear nothing new graphically is getting pushed this go around. Like DX10 and DX11, this is more or less a release to fix the low-hanging fruit within the API.