Rilevamento dell'utilizzo dell'allocazione

Con l'elenco delle allocazioni che viene eliminato, il gestore di memoria video (VidMm) non ha più visibilità sugli insiemi di allocazioni a cui si fa riferimento in un determinato buffer di comando. Di conseguenza, VidMm non è più in grado di tenere traccia dell'utilizzo dell'allocazione e di gestire la sincronizzazione correlata. Questa responsabilità ricade ora sul driver in modalità utente (UMD). In particolare, il UMD deve gestire la sincronizzazione in relazione all'accesso diretto della CPU all'allocazione e alla ridenominazione.

VidMm rinvia in modo asincrono la distruzione dell'allocazione in modo sicuro, non bloccante per il thread chiamante e performante. Di conseguenza, un UMD non deve preoccuparsi di dover rinviare la distruzione dell'allocazione. Quando VidMm riceve una richiesta di distruzione di allocazione, presuppone per impostazione predefinita che i comandi accodati prima della richiesta di distruzione possano accedere all'allocazione distrutta. VidMm rimanda quindi l'operazione di distruzione fino al termine dei comandi in coda. Se l'UMD sa che i comandi in sospeso non accedono all'allocazione distrutta, può indicare a VidMm di elaborare la richiesta senza attendere impostando il flag AssumeNotInUse quando si chiama Deallocate2 o DestroyAllocation2.

Blocco2

Il UMD è responsabile della gestione della sincronizzazione corretta rispetto all'accesso diretto alla CPU. In particolare, è necessario un UMD per:

  1. Supportare la semantica di blocco senza sovrascrittura e scarto, il che implica che il driver in modalità utente (UMD) deve implementare uno schema di rinominazione proprio.

  2. Per le operazioni sulla mappa che richiedono la sincronizzazione (cioè, non la sovrascrittura o eliminazione sopra menzionate):

    • Restituisce WasStillDrawing se viene tentato di accedere a un'allocazione attualmente in uso e il chiamante ha richiesto che l'operazione Lock non blocchi il thread chiamante (D3D11_MAP_FLAG_DO_NOT_WAIT).
    • In alternativa, se il flag D3D11_MAP_FLAG_DO_NOT_WAIT non è impostato, attendere fino a quando non diventa disponibile un'allocazione per l'accesso alla CPU. L'UMD deve implementare un'attesa senza polling. Il UMD userà il nuovo meccanismo di monitoraggio del contesto.

Per il momento, UMD continua a dover chiamare LockCb/UnlockCb per chiedere a VidMm di configurare un'allocazione per l'accesso alla CPU. Nella maggior parte dei casi, il UMD è in grado di mantenere l'allocazione mappata per l'intera durata. Tuttavia, in futuro, LockCb e UnlockCb saranno deprecati a favore delle nuove chiamate Lock2Cb e Unlock2Cb . L'obiettivo di questi callback più recenti è fornire una nuova implementazione pulita con un insieme rinnovato di argomenti e flag.

Gli intervalli di swizzling vengono rimossi da WDDM versione 2. È responsabilità dello sviluppatore del driver rimuovere la dipendenza dagli intervalli di swizzling dalle chiamate a LockCb mentre si passa a un'implementazione basata su Lock2Cb.

Lock2Cb viene esposto come metodo semplice per ottenere un indirizzo virtuale per un'allocazione. Esistono alcune restrizioni in base al tipo di allocazione e al segmento corrente in cui si trova attualmente.

Il driver indica se un segmento è accessibile dalla CPU tramite il flag CpuVisible , che si trova nel membro Flags della struttura DXGK_SEGMENTDESCRIPTOR .

Per le allocazioni accessibili dalla CPU:

  • Le allocazioni accessibili dalla CPU memorizzate nella cache devono trovarsi all'interno di un segmento di apertura o non essere residenti per essere bloccate. Non è possibile garantire la coerenza della cache tra la CPU e un segmento di memoria nell'unità di elaborazione grafica (GPU).
  • Le allocazioni accessibili dalla CPU che si trovano in un segmento di memoria completamente accessibile dalla CPU (ridimensionato usando la barra ridimensionabile) sono sicuramente bloccabili e in grado di restituire un indirizzo virtuale. In questo scenario non sono necessari vincoli speciali.
  • Le allocazioni accessibili dalla CPU che si trovano all'interno di un segmento di memoria non accessibile dalla CPU (con o senza accesso a CpuHostAperture) non possono essere mappate a un indirizzo virtuale della CPU per diversi motivi. Se CpuHostAperture non è disponibile o l'allocazione non specifica un segmento di apertura, è impossibile ottenere un indirizzo virtuale. Per questo motivo, tutte le allocazioni accessibili dalla CPU in segmenti di memoria non accessibili dalla CPU devono contenere un segmento di apertura nel set di segmenti supportati. Questo requisito garantisce che VidMm sia in grado di inserire l'allocazione all'interno della memoria di sistema e di fornire un indirizzo virtuale.
  • Le allocazioni accessibili dalla CPU già posizionate all'interno della memoria di sistema (e/o mappate in un segmento di apertura) sono garantite per funzionare.

Per le allocazioni non accessibili dalla CPU:

  • Le allocazioni accessibili dalla CPU sono supportate da oggetti di sezione che non possono puntare direttamente al frame buffer delle GPU. Per bloccare un'allocazione non accessibile dalla CPU, l'allocazione deve supportare un segmento di apertura nel set di segmenti supportato o già presente nella memoria di sistema (non deve essere residente nel dispositivo).

Se un'allocazione è bloccata correttamente mentre l'allocazione non è residente nel dispositivo ma non supporta un segmento di aperture, l'allocazione non deve essere committata in un segmento di memoria per la durata del blocco.

Lock2 non contiene attualmente flag e i bit dei flag riservati devono essere tutti 0.

CpuHostAperture

Per supportare meglio il blocco con segmenti di memoria non accessibili dalla CPU quando il ridimensionamento della BAR ha esito negativo, viene fornito un CpuHostAperture nell'apertura PCI. CpuHostAperture si comporta come gestore basato su pagine, che può quindi essere mappato direttamente alle aree di memoria video tramite la funzione DDI (Device Driver Interface) DxgkDdiMapCpuHostAperture. VidMm può quindi eseguire il mapping di un intervallo di spazio indirizzi virtuale direttamente a un intervallo non contiguo di CpuHostAperture e quindi eseguire il mapping di CpuHostAperture alla memoria video senza la necessità di intervalli swizzling.

La quantità massima di memoria bloccabile a cui può fare riferimento la CPU all'interno di segmenti di memoria non accessibili dalla CPU è limitata alle dimensioni di CpuHostAperture. I dettagli per l'esposizione di CpuHostAperture al kernel grafico DirectX si possono trovare in CPU host aperture.

Coerenza di I/O

In x86/x64 oggi, tutte le GPU devono supportare la coesistenza di I/O su PCIe per consentire a una GPU di leggere o scrivere in una superficie di memoria di sistema memorizzabile nella cache e mantenere la coerenza con la CPU. Quando una superficie viene mappata come coerente con la cache dal punto di vista della GPU, la GPU deve controllare le cache della CPU durante l'accesso alla superficie. Questa forma di coerenza viene in genere usata per le risorse da cui la CPU è destinata a leggere, ad esempio alcune superfici di staging.

In alcune piattaforme Arm, la coescenza di I/O non è supportata direttamente nell'hardware. In queste piattaforme, la coescenza di I/O deve essere emulata invalidando manualmente la gerarchia della cache della CPU. VidMm esegue questa operazione monitorando le operazioni relative a un'allocazione proveniente dalla GPU (operazione di lettura/scrittura sulla lista delle allocazioni) e dalla CPU (operazione di mapping, di lettura/scrittura). VidMm genera un invalidamento della cache quando determina che la cache può contenere:

  • Dati che devono essere scritti indietro (scrittura da CPU, lettura da GPU)
  • Dati obsoleti che devono essere invalidati (scrittura GPU, letture CPU).

Nella piattaforma senza coescenza di I/O, la responsabilità di tenere traccia dell'accesso della CPU e della GPU alle allocazioni rientra nel UMD. Il kernel grafico espone una nuova DDI Invalidate Cache che la UMD può usare per eseguire il writeback e invalidare l'intervallo di indirizzi virtuali associato a un'allocazione memorizzabile nella cache. Nelle piattaforme che non dispongono del supporto per la coerenza di I/O, è necessario che l'UMD chiami questa funzione dopo scrittura CPU e prima della lettura GPU, nonché dopo la scrittura GPU e prima della lettura CPU. Quest'ultimo potrebbe sembrare non intuitivo in un primo momento. Tuttavia, poiché la CPU potrebbe aver letto speculativamente i dati prima che la scrittura della GPU li renda disponibili in memoria, è necessario invalidare tutte le cache della CPU per garantire che la CPU rilegga i dati dalla RAM.