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
- Estructuras de búfer de argumentos indirectos
- Creación de firma de comando
- Temas relacionados
Firmas de comando
El objeto de firma de comando (ID3D12CommandSignature) permite a las aplicaciones especificar el dibujo indirecto, en particular al establecer lo siguiente:
- El formato de búfer de los argumentos indirectos.
- Tipo de comando que se usará (desde los métodos de ID3D12GraphicsCommandList DrawInstanced, DrawIndexedInstanced o Dispatch).
- El conjunto de enlaces de recursos que cambiará la llamada por comando frente al conjunto que se heredará.
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:
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):
- D3D12_DRAW_ARGUMENTS
- D3D12_DRAW_INDEXED_ARGUMENTS
- D3D12_DISPATCH_ARGUMENTS
- D3D12_VERTEX_BUFFER_VIEW
- D3D12_INDEX_BUFFER_VIEW
- D3D12_GPU_VIRTUAL_ADDRESS (un sinónimo typedef of UINT64).
- D3D12_CONSTANT_BUFFER_VIEW
Creación de firma de comando
Para crear una firma de comando, usa los siguientes elementos de API:
- ID3D12Device::CreateCommandSignature (genera un ID3D12CommandSignature)
- D3D12_INDIRECT_ARGUMENT_TYPE
- D3D12_INDIRECT_ARGUMENT_DESC
- D3D12_COMMAND_SIGNATURE_DESC
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 |
Temas relacionados