Share via


Portar de Direct3D 11 a Direct3D 12

En esta sección se proporcionan algunas instrucciones sobre cómo migrar desde un motor de gráficos direct3D 11 personalizado a Direct3D 12.

Creación de dispositivos

Tanto Direct3D 11 como Direct3D 12 comparten un patrón de creación de dispositivos similar. Los controladores existentes de Direct3D 12 son todos D3D_FEATURE_LEVEL_11_0 o superior, por lo que puede omitir los niveles de características anteriores y las limitaciones asociadas.

Tenga en cuenta también que con Direct3D 12, debe enumerar explícitamente la información del dispositivo mediante interfaces DXGI. En Direct3D 11, puedes volver a encadenar al dispositivo DXGI desde el dispositivo Direct3D y esto no es compatible con Direct3D 12.

La creación de un dispositivo de software WARP en Direct3D 12 se realiza proporcionando un adaptador explícito obtenido de IDXGIFactory4::EnumWarpAdapter. El dispositivo WARP para Direct3D 12 solo está disponible en sistemas con la característica opcional Herramientas de gráficos habilitada.

Nota

No hay ningún equivalente a D3D11CreateDeviceAndSwapChain. Incluso con Direct3D 11, se desaconseja el uso de esta función, ya que a menudo es mejor crear el dispositivo y la cadena de intercambio en pasos distintos.

Recursos confirmados

Los objetos creados con las siguientes interfaces en Direct3D 11 se traducen en lo que se denomina "recursos confirmados" en Direct3D 12. Un recurso confirmado es un recurso que tiene espacio de direcciones virtuales y páginas físicas asociadas a él. Este es un concepto del modelo de memoria de Microsoft Windows Device Driver 2 (WDD2), en el que se basa Direct3D 12.

Recursos de Direct3D 11:

En Direct3D 12, todos están representados por ID3D12Resource e ID3D12Device::CreateCommittedResource.

Recursos reservados

Los recursos reservados son recursos en los que solo se ha asignado espacio de direcciones virtuales, la memoria física no se asigna hasta que haya una llamada a ID3D12Device::CreateHeap. Este es básicamente el mismo concepto que los recursos en mosaico en Direct3D 11.

Las marcas (D3D11_RESOURCE_MISC_FLAG) usadas en Direct3D 11 para configurar recursos en mosaico y, a continuación, asignarlas a la memoria física.

  • D3D11_RESOURCE_MISC_TILED
  • D3D11_RESOURCE_MISC_TILE_POOL

Carga de datos

En Direct3D 11 hay la apariencia de una sola escala de tiempo (llamadas después de una secuencia, como los datos inicializados con D3D11_SUBRESOURCE_DATA, se realiza una llamada a ID3D11DeviceContext::UpdateSubresource y, a continuación, una llamada a ID3D11DeviceContext::Map). El número de copias creadas de los datos no es obvio para un desarrollador de Direct3D 11.

En Direct3D 12 hay dos escalas de tiempo, la escala de tiempo de GPU (configurada por llamadas a CopyTextureRegion y CopyBufferRegion desde la memoria asignable) y la escala de tiempo de CPU (determinada por las llamadas a Map). Las funciones auxiliares se proporcionan (en el archivo d3dx12.h) denominadas Updatesubresources que usan una escala de tiempo compartida. Hay varias variaciones de esta función auxiliar, una que usa ID3D12Device::GetCopyableFootprints, otra que usa un mecanismo de asignación de montón y otro que usa un mecanismo de asignación de pila. Estas funciones auxiliares copian recursos tanto en la GPU como en la CPU, a través de un área de almacenamiento provisional intermedia de memoria.

Normalmente, la GPU y la CPU tienen su propia copia de un recurso vinculado a su propia escala de tiempo. El enfoque de escala de tiempo compartida mantiene de forma similar dos copias.

Sombreadores y objetos de sombreador

En Direct3D 11 hay una gran cantidad de creación de objetos de sombreador y estado, y establecer el estado de esos objetos, usando los métodos de creación ID3D11Device y los métodos de conjunto ID3D11DeviceContext . Normalmente, se realiza un gran número de llamadas a estos métodos, que el controlador combina en tiempo de dibujo para establecer el estado de canalización correcto.

En Direct3D 12, esta configuración de estado de canalización se ha combinado en un único objeto (CreateComputePipelineState para un motor de proceso y CreateGraphicsPipelineState para un motor de gráficos), que luego se adjunta a una lista de comandos antes de la llamada draw con una llamada a SetPipelineState.

Estas llamadas reemplazan todas las llamadas individuales para establecer sombreadores, diseño de entrada, estado de mezcla, estado de rasterizador, estado de galería de símbolos de profundidad, etc., en Direct3D 11

  • Métodos del dispositivo 11: CreateInputLayout, CreateXShader, CreateDepthStencilStatey CreateRasterizerState.
  • Métodos del contexto de dispositivo 11: IASetInputLayout, xxSetShader, OMSetBlendState, OMSetDepthStencilStatey RSSetState.

Aunque Direct3D 12 puede admitir blobs de sombreador compilados más antiguos, los sombreadores deben compilarse mediante el modelo de sombreador 5.1 con las API FXC/D3DCompile, o mediante el modelo de sombreador 6 mediante el compilador DXIL DXC. Debe validar la compatibilidad del modelo de sombreador 6 con CheckFeatureSupport y D3D12_FEATURE_SHADER_MODEL.

Envío del trabajo a la GPU

en Direct3D 11 hay poco control sobre cómo se envía realmente el trabajo, se controla en gran medida por el controlador, aunque algunos controles están habilitados a través de las llamadas ID3D11DeviceContext::Flush e IDXGISwapChain1::P resent1 .

En el envío de trabajo de Direct3D 12 es muy explícito y controlado por la aplicación. La construcción principal para enviar trabajo es id3D12GraphicsCommandList, que se usa para registrar todos los comandos de aplicaciones (y es bastante similar en concepto al contexto diferido ID3D11). La memoria auxiliar de una lista de comandos se proporciona mediante id3D12CommandAllocator, que permite a la aplicación administrar el uso de memoria de la lista de comandos exponiendo realmente la memoria que el controlador Direct3D 12 va a usar para almacenar la lista de comandos.

Por último, ID3D12CommandQueue es una cola primero en salir, que almacena el orden correcto de las listas de comandos para su envío a la GPU. Solo cuando una lista de comandos haya completado la ejecución en la GPU, el controlador enviará la siguiente lista de comandos de la cola.

En Direct3D 11 no hay ningún concepto explícito de una cola de comandos. En la configuración común de Direct3D 12, la lista de comandos de D3D12_COMMAND_LIST_TYPE_DIRECT abierta actualmente para el marco actual se puede considerar análoga al contexto inmediato de Direct3D 11. Esto proporciona muchas de las mismas funciones.

D3D11DeviceContext ID3D12GraphicsCommand List
ClearDepthStencilView ClearDepthStencilView
ClearRenderTargetView ClearRenderTargetView
ClearUnorderedAccess* ClearUnorderedAccess*
Draw, DrawInstanced DrawInstanced
DrawIndexed, DrawIndexedInstanced DrawIndexedInstanced
Dispatch Dispatch
IASetInputLayout, xxSetShader, etc. SetPipelineState
OMSetBlendState OMSetBlendFactor
OMSetDepthStencilState OMSetStencilRef
OMSetRenderTargets OMSetRenderTargets
RSSetViewports RSSetViewports
RSSetScissorRects RSSetScissorRects
IASetPrimitiveTopology IASetPrimitiveTopology
IASetVertexBuffers IASetVertexBuffers
IASetIndexBuffer IASetIndexBuffer
ResolveSubresource ResolveSubresource
CopySubresourceRegion CopyBufferRegion
UpdateSubresource CopyTextureRegion
CopyResource CopyResource

Nota

Una lista de comandos creada con D3D12_COMMAND_LIST_TYPE_BUNDLE es simliar en un contexto diferido. Direct3D 12 también admite la abiilty para acceder a algunas características de un contexto inmediato al mismo tiempo que la representación a través de D3D12_COMMAND_LIST_TYPE_COPY y D3D12_COMMAND_LIST_TYPE_COMPUTE tipos de lista de comandos.

Sincronización de CPU/GPU

En la sincronización de CPU/GPU de Direct3D 11 era en gran medida automática y no era necesario que la aplicación mantenga el estado de la memoria física.

en Direct3D 12, la aplicación debe administrar explícitamente las dos escalas de tiempo (CPU y GPU). Esto requiere que la aplicación mantenga la información en qué recursos requiere la GPU y durante cuánto tiempo. Esto también significa que la aplicación es responsable de garantizar que el contenido de los recursos (recursos confirmados, montones, asignadores de comandos, por ejemplo) no cambie hasta que la GPU haya terminado de usarlos.

El objeto principal para sincronizar las escalas de tiempo es el objeto ID3D12Fence . El funcionamiento de las barreras es bastante sencillo, permiten que la GPU señale cuando haya completado una tarea. Tanto la GPU como la CPU pueden indicar y pueden esperar en vallas.

Normalmente, el enfoque es que, al enviar una lista de comandos para su ejecución, la GPU transmite una señal de barrera al finalizar (cuando haya terminado de leer los datos), lo que permite que la CPU reutilice o destruya los recursos.

En Direct3D 11, la marca ID3D11DeviceContext::Map D3D11_MAP_WRITE_DISCARD tratar básicamente cada recurso como un suministro sin fin de memoria en la que la aplicación podría escribir (un proceso conocido como "cambio de nombre"). En Direct3D 12 de nuevo, el proceso es explícito: es necesario asignar memoria adicional y se deben usar barreras para sincronizar las operaciones. Los búferes de anillo (que constan de búferes grandes) pueden ser una buena técnica para ello, consulte el escenario de búfer de anillo en Administración de recursos basada en barreras.

usar un búfer de anillo

Enlace de recursos

Las vistas de Direct3D 11 (vistas de recursos de sombreador, vistas de destino de representación, etc.), se han reemplazado en gran medida en Direct3D 12 por el concepto de descriptor. Los métodos de creación siguen existiendo en Direct3D 12 (como CreateShaderResourceView y CreateRenderTargetView), a los que se llama después de crear el montón del descriptor, para escribir los datos en el montón. El enlace en Direct3D 12 ahora se controla mediante identificadores de descriptor descritos en una firma raíz y se envía mediante los métodos SetGraphicsRootDescriptorTable o SetComputeRootDescriptorTable .

Las firmas raíz detallan las asignaciones entre el número de ranura de firma raíz y las tablas descriptores, donde la tabla descriptor puede contener referencias a recursos disponibles para sombreadores de vértices, sombreadores de píxeles y otros sombreadores, como búferes de constantes, vistas de recursos de sombreador y muestradores. Esta flexibilidad desconecta el espacio de registro de HLSL del espacio de enlace de API en Direct3D 12, a diferencia de Direct3D 11, donde hay una asignación uno a uno entre ellos.

Una de las implicaciones de este sistema es que la aplicación es responsable de cambiar el nombre de las tablas de descriptores, lo que permite a los desarrolladores comprender el costo de rendimiento de cambiar incluso un único descriptor por llamada a draw.

Una nueva característica de Direct3D 12 es que una aplicación puede controlar qué descriptores se comparten entre las fases del sombreador. En los recursos de Direct3D 11, como los UAV, se comparten entre todas las fases del sombreador. Al habilitar los descriptores para deshabilitarse para determinadas fases del sombreador, los registros usados por los descriptores que se han deshabilitado están disponibles para que los descriptores que estén habilitados para una fase de sombreador determinada.

En la tabla siguiente se muestra una firma raíz de ejemplo.

Ranura de parámetro raíz Entrada de tabla descriptor
0 Intervalo de descriptores de VS b0-b13
1 Intervalo de descriptores de VS t0-t127
2 Intervalo de descriptores de VS s0-s16
3 Intervalo de descriptores de PS b0-b13
...
14 Intervalo de descriptores DS s0-16
15 Intervalo de descriptores compartidos u0-u63

 

Estado del recurso

En el estado de recurso de Direct3D 11, la aplicación no lo mantiene, sino el controlador.

En Direct3D 12 mantener el estado de los recursos se convierte en responsabilidad de la aplicación, para habilitar el paralelismo completo en la grabación de listas de comandos: la aplicación debe controlar las escalas de tiempo de grabación de las listas de comandos (que se pueden realizar en paralelo) y las escalas de tiempo de ejecución que deben ser secuenciales.

El método ResourceBarrier controla una transición de estado de recurso. Principalmente, la aplicación debe informar al controlador cuando cambia el uso de recursos. Por ejemplo, si un recurso se usa como destino de representación y, a continuación, se va a usar como entrada para un sombreador de vértices en la siguiente llamada a draw, lo que podría requerir una breve parada en la operación de GPU para completar la operación de destino de representación antes de controlar el sombreador de vértices.

Este sistema permite la sincronización específica (los puestos de GPU) de la canalización de gráficos, así como el vaciado de caché y, posiblemente, algunos cambios de diseño de memoria (como la vista de destino de representación a la descompresión de la vista de galería de símbolos de profundidad).

Esto se conoce como barrera de transición. Hay otros tipos de barreras, en Direct3D 11, ID3D11DeviceContext2::TiledResourceBarrier habilitó la misma memoria física que usarán dos recursos en mosaico diferentes. En Direct3D 12, esto se conoce como una "barrera de alias". Las barreras de alias se pueden usar para los recursos en mosaico y colocados en Direct3D 12. Además, hay la barrera UAV. En Direct3D 11, es necesario serializar todas las operaciones de distribución y dibujo de UAV, aunque estas operaciones se pueden canalizar o trabajar en paralelo. Para Direct3D 12, esta restricción se elimina mediante la adición de una barrera UAV. Una barrera UAV garantiza que las operaciones UAV sean secuenciales, por lo que si una segunda operación requiere que la primera operación se complete, la segunda se verá obligada a esperar por la adición de la barrera. La operación predeterminada para uaV es simplemente que las operaciones continuarán lo más rápido posible.

Claramente hay mejoras de rendimiento si se puede paralelizar una carga de trabajo.

Cadenas de intercambio

La cadena de intercambio DXGI es la base de las cadenas de intercambio en Direct3D 11 y 12. Hay algunas diferencias menores, en Direct3D 11 los tres tipos de cadena de intercambio son SECUENCIAL, DESCARTE y FLIP_SEQUENTIAL. Para Direct3D 12 hay solo dos tipos: FLIP_SEQUENTIAL y FLIP_DISCARD. Como se indicó anteriormente, debe crear explícitamente la cadena de intercambio a través de IDXGIFactory4 o posterior, y usar la misma interfaz para cualquier enumeración de adaptador.

En Direct3D 11 hay rotación automática del búfer de reserva: solo se necesita una vista de destino de representación para el búfer de reserva 0. En la rotación del búfer de Direct3D 12 es explícito, debe haber una vista de destino de representación para cada búfer de reserva. Use el método IDXGISwapChain3::GetCurrentBackBufferIndex para seleccionar el que se va a representar. De nuevo, esta flexibilidad adicional permite una mayor paralelización.

Nota

Aunque hay muchas maneras de configurar la aplicación, normalmente las aplicaciones tienen un id3D12CommandAllocator por búfer de cadena de intercambio. Esto permite a la aplicación continuar con la creación de un conjunto de comandos para el siguiente fotograma mientras la GPU representa el anterior.

Representación de funciones fijas

En Direct3D 11 había algunos métodos que simplificaban varias operaciones de nivel superior, como GenerateMips (creando cadenas MIP completas) y DrawAuto (mediante la salida de flujo como entrada de sombreador sin más entrada de la aplicación). Estos métodos no están disponibles en Direct3D 12, la aplicación debe controlar estas operaciones mediante la creación de sombreadores para realizarlas.

Probabilidades y finales

En la tabla siguiente se muestran varias características similares entre Direct3D 11 y 12, pero que no son idénticas.

Direct3D 11 Direct3D 12
ID3D11Query ID3D12QueryHeap permite agrupar las consultas, lo que reduce el costo.
ID3D11Predicate El predicado ahora está habilitado al tener datos en un búfer totalmente transparente. El objeto Id3D 11 ID3D11Predicate se reemplaza por ID3D12Resource::Map, que debe seguir una llamada a ResolveQueryData y una operación de sincronización de GPU mediante una barrera para esperar a que los datos estén listos. Consulte Predicación.
Contador oculto UAV/SO La aplicación es responsable de la asignación y administración de contadores SO/UAV. Consulte Contadores de salida de flujo y Contadores UAV.
MinLOD dinámico de recursos (nivel mínimo de detalle) Esto se ha movido al minLOD estático del descriptor SRV.
Draw*Indirect/DispatchIndirect Los métodos indirectos de dibujo se combinan en el método ExecuteIndirect .
Los formatos depthStencil están intercalados Los formatos depthStencil son planar. Por ejemplo, un formato de 24 bits de profundidad, 8 bits de galería de símbolos se almacenaría en el formato 24/8/24/8... etc en Direct3D 11, pero como 24/24/24... seguido de 8/8/8... en Direct3D 12. Tenga en cuenta que cada plano es su propio subrecurso en D3D12 (consulte Subrecursos).
ResizeTilePool Los recursos reservados se pueden asignar a varios montones. Cuando un grupo de mosaicos habría crecido en D3D11, se puede asignar un montón adicional en D3D12 en su lugar.

 

Tutoriales en vídeo de aprendizaje avanzado de DirectX: Guía de migración de DirectX 11 a DirectX 12

Descripción de Direct3D 12

Trabajar con Direct3D 11, Direct3D 10 y Direct2D