Dela via


Viktiga ändringar från Direct3D 11 till Direct3D 12

Direct3D 12 representerar en betydande avvikelse från Direct3D 11-programmeringsmodellen. Med Direct3D 12 kan appar komma närmare maskinvara än någonsin tidigare. Genom att vara närmare maskinvara är Direct3D 12 snabbare och effektivare. Men kompromissen med att din app har ökat hastigheten och effektiviteten med Direct3D 12 är att du ansvarar för fler uppgifter än du var med Direct3D 11.

Direct3D 12 är en återgång till lågnivåprogrammering. Det ger dig mer kontroll över de grafiska elementen i dina spel och appar genom att introducera dessa nya funktioner: objekt som representerar pipelinens övergripande tillstånd, kommandolistor och paket för arbetsöverföring och beskrivande heaps och tabeller för resursåtkomst.

Din app har ökad hastighet och effektivitet med Direct3D 12, men du ansvarar för fler uppgifter än du var med Direct3D 11.

Explicit synkronisering

  • I Direct3D 12 är CPU-GPU synkronisering nu appens uttryckliga ansvar och utförs inte längre implicit av körningen, som i Direct3D 11. Det innebär också att ingen automatisk kontroll av pipelinerisker utförs av Direct3D 12, så återigen är det appansvaret.
  • I Direct3D 12 ansvarar appar för pipelining av datauppdateringar. D.v.s. mönstret "Map/Lock-DISCARD" i Direct3D 11 måste utföras manuellt i Direct3D 12. Om GPU:n fortfarande använder bufferten i Direct3D 11 när du anropar ID3D11DeviceContext::Map med D3D11_MAP_WRITE_DISCARDreturnerar körningen en pekare till en ny minnesregion i stället för gamla buffertdata. På så sätt kan GPU:n fortsätta att använda gamla data medan appen placerar data i den nya bufferten. Ingen ytterligare minneshantering krävs i appen. den gamla bufferten återanvänds eller förstörs automatiskt när GPU:n är klar med den.
  • I Direct3D 12 styrs alla dynamiska uppdateringar (inklusive konstanta buffertar, dynamiska hörnbuffertar, dynamiska texturer och så vidare) explicit av appen. Dessa dynamiska uppdateringar omfattar alla nödvändiga GPU-staket eller buffring. Appen ansvarar för att hålla minnet tillgängligt tills det inte längre behövs.
  • Direct3D 12 använder referensräkning i COM-stil endast för livslängden för gränssnitt (genom att använda den svaga referensmodellen för Direct3D som är kopplad till enhetens livslängd). Alla livslängder för resurs- och beskrivningsminnen är de enda som appen ansvarar för att underhålla under rätt tid och räknas inte som referens. Direct3D 11 använder referensräkning för att hantera livslängden för gränssnittsberoenden också.

Fysisk minnesplaceringshantering

Ett Direct3D 12-program måste förhindra konkurrensförhållanden mellan flera köer, flera kort och CPU-trådarna. D3D12 synkroniserar inte längre processorn och GPU:n och har inte heller stöd för praktiska mekanismer för resursbyte eller multibuffertning. Stängsel måste användas för att undvika att flera bearbetningsenheter skriver över minnet innan en annan bearbetningsenhet slutför användningen.

Direct3D 12-programmet måste se till att data finns i minnet medan GPU:n läser dem. Minnet som används av varje objekt görs tillgängligt när objektet skapas. Program som anropar dessa metoder måste använda stängsel för att säkerställa att GPU:n inte kommer åt objekt som har avlägsnats.

Resursbarriärer är en annan typ av synkronisering som behövs för att synkronisera resurs- och underresursövergångar på en mycket detaljerad nivå.

Se Minneshantering i Direct3D 12.

Pipelinetillståndsobjekt

Direct3D 11 tillåter manipulering av pipelinetillstånd via en stor uppsättning oberoende objekt. Till exempel kan indatamonterarens tillstånd, pixelskuggningstillstånd, rastreringstillstånd och utdatasammanslagningstillstånd ändras oberoende av varandra. Den här designen ger en bekväm och relativt högnivårepresentation av grafikpipelinen, men den använder inte funktionerna i modern maskinvara, främst eftersom de olika tillstånden ofta är beroende av varandra. Många GPU:er kombinerar till exempel pixelskuggning och utdatasammanslagningstillstånd till en enda maskinvarurepresentation. Men eftersom Direct3D 11-API:et tillåter att dessa pipelinefaser anges separat, kan visningsdrivrutinen inte lösa problem med pipelinetillstånd förrän tillståndet har slutförts, vilket inte är förrän dragningstiden är slut. Det här schemat fördröjer konfigurationen av maskinvarutillståndet, vilket innebär extra omkostnader och färre maximala anrop per bildruta.

Direct3D 12 hanterar det här schemat genom att ena mycket av pipelinetillståndet till oföränderliga pipelinetillståndsobjekt (PSOs), som slutförs när de skapas. Maskinvara och drivrutiner kan sedan omedelbart konvertera PSO till de maskinvaruinbyggda instruktioner och tillstånd som krävs för att köra GPU-arbete. Du kan fortfarande dynamiskt ändra vilken PSO som används, men för att göra det behöver maskinvaran bara kopiera den minimala mängden förberäknat tillstånd direkt till maskinvaruregistren i stället för att beräkna maskinvarutillståndet i farten. Med hjälp av PSO:er minskas anropskostnaderna avsevärt och många fler anrop kan ske per bildruta. Mer information om PSOs finns i Hantera status för grafikpipeline i Direct3D 12.

Kommandolistor och paket

I Direct3D 11 görs all arbetsöverföring via den omedelbara kontexten, som representerar en enda ström med kommandon som går till GPU:n. För att uppnå flertrådad skalning har spel också uppskjutna kontexter tillgängliga för dem. Uppskjutna kontexter i Direct3D 11 mappas inte perfekt till maskinvara, så relativt lite arbete kan göras i dem.

Direct3D 12 introducerar en ny modell för arbetsöverföring baserat på kommandolistor som innehåller hela den information som behövs för att köra en viss arbetsbelastning på GPU:n. Varje ny kommandolista innehåller information som vilken PSO som ska användas, vilken struktur och vilka buffertresurser som behövs och argumenten för alla anrop. Eftersom varje kommandolista är fristående och inte ärver något tillstånd kan drivrutinen förberäkna alla nödvändiga GPU-kommandon i förväg och på ett fritt trådat sätt. Den enda seriell process som krävs är den slutliga överföringen av kommandolistor till GPU:n via kommandokön.

Förutom kommandolistor introducerar Direct3D 12 även en andra arbetsberäkningsnivå: paket. Till skillnad från kommandolistor, som är helt fristående och vanligtvis konstrueras, skickas en gång och ignoreras, ger paket en form av tillståndsarv som tillåter återanvändning. Om ett spel till exempel vill rita två teckenmodeller med olika texturer är en metod att registrera en kommandolista med två uppsättningar identiska anrop. Men en annan metod är att "spela in" ett paket som ritar en modell med en enda tecken och sedan "spela upp" paketet två gånger i kommandolistan med olika resurser. I det senare fallet behöver visningsdrivrutinen bara beräkna lämpliga instruktioner en gång, och att skapa kommandolistan innebär i stort sett två lågkostnadsfunktionsanrop.

Mer information om kommandolistor och paket finns i Work Submission in Direct3D 12.

Beskrivningshögar och tabeller

Resursbindningen i Direct3D 11 är mycket abstrakt och praktisk, men lämnar många moderna maskinvarufunktioner underutnytttagna. I Direct3D 11 skapar spel visa resursobjekt och binder sedan dessa vyer till flera platser i olika skuggningssteg i pipelinen. Skuggare läser i sin tur data från de explicita bindningsplatserna, som är fasta vid dragningstid. Den här modellen innebär att när ett spel ritas med olika resurser måste det binda om olika vyer till olika platser och anropa dragningen igen. Det här fallet representerar också omkostnader som kan elimineras genom att använda moderna maskinvarufunktioner fullt ut.

Direct3D 12 ändrar bindningsmodellen så att den matchar modern maskinvara och förbättrar prestanda avsevärt. I stället för att kräva fristående resursvyer och explicit mappning till platser tillhandahåller Direct3D 12 en beskrivnings heap där spel skapar sina olika resursvyer. Det här schemat tillhandahåller en mekanism för GPU:n att direkt skriva den maskinvarubaserade resursbeskrivningen (deskriptorn) till minnet i förväg. För att deklarera vilka resurser som ska användas av pipelinen för ett visst anrop anger spel en eller flera deskriptortabeller som representerar underintervall för den fullständiga deskriptor-heapen. Eftersom deskriptor-heapen redan har fyllts med lämpliga maskinvaruspecifika deskriptordata är det en extremt låg kostnad att ändra deskriptortabeller.

Förutom de förbättrade prestanda som erbjuds av beskrivande heaps och tabeller tillåter Direct3D 12 också att resurser indexeras dynamiskt i skuggningar, vilket ger oöverträffad flexibilitet och låser upp nya renderingstekniker. Till exempel kodar moderna uppskjutna återgivningsmotorer vanligtvis ett material- eller objektidentifierare av något slag till den mellanliggande g-bufferten. I Direct3D 11 måste dessa motorer vara försiktiga för att undvika att använda för många material, eftersom för många i en g-buffert kan göra det slutliga återgivningspasset betydligt långsammare. Med dynamiskt indexerbara resurser kan en scen med tusen material slutföras lika snabbt som en med bara tio.

Mer information om beskrivande heaps och tabeller finns i Resursbindningoch skillnader i bindningsmodellen från Direct3D 11.

Portning från Direct3D 11

Portning från Direct3D 11 är en process som beskrivs i portning från Direct3D 11 till Direct3D 12. Se även alternativen i Arbeta med Direct3D 11, Direct3D 10 och Direct2D.

Understanding Direct3D 12