Tatsächlich stellt PSO-Management eins der häufigsten Probleme dar. Wenn deine Engine (wie viele Engines) ein DX11 (oder sogar DX9) orientiertes Design hat, ist das weitgehend inkompatibel mit vielen DX12 Konzepten. Der einzige Vorteil den du dann hast, ist, das du mal siehst was du dem Treiber bisher zugemutet hast! (
)
Also: Idealerweise würdest du dein Usercode/Highlevel-Render-Code/etc (wie bereits von dot und Schrompf angesprochen) so designen das du im Voraus weißt was für Pipelines du brauchst. D.h. du könntest PSOs wie Assets behandeln und einfach mit allen anderen Assets laden. Dafür brauchst du Kontrolle über deine Pipeline, also keine fein granulares "SetXYZ"-Stateinterface mehr. Mit einem "Stateless-Rendering"-Design (einfach mal googlen) bekommst du das quasi "umsonst". Das hat viele nette Nebeneffekte, dein Rendercode wird deutlich sauberer, dein Spiel bekommt keine "zufälligen" Framespikes usw...
Falls ein Refactoring für dein Highlevel-Code nicht möglich ist dann gibt es natürlich andere Optionen. Viele Engines haben eine art Statemanager in dem Pipeline-States getracked werden. Wenn du einen Draw/Dispatch absetzt wird ein neues PSO erzeugt (oder ein altes, äquivalentes PSO aus einem Dictionary geladen). Der Ansatz funktioniert selbst mit "DX9-Style" Interfaces aber kann
extreme Framedrops zur Folge haben. Das Problem ist nämlich, dass die Zeit zum Compilen von PSOs gern mal im Millisekundenbreich liegen kann. Um das zu vermeiden kannst du eine Liste von den am häufigst genutzten PSOs führen und beim Programmstart erstellen. Wie du an die Informationen kommst bleibt dir überlassen, das kann so simpel sein wie, einfach das Spiel zu spielen und sich alle erzeugten PSO-Beschreibungen zu dumpen, fertig! (Doom macht das z.B. so mit deren Vulkan Implementierung).
Damit wirst du aber sicherlich keine optimale Performanz erreichen können. Dafür ist es absolut notwendig dein Design auf einer hohen Ebene zu ändern:
"DX12-Backends profitieren von Applikationswissen und sollten
so flach wie möglich sein. Einen DX11-Treiber zu emulieren wird zwangsläufig in schlechter(er) Performanz enden"
Ein wesentlicher Unterschied scheint mir im Moment vor allem das Erstellen eines Pipeline-State Objekts zu sein.
Auch andere Konzepte unterscheiden sich deutlich von DX11/GL. PSOs sind nur eines von vielen Puzzleteilen (aka Stolpersteinen??) die notwendig sind um ein wirklich performantes DX12-Backend zu bekommen.