Geht es da jetzt eigentlich um Draw Calls?
Es geht hauptsächlich darum den CPU Overhead zu minimieren. Viele PC Spiele sind aktuell "CPU bound" und können die Möglichkeiten von modernen Grafikkarten nicht wirklich nutzen. Das Problem liegt in der Logik die in OpenGL und DirectX 9/10/11 Treibern implementiert wird. Da wird auf Treiberebene versucht möglichst viele Pitfalls zu umgehen, über die eine Anwendung stolpern könnte. Zwei Beispiele:
Beispiel 1:
Die GPU läuft weitgehend asynchron zur CPU. Die CPU bereitet sog. Commandbuffer vor, mit allen Operationen die auf der GPU ausgeführt werden (Ressourcen binden, Kopieroperationen, Drawcalls etc...). Wenn eine Anwendung also eine Funktion auf einem Immediate-Context aufrufst (z.B.
DrawIndexed) dann wird dieses Kommando nicht direkt an die GPU weitergeleitet, sondern erstmal in einem Puffer gemerkt (auch wenn die Bezeichnung 'Immediate Device Context' anderes suggeriert). Irgendwann wir der Puffer dann an die GPU weitergereicht und dort abgearbeitet. Die CPU kann durchaus mehrere Frames vorbereiten und die GPU arbeitet diese dann später ab, dadurch muss die CPU nicht auf die GPU warten und kann diese Zeit für andere Operationen verwenden.
Dies bringt viele Probleme mit sich, die umgangen/behandelt werden müssen. Nimmt man z.B. ein CPU-Partikelsystem. Die Partikeldaten werden pro Frame in einen Puffer geschrieben, der dann von der GPU gelesen wird, d.h. der Puffer wird pro Frame überschrieben. Wenn die GPU ohnehin schon einie Frames hinterherhinkt, dann würde das den bereits gebundenen Puffer für alle vorherigen Frames einfach überschreiben. Um dies zu verhindern implementieren Treiber ein 'renaming' Mechanismus. Im einfachsten Fall wird geschaut ob der Puffer (die Ressource) noch in einem Commandbuffer referenziert wird, der noch nicht abgearbeitet wurde. Ist dies der Fall, wird ein neuer Speicherbereich allokiert und (transparent für die Anwendung) ausgetauscht.
Beispiel 2:
Anwendungen geben GPU Ressourcen frei (z.B. bei Streaming Systemen i.Ä.). Werden die entsprechenden Ressourcen aber noch von der GPU benötigt dann gibts Zugriffe auf nicht verfügbaren Speicher. Im besten Fall resultiert das in einen GPU-Hang (o.Ä.) und wird vom System über ein Treibrereset abgefangen. Die Anwendung stürzt dennoch ab. Treiber versuchen also zu 'tracken' ob Ressourcen noch von einer GPU benötigt werden und verzögern das Löschen entsprechend.
Mit dieser (und viel andere Logik) sorgen Treiber dafür, das Anwendungen ziemlich sorglos tun können was sie wollen. Früher war das sogar noch toleranter, DX9 z.B. patched nicht verfügbare Vertexattribute usw... Weil Treiber aber nichts über die speziellen Anwendungeanforderungen wissen, muss die Logik möglichst allgemein Funktionieren. Das kostet i.A. massiv CPU Power die im Grunde oft gar nicht notwendig ist.
Vulkan und DirectX 12 gehen einen anderen Weg. Der ganze Overhead fliegt aus den Treibern raus und wird an die Anwendungen übertragen. D.h. alle Problemfälle müssen von Anwendungen behandelt werden. Das ermöglicht es den Anwendungen aber sehr spezielle Lösungen für die Probleme zu finden und den unnützen CPU Overhead einfach zu reduzieren.
Ein weiteres Problem von DX11/GL ist, das die APIs nicht wirklich für Multithreading ausgelegt waren. Das ist absoluter Unsinn im Hinblick darauf, das aktuelle Systeme immer mehr Prozessorkerne bekommen und die Leistung überhaupt nicht genutzt werden kann. DX12 und Vulkan ändern das, so das Anwendungen den Frame auf mehrere Kerne verteilen können und so nochmals deutlich Performanz gewinnen können.
Im Normalfall wird es also für Anwendungen deutlich einfacher sein GPU bound zu werden, d.h. die GPU Leistung optimal (besser) ausnutzen zu können. Hier wird oft, als anschauliches Beispiel, die große Anzahl der möglichen Drawcalls aufgezeigt. Eigentlich geht es eher darum das die CPU Kosten extrem sinken und die Anwendung i.A. einfach viel
mehr machen können. Im Rückschluss kann das durchaus bessere Grafik bedeuten aber es ist auch für mobile Endgeräte interessant wenn die CPU dadurch weniger Energie benötigt.