Compartir a través de


Programación asincrónica (DirectX y C++)

En este tema se tratan varios puntos que se deben tener en cuenta al usar la programación asincrónica y el subproceso con DirectX.

Programación asincrónica y DirectX

Si solo está aprendiendo sobre DirectX o incluso si tiene experiencia con él, considere la posibilidad de colocar toda la canalización de procesamiento de gráficos en un subproceso. En cualquier escena determinada de un juego, hay recursos comunes, como mapas de bits, sombreadores y otros recursos que requieren acceso exclusivo. Estos mismos recursos requieren que se sincronice cualquier acceso a estos recursos en los subprocesos paralelos. La representación es un proceso difícil de paralelizar en varios subprocesos.

Sin embargo, si tu juego es lo suficientemente complejo o si estás buscando mejorar el rendimiento, puedes usar la programación asincrónica para paralelizar algunos de los componentes que no son específicos de la canalización de representación. Las modernas características de hardware son varias CPU principales e hiperprocesadas, y la aplicación debe aprovechar esto. Puedes asegurarte de esto mediante la programación asincrónica para algunos de los componentes del juego que no necesitan acceso directo al contexto del dispositivo Direct3D, como:

  • E/S de archivo
  • física
  • INTELIGENCIA ARTIFICIAL
  • networking
  • audio
  • controls
  • Componentes de interfaz de usuario basados en XAML

La aplicación puede controlar estos componentes en varios subprocesos simultáneos. La E/S de archivos, especialmente la carga de recursos, se beneficia en gran medida de la carga asincrónica, ya que el juego o la aplicación pueden estar en un estado interactivo mientras se cargan o transmiten varios (o varios cientos) megabytes de recursos. La manera más fácil de crear y administrar estos subprocesos es usar la biblioteca de patrones paralelos y el patrón de tarea , tal como se incluye en el espacio de nombres de simultaneidad definido en PPLTasks.h. El uso de la biblioteca de patrones paralelos aprovecha directamente varias CPU de núcleo e hiperproceso, y puede mejorar todo, desde los tiempos de carga percibidos hasta los aciertos y retrasos que vienen con cálculos intensivos de CPU o procesamiento de red.

Nota En una aplicación de Plataforma universal de Windows (UWP), la interfaz de usuario se ejecuta completamente en un apartamento de un solo subproceso (STA). Si vas a crear una interfaz de usuario para tu juego directX mediante la interoperabilidad XAML, solo puedes acceder a los controles mediante sta.

 

Multithreading con dispositivos Direct3D

La multithreading para contextos de dispositivo solo está disponible en dispositivos gráficos que admiten un nivel de característica de Direct3D de 11_0 o posterior. Sin embargo, es posible que quiera maximizar el uso de la GPU eficaz en muchas plataformas, como plataformas de juegos dedicadas. En el caso más sencillo, es posible que quiera separar la representación de una superposición de visualización de encabezados (HUD) de la representación y proyección de la escena 3D y hacer que ambos componentes usen canalizaciones paralelas independientes. Ambos subprocesos deben usar el mismo ID3D11DeviceContext para crear y administrar los objetos de recursos (texturas, mallas, sombreadores y otros recursos), aunque, que es un solo subproceso, y que requiere que implemente algún tipo de mecanismo de sincronización (como secciones críticas) para acceder a él de forma segura. Y, aunque puede crear listas de comandos independientes para el contexto del dispositivo en diferentes subprocesos (para la representación diferida), no puede reproducir esas listas de comandos simultáneamente en la misma instancia id3D11DeviceContext .

Ahora, la aplicación también puede usar ID3D11Device, que es seguro para multithreading, para crear objetos de recursos. Por lo tanto, ¿por qué no usar siempre ID3D11Device en lugar de ID3D11DeviceContext? Actualmente, es posible que la compatibilidad con controladores para multithreading no esté disponible para algunas interfaces gráficas. Puede consultar el dispositivo y averiguar si admite multithreading, pero si busca llegar al público más amplio, puede seguir con ID3D11DeviceContext de un solo subproceso para la administración de objetos de recursos. Dicho esto, cuando el controlador de dispositivos gráficos no admite listas de comandos o multithreading, Direct3D 11 intenta controlar el acceso sincronizado al contexto del dispositivo internamente; y si no se admiten listas de comandos, proporciona una implementación de software. Como resultado, puede escribir código multiproceso que se ejecutará en plataformas con interfaces gráficas que carecen de compatibilidad con controladores para el acceso al contexto de dispositivo multiproceso.

Si la aplicación admite subprocesos independientes para procesar listas de comandos y para mostrar fotogramas, es probable que quieras mantener la GPU activa, procesando las listas de comandos mientras se muestran fotogramas de forma oportuna sin que se produzca un retraso o un retraso perceptibles. En este caso, podría usar un id3D11DeviceContext independiente para cada subproceso y compartir recursos (como texturas) creandolos con la marca D3D11_RESOURCE_MISC_SHARED. En este escenario, se debe llamar a ID3D11DeviceContext::Flush en el subproceso de procesamiento para completar la ejecución de la lista de comandos antes de mostrar los resultados del procesamiento del objeto de recurso en el subproceso para mostrar.

Representación diferida

La representación diferida registra comandos gráficos en una lista de comandos para que se puedan reproducir en algún otro momento, y está diseñado para admitir la representación en un subproceso mientras se graban comandos para la representación en subprocesos adicionales. Una vez completados estos comandos, se pueden ejecutar en el subproceso que genera el objeto de visualización final (búfer de fotogramas, textura u otra salida de gráficos).

Cree un contexto diferido mediante ID3D11Device::CreateDeferredContext (en lugar de D3D11CreateDevice o D3D11CreateDeviceAndSwapChain, que crean un contexto inmediato). Para obtener más información, consulta Representación inmediata y diferida.