Direct3D 11 en 12
D3D11On12 es un mecanismo por el que los desarrolladores pueden usar interfaces y objetos D3D11 para controlar la API D3D12. D3D11on12 permite a los componentes escritos mediante D3D11 (por ejemplo, texto D2D y interfaz de usuario) trabajar junto con componentes escritos destinados a la API D3D12. D3D11on12 también permite la portabilidad incremental de una aplicación de D3D11 a D3D12, al permitir que partes de la aplicación sigan teniendo como destino D3D11 por motivos de simplicidad, mientras que otros tienen como destino D3D12 para el rendimiento, a la vez que siempre tienen una representación completa y correcta. D3D11On12 facilita el uso de técnicas de interoperabilidad para compartir recursos y sincronizar el trabajo entre las dos API.
Inicialización de D3D11On12
Para empezar a usar D3D11On12, el primer paso es crear un dispositivo D3D12 y una cola de comandos. Estos objetos se proporcionan como entrada para el método de inicialización D3D11On12CreateDevice. Puede considerar este método como crear un dispositivo D3D11 con el tipo de controlador imaginario D3D_DRIVER_TYPE_11ON12, donde el controlador D3D11 es responsable de crear objetos y enviar listas de comandos a la API D3D12.
Después de tener un dispositivo D3D11 y un contexto inmediato, puede QueryInterface
desactivarlo para la interfaz ID3D11On12Device . Esta es la interfaz principal que se usa para la interoperabilidad entre D3D11 y D3D12. Para que tanto el contexto del dispositivo D3D11 como las listas de comandos D3D12 funcionen en los mismos recursos, es necesario crear "recursos ajustados" mediante la API CreateWrappedResource . Este método "promueve" un recurso D3D12 para que sea comprensible en D3D11. Un recurso ajustado se inicia en el estado "adquirido", una propiedad manipulada por los métodos AcquireWrappedResources y ReleaseWrappedResources .
Ejemplo de uso
El uso típico de D3D11On12 sería usar D2D para representar texto o imágenes sobre un búfer de reserva D3D12. Consulte el ejemplo D3D11On12 para obtener código de ejemplo. Este es un esquema aproximado de los pasos que debe seguir para hacerlo:
- Cree un dispositivo D3D12 (D3D12CreateDevice) y una cadena de intercambio D3D12 (CreateSwapChain con id3D12CommandQueue como entrada).
- Cree un dispositivo D3D11On12 con el dispositivo D3D12 y la misma cola de comandos que la entrada.
- Recupere los búferes de reserva de la cadena de intercambio y cree recursos encapsulados D3D11 para cada uno de ellos. El estado de entrada usado debe ser la última manera en que D3D12 lo usó (por ejemplo, RENDER_TARGET) y el estado de salida debe ser la forma en que D3D12 lo usará después de que D3D11 haya finalizado (por ejemplo, PRESENT).
- Inicialice D2D y proporcione los recursos encapsulados D3D11 a D2D para prepararse para la representación.
A continuación, en cada fotograma, haga lo siguiente:
- Represente en el búfer de reserva de la cadena de intercambio actual mediante una lista de comandos D3D12 y ejecútelo.
- Adquiera el recurso ajustado del búfer de reserva actual (AcquireWrappedResources).
- Emita comandos de representación D2D.
- Libere el recurso ajustado (ReleaseWrappedResources).
- Vacíe el contexto inmediato D3D11.
- Presente (IDXGISwapChain1::P resent1).
Información previa
D3D11On12 funciona sistemáticamente. Cada llamada API D3D11 pasa por la validación típica en tiempo de ejecución y hace su camino al controlador. En la capa de controlador, el estado especial del controlador 11on12 registra el estado y emite operaciones de representación en las listas de comandos D3D12. Estas listas de comandos se envían según sea necesario (por ejemplo, una consulta GetData
o un recurso Map
pueden requerir que los comandos se vacíe) o según lo solicite Flush. La creación de un objeto D3D11 normalmente da como resultado la creación del objeto D3D12 correspondiente. Algunas operaciones fijas de representación de funciones en D3D11 como GenerateMips
o DrawAuto
no se admiten en D3D12, por lo que D3D11On12 las emula mediante sombreadores y recursos adicionales.
Para la interoperabilidad, es importante comprender cómo interactúa D3D11On12 con los objetos D3D12 que la aplicación ha creado y proporcionado. Para asegurarse de que el trabajo se produce en el orden correcto, el contexto inmediato D3D11 debe vaciarse antes de que se pueda enviar un trabajo adicional de D3D12 a esa cola. También es importante asegurarse de que la cola que se proporciona a D3D11On12 debe ser purgable en todo momento. Esto significa que las esperas de la cola deben cumplirse finalmente, incluso si el subproceso de representación D3D11 se bloquea indefinidamente. Tenga cuidado de no tomar una dependencia de cuando D3D11On12 inserte vaciados o esperas, ya que esto puede cambiar con versiones futuras. Además, D3D11On12 realiza un seguimiento y manipula los estados de los recursos por sí solos. La única manera de garantizar la coherencia de las transiciones de estado es usar las API de adquisición y versión para manipular el seguimiento de estado para que coincida con las necesidades de la aplicación.
Limpiar
Para liberar un recurso encapsulado D3D11On12, es necesario que se produzcan dos cosas en este orden:
- Todas las referencias al recurso, incluidas las vistas del recurso, deben liberarse.
- El procesamiento de destrucción diferida debe realizarse. La manera más sencilla de asegurarse de que esto sucede es invocar la API de contexto
Flush
inmediato.
Una vez completados ambos pasos, se deben liberar todas las referencias realizadas por el recurso encapsulado y el recurso D3D12 se convierte exclusivamente en propiedad del componente D3D12. Tenga en cuenta que D3D12 todavía requiere esperar la finalización de GPU antes de liberar completamente un recurso, así que asegúrese de contener una referencia en el recurso antes de realizar los dos pasos anteriores, a menos que ya haya confirmado que la GPU ya no usa el recurso.
Todos los demás recursos u objetos creados por D3D11On12 se limpiarán en el momento adecuado, cuando la GPU haya terminado de usarlas, mediante el mecanismo de destrucción diferido de D3D11. Sin embargo, si intenta liberar el propio dispositivo D3D11On12 mientras se ejecuta la GPU, la destrucción puede bloquearse hasta que se complete la GPU.
Limitaciones
La capa D3D11On12 implementa un subconjunto muy grande de la API D3D11, pero hay algunas brechas conocidas (además de errores en la implementación que pueden provocar una representación incorrecta).
A partir de Windows 10, versión 1809 (10.0; Compilación 17763), siempre que D3D11On12 se ejecute en un controlador que admita Shader Model 6.0 o posterior, puede ejecutar sombreadores que usen interfaces. En versiones anteriores de Windows, la característica de interfaces de sombreador no se implementa en D3D11On12 y al intentar usar la característica se producirán errores y mensajes de depuración.
A partir de Windows 10, versión 1803 (10.0; Compilación 17134), las cadenas de intercambio se admiten en dispositivos D3D11On12. En versiones anteriores de Windows, no lo son.
D3D11On12 no se ha optimizado para el rendimiento. Probablemente habrá una sobrecarga moderada de CPU en comparación con un controlador D3D11 estándar, una sobrecarga mínima de GPU y se sabe que hay una sobrecarga de memoria significativa. Por lo tanto, no se recomienda usar D3D11On12 para escenas 3D complicadas y, en su lugar, se recomienda para escenas simples o para la representación 2D.
API existentes
Las API que componen la capa 11on12 se describen en Referencia de 11on12.
Temas relacionados