> ## Documentation Index
> Fetch the complete documentation index at: https://devdocs.xbox.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Vue d'ensemble de DirectStorage

> Les API DirectStorage pour XBOX Series X|S offrent des E/S de stockage NVMe à haut débit avec une faible surcharge processeur pour de grands nombres de petites requêtes.

## Introduction

Cet article fournit une vue d'ensemble des API DirectStorage pour les
consoles XBOX Series X|S uniquement. Consultez
[DirectStorage sur ordinateur de bureau](https://aka.ms/directstorage) pour plus d'informations sur DirectStorage sur ordinateur de bureau.

Les derniers périphériques de stockage NVMe connectés via un bus PCIe peuvent atteindre des niveaux très
élevés de débit et d'IOPS (requêtes d'E/S par seconde). En raison de la surcharge des
API Win32, même si la bande passante de stockage disponible peut être
utilisée, en tirer parti peut entraîner une utilisation du processeur
inacceptablement élevée. C'est particulièrement vrai lorsque la charge de travail se compose d'un grand
nombre de petites requêtes.

Les API DirectStorage sont conçues pour éliminer la majeure partie de la surcharge
du système d'exploitation en interagissant étroitement avec le matériel NVMe sous-jacent. Cela permet
d'obtenir une bande passante plus élevée avec une utilisation moindre du processeur. L'objectif est de permettre
le traitement de jusqu'à 50 000 requêtes par seconde en utilisant au maximum 10 % d'un
seul cœur de processeur.

### Problèmes existants

Le contenu des jeux est de plus en plus volumineux, à mesure que le besoin de ressources en plus haute résolution
augmente à chaque génération de consoles. Le matériel et les logiciels XBOX One existants
présentent plusieurs limitations qui entravent la capacité des développeurs
à transférer les données du disque dur vers la mémoire pour ce contenu de nouvelle génération.

* Utilisation élevée du processeur
  * Les API Win32 existantes peuvent nécessiter un cœur de processeur entier en surcharge.
  * Cela dépend du nombre de requêtes du titre.

* Bande passante maximale insuffisante du disque
  * Les livres blancs [Optimisation des performances des fichiers sur XBOX Series X|S (rubrique sous NDA)](https://learn.microsoft.com/gaming/gdk/docs/gdk-dev/console-dev/overviews/file-system/Maximizing_File_Performance_Win32_Scarlett) et [Optimisation des performances des fichiers sur XBOX One (rubrique sous NDA)](https://learn.microsoft.com/gaming/gdk/docs/gdk-dev/console-dev/overviews/file-system/Maximizing_File_Performance_Win32_Xbox_One) abordent ce point en détail.

* Impossibilité de hiérarchiser les requêtes disque
  * Sans la possibilité de hiérarchiser les requêtes du titre, il peut être difficile de créer un
    système de streaming réactif.

* Impossibilité d'annuler les requêtes disque
  * Sans la possibilité d'annuler des requêtes, il peut être difficile de créer un
    système de lecture spéculative.

* Absence de décompression accélérée par le matériel
  * Sans décompression accélérée par le matériel, la décompression logicielle peut consommer beaucoup de
    ressources processeur.

L'ensemble d'API DirectStorage répond directement à chacun de ces problèmes. L'effet
global est une augmentation considérable des performances du système de fichiers XBOX.

### Utilisation du processeur

Le principal objectif de conception de DirectStorage est de permettre à un titre de soutenir 50 000 IOPS
en n'utilisant qu'entre 5 % et 10 % d'un seul cœur de processeur. Cela permet
au titre d'atteindre la bande passante maximale du sous-système de stockage NVMe, tout en
permettant d'utiliser le processeur pour d'autres besoins du titre.

DirectStorage ajoute également la prise en charge de la décompression matérielle. Chaque requête de lecture
peut être acheminée directement du lecteur NVMe vers le bloc de décompression
matérielle intégré. Le titre n'a ainsi plus besoin de consacrer des ressources processeur
à la décompression.

### Modèle de pipeline en file d'attente

DirectStorage utilise une méthode par lots, dans laquelle plusieurs requêtes sont ajoutées à une file d'attente.
Plus tard, la file d'attente est vidée vers l'étape suivante du pipeline. Cela
réduit immédiatement le coût processeur global d'une transition entre les étapes
du pipeline. Avec l'ensemble d'API Win32 existant, il y a une transition pour chaque requête.
Les files d'attente DirectStorage utilisent des algorithmes sans verrou pour réduire la contention.
Le titre contrôle le moment où chaque file d'attente est vidée.

Dans de nombreux cas avec les API Win32, les données du disque doivent être copiées
dans une autre mémoire tampon. Dans certains cas, les données doivent être copiées plusieurs fois.
DirectStorage élimine ce problème en mappant la mémoire tampon de destination fournie par le titre
directement dans chaque couche du pipeline. Le matériel écrit directement dans
la mémoire tampon fournie par le titre.

Ces modifications contribuent à réduire considérablement la surcharge du processeur.

### Décompression

La capacité de décompression des données par le matériel a été augmentée. Il peut désormais
gérer une plus grande variété de formats, à une vitesse supérieure à celle à laquelle le sous-système NVMe
peut fournir les données. De plus, DirectStorage prend en charge la décompression sur place, ce qui
évite d'avoir à gérer des mémoires tampons distinctes pour les données compressées et décompressées.

Le matériel prend en charge `BCPACK` et `DEFLATE`, et offre la possibilité de swizzler le
contenu final. Ces formats ne s'excluent pas mutuellement. Il est possible d'appliquer
les trois aux données. Le titre peut ainsi choisir la
méthode qui lui offre le meilleur taux de compression et les meilleures performances. Différentes ressources
peuvent utiliser différents paramètres de compression et de swizzle.

### Profondeur de file d'attente

La recommandation précédente était de ne maintenir que 12 à 16 requêtes asynchrones
en cours à la fois sur un disque rotatif. Aller au-delà n'apportait aucun gain de performances, et
rester en deçà nuisait considérablement aux performances. Les titres devaient donc
effectuer un travail supplémentaire pour équilibrer leurs requêtes de lecture en attente afin de rester dans
la cible recommandée.

Avec l'objectif de DirectStorage de permettre à un titre d'atteindre 50 000 IOPS, notre
recommandation a changé. Le titre n'a plus besoin d'essayer d'équilibrer le
travail en attente et la profondeur de file d'attente. Le titre doit soumettre toutes ses requêtes
en attente. Il n'y a aucun avantage à retenir certaines requêtes. Dans de nombreux cas,
retenir des requêtes peut nuire aux performances, car le matériel est bloqué en attente
de nouvelles requêtes.

Le système d'exploitation doit toujours fractionner les grandes requêtes de lecture en
plusieurs requêtes plus petites dans certains cas (par exemple, pour gérer la fragmentation du disque).
Toutefois, cela a été pris en compte dans l'architecture de DirectStorage. L'objectif de conception de
50 000 IOPS est basé sur le nombre d'opérations d'E/S du titre et non sur les requêtes
finales envoyées au matériel.

### Notification

Dans l'architecture Win32, une surcharge importante est consacrée aux
notifications d'achèvement de lecture. Le titre peut interroger une structure *OVERLAPPED*,
attendre un handle d'événement associé ou effectuer une lecture
bloquante synchrone. Globalement, cela augmente les besoins en ressources de chaque requête
de lecture.

DirectStorage conserve les deux concepts asynchrones de notification tout en
ajoutant une troisième méthode. Les lectures bloquantes synchrones ne sont pas prises en charge dans
DirectStorage ; un titre peut implémenter son propre système. Toutefois,
cela n'est pas recommandé.

La première méthode asynchrone est implémentée au moyen d'un bloc d'état défini
lorsque les requêtes associées sont terminées. Le titre peut interroger le bloc si
nécessaire pour déterminer quand les lectures sont terminées. Cela est similaire à la méthode Win32
consistant à interroger une structure *OVERLAPPED* pour détecter l'achèvement.

La deuxième méthode asynchrone utilise un objet `Event` Windows pour signaler l'achèvement.
Cela est similaire à l'utilisation d'une structure *OVERLAPPED* avec un objet `Event` correspondant.
Le titre peut utiliser la méthode [WaitForSingleObject](https://learn.microsoft.com/windows/win32/api/synchapi/nf-synchapi-waitforsingleobject)
pour suspendre le thread appelant jusqu'à ce que les opérations de lecture soient terminées.

La troisième méthode asynchrone est implémentée à l'aide d'un [ID3D12Fence](https://learn.microsoft.com/windows/win32/api/d3d12/nn-d3d12-id3d12fence). Le titre
peut se suspendre en attendant la clôture ou interroger la clôture si nécessaire.
Il y a également l'avantage que le GPU peut utiliser la clôture pour être directement notifié
des requêtes terminées.

Le système de notification de DirectStorage n'est pas lié à une seule requête de lecture. Il s'agit
d'une entrée placée dans la file d'attente, qui est signalée lorsque toutes les requêtes de lecture
précédentes sont terminées. Le titre contrôle ainsi la granularité
dont il a besoin pour les notifications. Les notifications sont toujours signalées dans l'ordre de la file d'attente.
La file d'attente peut être considérée comme une file FIFO (premier entré, premier sorti). Le titre n'a
besoin d'interroger que la dernière notification pertinente. Toutes les requêtes précédemment mises en file d'attente
sont assurément terminées.

### Décompression de mémoire à mémoire

DirectStorage fournit un type de file d'attente permettant d'appeler le matériel de décompression avec
la mémoire comme source de décompression au lieu d'un fichier sur disque. Cela permet
d'utiliser le matériel de décompression si la ressource compressée ne provient pas
d'un fichier ou si elle a été précédemment chargée et conservée en mémoire comme cache. Une
file d'attente à source mémoire n'accepte que des requêtes à source mémoire, et une file d'attente à source fichier
n'accepte que des requêtes à source fichier.

Si aucune option de décompression n'est spécifiée dans une requête à source mémoire, le
matériel de décompression peut également servir de moteur de copie DMA.

Bien que DirectStorage garantisse que les notifications d'achèvement sont dans l'ordre,
DirectStorage ne fournit aucune garantie quant au moment où le traitement des requêtes commence.
Par conséquent, il ne doit y avoir aucune dépendance de données entre les requêtes en attente. Autrement
dit, la destination de la requête A ne peut pas servir de source à la requête B, sauf si la requête
B est mise en file d'attente après l'achèvement de la requête A.

Les files d'attente à source mémoire doivent être créées avec une priorité en temps réel. En outre,
les requêtes en temps réel à source mémoire sont toujours traitées par le matériel de décompression
avant les requêtes à source disque qui nécessitent une décompression.
Si les files d'attente à source disque ne contiennent aucune requête de décompression, les deux
types de files d'attente sont traités entièrement en parallèle sans affecter l'autre type.

### Priorité

DirectStorage permet d'attribuer un niveau de priorité à chaque file d'attente. Chaque entrée de
la file d'attente hérite de la priorité de la file. Quatre niveaux de priorité différents sont
fournis : temps réel, haute, normale et basse. Les requêtes sont traitées selon un tourniquet
pondéré. Par exemple, traiter X requêtes de priorité haute avant de traiter
une requête de priorité normale. Traiter Y requêtes de priorité normale avant de
traiter une requête de priorité basse.

La pondération de priorité est calculée en fonction de la taille de chaque requête. La pondération par défaut
entre chaque priorité est d'environ 10x. Cela signifie que pour chaque 1 Ko de requête de priorité
basse, 10 Ko de requête de priorité moyenne et 100 Ko de requête de priorité haute
auront été traités.

Les requêtes de lecture Win32 existantes sont acheminées via le même système de priorité. Toutes les
requêtes Win32 sont considérées comme de priorité normale.

Les files d'attente à source mémoire doivent être créées avec une priorité en temps réel.

### Annulation

Chaque requête de lecture DirectStorage est associée à un masque de 64 bits fourni par le titre.
Cela permet de prendre en charge l'annulation des requêtes de lecture en attente. Le titre peut
annuler les requêtes qui correspondent à un ensemble spécifique d'indicateurs dans le masque.

Même avec la prise en charge de l'annulation, il est toujours possible qu'une requête de lecture soit
traitée par le matériel. La demande d'annulation du titre est une tentative
au mieux. Si la requête est déjà en cours de traitement actif par le matériel, elle
ne peut pas être annulée.

Comme la demande d'annulation est effectuée au mieux, le titre doit attendre
d'être notifié que le traitement de la requête de lecture est terminé. Le titre
ne peut libérer aucune des ressources nécessaires avant la réception d'une notification ultérieure dans la file d'attente.
Toutefois, pendant ce temps, de nouvelles requêtes correspondant aux indicateurs
utilisés dans une demande d'annulation précédente peuvent être mises en file d'attente et ne seront pas annulées.

Lorsqu'une requête annulée se termine, elle est considérée comme une **réussite**, même si elle
a été annulée et n'a pas produit le résultat complet. Autrement dit, si
une annulation est tentée sur une requête, le titre ne peut plus consommer le
résultat de la requête potentiellement annulée lors de son achèvement.

### Garantie

Les consoles XBOX One et XBOX One S offraient une garantie minimale de 40 Mo/s. La
console XBOX One X a augmenté la garantie minimale à 60 Mo/s. Ces chiffres sont
bien inférieurs aux limites réelles du matériel, qui se situent autour de 130 Mo/s. Cela était
entièrement dû à la surcharge causée par le système d'exploitation.

DirectStorage élimine la majeure partie de la surcharge causée par le système d'exploitation. Cela
permet une garantie minimale plus proche des limites du matériel. La nouvelle garantie minimale
de performances est de 2,0 Go/s sur une fenêtre de 250 ms pour les données brutes. L'utilisation de
la décompression sur le contenu augmente encore la bande passante finale.

Les futures consoles XBOX prendront en charge l'ajout de disques dynamiques installables par l'utilisateur
également basés sur NVMe. La même garantie minimale de performances
que celle fournie pour le disque interne s'applique également au disque installable par l'utilisateur.

## Vue d'ensemble de l'API

Les interfaces DirectStorage suivent le même modèle que les interfaces Direct3D.
Le titre obtient d'abord une fabrique singleton. La fabrique sert à créer des
files d'attente de requêtes et à ouvrir des fichiers ; chacun de ces objets est mappé
directement au matériel. Les requêtes individuelles sont ensuite mises en file d'attente pour
être soumises au matériel.

### IDStorageFactoryX

`IDStorageFactoryX` est l'interface principale permettant de créer des files d'attente, d'ouvrir des fichiers et de
soumettre les requêtes en attente.

L'objet `IDStorageFactoryX `possède les méthodes suivantes.

* [OpenFile](/fr/reference/system/dstorage/interfaces/IDStorageFactoryX/methods/idstoragefactoryx_openfile)
  * Crée un objet `IDStorageFileX `, qui représente un fichier.

* [CreateQueue](/fr/reference/system/dstorage/interfaces/IDStorageFactoryX/methods/idstoragefactoryx_createqueue)
  * Crée un objet `IDStorageQueueX`. Sert à créer des requêtes de lecture.

* [CreateStatusArray](/fr/reference/system/dstorage/interfaces/IDStorageFactoryX/methods/idstoragefactoryx_createstatusarray)
  * Crée un objet `IDStorageStatusArray`, qui gère les indicateurs d'état
    d'achèvement.

* [SetCPUAffinity](/fr/reference/system/dstorage/interfaces/IDStorageFactoryX/methods/idstoragefactoryx_setcpuaffinity)
  * Limite le travail de DirectStorage effectué hors du thread appelant à un ensemble de cœurs
    de processeur défini par le titre.
  * **REMARQUE** DirectStorage tente d'effectuer la majeure partie du travail dans
    le thread appelant. Le travail hors du thread appelant n'a lieu que lorsqu'il ne peut pas être
    effectué dans le thread appelant. Voici quelques exemples.
    * Le pipeline de ressources sous-jacent est plein pendant `IDStorageQueueX::Submit`,
      et toutes les requêtes de la file d'attente ne peuvent pas être transmises. Les requêtes
      restantes seront traitées ultérieurement, lorsque les ressources se libéreront, et ce
      traitement est effectué dans un thread de travail DirectStorage.
    * Traitement de l'achèvement des requêtes dans `ID3DFence` ou `IDStorageStatusArray`.

* [SetDebugFlags](/fr/reference/system/dstorage/interfaces/IDStorageFactoryX/methods/idstoragefactoryx_setdebugflags)
  * Détermine si DirectStorage effectue des validations supplémentaires lors de la mise en file d'attente
    des requêtes afin de faciliter le débogage.

* [SetStagingBufferSize](/fr/reference/system/dstorage/interfaces/IDStorageFactoryX/methods/idstoragefactoryx_setstagingbuffersize)
  * Définit la taille de la mémoire tampon intermédiaire utilisée pour stocker temporairement le contenu chargé
    depuis le périphérique de stockage avant son déchiffrement/sa décompression. Si seules
    des files d'attente à source mémoire sont utilisées, la mémoire tampon intermédiaire peut avoir une taille de 0.

### IDStorageFactoryX1

L'interface `IDStorageFactoryX1` étend l'interface `IDStorageFactoryX` avec
une méthode [GetStats](/fr/reference/system/dstorage/interfaces/IDStorageFactoryX1/methods/idstoragefactoryx1_getstats).

* [GetStats](/fr/reference/system/dstorage/interfaces/IDStorageFactoryX1/methods/idstoragefactoryx1_getstats)
  * Obtient les statistiques de DirectStorage. Cette fonction peut servir à intégrer
    DirectStorage aux pipelines de diagnostic et de télémétrie existants.
    Elle effectue un traitement minimal et peut donc être appelée fréquemment. Les statistiques
    n'incluent pas les opérations d'E/S de fichiers Win32.

### IDStorageFactoryX2

L'interface `IDStorageFactoryX2` étend l'interface \`IDStorageFactoryX1 avec
une méthode [CreateQueue1](/fr/reference/system/dstorage/interfaces/IDStorageFactoryX2/methods/idstoragefactoryx_createqueue1).

* [CreateQueue1](/fr/reference/system/dstorage/interfaces/IDStorageFactoryX2/methods/idstoragefactoryx_createqueue1)
  * Crée un objet `IDStorageQueueX2`. Utilise une nouvelle structure pour permettre
    des options supplémentaires lors de la création de la file d'attente, notamment la possibilité de remplacer
    la fonctionnalité de soumission automatique d'une file d'attente.

### IDStorageFileX

Tous les fichiers doivent d'abord être ouverts par DirectStorage via
l'objet `IDStorageFactoryX`. Cela équivaut à utiliser `CreateFile` dans les interfaces
d'API Win32.

Les fichiers sont ouverts avec l'autorisation `FILE_SHARED_READ`. Si nécessaire, les titres peuvent
ouvrir simultanément le fichier à l'aide des API Win32, à condition de respecter les
autorisations appropriées. Pendant le développement, les déploiements libres et empaquetés sont pris en charge.

Les fichiers sont fermés soit en appelant explicitement la fonction [Close](/fr/reference/system/dstorage/interfaces/IDStorageFileX/methods/idstoragefilex_close)
sur l'objet fichier, soit lorsque la dernière référence à l'objet
`IDStorageFileX` correspondant est libérée. Toutefois, toutes les opérations d'E/S en attente doivent
être terminées avant que le fichier puisse être fermé. Cela signifie que les deux méthodes de fermeture
d'un fichier bloquent jusqu'à ce que toutes les opérations d'E/S en attente sur ce fichier soient terminées.

Le jeu peut obtenir un handle Win32 vers un fichier représenté par un objet `IDStorageFileX`
en appelant la fonction [GetHandle](/fr/reference/system/dstorage/interfaces/IDStorageFileX/methods/idstoragefilex_gethandle).
Le handle est ouvert avec les autorisations `GENERIC_READ` et le mode de partage `FILE_SHARE_READ`.
Il peut servir à interroger la taille du fichier, entre autres. Le handle doit être fermé
avec `CloseHandle()` lorsqu'il n'est plus nécessaire.

### IDStorageQueueX

Les requêtes de lecture sont soumises au NVMe via un objet `IDStorageQueueX`.
Toutefois, les requêtes ne sont pas soumises au périphérique tant que le titre n'a pas appelé
[Submit](/fr/reference/system/dstorage/interfaces/IDStorageQueueX/methods/idstoragequeuex_submit) sur la file d'attente, ou que l'une des méthodes Enqueue
n'a pas rempli plus de la moitié de la capacité de la file d'attente depuis la dernière soumission, déclenchant
ainsi une soumission automatique. Les soumissions sont traitées comme une seule transition vers
l'étape suivante du pipeline. Le titre peut ainsi contrôler le moment où le coût processeur
de la transition entre le titre et le noyau est engagé.

Les objets `IDStorageQueueX` possèdent quatre propriétés.

* [SourceType](/fr/reference/system/dstorage/enums/dstorage_request_source_type)
  * Indique si la file d'attente peut recevoir des requêtes à source fichier ou
    des requêtes à source mémoire.

* [Priority](/fr/reference/system/dstorage/enums/dstorage_priority)
  * Priorité de toutes les requêtes soumises à la file d'attente : temps réel, haute, normale ou basse.
  * Les files d'attente à source mémoire doivent être créées avec une priorité en temps réel.
  * Les requêtes sont traitées selon un tourniquet pondéré basé sur la priorité.
  * Les requêtes Win32 sont traitées au niveau de priorité normal.

* **Capacity**
  * Nombre maximal de requêtes en attente que la file d'attente peut contenir.
  * Toute tentative de mise en file d'attente d'une requête lorsque la file d'attente est pleine bloque
    jusqu'à ce que des entrées soient terminées par le matériel.
  * La quantité de mémoire nécessaire pour une file d'attente correspond approximativement à la capacité de la file d'attente
    multipliée par la taille d'une `DSTORAGE_REQUEST`.

* **Name**
  * Cette propriété sert uniquement à faciliter le débogage. Le nom n'est utilisé par aucune partie du
    code DirectStorage, mais il est visible dans les outils de développement, comme
    [PIX (rubrique sous NDA)](/fr/tools/tools-console/pix/pix-directstorage).

Le matériel traite les requêtes de manière asynchrone pour obtenir le débit
le plus élevé. Toutefois, contrairement à Win32, le titre est notifié de l'achèvement dans l'ordre
FIFO. À la notification de l'achèvement, il est garanti que toutes les requêtes précédentes
adressées à la même file d'attente sont également terminées.

### IDStorageQueueX1

L'interface `IDStorageQueueX1` étend l'interface `IDStorageQueueX` avec la
méthode [EnqueueSetEvent](/fr/reference/system/dstorage/interfaces/IDStorageQueueX1/methods/idstoragequeuex_enqueuesetevent).

### IDStorageQueueX2

L'interface `IDStorageQueueX2` étend l'interface \`IDStorageQueueX1 avec la méthode [CreateQueue1](/fr/reference/system/dstorage/interfaces/IDStorageFactoryX2/methods/idstoragefactoryx_createqueue1).

Ainsi qu'une propriété supplémentaire.

* [Options](/fr/reference/system/dstorage/structs/dstorage_queue_options)
  * Indicateurs utilisés pour contrôler le comportement de la file d'attente, notamment la désactivation de la soumission automatique.

### EnqueueRequest

Cette interface est fonctionnellement identique à l'interface Win32 `ReadFile`.
Des requêtes de lecture individuelles sont créées et soumises à la file d'attente. La principale
différence est que DirectStorage permet de mettre en file d'attente de nombreuses requêtes avant
la soumission, prend en charge la décompression matérielle et prend en charge l'annulation.

Les requêtes possèdent plusieurs propriétés principales.

**Source de la requête**
Selon la combinaison de `Options.SourceType` et
`Options.SourceIsPhysicalPages`, DirectStorage utilise l'un des trois
groupes de propriétés suivants pour indiquer l'emplacement des données sources.

* **File** et **FileOffset**
  * Ce groupe est utilisé lorsque `Options.SourceType` a la valeur `DSTORAGE_REQUEST_SOURCE_FILE`
  * **File** est préalablement ouvert avec `IDStorageFactoryX::OpenFile`.
  * **FileOffset** doit être aligné sur 16 octets si la décompression est utilisée, ou
    n'a aucune exigence d'alignement si la décompression n'est pas utilisée.
    * Il s'agit d'un changement majeur par rapport à Win32, qui exigeait un alignement de 4 Kio dans
      le fichier pour les lectures asynchrones.

* **Source**
  * Ce groupe est utilisé lorsque `Options.SourceType` a la valeur `DSTORAGE_REQUEST_SOURCE_MEMORY`
    et `Options.SourceIsPhysicalPages` a la valeur `FALSE`.
  * Mémoire tampon contenant les données à décompresser.

* **SourcePageArray** et **SourcePageOffset**
  * Ce groupe est utilisé lorsque `Options.SourceType` a la valeur `DSTORAGE_REQUEST_SOURCE_MEMORY`
    et `Options.SourceIsPhysicalPages` a la valeur `TRUE`.
  * Similaire à `Source`, mais fournit la mémoire tampon source sous la forme d'un
    tableau de pages physiques de 64 Ko et du décalage en octets dans la première page.
  * Les pages physiques de 64 Ko peuvent être allouées par `XMemAllocatePhysicalPages`.

**SourceSize**

* Taille, en octets, des données sources à lire, à partir d'une mémoire tampon
  ou d'un fichier.

**IntermediateSize**

* Lorsque les décompressions `zlib` et `BCPACK`sont toutes deux activées dans cette requête,
  `IntermediateSize` sert à indiquer la taille intermédiaire vers laquelle les données
  sources sont décompressées par zlib (et à partir de laquelle elles sont décompressées par BCPACK).
* Sinon, cette propriété doit être définie sur 0.

**Destination de la requête**
Selon `Options.DestinationIsPhysicalPages`, DirectStorage utilise l'un des
deux groupes de propriétés suivants pour indiquer l'emplacement de la destination.

* **Destination**
  * Ce groupe est utilisé lorsque `Options.DestinationIsPhysicalPages` a la valeur `FALSE`.
  * Mémoire tampon de destination des données chargées finales.
  * La décompression s'effectue à l'aide de mémoires tampons internes partagées et peut être considérée
    comme effectuée sur place.

* **DestinationPageArray** et **DestinationPageOffset**
  * Ce groupe est utilisé lorsque `Options.DestinationIsPhysicalPages` a la valeur `TRUE`.
  * Similaire à `Destination`, mais fournit la mémoire tampon de destination sous la
    forme d'un tableau de pages physiques de 64 Ko et du décalage en octets dans la première
    page.
  * Les pages physiques de 64 Ko peuvent être allouées par `XMemAllocatePhysicalPages`.

**DestinationSize**

* Taille attendue, en octets, du contenu chargé final. La destination doit
  disposer d'un espace suffisant pour l'opération.
* La taille doit être égale à **SourceSize** lorsque la décompression n'est pas utilisée, ou
  supérieure à **SourceSize** lorsque la décompression est utilisée.

**CancellationTag**

* Balise arbitraire de 64 bits définie par le titre.
* Cette balise sert de masque pour les demandes d'annulation.

**Name**

* Chaîne facultative destinée à faciliter le débogage. Le nom peut apparaître dans les outils
  de développement, comme [PIX (rubrique sous NDA)](/fr/tools/tools-console/pix/pix-directstorage), ou dans l'enregistrement d'erreur
  obtenu à partir de `IDStorageQueueX::RetrieveErrorRecord`. La chaîne `Name` doit
  rester accessible pendant toute la durée de vie de la requête.

**Options**

* **ZlibDecompress**
  * Indique que les données doivent être décompressées à l'aide de la norme de
    décompression RFC 1950.
* **BcpackMode**
  * Indique le mode `BCPACK` à utiliser pour décompresser les données.
  * None est une option valide et signifie que les données ne sont pas compressées avec `BCPACK`.
* **SwizzleMode**
  * Indique comment les données finales doivent être swizzlées en mémoire.
* **DestinationIsPhysicalPages**
  * Indique que la mémoire tampon de destination est spécifiée à l'aide de
    **DestinationPageArray** et **DestinationPageOffset** au lieu de
    **Destination**.
* **SourceType**
  * Une requête peut être à source mémoire, et possède alors les propriétés `Source`/
    `SourcePageArray` et `SourcePageOffset`, ou à source fichier, et possède alors
    les propriétés `File`/`FileOffset`.
* **SourceIsPhysicalPages**
  * Indique que la mémoire tampon source est spécifiée à l'aide de **SourcePageArray**
    et **SourcePageOffset** au lieu de **Source**.

### EnqueueStatus/EnqueueSignal/EnqueueSetEvent

Les requêtes peuvent être mises en file d'attente et traitées comme une série de requêtes liées. Pour ce
faire, on met en file d'attente une notification lorsque le traitement atteint un certain point
de la file d'attente. Les notifications ne sont traitées que lorsque toutes les requêtes de lecture précédentes
sont terminées. Cela garantit que les données de toutes les requêtes précédentes sont immédiatement
disponibles.

Le titre dispose de deux méthodes d'interrogation et d'une méthode d'attente pour les notifications. Le
titre peut insérer un objet `ID3D12Fence`, un objet `IDStorageStatusArrayX` ou une
opération de définition d'événement. L'objet `ID3D12Fence` se comporte comme prévu pour un objet
`ID3D12Fence`. Un thread du titre peut attendre un `Event`, le processeur peut interroger la clôture et le
GPU peut interroger la clôture. L'objet `IDStorageStatusArrayX` permet au processeur d'interroger
l'achèvement et d'accéder aux éventuels échecs de lecture. La méthode `EnqueueSetEvent`
permet à un thread du titre d'attendre l'événement spécifié au lieu d'effectuer une interrogation.
Cela diffère de `ID3D12Fence::SetEventOnCompletion`, car l'implémentation XBOX
de `ID3D12Fence::SetEventOnCompletion` tourne en boucle sur la clôture jusqu'à ce qu'elle soit signalée,
consommant ainsi le thread matériel du processeur jusqu'au signal, tandis que `EnqueueSetEvent`
permet au thread du titre d'utiliser `WaitForSingleObject`/`WaitForMultipleObjects` pour
céder le processeur à d'autres threads jusqu'à ce que l'événement soit signalé.

Comme indiqué précédemment, toutes les requêtes sont terminées dans l'ordre, même si le matériel
sous-jacent décide de les réorganiser pour des raisons de performances. Les notifications ne sont pas signalées
tant que toutes les requêtes précédemment mises dans la file d'attente ne sont pas terminées.

### Décompression

La décompression est gérée par un matériel dédié. Cela élimine la surcharge processeur
des algorithmes de décompression traditionnels. DirectStorage alloue un bloc fixe
de mémoire lors de l'initialisation pour l'utiliser comme mémoire tampon de travail pour la décompression.
Cela permet la décompression sur place et évite de devoir conserver en mémoire à la fois les
données compressées et décompressées.

Le matériel de décompression prend en charge trois modes de fonctionnement. Les modes ne
s'excluent pas mutuellement ; toute combinaison de modes peut donc être spécifiée. Les modes de
décompression sont appliqués dans l'ordre suivant : `DEFLATE`, `BCPACK` et `Swizzle`.

* `ZLibDecompress`
  * Il s'agit de la norme de compression [IETF RFC 1950](https://www.ietf.org/rfc/rfc1950.txt).

* `BCPack`
  * `BCPack` est un codeur entropique personnalisé conçu spécifiquement pour les données BCn.
    En général, cela signifie que les points de terminaison de couleur sont séparés des
    indices de palette (c'est-à-dire des poids) et compressés à l'aide d'un algorithme rANS.

* `Swizzle`
  * Les modes `Swizzle` et shuffle peuvent apporter des optimisations supplémentaires dans les pipelines de contenu.

Lorsque des données à entropie élevée sont compressées, il est possible que la compression
augmente en fait leur taille. À l'inverse, la décompression correspondante réduit
la taille. DirectStorage n'autorise pas une décompression qui réduit la taille, et il appartient
au titre de détecter les données à entropie élevée incompressibles et d'éviter
de compresser ces ressources. Pour plus d'informations, consultez le guide [Optimisation
du contenu compressé à l'aide de DirectStorage et XBTC (rubrique sous NDA)](/fr/build/console-features/storage/directstorage/directstorage-compression).

### Mémoire tampon intermédiaire

DirectStorage utilise en interne une mémoire tampon pour placer tout le contenu lu à partir du stockage
NVMe brut avant d'effectuer des opérations telles que le déchiffrement et la
décompression. Cette mémoire tampon intermédiaire permet au lecteur NVMe et au circuit de déchiffrement/décompression de fonctionner en pipeline, en parallèle. Sa taille par défaut est de 32 Mio
et elle est allouée lorsque le premier pointeur de fabrique DirectStorage est récupéré.

Si un titre utilise DirectStorage uniquement pour des opérations de décompression de mémoire à mémoire,
la mémoire tampon intermédiaire n'est pas nécessaire, et
[SetStagingBufferSize](/fr/reference/system/dstorage/interfaces/IDStorageFactoryX/methods/idstoragefactoryx_setstagingbuffersize) peut être appelée
pour définir la taille de la mémoire tampon intermédiaire sur 0.

La version actuelle de DirectStorage prend en charge des tailles de mémoire tampon intermédiaire de 0, 16, 20, 24, 28 et 32 Mio. Une taille inférieure à la valeur par défaut permet au titre d'économiser de la mémoire, mais peut affecter les performances de lecture globales.

**REMARQUE :** [SetStagingBufferSize](/fr/reference/system/dstorage/interfaces/IDStorageFactoryX/methods/idstoragefactoryx_setstagingbuffersize)
ne peut être appelée que lorsqu'il n'existe aucun objet `IDStorageQueueX` ni aucun objet `IDStorageFileX` ; sinon, elle lève une erreur.

### CancelRequestsWithTag

DirectStorage prend en charge l'annulation des requêtes. Chaque requête est associée à une balise de
64 bits définie par le titre. Elle sert de masque de bits pour déterminer
les requêtes à annuler. Le titre fournit un masque et une valeur pour
l'annulation. La file d'attente tente d'annuler toutes les requêtes qui correspondent au
critère : `tag & mask == value`.

L'annulation est une opération effectuée au mieux. Selon l'emplacement de la requête dans
le pipeline, il peut être impossible de l'annuler. Par exemple, la requête peut
être en cours de décompression par le matériel, ce qui ne peut pas être annulé. L'API
retourne immédiatement et ne bloque pas en attendant que toutes les requêtes annulées soient
traitées. Les titres doivent attendre qu'une notification ultérieure dans la file d'attente soit signalée
avant de libérer les ressources associées aux requêtes annulées.

Veillez à ne pas ajouter de requêtes à une file d'attente au moment même où
[CancelRequestsWithTag](/fr/reference/system/dstorage/interfaces/IDStorageQueueX/methods/idstoragequeuex_cancelrequestswithtag) est appelée.
Dans ce cas, le comportement n'est pas défini. Toutefois, les requêtes ajoutées à la file d'attente
après le retour de l'appel à [CancelRequestsWithTag](/fr/reference/system/dstorage/interfaces/IDStorageQueueX/methods/idstoragequeuex_cancelrequestswithtag)
ne seront pas annulées, même si elles correspondent aux critères. Seules les requêtes précédemment
mises en file d'attente seront annulées.

### GetErrorEvent/RetrieveErrorRecord

Si une lecture provoque une erreur, cette lecture est marquée comme terminée. Les notifications
ultérieures de la file d'attente ne sont pas empêchées d'être signalées. La notification des erreurs
est gérée par un objet `Event` associé à la file d'attente, qui peut être
récupéré avec [GetErrorEvent](/fr/reference/system/dstorage/interfaces/IDStorageQueueX/methods/idstoragequeuex_geterrorevent). Le titre peut
utiliser **WaitForSingleObject** sur l'objet `Event` renvoyé par
[GetErrorEvent](/fr/reference/system/dstorage/interfaces/IDStorageQueueX/methods/idstoragequeuex_geterrorevent). Si l'événement est signalé,
le titre peut obtenir la première erreur survenue depuis le dernier appel à
la fonction [RetrieveErrorRecord](/fr/reference/system/dstorage/interfaces/IDStorageQueueX/methods/idstoragequeuex_retrieveerrorrecord)
en appelant la fonction [RetrieveErrorRecord](/fr/reference/system/dstorage/interfaces/IDStorageQueueX/methods/idstoragequeuex_retrieveerrorrecord).

L'enregistrement d'erreur renvoyé par
[RetrieveErrorRecord](/fr/reference/system/dstorage/interfaces/IDStorageQueueX/methods/idstoragequeuex_retrieveerrorrecord) contient uniquement les données
de la première requête ayant échoué dans la file d'attente depuis le dernier appel à
[RetrieveErrorRecord](/fr/reference/system/dstorage/interfaces/IDStorageQueueX/methods/idstoragequeuex_retrieveerrorrecord). Les données de
l'enregistrement d'erreur ne sont pas définies si l'objet `Event` d'erreur n'est pas signalé ou si les données ont
déjà été récupérées.

### Query

Obtient des informations sur la file d'attente. Cela inclut les structures [DSTORAGE\_QUEUE\_DESC](/fr/reference/system/dstorage/structs/dstorage_queue_desc) ou [DSTORAGE\_QUEUE\_DESC1](/fr/reference/system/dstorage/structs/dstorage_queue_desc1)
utilisées pour la création de la file d'attente, ainsi que le nombre d'emplacements vides
et le nombre d'entrées à mettre en file d'attente pour déclencher la soumission
automatique.

## Meilleures pratiques

Les mêmes conseils de meilleures pratiques donnés pour Win32 s'appliquent également à DirectStorage.
Les seuils de performances optimales ont radicalement changé.

### Tailles de lecture

Le conseil d'origine pour un disque rotatif était de lire par blocs d'au moins 128 Kio.
Les performances continuent d'augmenter avec des tailles de bloc plus importantes. Les blocs de
512 Kio offraient les meilleures performances.

L'absence de pièces mobiles sur le NVMe crée un seuil beaucoup plus bas. Les performances
de lecture font un bond important à partir des lectures de 32 Kio et commencent à plafonner
à 64 Kio. Lire au-delà n'augmente pas les performances. Cela signifie
qu'il faut moins d'efforts pour fusionner les données en blocs plus importants dans le
package afin d'obtenir des performances optimales.

Au-delà de 512 Kio, si la décompression est utilisée, préférez des requêtes plus petites mais plus nombreuses en
parallèle à une seule requête volumineuse. Une seule requête volumineuse oblige la
décompression à être sérialisée, tandis que plusieurs requêtes simultanées permettent à
plusieurs unités matérielles de décompression de fonctionner en parallèle et d'atteindre le débit
maximal.

Dans la version d'octobre 2022 du Microsoft Game Development Kit (GDK), la taille maximale d'une requête
unique est passée de 32 Mio pour la destination à 1 Gio d'utilisation mémoire combinée (source plus
destination). Cela permet de faciliter le portage depuis d'autres API de stockage
qui autorisent de grandes tailles de lecture. Mais la recommandation de taille précédente pour atteindre
le débit maximal reste la même, car les requêtes volumineuses ne permettent pas à
plusieurs unités matérielles de décompression de fonctionner en parallèle.

### Ordre

Auparavant, avec les disques rotatifs, des efforts étaient consacrés à l'ordonnancement de l'emplacement des
lectures sur le disque. La situation idéale consistait à lire à partir d'emplacements séquentiels sur
le disque. Cela réduisait au minimum les mouvements de la tête du disque, ce qui
éliminait le temps de recherche comme facteur. Cela pouvait augmenter les performances d'un ordre
de grandeur. Il était même avantageux de soumettre des lectures aléatoires triées par
emplacement, ce qui était dans certains cas 2 fois plus rapide.

Il reste utile d'ordonner les requêtes de lecture de manière aussi séquentielle que possible sur un
lecteur NVMe. Le lecteur NVMe lit par blocs alignés sur 64 Kio. De ce fait,
de la bande passante peut être gaspillée à lire des sections inutilisées d'un bloc de 64 Kio. Si une
requête de lecture ne porte que sur 4 Kio, 60 Kio de bande passante seront gaspillés. Le
NVMe réutilise ces 60 Kio supplémentaires pour satisfaire d'autres requêtes en attente si possible.
Par exemple, si vous avez deux lectures séquentielles, une de 32 Kio suivie d'une de 8 Kio,
il n'y a toujours qu'une seule lecture de 64 Kio depuis le lecteur.

### Gestion des files d'attente

La recommandation pour les disques rotatifs était d'avoir une taille de file d'attente comprise entre 12 et
16\. Une profondeur de file d'attente plus importante n'apportait aucun avantage, et la baisse
de performances liée à l'utilisation de profondeurs plus faibles était importante.

La spécification NVMe indique qu'un lecteur NVMe doit prendre en charge plusieurs files d'attente d'une
profondeur allant jusqu'à 65 536 entrées par file. DirectStorage prend en charge cette exigence,
ce qui permet au titre de soumettre des milliers de requêtes à la fois.

Auparavant, avec les disques rotatifs, les titres mettaient en mémoire tampon les requêtes en attente pour maintenir une
profondeur de file d'attente comprise entre 12 et 16. La recommandation pour DirectStorage est de
ne pas mettre en mémoire tampon les requêtes, mais de les mettre en file d'attente dès leur création. L'ensemble du
système est un pipeline, et la mise en mémoire tampon par le titre crée des bulles dans le pipeline,
ce qui peut nuire gravement aux performances.

Une autre recommandation consiste à créer une file d'attente d'une capacité au moins quatre fois supérieure
au plus grand nombre de requêtes créées par image. Cela devrait offrir une
capacité suffisante pour que de nouvelles requêtes puissent être ajoutées sans blocage en attendant que les
requêtes existantes se terminent.

### Gestion des notifications

En général, moins il y a de requêtes de notification ajoutées à la file d'attente, mieux c'est. La
recommandation est de trouver un équilibre entre les besoins du titre et la réduction au minimum des requêtes de notification
mises en file d'attente. Mettre en file d'attente une notification après chaque requête
ne fait que nuire aux performances globales en raison de la surcharge accrue liée au traitement
de ces notifications.

Un exemple consisterait à regrouper par contenu. Par exemple, les textures SFS, les besoins du terrain
(par exemple, maillage et texture) et les besoins des acteurs (par exemple, maillage,
texture et animation). Cela permet de lier une seule notification à la
disponibilité de toutes les ressources nécessaires pour créer un objet.

Le choix entre l'utilisation d'un `ID3D12Fence` et celle d'un tableau d'état dépend
des besoins du titre. Les données doivent-elles être utilisées immédiatement par le GPU ? Est-il
acceptable que le thread de vérification se suspende jusqu'à la fin des lectures ? Une interrogation
périodique suffit-elle parce que les données ne peuvent être traitées qu'à certains moments de
l'image ?

### Considérations

Avec la possibilité d'avoir un nombre beaucoup plus élevé de requêtes en cours, il faut veiller
à ne pas créer de goulots d'étranglement dans d'autres parties du titre. Les coûts
de gestion des requêtes par le titre pourraient rapidement dépasser les gains
obtenus grâce à DirectStorage. La recommandation est d'examiner tout le code de prise en charge
par requête et de déterminer ce qui peut être réduit.

Chaque requête nécessite-t-elle l'allocation d'un nouveau bloc de mémoire ?

* Le système de mémoire engendre une surcharge pour trouver un nouveau bloc et mettre à jour les listes internes.
* Envisagez de réutiliser les blocs de mémoire autant que possible.

Un verrou est-il nécessaire pour mettre à jour les gestionnaires ?

* Cela crée davantage de contention à mesure que les mises à jour se multiplient.
* Envisagez d'adopter une approche sans verrou autant que possible.

Le chargement spéculatif est-il utilisé ?

* L'annulation est prise en charge, ce qui pourrait conduire à créer davantage de requêtes.
* Toutefois, de la mémoire doit être disponible pour la spéculation.
* Envisagez des limites strictes pour les seuils de spéculation.

## Voir aussi

[DirectStorage](/fr/build/console-features/storage/directstorage-toc)
[Utilisation et détails internes de DirectStorage (rubrique sous NDA)](/fr/build/console-features/storage/directstorage/directstorage-white-paper)
[Optimisation du contenu compressé à l'aide de DirectStorage et XBTC (rubrique sous NDA)](/fr/build/console-features/storage/directstorage/directstorage-compression)
[Analyse des performances de DirectStorage (rubrique sous NDA)](/fr/tools/tools-console/pix/pix-directstorage)


## Related topics

- [Vue d'ensemble de XBOX Series X|S](/fr/paths/series-xs/overview.md)
- [Vue d'ensemble de Play Anywhere (console + PC)](/fr/paths/play-anywhere/overview.md)
- [Vue d'ensemble de l'accessibilité GDK](/fr/build/game-principles/accessibility/accessibility-overview.md)
- [Vue d'ensemble de Windows & ROG XBOX Ally](/fr/paths/windows/overview.md)
- [Vue d'ensemble de Godot et des moteurs communautaires](/fr/paths/community-engines/overview.md)
