Share via


Pases de representación de Direct3D 12

La característica de pases de representación es nueva para Windows 10, versión 1809 (10.0; Compilación 17763) y presenta el concepto de pase de representación de Direct3D 12. Un pase de representación consta de un subconjunto de los comandos que se registran en una lista de comandos.

Para declarar dónde comienza y finaliza cada paso de representación, anida los comandos que pertenecen a ese paso dentro de las llamadas a ID3D12GraphicsCommandList4::BeginRenderPass y EndRenderPass. Por lo tanto, cualquier lista de comandos contiene cero, uno o más pases de representación.

Escenarios

Los pases de representación pueden mejorar el rendimiento del representador si se basa en Tile-Based representación diferida (TBDR), entre otras técnicas. Más concretamente, la técnica ayuda al representador a mejorar la eficacia de la GPU mediante la reducción del tráfico de memoria hacia y desde la memoria fuera del chip al permitir que la aplicación identifique mejor los requisitos de ordenación de representación de recursos y las dependencias de datos.

Un controlador de pantalla escrito expresamente para aprovechar la característica de pases de representación proporciona los mejores resultados. Sin embargo, la representación pasa las API puede ejecutarse incluso en controladores preexistentes (aunque no necesariamente con mejoras de rendimiento).

Estos son los escenarios en los que los pases de representación están diseñados para proporcionar valor.

Permitir que la aplicación evite cargas o almacenes innecesarios de recursos desde o hacia la memoria principal en una arquitectura de representación diferida (TBDR) de Tile-Based

Una de las propuestas de valor de los pasos de representación es que proporciona una ubicación central para indicar las dependencias de datos de la aplicación para un conjunto de operaciones de representación. Estas dependencias de datos permiten al controlador de visualización inspeccionar estos datos en tiempo de enlace o barrera, y emitir instrucciones que minimicen las cargas o almacenes de recursos desde y hacia la memoria principal.

Permitir que la arquitectura de TBDR sea persistente oportunistamente en la caché en chip a través de pases de representación (incluso en listas de comandos independientes)

Nota

En concreto, este escenario se limita a los casos en los que se escriben en los mismos destinos de representación en varias listas de comandos.

Un patrón de representación común es que la aplicación se represente en los mismos destinos de representación en varias listas de comandos en serie, aunque los comandos de representación se generen en paralelo. El uso de pases de representación en este escenario permite combinar estos pases de tal manera (ya que la aplicación sabe que reanudará la representación en la lista de comandos correcta inmediata) que el controlador de pantalla puede evitar un vaciado en la memoria principal en los límites de la lista de comandos.

Responsabilidades de la aplicación

Incluso con la característica de pases de representación, ni el tiempo de ejecución de Direct3D 12 ni el controlador de pantalla tienen la responsabilidad de deducir oportunidades de reordenación o evitar cargas y almacenes. Para aprovechar correctamente la característica de pases de representación, la aplicación tiene estas responsabilidades.

  • Identifique correctamente las dependencias de datos y pedidos para sus operaciones.
  • Ordene sus envíos de forma que minimice los vaciados (por lo tanto, minimice el uso de _PRESERVE marcas).
  • Use correctamente las barreras de recursos y realice un seguimiento del estado de los recursos.
  • Evite copias o borrados innecesarios. Para ayudar a identificarlos, puede usar las advertencias de rendimiento automatizadas de la herramienta PIX en Windows.

Uso de la característica de pase de representación

¿Qué es un pase de representación?

Estos elementos definen un pase de representación.

  • Un conjunto de enlaces de salida que se fijan durante el paso de representación. Estos enlaces son para una o varias vistas de destino de representación (RTV) o para una vista de galería de símbolos de profundidad (DSV).
  • Lista de operaciones de GPU destinadas a ese conjunto de enlaces de salida.
  • Metadatos que describen las dependencias de carga y almacenamiento para todos los enlaces de salida de destino del pase de representación.

Declaración de los enlaces de salida

Al principio de un pase de representación, se declaran enlaces a los destinos de representación o al búfer de profundidad o galería de símbolos. Es opcional enlazar a destinos de representación y es opcional enlazar a un búfer de profundidad o galería de símbolos. Pero debe enlazar con al menos uno de los dos y, en el ejemplo de código siguiente, se enlazan a ambos.

Estos enlaces se declaran en una llamada a ID3D12GraphicsCommandList4::BeginRenderPass.

void render_passes(::ID3D12GraphicsCommandList4 * pIGCL4,
    D3D12_CPU_DESCRIPTOR_HANDLE const& rtvCPUDescriptorHandle,
    D3D12_CPU_DESCRIPTOR_HANDLE const& dsvCPUDescriptorHandle)
{
    const float clearColor4[]{ 0.f, 0.f, 0.f, 0.f };
    CD3DX12_CLEAR_VALUE clearValue{ DXGI_FORMAT_R32G32B32_FLOAT, clearColor4 };

    D3D12_RENDER_PASS_BEGINNING_ACCESS renderPassBeginningAccessClear{ D3D12_RENDER_PASS_BEGINNING_ACCESS_TYPE_CLEAR, { clearValue } };
    D3D12_RENDER_PASS_ENDING_ACCESS renderPassEndingAccessPreserve{ D3D12_RENDER_PASS_ENDING_ACCESS_TYPE_PRESERVE, {} };
    D3D12_RENDER_PASS_RENDER_TARGET_DESC renderPassRenderTargetDesc{ rtvCPUDescriptorHandle, renderPassBeginningAccessClear, renderPassEndingAccessPreserve };

    D3D12_RENDER_PASS_BEGINNING_ACCESS renderPassBeginningAccessNoAccess{ D3D12_RENDER_PASS_BEGINNING_ACCESS_TYPE_NO_ACCESS, {} };
    D3D12_RENDER_PASS_ENDING_ACCESS renderPassEndingAccessNoAccess{ D3D12_RENDER_PASS_ENDING_ACCESS_TYPE_NO_ACCESS, {} };
    D3D12_RENDER_PASS_DEPTH_STENCIL_DESC renderPassDepthStencilDesc{ dsvCPUDescriptorHandle, renderPassBeginningAccessNoAccess, renderPassBeginningAccessNoAccess, renderPassEndingAccessNoAccess, renderPassEndingAccessNoAccess };

    pIGCL4->BeginRenderPass(1, &renderPassRenderTargetDesc, &renderPassDepthStencilDesc, D3D12_RENDER_PASS_FLAG_NONE);
    // Record command list.
    pIGCL4->EndRenderPass();
    // Begin/End further render passes and then execute the command list(s).
}

Establezca el primer campo de la estructura de D3D12_RENDER_PASS_RENDER_TARGET_DESC en el identificador del descriptor de CPU correspondiente a una o varias vistas de destino de representación (RTV). Del mismo modo, D3D12_RENDER_PASS_DEPTH_STENCIL_DESC contiene el identificador del descriptor de CPU correspondiente a una vista de galería de símbolos de profundidad (DSV). Esos identificadores de descriptor de CPU son los mismos que se pasarían a ID3D12GraphicsCommandList::OMSetRenderTargets. Y, al igual que con OMSetRenderTargets, los descriptores de CPU se acoplan desde sus respectivos montones (descriptores de CPU) en el momento de la llamada a BeginRenderPass.

Los RTV y DSV no se heredan en el pase de representación. En su lugar, deben establecerse. Tampoco se propagan los RTV y DSV en BeginRenderPass a la lista de comandos. En su lugar, están en un estado indefinido después del paso de representación.

Representación de pases y cargas de trabajo

No se pueden anidar los pases de representación y no se puede tener un pase de representación entre más de una lista de comandos (deben comenzar y terminar mientras se graban en una sola lista de comandos). Las optimizaciones diseñadas para habilitar una generación eficaz de varios subprocesos de pasos de representación se describen en la sección Marcas de paso de representación, a continuación.

Una escritura que se realiza desde dentro de un pase de representación no es válida para leer desde hasta un paso de representación posterior. Esto impide que algunos tipos de barreras entre el paso de representación( por ejemplo, la barrera de RENDER_TARGET a SHADER_RESOURCE en el destino de representación enlazado actualmente. Para obtener más información, consulte la sección Render passes and resource barriers (Representación de pasos y barreras de recursos), a continuación.

La única excepción a la restricción de lectura de escritura que acaba de mencionar implica las lecturas implícitas que se producen como parte de las pruebas de profundidad y la combinación de destino de representación. Por lo tanto, estas API no se permiten dentro de un paso de representación (el tiempo de ejecución principal quita la lista de comandos si se llama a alguna de ellas durante la grabación).

Representación de pasos y barreras de recursos

No puede leer ni consumir una escritura que se produjo dentro del mismo paso de representación. Algunas barreras no se ajustan a esta restricción, por ejemplo, de D3D12_RESOURCE_STATE_RENDER_TARGET a *_SHADER_RESOURCE en el destino de representación enlazado actualmente (y la capa de depuración producirá un error en ese efecto). Sin embargo, esa misma barrera en un destino de representación escrito fuera del paso de representación actual es compatible, ya que las escrituras se completarán antes del inicio del pase de representación actual. Es posible que se beneficie de conocer ciertas optimizaciones que un controlador de pantalla puede hacer en este sentido. Dada una carga de trabajo conforme, un controlador de pantalla podría mover las barreras encontradas en el paso de representación al principio del paso de representación. Allí, se pueden fusionar (y no interferir con ninguna operación de mosaico o discretización). Se trata de una optimización válida siempre que todas las escrituras hayan finalizado antes de que se inicie el paso de representación actual.

Este es un ejemplo de optimización de controladores más completo, que supone que tiene un motor de representación que tiene un diseño de enlace de recursos de estilo pre-Direct3D 12, haciendo barreras a petición en función de cómo se enlazan los recursos. Al escribir en una vista de acceso desordenada (UAV) hacia el final de un fotograma (que se va a consumir en el fotograma siguiente), es posible que el motor deje el recurso en el estado de D3D12_RESOURCE_STATE_UNORDERED_ACCESS en la conclusión del marco. En el marco siguiente, cuando el motor vaya a enlazar el recurso como una vista de recursos del sombreador (SRV), encontrará que el recurso no está en el estado correcto y emitirá una barrera de D3D12_RESOURCE_STATE_UNORDERED_ACCESS a D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE. Si esa barrera se produce dentro del paso de representación, el controlador de pantalla se justifica en suponiendo que todas las escrituras ya se han producido fuera de este paso de representación actual y, por lo tanto, (y aquí está donde entra la optimización), el controlador de pantalla podría mover la barrera hasta el inicio del paso de representación. De nuevo, esto es válido, siempre que el código se ajuste a la restricción de lectura de escritura descrita en esta sección y en la última.

Estos son ejemplos de barreras conformes.

  • D3D12_RESOURCE_STATE_UNORDERED_ACCESS a D3D12_RESOURCE_STATE_INDIRECT_ARGUMENT.
  • D3D12_RESOURCE_STATE_COPY_DEST a *_SHADER_RESOURCE.

Y estos son ejemplos de barreras no conformes.

  • D3D12_RESOURCE_STATE_RENDER_TARGET a cualquier estado de lectura en rtVs/DSV enlazados actualmente.
  • D3D12_RESOURCE_STATE_DEPTH_WRITE a cualquier estado de lectura en RTVs/DSV enlazados actualmente.
  • Cualquier barrera de alias.
  • Barreras de la vista de acceso sin ordenar (UAV). 

Declaración de acceso a recursos

En la hora BeginRenderPass , así como declarar todos los recursos que sirven como RTV o DSV dentro de ese paso, también debe especificar sus características de acceso inicial y final. Como puede ver en el ejemplo de código de la sección Declare los enlaces de salida anteriores, haga esto con las estructuras D3D12_RENDER_PASS_RENDER_TARGET_DESC y D3D12_RENDER_PASS_DEPTH_STENCIL_DESC .

Para obtener más información, consulte las estructuras D3D12_RENDER_PASS_BEGINNING_ACCESS y D3D12_RENDER_PASS_ENDING_ACCESS , así como las enumeraciones D3D12_RENDER_PASS_BEGINNING_ACCESS_TYPE y D3D12_RENDER_PASS_ENDING_ACCESS_TYPE .

Representación de marcas de paso

El último parámetro pasado a BeginRenderPass es una marca de paso de representación (un valor de la enumeración D3D12_RENDER_PASS_FLAGS ).

enum D3D12_RENDER_PASS_FLAGS
{
    D3D12_RENDER_PASS_FLAG_NONE = 0,
    D3D12_RENDER_PASS_FLAG_ALLOW_UAV_WRITES = 0x1,
    D3D12_RENDER_PASS_FLAG_SUSPENDING_PASS = 0x2,
    D3D12_RENDER_PASS_FLAG_RESUMING_PASS = 0x4
};

Escrituras de UAV dentro de un paso de representación

Las escrituras de la vista de acceso sin ordenar (UAV) se permiten dentro de un pase de representación, pero debe indicar específicamente que va a emitir escrituras UAV dentro del paso de representación especificando D3D12_RENDER_PASS_FLAG_ALLOW_UAV_WRITES, de modo que el controlador de pantalla pueda optar por no realizar mosaicos si es necesario.

Los accesos UAV deben seguir la restricción de lectura de escritura descrita anteriormente (las escrituras en un pase de representación no son válidas para leerse hasta que pase una representación posterior). No se permiten barreras UAV dentro de un pase de representación.

Los enlaces UAV (a través de tablas raíz o descriptores raíz) se heredan en pasos de representación y se propagan fuera de los pasos de representación.

Suspending-passes y resuming-passes

Puede indicar un pase de representación completo como un pase de suspensión o un paso de reanudación. Un par suspending-follow-by-resuming debe tener marcas de acceso o vistas idénticas entre los pases y es posible que no tenga ninguna operación de GPU intermedia (por ejemplo, draws, dispatches, descartes, clears, copias, update-tile-mappings, write-buffer-immediates, consultas, query resolves) entre el pase de representación suspendiendo y el pase de representación reanudando.

El caso de uso previsto es la representación multiproceso, donde las cuatro listas de comandos (cada una con sus propios pasos de representación) pueden tener como destino los mismos destinos de representación. Cuando se suspenden o reanudan los pasos de representación en las listas de comandos, las listas de comandos se deben ejecutar en la misma llamada a ID3D12CommandQueue::ExecuteCommandLists.

Un pase de representación puede reanudarse y suspenderse. En el ejemplo de varios subprocesos, las listas de comandos 2 y 3 se reanudarían de 1 y 2, respectivamente. Y al mismo tiempo 2 y 3 estarían suspendiendo a 3 y 4, respectivamente.

Compatibilidad con la característica consultas de pases de representación

Puede llamar a ID3D12Device::CheckFeatureSupport para consultar la medida en que un controlador de dispositivo o el hardware admite de forma eficaz los pases de representación.

D3D12_RENDER_PASS_TIER get_render_passes_tier(::ID3D12Device * pIDevice)
{
    D3D12_FEATURE_DATA_D3D12_OPTIONS5 featureSupport{};
    winrt::check_hresult(
        pIDevice->CheckFeatureSupport(D3D12_FEATURE_D3D12_OPTIONS5, &featureSupport, sizeof(featureSupport))
    );
    return featureSupport.RenderPassesTier;
}
...
    D3D12_RENDER_PASS_TIER renderPassesTier{ get_render_passes_tier(pIDevice) };

Debido a la lógica de asignación del tiempo de ejecución, la representación pasa siempre la función . Sin embargo, dependiendo de la compatibilidad con características, no siempre proporcionarán una ventaja. Puede usar código similar al ejemplo de código anterior para determinar si vale la pena emitir comandos como pasos de representación y, cuando definitivamente no es una ventaja (es decir, cuando el tiempo de ejecución simplemente se asigna a la superficie de API existente). Realizar esta comprobación es especialmente importante si usa D3D11On12).

Para obtener una descripción de los tres niveles de soporte técnico, consulte la enumeración D3D12_RENDER_PASS_TIER .