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 un 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 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 pasos 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 la representación de recursos y las dependencias de datos.
Un controlador de visualización escrito expresamente para aprovechar la característica de pases de representación proporciona los mejores resultados. Pero las API de pasos de representación se pueden ejecutar 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 o hacia la memoria principal.
Permitir que la arquitectura de TBDR sea persistente de forma oportunista en la caché en chip a través de los pasos de representación (incluso en listas de comandos independientes)
Nota
En concreto, este escenario se limita a los casos en los que se escribe 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 para volver a ordenar 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 ordenación para sus operaciones.
- Ordene sus envíos de forma que minimice los vaciados (por lo que, minimice el uso de marcas de _PRESERVE).
- 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 de en Windows.
Uso de la característica de paso de representación
¿Qué es un de representación dede 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 destinados al pase de representación.
Declarar los enlaces de salida
Al principio de un pase de representación, declara enlaces a los destinos de representación o al búfer de profundidad/galería de símbolos. Es opcional enlazar a destinos de representación y es opcional enlazar a un búfer de profundidad/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 pasaría a ID3D12GraphicsCommandList::OMSetRenderTargets. Y, al igual que con OMSetRenderTargets, los descriptores de CPU se acoplan desde sus respectivos montones (descriptor 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 declaran los RTV y DSV en BeginRenderPass propagados a la lista de comandos. En su lugar, se encuentran en un estado indefinido después del paso de representación.
Representación de cargas de trabajo y pasos
No se pueden anidar los pases de representación y no se puede tener un pase de representación en más de una lista de comandos (deben comenzar y terminar mientras se graba en una sola lista de comandos). Las optimizaciones diseñadas para habilitar la generación eficaz de varios subprocesos de pasos de representación se describen en la sección representar marcas de paso, a continuación.
Una escritura que realice desde dentro de un pase de representación no es válidas desde la que leer hasta un paso de representación posterior. Esto impide que algunos tipos de barreras estén dentro del 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 Representar 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 pase de representación (el entorno de ejecución principal quita la lista de comandos si se llama a alguna de ellas durante la grabación).
- ID3D12GraphicsCommandList1::AtomicCopyBufferUINT
- ID3D12GraphicsCommandList1::AtomicCopyBufferUINT64
- ID3D12GraphicsCommandList4::BeginRenderPass
- ID3D12GraphicsCommandList::ClearDepthStencilView
- ID3D12GraphicsCommandList::ClearRenderTargetView
- ID3D12GraphicsCommandList::ClearState
- ID3D12GraphicsCommandList::ClearUnorderedAccessViewFloat
- ID3D12GraphicsCommandList::ClearUnorderedAccessViewUint
- ID3D12GraphicsCommandList::CopyBufferRegion
- ID3D12GraphicsCommandList::CopyResource
- ID3D12GraphicsCommandList::CopyTextureRegion
- ID3D12GraphicsCommandList::CopyTiles
- id3D12GraphicsCommandList::D iscardResource
- id3D12GraphicsCommandList::D ispatch
- id3D12GraphicsCommandList::OMSetRenderTargets
- ID3D12GraphicsCommandList::ResolveQueryData
- ID3D12GraphicsCommandList::ResolveSubresource
- ID3D12GraphicsCommandList1::ResolveSubresourceRegion
- id3D12GraphicsCommandList3::SetProtectedResourceSession
Representación de pasos y barreras de recursos
Es posible que no lea o consuma una escritura que se produjo dentro del mismo pase 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 que se escribió fuera de el pase 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 compatible, un controlador de pantalla podría mover las barreras encontradas en el paso de representación al principio del pase de representación. Allí, se pueden fusionar (y no interferir con las operaciones de mosaico o de anclaje). Se trata de una optimización válida siempre que todas las escrituras hayan finalizado antes de que se inicie el pase 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 anterior a Direct3D 12, lo que hace 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 marco (que se va a consumir en el marco siguiente), es posible que el motor deje el recurso en el estado D3D12_RESOURCE_STATE_UNORDERED_ACCESS en la conclusión del marco. En el marco siguiente, cuando el motor va a enlazar el recurso como una vista de recursos de 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 hayan producido fuera de 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 y cuando el código se ajuste a la restricción de lectura de escritura descrita en esta sección y 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 vista de acceso desordenadas (UAV).
Declaración de acceso a recursos
En hora de BeginRenderPass, así como declarar todos los recursos que sirven como RTV o DSV dentro de ese paso, también debe especificar sus características iniciales y finales acceso. Como puede ver en el ejemplo de código de la sección Declarar los enlaces de salida anterior, lo hace 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 y las enumeraciones D3D12_RENDER_PASS_BEGINNING_ACCESS_TYPE y D3D12_RENDER_PASS_ENDING_ACCESS_TYPE.
Representar 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 pase 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 visualización pueda optar por no aplicar 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 pasos, y puede 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 la suspensión del paso de representación y el paso de representación reanudante.
El caso de uso previsto es la representación multiproceso, donde decir cuatro listas de comandos (cada una con sus propios pases de representación) pueden tener como destino los mismos destinos de representación. Cuando los pases de representación se suspenden o reanudan en las listas de comandos, las listas de comandos deben ejecutarse 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 se suspenderían a 3 y 4, respectivamente.
Consulta para la compatibilidad con características de pases de representación
Puede llamar a ID3D12Device::CheckFeatureSupport para consultar la medida en que un controlador de dispositivo o el hardware admite eficazmente los pasos 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 entorno de ejecución, la representación pasa siempre la función . Pero, 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 pases de representación y, cuando definitivamente no es una ventaja (es decir, cuando el tiempo de ejecución está simplemente asignando 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.