Compartir a través de


Barreras mejoradas de D3D12

La interfaz DDI para barreras mejoradas está disponible en el WDK de Windows 11, versión 22H2 (WDDM 3.0). Para usar barreras mejoradas en 22H2 (o versiones anteriores del sistema operativo), debe instalar el SDK de agilidad 1.706.4-preview.

Las barreras mejoradas de 3D12 proporcionan a los desarrolladores un control independiente sobre la sincronización de trabajos de GPU, las transiciones de diseño de texturas y el vaciado de caché (acceso a memoria de recursos). Esta característica ofrece un conjunto de API y DDI de Direct3D que proporcionan a los desarrolladores un control independiente sobre la sincronización de trabajos de GPU, transiciones de diseño de texturas y vaciado de caché (acceso a memoria de recursos).

Las barreras mejoradas reemplazan las barreras de recursos heredadas por tipos de barrera más expresivos. Tienen las siguientes características:

  • Menor latencia de sincronización.
  • Reducción de los vaciados excesivos de caché.
  • No hay reglas misteriosas de promoción y descomposición.
  • Aliasing rápido y flexible de recursos (topologías de aliasing diversas).
  • Descarte durante la transición de barrera.
  • Compatibilidad con lectura y escritura simultáneas, incluida la copia del mismo recurso (autocopia).
  • Compatibilidad con los comandos de descarte asincrónico, copiar, resolver y borrar.

Las barreras mejoradas no son más sencillas que las barreras de recursos heredadas, sino que son menos ambiguas y, por tanto, son más fáciles de usar para los desarrolladores.

Compatibilidad con la generación de informes de barrera mejorada

Actualmente, la característica de barreras mejoradas no es un requisito de hardware o controlador. Un controlador indica la compatibilidad estableciendo el miembro EnhancedBarriersSupported de D3D12DDI_D3D12_OPTIONS_DATA_0089 en TRUE.

  • D3D12DDI_FEATURE_VERSION_VIDEO_0088_0 es el número de versión que define la implementación preliminar de todos los hitos de barrera mejorada de D3D12 que se introdujeron en Windows 11.

Funciones de devolución de llamada de barrera mejorada de D3D12

Los controladores que indican la compatibilidad con las barreras mejoradas implementan las siguientes funciones de devolución de llamada:

Detalles de diseño

Normalmente, los controladores controlan las barreras de recursos heredadas mediante tres operaciones independientes:

  1. Sincronizar el trabajo de GPU.
  2. Realizar las operaciones de vaciado de caché necesarias.
  3. Realizar los cambios de diseño necesarios.

Las barreras mejoradas proporcionan a los desarrolladores la capacidad de controlar cada una de estas operaciones por separado.

Tipos de barreras mejoradas

Hay tres tipos de barreras mejoradas:

Las barreras con intervalo reemplazan las barreras de recursos heredadas. Se proporcionan barreras con intervalo para que las barreras de recursos heredadas se puedan implementar completamente sin una pérdida de rendimiento notable.

  • Todos los tipos de barrera controlan la sincronización del trabajo de GPU y los tipos de acceso de lectura o escritura antes y después de la barrera.

  • Además, las barreras de textura administran el diseño de subrecursos de textura. La selección de subrecursos se puede expresar como un intervalo de sectores mip, matriz y plano, además de la conocida opción de uno o todos que usan las barreras de recursos heredadas.

  • Las barreras de búfer y las barreras globales controlan solo la sincronización y el acceso a los recursos y no afectan al diseño de recursos (los búferes no tienen un diseño). Las barreras globales afectan a toda la memoria caché, por lo que pueden resultar caras y solo deberían utilizarse cuando una barrera de mayor alcance sea insuficiente.

Barreras de textura

  • Controlan el vaciado de caché, el diseño de memoria y la sincronización de subrecursos de textura.
  • Solo se deben usar con recursos de textura.
  • Permiten seleccionar un único subrecurso, todos los subrecursos o un intervalo coherente de subrecursos (es decir, intervalo mip e intervalo de matriz).
  • Debe proporcionar un puntero de recurso válido que no sea NULL.

Barreras de búfer

  • Controlan el vaciado de caché y la sincronización para los recursos de búfer.
  • Solo se deben usar con recursos de búfer.
  • A diferencia de las texturas, los búferes solo tienen un único subrecurso y no tienen un diseño del que se pueda realizar la transición.
  • Debe proporcionar un puntero de recurso válido que no sea NULL.

Barreras globales

  • Controlan el vaciado de caché y la sincronización de todos los tipos de acceso a recursos indicados en una sola cola de comandos.
  • No tienen ningún efecto en el diseño de textura.
  • Se necesitan para proporcionar funcionalidades similares a las barreras de UAV NULL heredadas y las barreras de aliasing NULL/NULL.

Dado que las barreras globales no cambian el diseño de la textura, no pueden utilizarse en transiciones que, de otro modo, requerirían un cambio de diseño. Por ejemplo, no se puede usar una barrera global para realizar la transición de una textura de acceso no simultáneo de D3D12DDI_BARRIER_ACCESS_RENDER_TARGET a D3D12DDI_BARRIER_ACCESS_SHADER_RESOURCE, ya que también requeriría un cambio de D3D12DDI_BARRIER_LAYOUT_RENDER_TARGET a D3D12DDI_BARRIER_LAYOUT_SHADER_RESOURCE.

Synchronization

Los procesadores gráficos están diseñados para ejecutar tanto trabajo en paralelo como sea posible. Cualquier trabajo de GPU que dependa del trabajo de GPU anterior debe sincronizarse antes de acceder a los datos dependientes.

La interfaz de barrera mejorada usa valores SyncBefore y SyncAfter explícitos como máscaras de campo de bits lógicas. Una barrera debe esperar a que se completen todos los ámbitos SyncBefore del comando anterior antes de ejecutar la barrera. De forma similar, una barrera debe bloquear todos los ámbitos SyncAfter posteriores hasta que se complete la barrera. D3D12DDI_BARRIER_SYNC especifica el ámbito de sincronización del trabajo de GPU con respecto a la barrera.

Para obtener más información, consulte la Especificación de barreras mejoradas.

Transiciones de diseño

Los subrecursos de textura pueden usar diseños diferentes para varios métodos de acceso. Por ejemplo, las texturas a menudo se comprimen cuando se usan como destino de representación o galería de símbolos de profundidad y a menudo no se comprimen para los comandos de lectura o copia del sombreador. Las barreras de textura usan los valores de D3D12DDI_BARRIER_LAYOUT LayoutBefore y LayoutAfter para describir las transiciones de diseño.

Las transiciones de diseño solo son necesarias para las texturas, por lo que solo se expresan en la estructura de datos D3D12DDI_TEXTURE_BARRIER.

LayoutBefore y LayoutAfter deben ser compatibles con el tipo de cola que realiza la barrera. Por ejemplo, una cola de cálculo no puede realizar una transición de un subrecurso a o desde D3D12DDI_BARRIER_LAYOUT_RENDER_TARGET.

Para proporcionar un orden de barrera bien definido, el diseño de un subrecurso después de completar una secuencia de barreras es el LayoutAfter final en la secuencia.

Transiciones de acceso

Dado que muchas operaciones de escritura con GPU se almacenan en caché, cualquier barrera de un acceso de escritura a otro acceso de escritura o un acceso de solo lectura podría requerir un vaciado de caché. Las API de barrera mejorada usan transiciones de acceso para indicar que la memoria de un subrecurso debe hacerse visible para un nuevo tipo de acceso específico. Al igual que las transiciones de diseño, es posible que algunas transiciones de acceso no sean necesarias si se sabe que la memoria del subrecurso asociado ya es accesible para el uso deseado.

Las transiciones de acceso se expresan de la siguiente manera:

  • En el caso de las texturas, como parte de la estructura D3D12DDI_TEXTURE_BARRIER.
  • En el caso de los búferes, como parte de la estructura D3D12DDI_BUFFER_BARRIER.

Las transiciones de acceso no realizan la sincronización. Se espera que la sincronización entre los accesos dependientes se controle mediante los valores SyncBefore y SyncAfter adecuados en la barrera.

Un AccessBefore hecho visible para un AccessAfter especificado no garantiza que la memoria del recurso también sea visible para un tipo de acceso diferente. Por ejemplo:

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

Esta transición de acceso indica que un acceso de lectura del sombreador posterior depende de una escritura sin ordenar. Sin embargo, si el hardware es capaz de leer recursos del sombreador directamente desde la memoria caché de UAV, es posible que el controlador no vacíe realmente la caché de UAV.

D3D12DDI_BARRIER_ACCESS_COMMON

D3D12DDI_BARRIER_ACCESS_COMMON es un tipo de acceso especial que indica cualquier acceso compatible con el diseño. La transición a D3D12DDI_BARRIER_ACCESS_COMMON significa que los datos de subrecursos deben estar disponibles para cualquier acceso compatible con el diseño después de una barrera. Dado que los búferes no tienen diseño, D3D12DDI_BARRIER_ACCESS_COMMON simplemente significa cualquier acceso compatible con el búfer.

Especificar D3D12DDI_BARRIER_ACCESS_COMMON como AccessBefore en una barrera implica el conjunto de todos los tipos de acceso de escritura. No se recomienda usar D3D12DDI_BARRIER_ACCESS_COMMON como AccessBefore , ya que podría provocar costosos vaciados de caché no deseados. En su lugar, se recomienda a los desarrolladores que usen solo los bits de acceso a escritura más restringidos para restringir correctamente la sobrecarga de barreras. Se emite una advertencia de capa de depuración cuando AccessBefore se establece en D3D12DDI_BARRIER_ACCESS_COMMON.

Acceso simultáneo de cola única

Las barreras mejoradas permiten operaciones simultáneas de lectura y escritura en el mismo búfer o textura de acceso simultáneo en la misma cola de comandos.

Los búferes y los recursos de acceso simultáneo siempre admitían accesos de escritura desde una cola con accesos de lectura simultáneos, no dependientes, desde otra o varias colas. Esta compatibilidad se debe a que estos recursos siempre usan el diseño COMMON y no tienen riesgos de lectura y escritura, ya que las lecturas no deben depender de escrituras simultáneas. (Las reglas de barrera de recursos heredadas no permiten combinar bits de estado de escritura con otros bits de estado. Por lo tanto, los recursos no se pueden leer ni escribir simultáneamente en la misma cola mediante barreras de recursos heredadas).

La política de un escritor a la vez se sigue aplicando, ya que dos regiones de escritura aparentemente no superpuestas podrían tener líneas de caché superpuestas.

Intervalos de subrecursos

Es habitual que los desarrolladores quieran realizar la transición de un intervalo de subrecursos. Un ejemplo consiste en realizar una transición de una cadena mip completa para una matriz de textura determinada o un solo nivel mip para todos los sectores de matriz. Las barreras mejoradas permiten a los desarrolladores realizar la transición de intervalos lógicos adyacentes de subrecursos mediante la estructura D3D12DDI_BARRIER_SUBRESOURCE_RANGE. (Las barreras de transición de estado de recursos heredadas solo proporcionan a los desarrolladores la opción de realizar la transición de todos los estados de subrecursos o un único estado de subrecurso de forma atómica).

Diseños de cola directa y de proceso

Se garantiza que los siguientes diseños de barrera mejorada son los mismos para las colas directas y de proceso:

  • D3D12DDI_BARRIER_LAYOUT_GENERIC_READ
  • D3D12DDI_BARRIER_LAYOUT_UNORDERED_ACCESS
  • D3D12DDI_BARRIER_LAYOUT_SHADER_RESOURCE
  • D3D12DDI_BARRIER_LAYOUT_COPY_SOURCE
  • D3D12DDI_BARRIER_LAYOUT_COPY_DEST

Un subrecurso en uno de estos diseños se puede usar en colas directas o en colas de proceso sin una transición de diseño.

En algunos hardware, las barreras de transición de diseño en las colas directas pueden ser significativamente más rápidas si los accesos anteriores o posteriores también están en colas directas. Se recomienda encarecidamente acceder a los recursos en colas directas mediante los siguientes diseños:

  • D3D12DDI_BARRIER_LAYOUT_DIRECT_QUEUE_GENERIC_READ
  • D3D12DDI_BARRIER_LAYOUT_DIRECT_QUEUE_UNORDERED_ACCESS
  • D3D12DDI_BARRIER_LAYOUT_DIRECT_QUEUE_SHADER_RESOURCE
  • D3D12DDI_BARRIER_LAYOUT_DIRECT_QUEUE_COPY_SOURCE
  • D3D12DDI_BARRIER_LAYOUT_DIRECT_QUEUE_COPY_DEST

Las variantes de diseño DIRECT_QUEUE no son compatibles con las colas de proceso y no se pueden usar en las barreras de lista de comandos de proceso. Sin embargo, son compatibles con las operaciones de proceso en colas directas.

Acceso sin barreras

Dado que no debe haber comandos pendientes ni operaciones de vaciado de caché entre los límites de ExecuteCommandLists, es posible que se acceda inicialmente a los búferes en un ámbito ExecuteCommandLists sin barrera. Del mismo modo, también se puede acceder inicialmente a los subrecursos de textura sin una barrera en las condiciones siguientes:

  • El diseño del subrecurso es compatible con el tipo de acceso.
  • Se inicializan los metadatos de compresión necesarios.

Se puede acceder a los subrecursos de texturas en el diseño D3D12DDI_BARRIER_LAYOUT_COMMON (o un diseño común específico de cola como D3D12DDI_BARRIER_LAYOUT_DIRECT_QUEUE_COMMON) que no tengan operaciones de lectura o escritura potencialmente pendientes en un flujo de comandos ExecuteCommandLists sin una barrera utilizando cualquiera de los siguientes tipos de acceso:

  • D3D12DDI_BARRIER_ACCESS_SHADER_RESOURCE
  • D3D12DDI_BARRIER_ACCESS_COPY_SOURCE
  • D3D12DDI_BARRIER_ACCESS_COPY_DEST

Además, un búfer o textura mediante un diseño común específico de la cola puede usar D3D12DDI_BARRIER_ACCESS_UNORDERED_ACCESS sin barrera.

Se puede acceder inicialmente a los búferes y las texturas de acceso simultáneo (texturas creadas con la marca D3D12DDI_RESOURCE_FLAG_ALLOW_SIMULTANEOUS_ACCESS) en una secuencia de comandos ExecuteCommandLists sin una barrera mediante cualquiera de los siguientes tipos de acceso:

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

Los accesos posteriores también pueden realizarse sin barrera con no más de un tipo de acceso de escritura. Sin embargo, excepto para D3D12DDI_BARRIER_ACCESS_RENDER_TARGET, las barreras deben usarse para vaciar las escrituras secuenciales en el mismo recurso.

Copia de recursos propios

Aunque no se relaciona exclusivamente con las barreras mejoradas, la capacidad de permitir copias de una región de un subrecurso a otra región sin intersección es una característica muy solicitada. Con las barreras mejoradas, se puede usar un subrecurso con un diseño común como origen y destino en la misma llamada a CopyBufferRegion o CopyTextureRegion. Las copias entre las regiones de memoria de origen y destino entre intersección generan resultados indefinidos. La capa de depuración DEBE validarse con estos resultados. (El diseño de barrera de recursos heredada no permite que un subrecurso esté en el estado D3D12DDI_RESOURCE_STATE_COPY_SOURCE y D3D12DDI_RESOURCE_STATE_COPY_DEST al mismo tiempo y, por tanto, no se puede copiar a sí mismo).

Inicialización de metadatos de recursos colocados

El diseño de barrera de recursos heredada requiere borrar, copiar o descartar para inicializar los recursos de textura con alias recién colocados y activados antes de usarse como un recurso de galería de símbolos de profundidad o destino de representación. Este requisito se debe a que los recursos de destino de representación y galería de símbolos de profundidad suelen usar metadatos de compresión que se deben inicializar para que los datos sean válidos. Lo mismo sucede con las texturas reservadas con la asignación de iconos recién actualizada.

Las barreras mejoradas admiten una opción de descartar como parte de una barrera. Las transiciones de diseño de barrera de D3D12DDI_BARRIER_LAYOUT_UNDEFINED a cualquier diseño potencialmente comprimido (por ejemplo, D3D12DDI_BARRIER_LAYOUT_RENDER_TARGET, D3D12DDI_BARRIER_LAYOUT_DEPTH_STENCIL, D3D12DDI_BARRIER_LAYOUT_UNORDERED_ACCESS) DEBEN inicializar los metadatos de compresión cuando D3D12DDI_TEXTURE_BARRIER_FLAG_DISCARD está presente en el miembro D3D12DDI_TEXTURE_BARRIER::Flags.

Además de representar los recursos de destino y profundidad/galería de símbolos, hay optimizaciones de compresión de textura de UAV similares que el modelo de barrera heredada no admitía.

Ordenación de barreras

Las barreras se ponen en cola por orden de reenvío (orden de llamada API, barrier-group-index, barrier-array-index). Múltiples barreras en el mismo subrecurso deben funcionar como si las barreras se completaran en orden de cola.

Las barreras en cola con ámbitos SyncAfter coincidentes que potencialmente escriben en la misma memoria deben completar todas las escrituras en orden de cola. Este requisito evita las carreras de datos en barreras que admiten el aliasing de recursos. Por ejemplo, una barrera que desactiva un recurso debe vaciar las memorias caché antes de otra barrera que active un recurso diferente en la misma memoria, posibles metadatos de borrado.