Vylepšené bariéry D3D12

Rozhraní DDI pro vylepšené bariéry je k dispozici ve Windows 11 verze 22H2 WDK (WDDM 3.0). Pokud chcete používat vylepšené bariéry ve verzích 22H2 (nebo starších verzích operačního systému), musíte nainstalovat SDK 1.706.4-preview.

Vylepšené bariéry D3D12 poskytují vývojářům nezávislou kontrolu nad synchronizací práce GPU, přechody rozložení textury a vyprázdněním mezipaměti (přístup k paměti prostředků). Tato funkce nabízí sadu rozhraní API Direct3D a DDI, které vývojářům poskytují nezávislou kontrolu nad synchronizací práce GPU, přechody rozložení textury a vyprázdněním mezipaměti (přístup k paměti prostředků).

Vylepšené překážky nahrazují starší bariéry výraznějšími typy bariér. Mají následující funkce:

  • Menší latence synchronizace.
  • Snížení nadměrného vyprázdnění mezipaměti.
  • Žádná záhadná pravidla povýšení a rozpadu.
  • Rychlé a flexibilní aliasování prostředků (různé aliasové topologie).
  • Zlikvidujte během přechodu bariéry.
  • Podpora souběžného čtení a zápisu, včetně kopie v rámci stejného prostředku (vlastní kopie).
  • Podpora asynchronních příkazů Zahodit, Kopírovat, Řešit a Vyčistit

Vylepšené bariéry nejsou jednodušší než starší bariéry prostředků, ale jsou méně nejednoznačné, a proto jsou pro vývojáře jednodušší.

Zprávy o rozšířené podpoře bariér

Funkce vylepšených bariér není v současné době požadavkem na hardware ani ovladač. Ovladač označuje podporu nastavením členu EnhancedBarriersSupported v D3D12DDI_D3D12_OPTIONS_DATA_0089 na TRUE.

  • D3D12DDI_FEATURE_VERSION_VIDEO_0088_0 je číslo verze, které definuje předběžnou implementaci milníků rozšířených bariér D3D12 zavedených ve Windows 11.

Vylepšené funkce zpětného volání zábran D3D12

Ovladače, které označují podporu vylepšených překážek, implementují následující funkce zpětného volání:

Detaily návrhu

Ovladače obvykle zpracovávají zděděné překážky prostředků pomocí tří samostatných operací.

  1. Synchronizace práce s GPU
  2. Proveďte všechny potřebné operace vyprázdnění mezipaměti.
  3. Proveďte potřebné změny rozložení.

Vylepšené bariéry umožňují vývojářům řídit každou z těchto operací samostatně.

Typy vylepšených bariér

Existují tři typy vylepšených bariér:

Rozsahové bariéry nahrazují starší bariéry prostředků. K dispozici jsou rozsahové bariéry, aby bylo možné plně implementovat starší bariéry prostředků bez znatelné ztráty výkonu.

  • Všechny typy bariér řídí synchronizaci práce GPU a typy přístupu pro čtení nebo zápis před a za bariérou.

  • Bariéry textury navíc spravují rozložení podsourců textury. Výběr dílčího zdroje se dá vyjádřit jako rozsah řezů mip, pole a roviny, a navíc jako známou možnost 1 nebo vše, kterou používají starší překážky zdrojů.

  • Bariéry vyrovnávací paměti a globální bariéry řídí pouze synchronizaci a přístup k prostředkům a nemají vliv na rozložení zdrojů (vyrovnávací paměti nemají rozložení). Globální bariéry ovlivňují veškerou paměť uloženou v mezipaměti, takže mohou být nákladné a měly by se používat pouze v případě, že bariéra s užším rozsahem není dostačující.

Texturové bariéry

  • Řídit vyprázdnění mezipaměti, rozložení paměti a synchronizaci pro podresurzy textury.
  • Musí být používáno pouze se zdroji textury.
  • Povolit výběr jednoho podsourcu, všech dílčích zdrojů nebo koherentního rozsahu dílčích zdrojů (to znamená rozsah mip a rozsah polí).
  • Musí obsahovat platný ukazatel prostředku, který není null.

Vyrovnávací bariéry

  • Kontrola vyprázdnění a synchronizace mezipaměti pro zdroje vyrovnávací paměti.
  • Smí být použity pouze s vyrovnávací pamětí.
  • Na rozdíl od textur mají vyrovnávací paměti pouze jeden podzdroj a nemají rozložení, které je možné při přechodu změnit.
  • Musí obsahovat platný ukazatel prostředku, který není null.

Globální bariéry

  • Řídit vyprazdňování a synchronizaci mezipaměti pro všechny uvedené typy přístupu k prostředkům v jedné příkazové frontě.
  • Nemá žádný vliv na rozložení textury.
  • Jsou potřeba k poskytování funkcí podobných starším bariérám NULL UAV a bariérám aliasů NULL/NULL.

Vzhledem k tomu, že globální bariéry nepřecházejí rozložení textury, globální bariéry se nedají použít v přechodech, které by jinak vyžadovaly změnu rozložení. Globální bariéra se například nedá použít k přechodu textury bez souběžného přístupu z D3D12DDI_BARRIER_ACCESS_RENDER_TARGET na D3D12DDI_BARRIER_ACCESS_SHADER_RESOURCE, protože to by také vyžadovalo změnu z D3D12DDI_BARRIER_LAYOUT_RENDER_TARGET na D3D12DDI_BARRIER_LAYOUT_SHADER_RESOURCE.

Synchronizace

Grafické procesory jsou navržené tak, aby prováděly co nejvíce práce paralelně. Před přístupem k závislým datům se musí synchronizovat jakákoli práce s GPU, která závisí na předchozí práci s GPU.

Rozšířené bariérové rozhraní používá explicitní hodnoty SyncBefore a SyncAfter jako masky logických bitových polí. Před spuštěním bariéry musí počkat na dokončení všech předcházejících rozsahů SyncBefore. Podobně musí bariéra blokovat všechny následné rozsahy SyncAfter , dokud se bariéra dokončí. D3D12DDI_BARRIER_SYNC určuje rozsah synchronizace práce GPU s ohledem na bariéru.

Další informace naleznete ve specifikaci Enhanced Barriers.

Přechody rozložení

Podsourcy textury můžou používat různá rozložení pro různé metody přístupu. Textury se například často komprimují, když se používají jako cíl vykreslení nebo vzorník hloubky, a jsou často dekomprimovány pro čtení nebo kopírování příkazů shaderu. Bariéry textury používají hodnoty LayoutBefore a LayoutAfterD3D12DDI_BARRIER_LAYOUT k popisu přechodů rozložení.

Přechody rozložení jsou potřeba pouze pro textury, takže jsou vyjádřeny pouze v datové struktuře D3D12DDI_TEXTURE_BARRIER.

LayoutBefore i LayoutAfter musí být kompatibilní s typem fronty, která provádí bariéru. Například výpočetní fronta nemůže přepnout dílčí zdroj do nebo z D3D12DDI_BARRIER_LAYOUT_RENDER_TARGET.

K zajištění dobře definovaného pořadí bariér je konečným rozložením podsouboru po dokončení posloupnosti bariér LayoutAfter v sekvenci.

Přechody přístupu

Vzhledem k tomu, že mnoho operací zápisu GPU se ukládá do mezipaměti, můžou všechny bariéry z přístupu k zápisu do jiného přístupu k zápisu nebo přístup jen pro čtení vyžadovat vyprázdnění mezipaměti. Rozšířená bariérová rozhraní API používají přechody přístupu k označení, že paměť podsourcu musí být viditelná pro konkrétní nový typ přístupu. Podobně jako přechody rozložení nemusí být některé přechody přístupu potřeba, pokud je známo, že paměť přidruženého podsourcu je již přístupná pro požadované použití.

Přechody přístupu jsou vyjádřeny takto:

  • Pro textury jako součást struktury D3D12DDI_TEXTURE_BARRIER.
  • Pro vyrovnávací paměti jako součást struktury D3D12DDI_BUFFER_BARRIER.

Přechody přístupu neprovádějí synchronizaci. Očekává se, že synchronizace mezi závislými přístupy se zpracovává pomocí odpovídajících hodnot SyncBefore a SyncAfter v bariérě.

Viditelnost AccessBefore pro zadaný AccessAfter nezaručuje, že paměť prostředku je viditelná také pro jiný typ přístupu. Například:

MyTexBarrier.AccessBefore=D3D12DDI_BARRIER_ACCESS_UNORDERED_ACCESS;
MyTexBarrier.AccessAfter=D3D12DDI_BARRIER_ACCESS_SHADER_RESOURCE;

Tento přechod přístupu označuje, že následný přístup shaderu pro čtení závisí na předchozím neuspořádaném přístupu k zápisu. Pokud ale hardware dokáže číst shaderové zdroje přímo z mezipaměti UAV, ovladač nemusí mezipaměť UAV skutečně vyprázdnit.

D3D12DDI_BARRIER_ACCESS_COMMON

D3D12DDI_BARRIER_ACCESS_COMMON je speciální typ přístupu, který označuje přístup, který je kompatibilní s libovolným rozložením. Přechod na D3D12DDI_BARRIER_ACCESS_COMMON znamená, že data podsouboru musí být k dispozici pro jakýkoli kompatibilní přístup s rozvržením po bariéře. Vzhledem k tomu, že vyrovnávací paměti nemají žádné rozložení, D3D12DDI_BARRIER_ACCESS_COMMON jednoduše znamená jakýkoli přístup kompatibilní s vyrovnávací pamětí.

Určení D3D12DDI_BARRIER_ACCESS_COMMON jako AccessBefore v bariérě znamená sadu všech typů přístupu k zápisu. Použití D3D12DDI_BARRIER_ACCESS_COMMON jako AccessBefore se nedoporučuje, protože by to mohlo vést k nákladným, nezamýšleným vyprázdnění mezipaměti. Místo toho se vývojářům doporučuje používat pouze nejužší požadované bity pro přístup k zápisu, aby správně omezili režijní náklady na bariéru. Upozornění na vrstvu ladění se vydává, když je AccessBefore nastavený na D3D12DDI_BARRIER_ACCESS_COMMON.

Současný přístup k jedné frontě

Vylepšené bariéry umožňují souběžné operace čtení a zápisu ve stejném bufferu nebo textuře se simultánním přístupem ve stejné frontě příkazů.

Vyrovnávací paměti a prostředky souběžného přístupu vždy podporují přístup k zápisu z jedné fronty se souběžnými, nezávislými přístupy pro čtení z jedné nebo více jiných front. Tato podpora je způsobená tím, že tyto prostředky vždy používají společné rozložení a nemají žádné nebezpečí čtení a zápisu, protože čtení nesmí záviset na souběžných zápisech. (Starší pravidla bariér prostředků nepovolují kombinování bitů stavu zápisu s jinými bity stavu. Proto není možné zdroje současně číst a zapisovat ve stejné frontě pomocí starších bariér prostředků.)

Zásady jednorázového zápisu se stále vztahují, protože dvě zdánlivě nepřekryvující oblasti zápisu můžou mít překrývající se řádky mezipaměti.

Rozsahy podzdrojů

Je běžné, že vývojáři chtějí převést řadu podresursů. Příkladem je přechod úplného mip-řetězce pro dané texturové pole nebo jedné úrovně mip pro všechny části pole. Vylepšené bariéry umožňují vývojářům přecházet logicky sousední oblasti podsourců pomocí struktury D3D12DDI_BARRIER_SUBRESOURCE_RANGE . (Starší překážky přechodu stavu prostředků poskytují vývojářům možnost přechodu všech stavů podzdrojů nebo jednoho stavu podzdroje atomicky.)

Rozložení výpočetních a přímých front

Pro přímé i výpočetní fronty jsou zaručená stejná následující rozšířená rozložení bariér :

  • D3D12DDI_BARRIER_LAYOUT_GENERIC_READ
  • D3D12DDI_BARRIER_LAYOUT_UNORDERED_ACCESS
  • D3D12DDI_BARRIER_LAYOUT_SHADER_RESOURCE
  • D3D12DDI_BARRIER_LAYOUT_COPY_SOURCE
  • D3D12DDI_BARRIER_LAYOUT_COPY_DEST

Podsourc v jednom z těchto rozložení lze použít buď v přímých frontách, nebo ve výpočetních frontách bez přechodu rozložení.

U některých typů hardwaru mohou být bariéry přechodu rozložení u přímých front výrazně rychlejší, pokud jsou předchozí a následné přístupy také v režimu přímých front. Důrazně doporučujeme přistupovat k prostředkům v přímých frontách pomocí následujících rozložení:

  • D3D12DDI_BARRIER_LAYOUT_DIRECT_QUEUE_GENERIC_READ
  • D3D12DDI_BARRIER_LAYOUT_DIRECT_QUEUE_UNORDERED_ACCESS
  • D3D12DDI_BARRIER_LAYOUT_DIRECT_QUEUE_SHADER_RESOURCE
  • D3D12DDI_BARRIER_LAYOUT_DIRECT_QUEUE_COPY_SOURCE
  • D3D12DDI_BARRIER_LAYOUT_DIRECT_QUEUE_COPY_DEST

Varianty rozložení DIRECT_QUEUE nejsou kompatibilní s výpočetními frontami a nelze je použít v bariérách seznamu příkazů pro výpočetní úlohy. Jsou však kompatibilní s výpočetními operacemi v přímých frontách.

Bezbariérový přístup

Vzhledem k tomu, že mezi hranicemi ExecuteCommandLists nesmí být žádné čekající příkazy ani operace vyprázdnění mezipaměti, mohou být vyrovnávací paměti zpočátku přístupné v rámci ExecuteCommandLists bez bariéry. Podobně mohou být dílčí zdroje textury také zpočátku přístupné bez bariéry za následujících podmínek:

  • Rozložení podsourcu je kompatibilní s typem přístupu.
  • Inicializují se všechna potřebná metadata komprese.

Podsourcy textury v rozložení D3D12DDI_BARRIER_LAYOUT_COMMON (nebo běžném rozložení specifickém pro frontu, jako je D3D12DDI_BARRIER_LAYOUT_DIRECT_QUEUE_COMMON), které nemají žádné potenciálně nevyřízené operace čtení nebo zápisu, lze přistupovat v příkazovém streamu ExecuteCommandLists bez překážky s použitím některého z následujících způsobů přístupu:

  • D3D12DDI_BARRIER_ACCESS_SHADER_RESOURCE
  • D3D12DDI_BARRIER_ACCESS_COPY_SOURCE
  • D3D12DDI_BARRIER_ACCESS_COPY_DEST

Kromě toho může vyrovnávací paměť nebo textura se společným rozložením specifickým pro frontu používat D3D12DDI_BARRIER_ACCESS_UNORDERED_ACCESS bez bariéry.

K vyrovnávacím pamětím a texturám souběžného přístupu (textury vytvořené pomocí příznaku D3D12DDI_RESOURCE_FLAG_ALLOW_SIMULTANEOUS_ACCESS) je možné zpočátku přistupovat v datovém proudu příkazu ExecuteCommandLists bez bariéry pomocí některého z následujících typů přístupu:

  • D3D12DDI_BARRIER_ACCESS_VERTEX_BUFFER
  • D3D12DDI_BARRIER_ACCESS_CONSTANT_BUFFER
  • D3D12DDI_BARRIER_ACCESS_INDEX_BUFFER
  • D3D12DDI_BARRIER_ACCESS_RENDER_TARGET
  • D3D12DDI_BARRIER_ACCESS_UNORDERED_ACCESS
  • D3D12DDI_BARRIER_ACCESS_SHADER_RESOURCE
  • D3D12DDI_BARRIER_ACCESS_STREAM_OUTPUT
  • D3D12DDI_BARRIER_ACCESS_INDIRECT_ARGUMENT
  • D3D12DDI_BARRIER_ACCESS_COPY_DEST
  • D3D12DDI_BARRIER_ACCESS_COPY_SOURCE
  • D3D12DDI_BARRIER_ACCESS_RESOLVE_DEST
  • D3D12DDI_BARRIER_ACCESS_RESOLVE_SOURCE
  • D3D12DDI_BARRIER_ACCESS_PREDICATION

Další přístupy lze provést také bez bariéry bez více než jednoho typu přístupu k zápisu. S výjimkou D3D12DDI_BARRIER_ACCESS_RENDER_TARGET se však musí překážky použít ke vyprázdnění sekvenčních zápisů do stejného prostředku.

Kopie vlastního zdroje

I když nesouvisí výhradně s vylepšenými bariérami, schopnost povolit kopie z jedné oblasti podsourcu do jiné neintersekcené oblasti je vysoce požadovaná funkce. S vylepšenými bariérami lze dílčí zdroj se společným rozložením použít jako zdroj i cíl ve stejném volání CopyBufferRegion nebo CopyTextureRegion. Kopie mezi protínajícími oblastmi zdrojové a cílové paměti vytvářejí nedefinované výsledky. Ladicí vrstva musí tyto výsledky ověřit. (Starší návrh bariéry prostředků neumožňuje, aby se podsoučástka nacházela současně ve stavu D3D12DDI_RESOURCE_STATE_COPY_SOURCE i D3D12DDI_RESOURCE_STATE_COPY_DEST, a proto nelze kopírovat do sebe.)

Inicializace umístěných metadat prostředků

Starší návrh bariéry prostředků vyžaduje, aby pro inicializaci nově umístěných a aktivovaných aliasovaných texturových prostředků bylo nutné provést operace Vymazat, Kopírovat nebo Zahodit, než budou použity jako prostředky typu Render Target nebo Depth Stencil. Tento požadavek vyplývá z toho, že prostředky Render Target a Depth Stencil obvykle používají kompresní metadata, která musí být inicializována, aby data byla platná. Totéž platí pro rezervované textury s nově aktualizovaným mapováním dlaždic.

Vylepšené bariéry umožňují použít funkci Zahodit jako součást bariéry. Rozložení bariéry musí se změnit z D3D12DDI_BARRIER_LAYOUT_UNDEFINED na libovolné potenciálně komprimované rozložení (například D3D12DDI_BARRIER_LAYOUT_RENDER_TARGET, D3D12DDI_BARRIER_LAYOUT_DEPTH_STENCIL, D3D12DDI_BARRIER_LAYOUT_UNORDERED_ACCESS) a musí inicializovat metadata komprese, pokud je přítomnost D3D12DDI_TEXTURE_BARRIER_FLAG_DISCARD ve členu D3D12DDI_TEXTURE_BARRIER::Flags.

Kromě prostředků vykreslení cíle a hloubky nebo vzorníku existují podobné optimalizace komprese textur UAV, které starší model bariéry nepodporuje.

Řazení bariér

Bariéry jsou zařazeny do fronty v pořadí volání rozhraní API, následovaném indexem skupiny bariér a indexem pole bariér. Více bariér na stejné podresurse musí fungovat tak, jako by se bariéry dokončily v pořadí ve frontě.

Bariéry ve frontě s odpovídajícími obory SyncAfter, které potenciálně zapisují do stejné paměti, musí dokončit všechny zápisy v pořadí, v jakém byly zařazeny do fronty. Tento požadavek zabraňuje datové konkurenci na bariérách, které podporují aliasování prostředků. Například bariéra, která deaktivuje prostředek, musí před bariérou, která aktivuje jiný prostředek ve stejné paměti, vyprázdnit všechny mezipaměti, což může zahrnovat vymazání metadat.