Compartir a través de


Dibujo indirecto

El dibujo indirecto permite mover algunos recorridos de escena y selecciones desde la CPU a la GPU, lo que puede mejorar el rendimiento. El búfer de comandos se puede generar mediante la CPU o la GPU.

Firmas de comando

El objeto de firma de comando (ID3D12CommandSignature) permite a las aplicaciones especificar el dibujo indirecto, en particular al establecer lo siguiente:

Al iniciarse, una aplicación crea un pequeño conjunto de firmas de comando. En tiempo de ejecución, la aplicación rellena un búfer con comandos (a través de cualquier medio que el desarrollador de la aplicación elija). Los comandos que contienen opcionalmente el estado que se va a establecer para las vistas del búfer de vértices, las vistas de búfer de índice, las constantes raíz y los descriptores raíz (SRV/UAV/CBV o sin formato). Estos diseños de argumento no son específicos del hardware, por lo que las aplicaciones pueden generar directamente los búferes. La firma de comando hereda el estado restante de la lista de comandos. A continuación, la aplicación llama a ExecuteIndirect para indicar a la GPU que interprete el contenido del búfer de argumentos indirectos según el formato definido por una firma de comando determinada.

Si la firma de comando cambia los argumentos raíz, estos cambios se almacenarán dentro de la firma de comando como un subconjunto de una firma raíz.

No se devuelve ningún estado de firma de comando a la lista de comandos una vez completada la ejecución. Sin embargo, después de ExecuteIndirect, todos los enlaces se restablecen a valores conocidos. En concreto:

  • Si la firma del comando enlaza un búfer de vértices a una ranura determinada, tras la llamada a ExecuteIndirect, se enlaza un búfer de vértices NULL a esa ranura.
  • Si la firma de comando enlaza un búfer de índice, después de ExecuteIndirect, se enlaza un búfer de índice NULL.
  • Si la firma del comando establece una constante raíz, después de llamar a ExecuteIndirect, el valor de constante raíz se establece en 0.
  • Si la firma del comando establece una vista raíz (CBV/SRV/UAV), después de llamar a ExecuteIndirect, la vista raíz se establece en una vista NULL.

Como ejemplo de uso de firmas de comando: supongamos que un desarrollador de aplicaciones quiere que se especifique una constante raíz única para cada llamada de dibujo en el búfer de argumentos indirectos. La aplicación crearía una firma de comando que permite al búfer de argumentos indirectos especificar los parámetros siguientes por llamada de dibujo:

  • El valor de una constante raíz.
  • Argumentos de dibujo (recuento de vértices, recuento de instancias, etc.).

El búfer de argumentos indirectos generado por la aplicación contendrá una matriz de registros de tamaño fijo. Cada estructura corresponde a una llamada de dibujo. Cada estructura contiene los argumentos de dibujo y el valor de la constante raíz. El número de llamadas de dibujo se especifica en un búfer visible para GPU independiente.

A continuación se muestra un búfer de comandos de ejemplo generado por la aplicación:

formato de búfer de comandos

Estructuras de búfer de argumentos indirectos

Las estructuras siguientes definen cómo aparecen los argumentos concretos en un búfer de argumentos indirectos. Estas estructuras no aparecen en ninguna API D3D12. Las aplicaciones usan estas definiciones al escribir en un búfer de argumentos indirecto (con la CPU o la GPU):

Creación de firma de comando

Para crear una firma de comando, usa los siguientes elementos de API:

El orden de los argumentos dentro de un búfer de argumentos indirecto se define para que coincida exactamente con el orden de los argumentos especificados en el parámetro pArguments de D3D12_COMMAND_SIGNATURE_DESC. Todos los argumentos de una llamada de dibujo (gráficos)/distribución (proceso) dentro de un búfer de argumentos indirecto están estrechamente empaquetados. Sin embargo, las aplicaciones pueden especificar un intervalo de bytes arbitrario entre los comandos draw/dispatch en un búfer de argumentos indirecto.

La firma raíz debe especificarse únicamente si la firma de comando cambia uno de los argumentos raíz.

En el caso de SRV/UAV/CBV raíz, el tamaño especificado de la aplicación está en bytes. La capa de depuración validará las restricciones siguientes en la dirección:

  • CBV: la dirección debe ser un múltiplo de 256 bytes.
  • UAV/SRV sin formato: la dirección debe ser un múltiplo de 4 bytes.
  • UAV/SRV estructurado: la dirección debe ser un múltiplo del intervalo de bytes de la estructura (declarado en el sombreador).

Una firma de comando determinada es un dibujo o una firma de comando de proceso. Si una firma de comando contiene una operación de dibujo, se trata de una firma de comando de gráficos. De lo contrario, la firma de comando debe contener una operación de envío y es una firma de comando de proceso.

En las secciones siguientes se muestran algunos ejemplos de firmas de comando.

Sin cambios de argumento

En este ejemplo, el búfer de argumentos indirectos generado por la aplicación contiene una matriz de estructuras de 36 bytes. Cada estructura solo contiene los cinco parámetros pasados a DrawIndexedInstanced (más el relleno).

El código para crear la descripción de la firma de comando es la siguiente:

D3D12_INDIRECT_ARGUMENT_DESC Args[1];
Args[0].Type = D3D12_INDIRECT_ARGUMENT_TYPE_DRAW_INDEXED;

D3D12_COMMAND_SIGNATURE_DESC ProgramDesc;
ProgramDesc.ByteStride = 36;
ProgramDesc.NumArgumentDescs = 1;
ProgramDesc.pArguments = Args;

El diseño de una sola estructura dentro de un búfer de argumentos indirecto es el siguiente:

Bytes Descripción
0:3 IndexCountPerInstance
4:7 InstanceCount
8:11 StartIndexLocation
12:15 BaseVertexLocation
16:19 StartInstanceLocation
20:35 Relleno

 

Constantes raíz y búferes de vértices

En este ejemplo, cada estructura de un búfer de argumentos indirectos cambia dos constantes raíz, cambia un enlace de búfer de vértices y realiza una operación no indexada de dibujo. No hay relleno entre estructuras.

El código para crear la descripción de la firma de comando es la siguiente:

D3D12_INDIRECT_ARGUMENT_DESC Args[4];
Args[0].Type = D3D12_INDIRECT_ARGUMENT_TYPE_CONSTANT;
Args[0].Constant.RootParameterIndex = 2;
Args[0].Constant.DestOffsetIn32BitValues = 0;
Args[0].Constant.Num32BitValuesToSet = 1;

Args[1].Type = D3D12_INDIRECT_ARGUMENT_TYPE_CONSTANT;
Args[1].Constant.RootParameterIndex = 6;
Args[1].Constant.DestOffsetIn32BitValues = 0;
Args[1].Constant.Num32BitValuesToSet = 1;

Args[2].Type = D3D12_INDIRECT_ARGUMENT_TYPE_VERTEX_BUFFER_VIEW;
Args[2].VertexBuffer.Slot = 3;

Args[3].Type = D3D12_INDIRECT_ARGUMENT_TYPE_DRAW;

D3D12_COMMAND_SIGNATURE_DESC ProgramDesc;
ProgramDesc.ByteStride = 40;
ProgramDesc.NumArgumentDescs = 4;
ProgramDesc.pArguments = Args;

El diseño de una sola estructura dentro del búfer de argumentos indirecto es el siguiente:

Bytes Descripción
0:3 Datos para el índice de parámetros raíz 2
4:7 Datos para el índice de parámetros raíz 6
8:15 Dirección virtual de VB en la ranura 3 (64 bits)
16:19 Tamaño de VB
20:23 Intervalo de VB
24:27 VertexCountPerInstance
28:31 InstanceCount
32:35 StartVertexLocation
36:39 StartInstanceLocation

 

Tutoriales de vídeo de aprendizaje avanzado de DirectX: Ejecución de la selección de GPU indirecta y asincrónica

Dibujo indirecto y selección de GPU: tutorial de código

Representación