¿Cómo funciona OpenGL en el nivel más bajo?

Entiendo cómo escribir progtwigs OpenGL / DirectX, y sé las matemáticas y las cuestiones conceptuales que lo respaldan, pero tengo curiosidad sobre cómo funciona la comunicación entre la GPU y la CPU en un nivel bajo.

Digamos que tengo un progtwig OpenGL escrito en C que muestra un triángulo y gira la cámara 45 grados. Cuando compilo este progtwig, se convertirá en una serie de ioctl-calls, y el controlador gpu luego envía los comandos apropiados al gpu, donde está conectada toda la lógica de girar el triángulo y configurar los píxeles apropiados en el color apropiado. ¿en? ¿O el progtwig se comstackrá en un “progtwig gpu” que se carga en el gpu y calcula la rotación, etc.? ¿O algo completamente diferente?

Editar : Unos días más tarde encontré esta serie de artículos, que básicamente responde a la pregunta: http://fgiesen.wordpress.com/2011/07/01/a-trip-through-the-graphics-pipeline-2011-part- 1 /

Esta pregunta es casi imposible de responder porque OpenGL por sí solo es solo una API de front-end, y siempre que una implementación se adhiera a la especificación y el resultado se ajuste a esto, puede hacerse de la forma que desee.

La pregunta puede haber sido: ¿Cómo funciona un controlador OpenGL en el nivel más bajo? Ahora, de nuevo, esto es imposible de responder en general, ya que un controlador está estrechamente ligado a alguna pieza de hardware, lo que puede volver a hacer las cosas, sin embargo, el desarrollador lo diseñó.

Así que la pregunta debería haber sido: “¿Cómo se ve en promedio detrás de las escenas de OpenGL y el sistema de gráficos?”. Veamos esto de abajo hacia arriba:

  1. En el nivel más bajo, hay algunos dispositivos gráficos. Hoy en día, estas son GPU que proporcionan un conjunto de registros que controlan su funcionamiento (cuyos registros dependen exactamente del dispositivo) tienen alguna memoria de progtwig para sombreadores, memoria masiva para datos de entrada (vértices, texturas, etc.) y un canal de E / S para el rest del sistema sobre el que recibe / envía flujos de datos y comandos.

  2. El controlador de gráficos realiza un seguimiento del estado de las GPU y de todos los progtwigs de aplicaciones de recursos que hacen uso de la GPU. También es responsable de la conversión o cualquier otro procesamiento de los datos enviados por las aplicaciones (convertir texturas en el formato de pixel admitido por la GPU, comstackr sombreadores en el código máquina de la GPU). Además, proporciona una interfaz abstracta, dependiente del controlador, para los progtwigs de aplicación.

  3. Luego está la biblioteca / controlador de cliente OpenGL dependiente del controlador. En Windows esto se carga por proxy a través de opengl32.dll, en sistemas Unix esto reside en dos lugares:

    • Módulo X11 GLX y controlador GLX dependiente del controlador
    • y /usr/lib/libGL.so puede contener algunas cosas dependientes del controlador para la representación directa

    En MacOS X, este es el “Marco OpenGL”.

    Es esta parte que traduce las llamadas de OpenGL cómo lo hace en las llamadas a las funciones específicas del controlador en la parte del controlador descrita en (2).

  4. Finalmente, la biblioteca de la API OpenGL real, opengl32.dll en Windows, y en Unix /usr/lib/libGL.so; esto solo pasa los comandos a la implementación de OpenGL propiamente dicha.

Cómo ocurre la comunicación real no se puede generalizar:

En Unix, la conexión 3 <-> 4 puede ocurrir ya sea en Sockets (sí, puede, y sí pasa por la red si lo desea) oa través de Shared Memory. En Windows, tanto la biblioteca de la interfaz como el cliente del controlador se cargan en el espacio de direcciones del proceso, de modo que no se trata tanto de comunicación sino de llamadas a funciones simples y paso variable / de puntero. En MacOS X esto es similar a Windows, solo que no hay separación entre la interfaz OpenGL y el cliente del controlador (esa es la razón por la que MacOS X es tan lento para mantenerse al día con las nuevas versiones de OpenGL, siempre requiere una actualización completa del sistema operativo para entregar el nuevo marco de referencia).

La comunicación entre 3 <-> 2 puede ir a través de ioctl, lectura / escritura, o mapeando alguna memoria en el espacio de direcciones de proceso y configurando la MMU para activar algún código de controlador cada vez que se realizan cambios en esa memoria. Esto es bastante similar en cualquier sistema operativo ya que siempre debe cruzar el límite kernel / userland: en última instancia, pasa por algunos syscall.

La comunicación entre el sistema y la GPU ocurre a través del bus periférico y los métodos de acceso que define, por lo que PCI, AGP, PCI-E, etc., que funcionan a través de Port-I / O, Memory Mapped I / O, DMA, IRQ.

Cuando compilo este progtwig, se convertirá en una serie de ioctl-calls, y el controlador gpu luego envía los comandos apropiados al gpu, donde está conectada toda la lógica de girar el triángulo y configurar los píxeles apropiados en el color apropiado. ¿en? ¿O el progtwig se comstackrá en un “progtwig gpu” que se carga en el gpu y calcula la rotación, etc.?

No estás lejos. Su progtwig llama al controlador de cliente instalable (que no es realmente un controlador, es una biblioteca compartida de espacio de usuario). Eso usará ioctl o un mecanismo similar para pasar datos al controlador del kernel.

Para la siguiente parte, depende del hardware. Las tarjetas de video antiguas tenían lo que se llama una “tubería de función fija”. Había espacios de memoria dedicados en la tarjeta de video para matrices y hardware dedicado para la búsqueda de texturas, combinación, etc. El controlador de video cargaba los datos y banderas correctos para cada una de estas unidades y luego configuraba DMA para transferir sus datos de vértice (posición , color, coordenadas de textura, etc.).

El hardware más nuevo tiene núcleos de procesador (“sombreadores”) dentro de la tarjeta de video, que difieren de su CPU en que cada uno de ellos funciona mucho más lento, pero hay muchos más trabajando en paralelo. Para estas tarjetas de video, el controlador prepara los binarios del progtwig para ejecutar en los sombreadores GPU.

Su progtwig no está comstackdo para ninguna GPU en particular; simplemente está vinculado dinámicamente contra una biblioteca que implementará OpenGL. La implementación real podría implicar el envío de comandos de OpenGL a la GPU, ejecutando versiones de software, comstackndo sombreadores y enviándolos a la GPU, o incluso utilizando reembolsos de sombreado a los comandos de OpenGL. El paisaje de gráficos es bastante complicado. Afortunadamente, el enlace lo aísla de la complejidad de la mayoría de los controladores, lo que deja a los implementadores del controlador la libertad de utilizar las técnicas que consideren adecuadas.

Los comstackdores / vinculadores C / C ++ hacen exactamente una cosa: convierten los archivos de texto en una serie de códigos de operación específicos de la máquina que se ejecutan en la CPU. OpenGL y Direct3D son solo API C / C ++; no pueden convertir mágicamente su comstackdor / enlazador C / C ++ en un comstackdor / enlazador para la GPU.

Cada línea de código C / C ++ que escriba se ejecutará en la CPU. Las llamadas a OpenGL / Direct3D harán una llamada a bibliotecas C / C ++, estáticas o dinámicas, según sea el caso.

El único lugar donde un “progtwig gpu” entraría en juego es si su código crea sombreadores explícitamente. Es decir, si realiza llamadas de API en OpenGL / D3D que causan la comstackción y el enlace de sombreadores. Para hacer esto, usted (en tiempo de ejecución, no en tiempo de comstackción C / C ++) genera o carga cadenas que representan sombreadores en algún lenguaje de sombreado. A continuación, los introduce en el comstackdor de sombreado y recupera un objeto en esa API que representa ese sombreador. A continuación, aplica uno o más sombreadores a un comando de representación particular. Cada uno de estos pasos ocurre explícitamente en la dirección de su código C / C ++, que como se estableció anteriormente se ejecuta en la CPU.

Muchos lenguajes de sombreado usan syntax tipo C / C ++. Pero eso no los hace equivalentes a C / C ++.