> ## 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.

# Información general de DirectStorage

> Las API de DirectStorage para XBOX Series X|S ofrecen E/S de almacenamiento NVMe de alto rendimiento con una baja sobrecarga de CPU para grandes cantidades de solicitudes pequeñas.

## Introducción

Este artículo proporciona información general de las API de DirectStorage solo para
las consolas XBOX Series X|S. Consulte
[DirectStorage en el escritorio](https://aka.ms/directstorage) para obtener detalles de DirectStorage en el escritorio.

Los dispositivos de almacenamiento NVMe más recientes conectados mediante un bus PCIe pueden lograr niveles muy
altos de rendimiento e IOPS (solicitudes de E/S por segundo). La sobrecarga de
las API Win32 significa que, aunque se pueda utilizar el ancho de banda de almacenamiento
disponible, aprovecharlo podría dar lugar a un uso de CPU
inaceptablemente alto. Esto es especialmente cierto cuando la carga de trabajo consta de un gran
número de solicitudes pequeñas.

Las API de DirectStorage están diseñadas para eliminar la mayor parte de la sobrecarga del sistema
operativo mediante una interacción estrecha con el hardware NVMe subyacente. Esto permite
lograr un ancho de banda mayor con un menor uso de CPU. El objetivo es permitir
el control de hasta 50 000 solicitudes por segundo usando como máximo el 10 % de un
único núcleo de CPU.

### Problemas existentes

El contenido de los juegos es cada vez más grande a medida que aumenta la necesidad de recursos de mayor
resolución con cada generación de consolas. El hardware y el software existentes de XBOX One
tienen varias limitaciones que dificultan a los desarrolladores su
capacidad de llevar los datos desde el disco duro a la memoria para este contenido
de próxima generación.

* Uso elevado de CPU
  * Las API Win32 existentes podrían requerir un núcleo de CPU completo en sobrecarga.
  * Esto se basa en el número de solicitudes del título.

* Ancho de banda máximo insuficiente desde el disco
  * Los documentos técnicos [Maximización del rendimiento de archivos en XBOX Series X|S (tema NDA)](https://learn.microsoft.com/gaming/gdk/docs/gdk-dev/console-dev/overviews/file-system/Maximizing_File_Performance_Win32_Scarlett) y [Maximización del rendimiento de archivos en XBOX One (tema NDA)](https://learn.microsoft.com/gaming/gdk/docs/gdk-dev/console-dev/overviews/file-system/Maximizing_File_Performance_Win32_Xbox_One) tratan esto en detalle.

* Imposibilidad de priorizar las solicitudes de disco
  * Sin la capacidad de priorizar las solicitudes del título, puede ser difícil crear un
    sistema de streaming con capacidad de respuesta.

* Imposibilidad de cancelar las solicitudes de disco
  * Sin la capacidad de cancelar solicitudes, puede ser difícil crear un
    sistema de lectura especulativa.

* Sin descompresión acelerada por hardware
  * Sin la descompresión acelerada por hardware, realizar la descompresión en software
    puede consumir muchos recursos de CPU.

El conjunto de API de DirectStorage aborda directamente cada uno de estos problemas. El efecto
general es un aumento drástico del rendimiento del sistema de archivos de XBOX.

### Uso de CPU

El objetivo de diseño principal de DirectStorage es permitir que un título mantenga 50 000 IOPS
y solo use entre el 5 % y el 10 % de un único núcleo de CPU. Esto permite
que el título logre el ancho de banda máximo del subsistema de almacenamiento NVMe y, al
mismo tiempo, permite que la CPU se use para otros requisitos del título.

DirectStorage también agrega compatibilidad con la descompresión de hardware. Cada solicitud de lectura
se puede enrutar directamente desde la unidad NVMe al bloque de descompresión de hardware
integrado. Esto elimina la necesidad de que un título dedique recursos de CPU
a la descompresión.

### Modelo de canalización en cola

DirectStorage usa un método por lotes, en el que se agregan varias solicitudes a una cola.
En un momento posterior, la cola se vacía hacia la siguiente fase de la canalización. Esto
reduce de inmediato el costo total de CPU de una transición entre fases de la
canalización. Con el conjunto de API Win32 existente, hay una transición por cada solicitud.
Las colas de DirectStorage utilizan algoritmos sin bloqueo para minimizar la contención.
El título tiene control sobre cuándo se vacía cada cola.

En muchos casos con las API Win32, es posible que los datos del disco deban copiarse
a otro búfer. En algunos casos, es posible que los datos deban copiarse más de una vez.
DirectStorage elimina este problema asignando el búfer de destino proporcionado por el título
directamente a cada capa de la canalización. El hardware escribirá directamente en
el búfer proporcionado por el título.

Esos cambios contribuyen a reducciones significativas de la sobrecarga de CPU.

### Descompresión

Se ha incrementado la capacidad del hardware para descomprimir datos. Ahora puede
manejar una variedad más amplia de formatos y a una velocidad mayor de la que el subsistema NVMe
puede proporcionar datos. Además, DirectStorage admite la descompresión en contexto, lo que
elimina la necesidad de administrar búferes independientes para los datos comprimidos y
descomprimidos.

El hardware admite `BCPACK`, `DEFLATE`, y proporciona la capacidad de aplicar swizzle al
contenido final. Estos formatos no son mutuamente excluyentes. Es posible aplicar
los tres a los datos. Esto da al título la capacidad de elegir qué
método le ofrece la mejor relación de compresión y rendimiento. Diferentes recursos
pueden usar diferentes configuraciones de compresión y swizzle.

### Profundidad de la cola

La recomendación anterior era mantener solo entre 12 y 16 solicitudes asincrónicas
en curso a la vez en una unidad rotacional. Ir más allá no aportaba ningún beneficio al rendimiento, y
usar menos perjudicaba significativamente el rendimiento. Esto llevaba a los títulos a
realizar trabajo adicional para equilibrar sus solicitudes de lectura pendientes y mantenerse dentro
del objetivo recomendado.

Con el objetivo de DirectStorage de permitir que un título logre 50 000 IOPS, nuestra
recomendación ha cambiado. El título ya no necesita intentar equilibrar entre
trabajo pendiente y profundidad de cola. El título debe enviar todas sus solicitudes
pendientes. No hay ningún beneficio en retener algunas solicitudes. En muchos casos,
retener solicitudes podría perjudicar el rendimiento, ya que el hardware se detiene esperando
nuevas solicitudes.

El sistema operativo todavía debe dividir las solicitudes de lectura más grandes en
varias solicitudes más pequeñas en algunos casos (por ejemplo, para manejar la fragmentación del disco).
Sin embargo, esto se tuvo en cuenta en la arquitectura de DirectStorage. El objetivo de diseño de
50 000 IOPS se basa en el recuento de operaciones de E/S del título y no en las solicitudes
finales que van al hardware.

### Notificación

En la arquitectura Win32, se dedica una cantidad significativa de sobrecarga a las
notificaciones de finalización de lectura. El título puede sondear una estructura *OVERLAPPED*,
esperar un identificador de evento asociado o realizar una lectura de bloqueo
sincrónica. En general, esto aumenta las demandas de recursos de cada solicitud de
lectura.

DirectStorage mantiene los dos conceptos asincrónicos de notificaciones y, además,
agrega un tercer método. No hay compatibilidad con lecturas de bloqueo sincrónicas en
DirectStorage; es posible que un título implemente su propio sistema. Sin embargo,
esto no se recomienda.

El primer método asincrónico se implementa a través de un bloque de estado que se establece
cuando se completan las solicitudes asociadas. El título puede sondear el bloque según
sea necesario para determinar cuándo se han completado las lecturas. Esto es similar al método Win32 de
sondear una estructura *OVERLAPPED* para comprobar su finalización.

El segundo método asincrónico consiste en usar un objeto `Event` de Windows para señalar la finalización.
Esto es similar a usar una estructura *OVERLAPPED* con un objeto `Event` correspondiente.
El título puede usar el método [WaitForSingleObject](https://learn.microsoft.com/windows/win32/api/synchapi/nf-synchapi-waitforsingleobject)
para hacer que el subproceso que llama se suspenda hasta que se completen las operaciones de lectura.

El tercer método asincrónico se implementa mediante un objeto [ID3D12Fence](https://learn.microsoft.com/windows/win32/api/d3d12/nn-d3d12-id3d12fence). El título
puede suspenderse esperando la barrera (fence) o puede sondearla si es necesario.
También existe el beneficio de que la GPU puede usar la barrera para la notificación directa
de solicitudes completadas.

El sistema de notificaciones de DirectStorage no está vinculado a una única solicitud de lectura. Es
una entrada colocada dentro de la cola, que se señala cuando todas las solicitudes de lectura
anteriores han finalizado. Esto da al título control sobre cuánta granularidad
necesita para la notificación. La notificación siempre se señala en el orden de la cola.
La cola se puede considerar una cola FIFO (primero en entrar, primero en salir). El título solo
necesita consultar la última notificación relevante. Se garantiza que todas las solicitudes
puestas en cola anteriormente se han completado.

### Descompresión de memoria a memoria

DirectStorage proporciona un tipo de cola para invocar el hardware de descompresión con
un origen de descompresión que es memoria en lugar de un archivo de disco. Esto permite
utilizar el hardware de descompresión si el recurso comprimido no procede
de un archivo o se obtuvo previamente y se mantuvo en memoria como caché. Una
cola con origen en memoria solo acepta solicitudes con origen en memoria, y una cola con origen
en archivo solo acepta solicitudes con origen en archivo.

Si no se especifica ninguna opción de descompresión en una solicitud con origen en memoria, el
hardware de descompresión también puede actuar como un motor de copia DMA.

Aunque DirectStorage garantiza que las notificaciones de finalización están en orden,
DirectStorage no ofrece ninguna garantía sobre cuándo comienzan a procesarse las solicitudes.
Como resultado, no debe haber dependencias de datos entre las solicitudes pendientes. Es
decir, el destino de la solicitud A no se puede usar como origen de la solicitud B, a menos que la solicitud
B se ponga en cola después de la finalización de la solicitud A.

Las colas con origen en memoria deben crearse con prioridad en tiempo real. Además,
las solicitudes en tiempo real con origen en memoria siempre se procesan mediante el hardware de
descompresión antes que las solicitudes con origen en disco que requieren descompresión.
Si las colas con origen en disco no tienen ninguna solicitud de descompresión, los dos
tipos de cola se procesan completamente en paralelo sin afectar al otro tipo.

### Prioridad

DirectStorage permite asignar un nivel de prioridad a cada cola. Cada entrada de
la cola hereda la prioridad de la cola. Se proporcionan cuatro niveles de prioridad
diferentes: tiempo real, alta, normal y baja. Las solicitudes se procesan de forma round-robin
ponderada. Por ejemplo, se procesan X solicitudes de prioridad alta antes de procesar
una solicitud de prioridad normal. Se procesan Y solicitudes de prioridad normal antes de
procesar una solicitud de prioridad baja.

La ponderación de prioridad se contabiliza según el tamaño de cada solicitud. La ponderación predeterminada
entre cada prioridad es de aproximadamente 10x. Esto significa que por cada 1 KB de solicitud de prioridad
baja, se habrían procesado 10 KB de solicitud de prioridad media y 100 KB de solicitud de prioridad
alta.

Las solicitudes de lectura Win32 existentes se enrutan a través del mismo sistema de prioridades. Todas
las solicitudes Win32 se consideran de prioridad normal.

Las colas con origen en memoria deben crearse con prioridad en tiempo real.

### Cancelación

Cada solicitud de lectura de DirectStorage tiene asociada una máscara de 64 bits proporcionada por el
título. Esto sirve para admitir la cancelación de solicitudes de lectura pendientes. El título puede
cancelar las solicitudes que coincidan con un conjunto específico de marcas dentro de la máscara.

Incluso con compatibilidad con la cancelación, sigue siendo posible que el hardware procese una solicitud de
lectura. La solicitud de cancelación del título es un intento de mejor
esfuerzo. Si el hardware ya está procesando activamente la solicitud,
no se puede cancelar.

Dado que la solicitud de cancelación es de mejor esfuerzo, el título debe esperar hasta
que se le notifique que la solicitud de lectura ha terminado de procesarse. El título
no puede liberar ningún recurso necesario hasta que se reciba una notificación posterior en la
cola. Sin embargo, durante este tiempo, se pueden poner en cola nuevas solicitudes que coincidan con las marcas
usadas en una solicitud de cancelación anterior y no se cancelarán.

Cuando se completa una solicitud cancelada, se considera un **éxito**, incluso si
se canceló y no produjo el resultado completo. En otras palabras, si
se intenta cancelar una solicitud, el título ya no puede consumir el
resultado de la solicitud potencialmente cancelada tras su finalización.

### Garantía

Las consolas XBOX One y XBOX One S tenían una garantía mínima de 40 MB/s. La
consola XBOX One X aumentó la garantía mínima a 60 MB/s. Estas cifras están
muy por debajo de los límites reales del hardware, que se sitúan en torno a los 130 MB/s. Esto se debía
por completo a la sobrecarga causada por el sistema operativo.

DirectStorage elimina la mayor parte de la sobrecarga causada por el sistema operativo. Esto
permite una garantía mínima más cercana a los límites del hardware. La nueva garantía mínima
de rendimiento es de 2.0 GB/s en una ventana de 250 ms para datos sin procesar. El uso de
descompresión en el contenido elevará aún más el ancho de banda final.

Las futuras consolas XBOX admitirán la adición de unidades dinámicas instalables por el usuario
que también se basan en NVMe. La misma garantía mínima de rendimiento que se
proporciona para la unidad interna también se proporciona para la unidad instalable por el usuario.

## Información general de la API

Las interfaces de DirectStorage siguen el mismo patrón que las interfaces de Direct3D.
El título obtiene inicialmente un generador (factory) singleton. El generador se usa para crear
colas de solicitudes y abrir archivos; cada uno de estos objetos tiene una asignación
directa al hardware. Las solicitudes individuales se ponen luego en una cola para
enviarse al hardware.

### IDStorageFactoryX

`IDStorageFactoryX` es la interfaz principal para crear colas, abrir archivos y
enviar solicitudes pendientes.

El objeto `IDStorageFactoryX `tiene los métodos siguientes.

* [OpenFile](/reference/system/dstorage/interfaces/IDStorageFactoryX/methods/idstoragefactoryx_openfile)
  * Crea un objeto `IDStorageFileX `, que representa un archivo.

* [CreateQueue](/reference/system/dstorage/interfaces/IDStorageFactoryX/methods/idstoragefactoryx_createqueue)
  * Crea un objeto `IDStorageQueueX`. Se usa para crear solicitudes de lectura.

* [CreateStatusArray](/reference/system/dstorage/interfaces/IDStorageFactoryX/methods/idstoragefactoryx_createstatusarray)
  * Crea un objeto `IDStorageStatusArray`, que administra las marcas de estado de
    finalización.

* [SetCPUAffinity](/reference/system/dstorage/interfaces/IDStorageFactoryX/methods/idstoragefactoryx_setcpuaffinity)
  * Restringe el trabajo de DirectStorage fuera del subproceso de llamada a un conjunto
    de núcleos de CPU definido por el título.
  * **NOTA** DirectStorage intenta hacer la mayor parte del trabajo en
    el subproceso de llamada. El trabajo fuera del subproceso de llamada solo se produce cuando no se puede
    realizar en el subproceso de llamada. Algunos ejemplos son los siguientes.
    * La canalización de recursos subyacente está llena durante `IDStorageQueueX::Submit`,
      y no todas las solicitudes de la cola pueden avanzar. Las solicitudes
      restantes se procesarán más adelante cuando se liberen los recursos, y esto
      se hace en un subproceso de trabajo de DirectStorage.
    * Procesamiento de la finalización de solicitudes en `ID3DFence` o `IDStorageStatusArray`.

* [SetDebugFlags](/reference/system/dstorage/interfaces/IDStorageFactoryX/methods/idstoragefactoryx_setdebugflags)
  * Controla si DirectStorage realizaría validaciones adicionales en el momento de poner
    en cola las solicitudes para ayudar en la depuración.

* [SetStagingBufferSize](/reference/system/dstorage/interfaces/IDStorageFactoryX/methods/idstoragefactoryx_setstagingbuffersize)
  * Establece el tamaño del búfer de almacenamiento provisional usado para almacenar temporalmente el contenido cargado
    desde el dispositivo de almacenamiento antes de descifrarlo o descomprimirlo. Si solo se
    usan colas con origen en memoria, el búfer de almacenamiento provisional puede tener tamaño 0.

### IDStorageFactoryX1

La interfaz `IDStorageFactoryX1` amplía la interfaz `IDStorageFactoryX` con
un método [GetStats](/reference/system/dstorage/interfaces/IDStorageFactoryX1/methods/idstoragefactoryx1_getstats).

* [GetStats](/reference/system/dstorage/interfaces/IDStorageFactoryX1/methods/idstoragefactoryx1_getstats)
  * Obtiene las estadísticas de DirectStorage. Esta función se puede usar para integrar
    DirectStorage con las canalizaciones de diagnóstico y telemetría existentes.
    Realiza un procesamiento mínimo y, por lo tanto, se puede llamar con frecuencia. Las estadísticas
    no incluyen las operaciones de E/S de archivos Win32.

### IDStorageFactoryX2

La interfaz `IDStorageFactoryX2` amplía la interfaz \`IDStorageFactoryX1 con
un método [CreateQueue1](/reference/system/dstorage/interfaces/IDStorageFactoryX2/methods/idstoragefactoryx_createqueue1).

* [CreateQueue1](/reference/system/dstorage/interfaces/IDStorageFactoryX2/methods/idstoragefactoryx_createqueue1)
  * Crea un objeto `IDStorageQueueX2`. Usa una nueva estructura para permitir
    opciones adicionales en la creación de colas, incluida la capacidad de invalidar
    la característica de envío automático de una cola.

### IDStorageFileX

Todos los archivos deben ser abiertos inicialmente por DirectStorage a través del
objeto `IDStorageFactoryX`. Esto es equivalente a usar `CreateFile` en las interfaces de
API Win32.

Los archivos se abren con el permiso `FILE_SHARED_READ`. Si es necesario, los títulos pueden
abrir simultáneamente el archivo usando las API Win32 siempre que se respeten los
permisos adecuados. Durante el desarrollo, se admiten tanto las implementaciones sueltas como las empaquetadas.

Los archivos se cierran llamando explícitamente a la función [Close](/reference/system/dstorage/interfaces/IDStorageFileX/methods/idstoragefilex_close)
en el objeto de archivo o cuando se libera la última referencia al objeto
`IDStorageFileX` correspondiente. Sin embargo, todas las operaciones de E/S pendientes deben
completarse antes de que se pueda cerrar el archivo. Esto significa que ambos métodos para cerrar
un archivo se bloquearán hasta que se hayan completado todas las operaciones de E/S pendientes en ese archivo.

El juego puede obtener un identificador win32 de un archivo representado por un objeto `IDStorageFileX`
llamando a la función [GetHandle](/reference/system/dstorage/interfaces/IDStorageFileX/methods/idstoragefilex_gethandle).
El identificador se abre con permisos `GENERIC_READ` y modo de uso compartido `FILE_SHARE_READ`.
Se puede usar para consultar el tamaño del archivo, etc. El identificador debe cerrarse
con `CloseHandle()` cuando ya no sea necesario.

### IDStorageQueueX

Las solicitudes de lectura se envían al NVMe a través de un objeto `IDStorageQueueX`.
Sin embargo, las solicitudes no se envían al dispositivo hasta que el título llama a
[Submit](/reference/system/dstorage/interfaces/IDStorageQueueX/methods/idstoragequeuex_submit) en la cola, o hasta que uno de los métodos Enqueue
llena más de la mitad de la capacidad de la cola desde el último envío y desencadena
un envío automático. Los envíos se manejan como una única transición a la
siguiente fase de la canalización. Esto permite que el título controle cuándo se produce el costo de CPU
por la transición entre el título y el kernel.

Los objetos `IDStorageQueueX` tienen cuatro propiedades.

* [SourceType](/reference/system/dstorage/enums/dstorage_request_source_type)
  * Especifica si la cola puede recibir solicitudes con origen en archivo o
    solicitudes con origen en memoria.

* [Priority](/reference/system/dstorage/enums/dstorage_priority)
  * La prioridad de todas las solicitudes enviadas a la cola: tiempo real, alta, normal o baja.
  * Las colas con origen en memoria deben crearse con prioridad en tiempo real.
  * Las solicitudes se procesan en un orden round-robin ponderado según la prioridad.
  * Las solicitudes Win32 se procesan en el nivel de prioridad normal.

* **Capacity**
  * El número máximo de solicitudes pendientes que puede contener la cola.
  * Intentar poner en cola una solicitud cuando la cola está a plena capacidad se bloqueará
    hasta que el hardware complete algunas entradas.
  * La cantidad de memoria necesaria para una cola es aproximadamente la capacidad de la cola
    multiplicada por el tamaño de una `DSTORAGE_REQUEST`.

* **Name**
  * Esto es únicamente para ayudar en la depuración. Ningún código de
    DirectStorage usa el nombre, pero es visible en las herramientas para desarrolladores, como
    [PIX (tema NDA)](/tools/tools-console/pix/pix-directstorage).

El hardware procesará las solicitudes de forma asincrónica para lograr el máximo
rendimiento. Sin embargo, a diferencia de Win32, el título recibe la notificación de finalización en orden
FIFO. Tras la notificación de finalización, se garantiza que todas las solicitudes anteriores
a la misma cola también se han completado.

### IDStorageQueueX1

La interfaz `IDStorageQueueX1` amplía la interfaz `IDStorageQueueX` con el
método [EnqueueSetEvent](/reference/system/dstorage/interfaces/IDStorageQueueX1/methods/idstoragequeuex_enqueuesetevent).

### IDStorageQueueX2

La interfaz `IDStorageQueueX2` amplía la interfaz \`IDStorageQueueX1 con el método [CreateQueue1](/reference/system/dstorage/interfaces/IDStorageFactoryX2/methods/idstoragefactoryx_createqueue1).

Y una propiedad adicional.

* [Options](/reference/system/dstorage/structs/dstorage_queue_options)
  * Marcas que se usan para controlar el comportamiento de la cola, incluida la deshabilitación del envío automático.

### EnqueueRequest

Esta interfaz es funcionalmente igual que la interfaz `ReadFile` de Win32.
Las solicitudes de lectura individuales se crean y se envían a la cola. La principal
diferencia es que DirectStorage permite poner en cola muchas solicitudes antes del
envío, admite la descompresión de hardware y admite la cancelación.

Las solicitudes tienen varias propiedades principales.

**Origen de la solicitud**
Según la combinación de `Options.SourceType` y
`Options.SourceIsPhysicalPages`, DirectStorage usa uno de los tres
grupos de propiedades siguientes para especificar dónde existen los datos de origen.

* **File** y **FileOffset**
  * Este grupo se usa cuando `Options.SourceType` es `DSTORAGE_REQUEST_SOURCE_FILE`
  * **File** se abre previamente con `IDStorageFactoryX::OpenFile`.
  * **FileOffset** debe estar alineado a 16 bytes si se usa descompresión, o
    no tiene requisito de alineación si no se usa descompresión.
    * Este es un cambio importante con respecto a Win32, que requería una alineación de 4 KiB dentro
      del archivo para las lecturas asincrónicas.

* **Source**
  * Este grupo se usa cuando `Options.SourceType` es `DSTORAGE_REQUEST_SOURCE_MEMORY`
    y `Options.SourceIsPhysicalPages` es `FALSE`.
  * El búfer de memoria que contiene los datos que se van a descomprimir.

* **SourcePageArray** y **SourcePageOffset**
  * Este grupo se usa cuando `Options.SourceType` es `DSTORAGE_REQUEST_SOURCE_MEMORY`
    y `Options.SourceIsPhysicalPages` es `TRUE`.
  * Similar a `Source`, pero proporciona el búfer de memoria de origen en forma de una
    matriz de páginas físicas de 64 KB y el desplazamiento en bytes en la primera página.
  * Las páginas físicas de 64 KB se pueden asignar mediante `XMemAllocatePhysicalPages`.

**SourceSize**

* Tamaño, en bytes, de los datos de origen que se van a leer, ya sea desde un búfer de memoria
  o desde un archivo.

**IntermediateSize**

* Cuando la descompresión `zlib` y `BCPACK`están habilitadas en esta solicitud,
  `IntermediateSize` se usa para especificar el tamaño intermedio al que los datos de
  origen se descomprimen con zlib (y desde el que se descomprimen con BCPACK).
* De lo contrario, debe establecerse en 0.

**Destino de la solicitud**
Según `Options.DestinationIsPhysicalPages`, DirectStorage usa uno de los
dos grupos de propiedades siguientes para especificar dónde existe el destino.

* **Destination**
  * Este grupo se usa cuando `Options.DestinationIsPhysicalPages` es `FALSE`.
  * El búfer de destino para los datos cargados finales.
  * La descompresión se realiza usando búferes internos compartidos y puede considerarse
    en contexto.

* **DestinationPageArray** y **DestinationPageOffset**
  * Este grupo se usa cuando `Options.DestinationIsPhysicalPages` es `TRUE`.
  * Similar a `Destination`, pero proporciona el búfer de memoria de destino en
    forma de una matriz de páginas físicas de 64 KB y el desplazamiento en bytes en la primera
    página.
  * Las páginas físicas de 64 KB se pueden asignar mediante `XMemAllocatePhysicalPages`.

**DestinationSize**

* Tamaño esperado, en bytes, del contenido cargado final. El destino debe
  contener espacio suficiente para dar cabida a la operación.
* El tamaño debe ser igual a **SourceSize** cuando no se usa descompresión, o
  ser mayor que **SourceSize** cuando se usa descompresión.

**CancellationTag**

* Una etiqueta arbitraria de 64 bits definida por el título.
* Esta etiqueta se usa como máscara para las solicitudes de cancelación.

**Name**

* Cadena opcional para ayudar en la depuración. El nombre puede aparecer en las herramientas
  para desarrolladores, como [PIX (tema NDA)](/tools/tools-console/pix/pix-directstorage), o en el registro de errores
  obtenido de `IDStorageQueueX::RetrieveErrorRecord`. La cadena `Name` debe
  ser accesible durante toda la vigencia de la solicitud.

**Options**

* **ZlibDecompress**
  * Indica que los datos deben descomprimirse usando el estándar de descompresión
    RFC 1950.
* **BcpackMode**
  * Indica qué modo de `BCPACK` debe usarse para descomprimir los datos.
  * None es una opción válida y significa que los datos no están comprimidos con `BCPACK`.
* **SwizzleMode**
  * Indica cómo deben reorganizarse (swizzle) los datos finales en la memoria.
* **DestinationIsPhysicalPages**
  * Indica que el búfer de destino se especifica usando
    **DestinationPageArray** y **DestinationPageOffset** en lugar de
    **Destination**.
* **SourceType**
  * Una solicitud puede tener origen en memoria y, por lo tanto, tener las propiedades `Source`/
    `SourcePageArray` y `SourcePageOffset`, o tener origen en archivo y, por lo tanto,
    tener las propiedades `File`/`FileOffset`.
* **SourceIsPhysicalPages**
  * Indica que el búfer de origen se especifica usando **SourcePageArray**
    y **SourcePageOffset** en lugar de **Source**.

### EnqueueStatus/EnqueueSignal/EnqueueSetEvent

Las solicitudes se pueden poner en cola y tratar como una serie de solicitudes relacionadas. Esto se
hace poniendo en cola una notificación para cuando el procesamiento haya alcanzado un punto determinado
de la cola. Las notificaciones se procesan solo cuando todas las solicitudes de lectura anteriores
se han completado. Esto garantiza que los datos estén disponibles de inmediato de todas las solicitudes
anteriores.

El título tiene dos métodos de sondeo y un método de espera para la notificación. El
título puede insertar un objeto `ID3D12Fence`, un objeto `IDStorageStatusArrayX` o una
operación de establecimiento de evento. `ID3D12Fence` se comporta como se espera de un objeto `ID3D12Fence`.
Un subproceso del título puede esperar en un `Event`, la CPU puede sondear la barrera y la
GPU puede sondear la barrera. El objeto `IDStorageStatusArrayX` permite que la CPU sondee la
finalización y acceda a posibles errores de lectura. El método `EnqueueSetEvent`
permite que un subproceso del título espere el evento especificado en lugar de sondear.
Esto difiere de `ID3D12Fence::SetEventOnCompletion`, ya que la implementación de XBOX
de `ID3D12Fence::SetEventOnCompletion` realiza un bucle de espera activa en la barrera hasta que se señala,
consumiendo así el subproceso de hardware de la CPU hasta la señal, mientras que `EnqueueSetEvent`
permite que el subproceso del título use `WaitForSingleObject`/`WaitForMultipleObjects` para
ceder la CPU a otros subprocesos hasta que se señale el evento.

Como se mencionó anteriormente, todas las solicitudes se completan en orden, incluso si el hardware
subyacente decide reordenarlas por rendimiento. Las notificaciones no se señalan
hasta que todas las solicitudes puestas en cola anteriormente en la cola se hayan completado.

### Descompresión

La descompresión se maneja con hardware dedicado. Esto elimina la sobrecarga de CPU
de los algoritmos de descompresión tradicionales. DirectStorage asigna un bloque fijo
de memoria durante la inicialización para usarlo como búfer de trabajo para la descompresión.
Esto permite la descompresión en contexto y elimina la necesidad de mantener los datos
comprimidos y descomprimidos en memoria al mismo tiempo.

El hardware de descompresión admite tres modos de operación. Los modos no son
mutuamente excluyentes, por lo que se puede especificar cualquier combinación de modos. Los modos de
descompresión se aplican en el orden siguiente: `DEFLATE`, `BCPACK` y `Swizzle`.

* `ZLibDecompress`
  * Este es el estándar de compresión [IETF RFC 1950](https://www.ietf.org/rfc/rfc1950.txt).

* `BCPack`
  * `BCPack` es un codificador de entropía personalizado diseñado específicamente para datos BCn.
    En general, lo que esto significa es que los puntos de extremo de color se separan de
    los índices de paleta (es decir, los pesos) y se comprimen usando un algoritmo rANS.

* `Swizzle`
  * Los modos `Swizzle` y de orden aleatorio pueden proporcionar optimizaciones adicionales en las canalizaciones de contenido.

Cuando se comprimen datos de alta entropía, es posible que la compresión
en realidad aumente el tamaño. Por el contrario, la descompresión correspondiente reducirá
el tamaño. DirectStorage no permite la descompresión con reducción, y corresponde al
título detectar los datos de alta entropía que son incompresibles y evitar
comprimir esos recursos. Para obtener más detalles, consulte la guía [Optimización de
contenido comprimido mediante DirectStorage y XBTC (tema NDA)](/build/console-features/storage/directstorage/directstorage-compression).

### Búfer de almacenamiento provisional

DirectStorage usa internamente un búfer para almacenar provisionalmente todo el contenido leído desde el
almacenamiento NVMe sin procesar antes de realizar operaciones como el descifrado y la
descompresión. Este búfer de almacenamiento provisional permite que la unidad NVMe y el silicio de descifrado/descompresión trabajen en una canalización en paralelo. De forma predeterminada es de 32 MiB
y se asigna cuando se recupera el primer puntero de generador de DirectStorage.

Si un título usa DirectStorage solo para operaciones de descompresión de memoria a
memoria, el búfer de almacenamiento provisional no es necesario, y se puede llamar a
[SetStagingBufferSize](/reference/system/dstorage/interfaces/IDStorageFactoryX/methods/idstoragefactoryx_setstagingbuffersize)
para establecer el tamaño del búfer de almacenamiento provisional en 0.

La versión actual de DirectStorage admite tamaños de búfer de almacenamiento provisional de 0, 16, 20, 24, 28 y 32 MiB. Un tamaño menor que el valor predeterminado ahorrará memoria para el título, pero podría afectar al rendimiento general de lectura.

**NOTA:** Solo se puede llamar a [SetStagingBufferSize](/reference/system/dstorage/interfaces/IDStorageFactoryX/methods/idstoragefactoryx_setstagingbuffersize)
cuando no existe ningún objeto `IDStorageQueueX` ni ningún objeto `IDStorageFileX`; de lo contrario, generará un error.

### CancelRequestsWithTag

DirectStorage admite la cancelación de solicitudes. Cada solicitud tiene asociada una etiqueta
de 64 bits definida por el título. Su propósito es servir como máscara de bits para
determinar qué solicitudes cancelar. El título proporciona una máscara y un valor para la
cancelación. La cola intentará cancelar todas las solicitudes que coincidan con el
criterio: `tag & mask == value`.

La cancelación es una operación de mejor esfuerzo. Según el punto de la canalización en que se encuentre
la solicitud, es posible que no se pueda cancelar. Por ejemplo, la solicitud podría
estar siendo descomprimida por el hardware, lo que no se puede cancelar. La API
devuelve el control inmediatamente y no se bloquea esperando a que se procesen todas las solicitudes
canceladas. Los títulos deben esperar hasta que se señale una notificación posterior en la cola
antes de liberar los recursos asociados a las solicitudes canceladas.

Se debe tener cuidado de evitar agregar solicitudes a una cola al mismo tiempo que
se llama a [CancelRequestsWithTag](/reference/system/dstorage/interfaces/IDStorageQueueX/methods/idstoragequeuex_cancelrequestswithtag).
En este caso, el comportamiento es indefinido. Sin embargo, las solicitudes agregadas a la cola
después de que la llamada a [CancelRequestsWithTag](/reference/system/dstorage/interfaces/IDStorageQueueX/methods/idstoragequeuex_cancelrequestswithtag)
haya devuelto el control no se cancelarán aunque se cumplan los criterios. Solo se cancelarán las solicitudes
puestas en cola anteriormente.

### GetErrorEvent/RetrieveErrorRecord

Si una lectura provoca un error, esa lectura se marca como completada. Las notificaciones
futuras de la cola no quedan bloqueadas para señalarse. La notificación de errores
se maneja a través de un objeto `Event` asociado a la cola que se puede
recuperar con [GetErrorEvent](/reference/system/dstorage/interfaces/IDStorageQueueX/methods/idstoragequeuex_geterrorevent). El título puede
usar **WaitForSingleObject** en el `Event` devuelto por
[GetErrorEvent](/reference/system/dstorage/interfaces/IDStorageQueueX/methods/idstoragequeuex_geterrorevent). Si el evento se señala,
el título puede obtener el primer error desde la última llamada a
la función [RetrieveErrorRecord](/reference/system/dstorage/interfaces/IDStorageQueueX/methods/idstoragequeuex_retrieveerrorrecord)
llamando a la función [RetrieveErrorRecord](/reference/system/dstorage/interfaces/IDStorageQueueX/methods/idstoragequeuex_retrieveerrorrecord).

El registro de errores devuelto por
[RetrieveErrorRecord](/reference/system/dstorage/interfaces/IDStorageQueueX/methods/idstoragequeuex_retrieveerrorrecord) solo contiene datos
de la primera solicitud con error en la cola desde la última llamada a
[RetrieveErrorRecord](/reference/system/dstorage/interfaces/IDStorageQueueX/methods/idstoragequeuex_retrieveerrorrecord). Los datos del
registro de errores no están definidos si el `Event` de error no se señala o si los datos ya
se han recuperado.

### Query

Obtiene información sobre la cola. Incluye las estructuras [DSTORAGE\_QUEUE\_DESC](/reference/system/dstorage/structs/dstorage_queue_desc) o [DSTORAGE\_QUEUE\_DESC1](/reference/system/dstorage/structs/dstorage_queue_desc1)
usadas para la creación de la cola, así como el número de posiciones vacías
y el número de entradas que deben ponerse en cola para desencadenar el envío
automático.

## Procedimientos recomendados

Los mismos consejos de procedimientos recomendados proporcionados para Win32 también se aplican a DirectStorage.
Los umbrales para el rendimiento óptimo han cambiado radicalmente.

### Tamaños de lectura

El consejo original para un disco rotacional era leer en bloques de al menos 128 KiB.
El rendimiento sigue aumentando con tamaños de bloque más grandes. Los bloques de 512
KiB lograban el mejor rendimiento.

La ausencia de piezas móviles en el NVMe crea un umbral mucho más bajo. El rendimiento
de lectura tiene un gran salto a partir de lecturas de 32 KiB y comienza a estabilizarse
con 64 KiB. Leer por encima de esto no aumenta el rendimiento. Esto significa
que se necesita menos esfuerzo para combinar datos en bloques más grandes en el
paquete para obtener un rendimiento óptimo.

Por encima de 512 KiB, si se usa descompresión, prefiera solicitudes más pequeñas pero más numerosas en
paralelo, en lugar de una única solicitud enorme. Una única solicitud enorme obligará a que la
descompresión se serialice, mientras que varias solicitudes simultáneas permiten que
varias unidades de hardware de descompresión trabajen en paralelo y logren el rendimiento
máximo.

En la versión de octubre de 2022 de Microsoft Game Development Kit (GDK), el tamaño máximo de una única solicitud
se ha aumentado de 32 MiB como destino a 1 GiB de uso de memoria combinado (origen más
destino). Se proporciona para facilitar la portabilidad desde otras API de almacenamiento
que permiten tamaños de lectura grandes. Pero la recomendación de tamaño anterior para lograr
el rendimiento máximo sigue siendo la misma, porque las solicitudes grandes no permiten
que varias unidades de hardware de descompresión trabajen en paralelo.

### Orden

Anteriormente, con los discos rotacionales, se dedicaba esfuerzo a ordenar la ubicación de
las lecturas en el disco. La situación ideal era leer desde ubicaciones secuenciales en
el disco. Esto creaba la cantidad mínima de movimiento del cabezal del disco, lo que
eliminaba el tiempo de búsqueda como factor. Hacer esto podía aumentar el rendimiento en un orden
de magnitud. Incluso había beneficio en enviar lecturas aleatorias ordenadas por
ubicación y, en algunos casos, era 2 veces más rápido.

Sigue siendo útil ordenar las solicitudes de lectura para que sean lo más secuenciales posible en una
unidad NVMe. La unidad NVMe lee en bloques alineados de 64 KiB. Debido a esto,
puede haber ancho de banda desperdiciado al leer secciones no usadas de un bloque de 64 KiB. Si una
solicitud de lectura es de solo 4 KiB, habrá 60 KiB de ancho de banda desperdiciado. El
NVMe reutilizará esos 60 KiB adicionales para satisfacer otras solicitudes pendientes si es posible.
Por ejemplo, si tiene dos lecturas secuenciales, una de 32 KiB seguida de una de 8 KiB,
sigue habiendo una única lectura de 64 KiB desde la unidad.

### Administración de colas

La recomendación con los discos rotacionales era tener un tamaño de cola de entre 12 y
16\. No había ningún beneficio con una profundidad de cola mayor, y la reducción de
rendimiento por usar profundidades de cola más pequeñas era significativa.

La especificación NVMe indica que una unidad NVMe debe admitir varias colas con una
profundidad de hasta 65 536 entradas por cola. DirectStorage admite este requisito,
lo que permite que el título envíe miles de solicitudes a la vez.

Anteriormente, con los discos rotacionales, los títulos almacenaban en búfer las solicitudes pendientes para mantener una
profundidad de cola en el rango de 12 a 16. La recomendación para DirectStorage es
no almacenar en búfer las solicitudes, sino ponerlas en cola tan pronto como se creen. Todo el
sistema es una canalización, y el almacenamiento en búfer del título creará burbujas en la canalización,
lo que puede perjudicar gravemente el rendimiento.

Otra recomendación es crear una cola con una capacidad de al menos cuatro veces
el mayor número de solicitudes creadas por fotograma. Esto debería permitir suficiente
capacidad para que se puedan agregar nuevas solicitudes sin detenerse a esperar a que se completen las
solicitudes existentes.

### Administración de notificaciones

En general, cuantas menos solicitudes de notificación se agreguen a la cola, mejor. La
recomendación es encontrar un equilibrio entre las necesidades del título y mantener al mínimo las
solicitudes de notificación en cola. Poner en cola una notificación después de cada solicitud
solo perjudicará el rendimiento general debido a la mayor sobrecarga del procesamiento
de esas notificaciones.

Un ejemplo podría ser agrupar por contenido. Por ejemplo, texturas SFS, necesidades del
terreno (por ejemplo, malla y textura) y necesidades de los actores (por ejemplo, malla,
textura y animación). Esto permite vincular una única notificación a la
disponibilidad de todos los recursos necesarios para crear un objeto.

La elección entre usar un `ID3D12Fence` o una matriz de estado depende de
las necesidades del título. ¿La GPU necesita usar los datos de inmediato? ¿Es
aceptable que el subproceso de comprobación se suspenda hasta que finalicen las lecturas? ¿Es suficiente sondear
periódicamente porque los datos solo se pueden procesar en ciertos puntos del
fotograma?

### Consideraciones

Con el potencial de un número mucho mayor de solicitudes en curso, se debe tener cierto cuidado
para evitar crear cuellos de botella en otras partes del título. Los costos
para que el título administre las solicitudes podrían superar rápidamente los ahorros
logrados por DirectStorage. La recomendación es examinar todo el código auxiliar
por solicitud y determinar qué se puede minimizar.

¿Cada solicitud requiere la asignación de un nuevo bloque de memoria?

* El sistema de memoria tiene sobrecarga para encontrar un nuevo bloque y actualizar las listas internas.
* Considere reutilizar los bloques de memoria tanto como sea posible.

¿Se requiere un bloqueo para actualizar los administradores?

* Crea más contención a medida que se realizan más actualizaciones.
* Considere prescindir de bloqueos tanto como sea posible.

¿Se usa la carga especulativa?

* Se admite la cancelación, lo que podría llevar a crear más solicitudes.
* Sin embargo, la memoria debe estar disponible para la especulación.
* Considere límites estrictos en los umbrales de especulación.

## Consulte también

[DirectStorage](/build/console-features/storage/directstorage-toc)
[Uso y detalles internos de DirectStorage (tema NDA)](/build/console-features/storage/directstorage/directstorage-white-paper)
[Optimización de contenido comprimido mediante DirectStorage y XBTC (tema NDA)](/build/console-features/storage/directstorage/directstorage-compression)
[Análisis del rendimiento de DirectStorage (tema NDA)](/tools/tools-console/pix/pix-directstorage)


## Related topics

- [DirectStorage](/es/build/console-features/storage/directstorage-toc.md)
- [IDStorageFactoryX](/es/reference/system/dstorage/interfaces/IDStorageFactoryX/idstoragefactoryx.md)
- [DStorageGetFactory](/es/reference/system/dstorage/functions/dstoragegetfactory.md)
- [IDStorageFactoryX1](/es/reference/system/dstorage/interfaces/IDStorageFactoryX1/idstoragefactoryx1.md)
- [IDStorageFactoryX2](/es/reference/system/dstorage/interfaces/IDStorageFactoryX2/idstoragefactoryx2.md)
