Página principal » cómo » ¿Cómo interactúan la CPU y la GPU para generar gráficos de computadora?

    ¿Cómo interactúan la CPU y la GPU para generar gráficos de computadora?

    La Unidad Central de Procesamiento (CPU) y la Unidad de Procesamiento de Gráficos (GPU) de su computadora interactúan en cada momento que usa su computadora para brindarle una interfaz visual nítida y receptiva. Siga leyendo para comprender mejor cómo trabajan juntos.

    Foto por Sskennel.

    La sesión de Preguntas y Respuestas de hoy nos llega por cortesía de SuperUser, una subdivisión de Stack Exchange, una agrupación impulsada por la comunidad de sitios web de preguntas y respuestas.

    La pregunta

    El lector superusuario Sathya planteó la pregunta:

    Aquí puede ver una captura de pantalla de un pequeño programa de C ++ llamado Triangle.exe con un triángulo giratorio basado en la API de OpenGL.

    Es cierto que es un ejemplo muy básico, pero creo que es aplicable a otras operaciones con tarjetas gráficas..

    Tenía curiosidad y quería saber todo el proceso desde hacer doble clic en Triangle.exe en Windows XP hasta que pueda ver el triángulo girando en el monitor. Qué sucede, cómo interactúan la CPU (que primero maneja el .exe) y la GPU (que finalmente genera el triángulo en la pantalla)?

    Supongo que participar en la visualización de este triángulo giratorio es principalmente el siguiente hardware / software, entre otros:

    Hardware

    • HDD
    • Memoria del sistema (RAM)
    • UPC
    • Memoria de video
    • GPU
    • pantalla LCD

    Software

    • Sistema operativo
    • API de DirectX / OpenGL
    • Driver nvidia

    ¿Alguien puede explicar el proceso, quizás con algún tipo de diagrama de flujo para ilustración??

    No debe ser una explicación compleja que cubra cada paso (supongo que iría más allá del alcance), sino una explicación que un individuo de informática intermedio puede seguir..

    Estoy bastante seguro de que muchas personas que incluso se llamarían profesionales de TI no podrían describir este proceso correctamente.

    La respuesta

    Aunque varios miembros de la comunidad respondieron la pregunta, Oliver Salzburg hizo un esfuerzo adicional y respondió no solo con una respuesta detallada sino con excelentes gráficos de acompañamiento..

    Imagen de JasonC, disponible como fondo de pantalla aquí..

    El escribe:

    Decidí escribir un poco sobre el aspecto de la programación y cómo los componentes se comunican entre sí. Tal vez arroje algo de luz sobre ciertas áreas.

    La presentación

    ¿Qué se necesita para tener esa única imagen, que usted publicó en su pregunta, dibujada en la pantalla??

    Hay muchas formas de dibujar un triángulo en la pantalla. Para simplificar, supongamos que no se utilizaron buffers de vértice. (UNA amortiguador de vérticees un área de la memoria donde se almacenan las coordenadas.) Supongamos que el programa simplemente le dijo a la tubería de procesamiento de gráficos sobre cada vértice individual (un vértice es solo una coordenada en el espacio) en una fila.

    Pero, antes de que podamos dibujar algo, primero tenemos que ejecutar algunos andamios. Ya veremos por qué luego:

    // Borrar la pantalla y el búfer de profundidad glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // Restablecer la matriz de modelo actual glMatrixMode (GL_MODELVIEW); glLoadIdentity (); // Dibujo usando triángulos glBegin (GL_TRIANGLES); // GlColor3f rojo (1.0f, 0.0f, 0.0f); // Parte superior del triángulo (Frente) glVertex3f (0.0f, 1.0f, 0.0f); // GlColor3f verde (0.0f, 1.0f, 0.0f); // Left Of Triangle (Front) glVertex3f (-1.0f, -1.0f, 1.0f); // Blue glColor3f (0.0f, 0.0f, 1.0f); // Right Of Triangle (Front) glVertex3f (1.0f, -1.0f, 1.0f); // Hecho Dibujo glEnd ();

    Entonces, ¿qué hizo eso?

    Cuando escribe un programa que quiere usar la tarjeta gráfica, usualmente elige algún tipo de interfaz para el controlador. Algunas interfaces bien conocidas para el controlador son:

    • OpenGL
    • Direct3D
    • CUDA

    Para este ejemplo nos quedaremos con OpenGL. Ahora tu interfaz al conductor Es lo que te da todas las herramientas que necesitas para hacer tu programa. hablar a la tarjeta gráfica (o al controlador, que luego negociaciones a la tarjeta).

    Esta interfaz está destinada a darle cierta herramientas. Estas herramientas toman la forma de una API a la que puede llamar desde su programa.

    Esa API es lo que vemos que se usa en el ejemplo anterior. Miremos más de cerca.

    El andamiaje

    Antes de que puedas hacer un dibujo real, deberás realizar una preparar. Debe definir su ventana gráfica (el área que realmente se representará), su perspectiva (la cámara en tu mundo), qué anti-aliasing usarás (para suavizar el borde de tu triángulo) ...

    Pero no vamos a ver nada de eso. Vamos a echar un vistazo a las cosas que tendrás que hacer cada cuadro. Me gusta:

    Borrar la pantalla

    La canalización de gráficos no borrará la pantalla para usted cada fotograma. Tendrás que decirlo. ¿Por qué? Esta es la razón por:

    Si no borras la pantalla, simplemente dibujar sobre Es cada cuadro. Por eso llamamos glClear con elGL_COLOR_BUFFER_BIT conjunto. El otro bit (GL_DEPTH_BUFFER_BIT) le dice a OpenGL que borre el profundidadbuffer. Este búfer se utiliza para determinar qué píxeles están delante (o detrás) de otros píxeles.

    Transformación


    Fuente de imagen

    La transformación es la parte donde tomamos todas las coordenadas de entrada (los vértices de nuestro triángulo) y aplicamos nuestra matriz ModelView. Esta es la matriz que explica como nuestro modelo (los vértices) se rotan, escalan y traducen (mueven).

    A continuación, aplicamos nuestra matriz de proyección. Esto mueve todas las coordenadas para que estén frente a nuestra cámara correctamente..

    Ahora nos transformamos una vez más, con nuestra matriz Viewport. Hacemos esto para escalar nuestro modelo al tamaño de nuestro monitor. Ahora tenemos un conjunto de vértices que están listos para ser renderizados.!

    Volveremos a la transformación un poco más tarde..

    Dibujo

    Para dibujar un triángulo, simplemente podemos decirle a OpenGL que comience un nuevo lista de triángulos llamando glegin con el GL_TRIANGLES constante.
    También hay otras formas que puedes dibujar. Como una tira triangular o un abanico triangular. Estas son principalmente optimizaciones, ya que requieren menos comunicación entre la CPU y la GPU para dibujar la misma cantidad de triángulos.

    Después de eso, podemos proporcionar una lista de conjuntos de 3 vértices que deberían formar cada triángulo. Cada triángulo usa 3 coordenadas (ya que estamos en el espacio 3D). Además, también proporciono un color para cada vértice, llamandoglColor3f antes de vocación glVertex3f.

    La sombra entre los 3 vértices (las 3 esquinas del triángulo) se calcula mediante OpenGLautomáticamente. Interpolará el color sobre toda la cara del polígono..

    Interacción

    Ahora, cuando haces clic en la ventana. La aplicación solo tiene que capturar el mensaje de la ventana que señala el clic. Entonces puedes ejecutar cualquier acción en tu programa que quieras.

    Esto recibe un mucho Más difícil una vez que quieras comenzar a interactuar con tu escena 3D.

    Primero debe saber claramente en qué píxel el usuario hizo clic en la ventana. Entonces, tomando tu perspectivaen cuenta, puede calcular la dirección de un rayo, desde el punto de clic del ratón hasta su escena. A continuación, puede calcular si cualquier objeto en su escena intersecta con ese rayo. Ahora sabes si el usuario hizo clic en un objeto..

    Entonces, ¿cómo lo haces girar?

    Transformación

    Soy consciente de dos tipos de transformaciones que generalmente se aplican:

    • Transformación basada en matrices
    • Transformación basada en el hueso

    La diferencia es que huesos afectar solo vértices. Las matrices siempre afectan a todos los vértices dibujados de la misma manera. Veamos un ejemplo.

    Ejemplo

    Anteriormente, cargamos nuestro matriz de identidad Antes de dibujar nuestro triángulo. La matriz de identidad es aquella que simplemente proporciona sin transformación en absoluto. Entonces, lo que dibuje, solo se ve afectado por mi perspectiva. Por lo tanto, el triángulo no se girará en absoluto.

    Si quiero rotarlo ahora, podría hacer los cálculos yo mismo (en la CPU) y simplemente llamar glVertex3f conotro Coordenadas (que se rotan). O podría dejar que la GPU haga todo el trabajo, llamando glRotatefantes de dibujar:

    // Girar el triángulo en el eje Y glRotatef (cantidad, 0.0f, 1.0f, 0.0f); 

    cantidad Es, por supuesto, sólo un valor fijo. Si quieres animar, tendrás que seguir la pista de cantidady aumentalo cada cuadro.

    Así que, espera, ¿qué pasó con toda la charla matricial anterior??

    En este ejemplo simple, no tenemos que preocuparnos por las matrices. Simplemente llamamos glRotatef Y se encarga de todo eso por nosotros..

    glRotate produce una rotación de ángulo grados alrededor del vector x y z. La matriz actual (seeglMatrixMode) se multiplica por una matriz de rotación con el producto reemplazando a la matriz actual, como se llamó a ifglMultMatrix con la siguiente matriz como argumento:

    x 2 ⁡ 1 - c + cx ⁢ y ⁡ 1 - c - z ⁢ sx ⁢ z ⁡ 1 - c + y ⁢ s 0 y ⁢ x ⁡ 1 - c + z ⁢ sy 2 ⁡ 1 - c + cy ⁢ z ⁡ 1 - c - x ⁢ s 0 x ⁢ z ⁡ 1 - c - y sy ⁢ z ⁡ 1 - c + x ⁢ sz 2 ⁡ 1 - c + c 0 0 0 0 1

    Bien gracias por eso!

    Conclusión

    Lo que se vuelve obvio es que se habla mucho. a OpenGL. Pero no es para decir nosotros cualquier cosa. Donde esta la comunicacion?

    Lo único que OpenGL nos está diciendo en este ejemplo es cuando este hecho. Cada operación tomará una cierta cantidad de tiempo. Algunas operaciones toman increíblemente largas, otras son increíblemente rápidas.

    Enviando un vértice para la GPU será tan rápido, que ni siquiera sabría cómo expresarlo. El envío de miles de vértices desde la CPU a la GPU, cada trama, es muy probable que no haya ningún problema..

    Borrar la pantalla puede tardar un milisegundo o peor (tenga en cuenta que, por lo general, solo dispone de unos 16 milisegundos de tiempo para dibujar cada marco), según el tamaño de la ventana gráfica. Para borrarlo, OpenGL tiene que dibujar cada píxel en el color que desee borrar, que podría ser millones de píxeles..

    Aparte de eso, solo podemos preguntarle a OpenGL sobre las capacidades de nuestro adaptador de gráficos (resolución máxima, máximo suavizado, profundidad de color máxima, ...).

    Pero también podemos rellenar una textura con píxeles que cada uno tiene un color específico. Por lo tanto, cada píxel tiene un valor y la textura es un "archivo" gigante lleno de datos. Podemos cargar eso en la tarjeta gráfica (creando un búfer de texturas), luego cargar un sombreado, decirle a ese sombreador que use nuestra textura como entrada y ejecutar algunos cálculos extremadamente pesados ​​en nuestro "archivo".

    Luego podemos "renderizar" el resultado de nuestro cálculo (en forma de nuevos colores) en una nueva textura..

    Así es como puedes hacer que la GPU funcione para ti de otras maneras. Asumo que CUDA tiene un desempeño similar a ese aspecto, pero nunca tuve la oportunidad de trabajar con él.

    Realmente solo tocamos un poco todo el tema. La programación de gráficos en 3D es una gran bestia..


    Fuente de imagen


    ¿Tienes algo que agregar a la explicación? Apague el sonido en los comentarios. ¿Quieres leer más respuestas de otros usuarios de Stack Exchange con experiencia en tecnología? Echa un vistazo a la discusión completa aquí.