¿Cómo funciona OpenGL al nivel más bajo? [cerrado]

84

Entiendo cómo escribir programas OpenGL / DirectX, y sé las matemáticas y las cosas conceptuales detrás de esto, pero tengo curiosidad por saber cómo funciona la comunicación GPU-CPU en un nivel bajo.

Digamos que tengo un programa OpenGL escrito en C que muestra un triángulo y gira la cámara 45 grados. Cuando compile este programa, ¿se convertirá en una serie de llamadas ioctl, y el controlador de gpu luego enviará los comandos apropiados a la gpu, donde se conectará toda la lógica de rotar el triángulo y configurar los píxeles apropiados en el color apropiado? ¿en? ¿O el programa se compilará en un "programa gpu" que se carga en la gpu y calcula la rotación, etc.? ¿O algo completamente diferente?

Editar : unos días después 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 /

Benno
fuente
La especificación OpenGL indica que los comandos se envían en modo cliente / servidor. La especificación es demasiado amplia para determinar una tecnología específica utilizada por las implementaciones de OpenGL.
Luca

Respuestas:

86

Esta pregunta es casi imposible de responder porque OpenGL en sí mismo es solo una API frontal, y siempre que una implementación se adhiera a la especificación y el resultado se ajuste a esto, se puede hacer de la forma que desee.

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

Entonces la pregunta debería haber sido: "¿Cómo se ve en promedio detrás de escena de OpenGL y el sistema de gráficos?". Veamos esto de abajo hacia arriba:

  1. En el nivel más bajo hay algún dispositivo gráfico. Hoy en día se trata de GPU que proporcionan un conjunto de registros que controlan su funcionamiento (cuyo registro depende exactamente del dispositivo) tienen algo de memoria de programa para shaders, memoria masiva para datos de entrada (vértices, texturas, etc.) y un canal de E / S para el resto del sistema sobre el que recibe / envía datos y flujos de comandos.

  2. El controlador de gráficos realiza un seguimiento del estado de las GPU y de todos los programas de aplicación de recursos que hacen uso de la GPU. También se encarga de la conversión o cualquier otro procesamiento de los datos enviados por las aplicaciones (convertir texturas al formato de píxel soportado por la GPU, compilar sombreadores en el código máquina de la GPU). Además, proporciona una interfaz abstracta dependiente del controlador para los programas de aplicación.

  3. Luego está el controlador / biblioteca 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 la que traduce las llamadas OpenGL cómo lo hace en llamadas a las funciones específicas del controlador en la parte del controlador descrita en (2).

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

No se puede generalizar cómo ocurre la comunicación real:

En Unix, la conexión 3 <-> 4 puede ocurrir a través de Sockets (sí, puede hacerlo, y pasa a través de la red si lo desea) oa través de la memoria compartida. En Windows, la biblioteca de interfaz y el cliente del controlador se cargan en el espacio de direcciones del proceso, por lo que no hay tanta comunicación, sino simples llamadas a funciones y paso de variables / punteros. 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 pasar por ioctl, lectura / escritura o mediante la asignación de memoria al espacio de direcciones del proceso y la configuración de la MMU para activar algún código de controlador siempre que se realicen cambios en esa memoria. Esto es bastante similar en cualquier sistema operativo, ya que siempre tienes que cruzar el límite del kernel / área de usuario: en última instancia, atraviesas una llamada al sistema.

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

datenwolf
fuente
1
Esta descripción es probablemente de muy bajo nivel y genérica con muy pocas especificaciones de OpenGL. Se aplica aproximadamente a cualquier componente de hardware presente en una computadora.
v.shashenko
1
@ v.shashenko: Bueno, por supuesto. Independientemente del componente de hardware con el que esté hablando, sigue este esquema general. Pero OpenGL no es una pieza de software en particular, es solo una especificación y cualquier cosa que se ajuste a la especificación es una implementación válida. Y debido a que al final una implementación de OpenGL está hablando con una GPU, seguirá aproximadamente el mismo script a lo largo del cual se implementan las API de hardware. Es imposible ser más específico que eso, porque no existe la implementación OpenGL " The ONE ". Y cada implementación es un poco diferente.
datenwolf
1
@ v.shashenko: Si desea obtener más detalles, deberá preguntar sobre una implementación en particular. Por ejemplo, digamos, X11 + GLX + DRI → Mesa / AMDGPU → Linux-KMS + DRM (Direct Rendering Manager). Y cada uno de estos componentes es una bestia bastante compleja con tantos detalles, que podría llenar libros con detalles sobre cómo funciona cada componente. Pero eso describiría la implementación de Linux-AMDGPU. Pero Linux + NVidia es una bestia completamente diferente. Y en Windows es diferente de nuevo.
datenwolf
¿Te acuerdas de que charlamos hace unos días, solo quería saber cómo contactar contigo en caso de que quiera saber algo?
Suraj Jain
Lo que enseñó ese día, despejó muchas de mis dudas, también hizo una nueva, pero en general ahora no considero que sea una magia que dibujemos ventanas e íconos en la pantalla.
Suraj Jain
23

Cuando compile este programa, ¿se convertirá en una serie de llamadas ioctl, y el controlador de gpu luego enviará los comandos apropiados a la gpu, donde se conectará toda la lógica de rotar el triángulo y configurar los píxeles apropiados en el color apropiado? ¿en? ¿O el programa se compilará en un "programa gpu" que se carga en la gpu y calcula la rotación, etc.?

No estás lejos. Su programa llama al controlador de cliente instalable (que en realidad no es un controlador, es una biblioteca compartida del 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 más antiguas tenían lo que se llama una "canalización 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, mezcla, 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 se diferencian 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 binarios del programa para que se ejecuten en los sombreadores de GPU.

Ben Voigt
fuente
20

Su programa no está compilado para ninguna GPU en particular; simplemente está vinculado dinámicamente con una biblioteca que implementará OpenGL. La implementación real podría implicar el envío de comandos OpenGL a la GPU, la ejecución de software alternativo, la compilación de sombreadores y su envío a la GPU, o incluso el uso de sombreadores alternativos a comandos OpenGL. El panorama de los gráficos es bastante complicado. Afortunadamente, la vinculación lo aísla de la mayor parte de la complejidad de los controladores, lo que deja a los implementadores de controladores libres para usar las técnicas que consideren adecuadas.

Tobu
fuente
18

Los compiladores / enlazadores de C / C ++ hacen exactamente una cosa: convierten 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 de C / C ++; no pueden convertir mágicamente su compilador / enlazador C / C ++ en un compilador / enlazador para la GPU.

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

El único lugar en el que entraría en juego un "programa gpu" es si su código crea sombreadores explícitamente. Es decir, si realiza las llamadas a la API en OpenGL / D3D que provocan la compilación y vinculación de sombreadores. Para hacer esto, usted (en tiempo de ejecución, no en tiempo de compilación de C / C ++) genera o carga cadenas que representan sombreadores en algún lenguaje de sombreado. Luego, los empuja a través del compilador de sombreadores y recupera un objeto en esa API que representa ese sombreador. A continuación, aplica uno o más sombreadores a un comando de renderizado en particular. Cada uno de estos pasos ocurre explícitamente en la dirección de su código C / C ++, que como se indicó anteriormente se ejecuta en la CPU.

Muchos lenguajes de sombreado utilizan una sintaxis similar a C / C ++. Pero eso no los hace equivalentes a C / C ++.

Nicol Bolas
fuente
He estado aprendiendo opengl últimamente y me pregunto por qué veo todos estos "programas de sombreado" en el código que veo escrito como cadenas literales. Como dijiste, se compilan en tiempo de ejecución. Vi algunos ejemplos en algunos códigos de opengl es de Android. Luego vi un código para iPhone también. Aparentemente, el iPhone tiene cuatro procesadores vectoriales que son capaces de hacer cálculos matemáticos de punto flotante mucho más rápido que la CPU del iPhone, por lo que puede escribir el ASM como cadenas literales para que se compile en tiempo de ejecución para usar esos procesadores en lugar de la CPU principal.
eggie5
1
La mayor parte de la "canalización de funciones fijas" ahora se implementa mediante un conjunto predeterminado de programas de sombreado. No es necesario solicitar explícitamente un sombreador para obtener uno.
Ben Voigt
1
@Ben Voigt: Cierto, pero si nadie te lo dijera, no podrías notar la diferencia.
Nicol Bolas
1
Lo que podría ser una actitud sensata, si esta pregunta no fuera sobre los detalles ocultos.
Ben Voigt