Condividi tramite


Rilevamento dell'utilizzo dell'allocazione

Con l'elenco di allocazione in uscita, la gestione memoria video (VidMm) non ha più visibilità sulle allocazioni a cui si fa riferimento in un determinato buffer dei comandi. Di conseguenza, VidMm non è più in grado di tenere traccia dell'utilizzo dell'allocazione e gestire la sincronizzazione correlata. Questa responsabilità rientra ora nel driver in modalità utente (UMD). In particolare, l'UMD deve gestire la sincronizzazione rispetto all'accesso diretto della CPU all'allocazione e alla ridenominazione.

La distruzione dell'allocazione di VidMm in modo asincrono defera in modo sicuro sia per il thread chiamante che per le prestazioni. 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 potenzialmente all'allocazione eliminata. VidMm riduce quindi l'operazione di distruzione fino al termine dei comandi in coda. Se 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

L'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 sovrascrivere ed eliminare la semantica del blocco, che implica che l'UMD deve implementare uno schema di ridenominazione personalizzato.

  2. Per le operazioni di mapping che richiedono la sincronizzazione, ovvero non la sovrascrittura o l'eliminazione precedenti:

    • Restituisce WasStillDrawing se viene effettuato un tentativo di accesso a un'allocazione attualmente occupato e il chiamante ha richiesto che l'operazione di blocco non blocchi il thread chiamante (D3D11_MAP_FLAG_DO_NOT_WAIT).
    • In alternativa, se il flag di 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 nonpolling. 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, l'UMD è in grado di mantenere mappata l'allocazione 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 consiste nel fornire un'implementazione pulita nuova con un nuovo set di argomenti e flag.

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

Lock2Cb è esposto come metodo semplice per ottenere un indirizzo virtuale a un'allocazione. Esistono alcune restrizioni in base al tipo di allocazione e al segmento corrente attualmente residente.

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

Per le allocazioni accessibili dalla CPU:

  • Le allocazioni accessibili dalla CPU memorizzate nella cache devono risiedere all'interno di un segmento di apertura o non devono essere residenti per essere bloccate. Non è possibile garantire la coesistenza 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 garantite per essere bloccate e in grado di restituire un indirizzo virtuale. In questo scenario non sono necessari vincoli speciali.
  • Le allocazioni accessibili dalla CPU all'interno di un segmento di memoria non accessibile dalla CPU (con o senza accesso a CpuHostAperture) non possono essere mappate in un indirizzo virtuale della CPU per vari motivi. Se cpuHostAperture non è disponibile o l'allocazione non specifica un segmento di apertura, un indirizzo virtuale è impossibile ottenere. Per questo motivo, tutte le allocazioni accessibili dalla CPU nei segmenti di memoria non accessibili dalla CPU devono contenere un segmento di apertura nel set di segmento supportato. Questo requisito garantisce che VidMm sia in grado di inserire l'allocazione all'interno della memoria di sistema e fornire un indirizzo virtuale.
  • Le allocazioni accessibili dalla CPU si trovano già all'interno della memoria di sistema (e/o mappate in un segmento di apertura) sono garantite per il funzionamento.

Per le allocazioni non accessibili dalla CPU:

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

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

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

CpuHostAperture

Per supportare meglio il blocco con segmenti di memoria non accessibili dalla CPU quando il ridimensionamento della BARRA ha esito negativo, viene fornito un cpuHostAperture nell'apertura PCI. CpuHostAperture si comporta come gestione basata su pagine, che può quindi essere mappata direttamente alle aree di memoria video tramite la funzione DxgkDdiMapCpuHostAperture(DDI). 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 alla memoria video senza la necessità di scorrere gli intervalli.

La quantità massima di memoria bloccabile a cui la CPU può fare riferimento all'interno di segmenti di memoria non accessibili dalla CPU è limitata alle dimensioni di CpuHostAperture. I dettagli per esporre CpuHostAperture al kernel della grafica DirectX sono disponibili nell'apertura host della CPU.

Coherency 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 del sistema memorizzata nella cache e mantenere la coesistenza con la CPU. Quando una superficie viene mappata come coerente nella cache dal punto di vista della GPU, la GPU deve snoopare le cache della CPU quando si accede alla superficie. Questa forma di coherency viene in genere usata per le risorse da cui è prevista la lettura della CPU, ad esempio alcune superfici di staging.

In alcune piattaforme Arm la coesistenza di I/O non è supportata direttamente nell'hardware. In queste piattaforme la coesistenza di I/O deve essere emulata manualmente invalidando la gerarchia della cache della CPU. VidMm esegue in questo modo le operazioni di rilevamento di un'allocazione proveniente dalla GPU (operazione di lettura/scrittura dell'elenco di allocazioni) e dalla CPU (operazione di mapping, lettura/scrittura). VidMm genera un'invalidazione della cache quando determina che la cache può contenere:

  • Dati che devono essere scritti di nuovo (scrittura CPU, lettura GPU)
  • Dati non aggiornati che devono essere invalidati (scrittura GPU, letture CPU).

Nella piattaforma senza coerenza di I/O, la responsabilità di tenere traccia dell'accesso della CPU e della GPU alle allocazioni rientra nell'UMD. Il kernel grafico espone una nuova DDI cache invalidatache l'UMD può usare per scrivere e invalidare l'intervallo di indirizzi virtuali associato a un'allocazione memorizzata nella cache. Nelle piattaforme che non hanno supporto per la coherency di I/O, è necessario chiamare questa funzione dopo la scrittura della CPU e prima della lettura della GPU e prima della lettura della CPU e prima della lettura della CPU. Quest'ultimo potrebbe sembrare involontario per primo. Tuttavia, poiché la CPU potrebbe avere dati di lettura speculativa prima della scrittura della GPU che lo rende in memoria, è necessario invalidare tutte le cache della CPU per garantire che i dati della CPU vengano rilette dalla RAM.