¿Qué problema resuelve el buffer doble o triple en los juegos modernos?


31

Quiero verificar si mi comprensión de las causas del uso del almacenamiento en búfer doble (o triple) es correcta:

Un monitor con 60Hz actualiza la pantalla del monitor 60 veces por segundo. Si el monitor actualiza la pantalla del monitor, actualiza píxel por píxel y línea por línea. El monitor solicita los valores de color para los píxeles de la memoria de video.

Si ejecuto ahora un juego, entonces este juego está constantemente manipulando esta memoria de video.

Si este juego no usa una estrategia de búfer (doble búfer, etc.), entonces puede ocurrir el siguiente problema:

El monitor ahora está actualizando su monitor. En este momento, el monitor ya había actualizado la primera mitad del monitor. Al mismo tiempo, el juego había manipulado la memoria de video con nuevos datos. Ahora el monitor accede para la segunda mitad del monitor: muestra estos nuevos datos manipulados de la memoria de video. Los problemas pueden ser desgarros o parpadeos.

¿Comprendo bien los casos de uso de la estrategia de amortiguación? ¿Hay otras razones?

Respuestas:


62

Fundamentalmente, un objetivo central en la representación es que cada cuadro que se muestra en el monitor presente una imagen única y coherente. Hay varias estrategias diferentes que se utilizan o se utilizaron para lograr esto.

A continuación, menciono "vsync". Vsync es el momento en que el monitor comienza a dibujar una nueva imagen de pantalla; es el punto en el que "vblank" comienza en una pantalla CRT tradicional, donde la línea de exploración detiene momentáneamente el dibujo y vuelve a la parte superior del monitor. Este momento es muy importante para muchos de los enfoques de coherencia de marcos.

"Desgarro" es lo que llamamos cuando una pantalla muestra dos imágenes diferentes, dentro de un solo cuadro. Si, por ejemplo, he dibujado dos imágenes de pantalla que están destinadas a mostrarse una después de la otra, pero el monitor ha mostrado la mitad superior del cuadro uno y la mitad inferior del cuadro dos, eso es "desgarro". Esto sucede debido al cambio de los datos que lee el monitor mientras el monitor dibuja, en lugar de hacerlo durante vblank. (En los programas modernos, esto suele suceder porque el usuario deshabilitó la espera de vsync en la configuración de su controlador)

Tampón cero

En el hardware más antiguo, a menudo no había suficiente memoria para contener una imagen de pantalla completa, por lo que en lugar de dibujar una imagen de pantalla, tenía que especificar colores para cada línea de escaneo individualmente, mientras el monitor estaba en el proceso de dibujar esa línea. En el Atari 2600, por ejemplo, tenía solo 76 ciclos de instrucciones de máquina para especificar qué color se aplicaba a cada píxel de la línea de exploración, antes de que el televisor comenzara a dibujar esa línea de exploración. Y luego tenía 76 ciclos de instrucciones para proporcionar el contenido para la siguiente línea de exploración, y así sucesivamente.

Single-Buffer

Al dibujar en un contexto de "búfer único", está dibujando directamente en la VRAM que el monitor está leyendo. En este enfoque, "compite con el scanline". La idea general es que cuando la línea de exploración comienza a dibujar el contenido del fotograma anterior en la parte superior de la pantalla, dibuja en VRAM detrás él. Entonces, mientras la línea de escaneo dibuja la imagen de la pantalla para el último cuadro, está dibujando el siguiente cuadro detrás de la línea de escaneo.

En general, está tratando de terminar de dibujar la imagen del siguiente cuadro antes de que la línea de exploración lo "gire" volviendo nuevamente y adelantando los píxeles que está dibujando, y también nunca avanzar a la línea de escaneo, o de lo contrario su nuevo el marco podría dibujar en lo que debería haber sido el marco anterior.

Por esta razón, la representación de un solo búfer generalmente funcionaba dibujando líneas de escaneo, de arriba a abajo y de izquierda a derecha. Si dibujaba en otro orden, era probable que la línea de exploración volviera a aparecer y detectara fragmentos de la "siguiente" imagen que aún no había dibujado.

Tenga en cuenta que en los sistemas operativos modernos, por lo general, nunca tiene la oportunidad de dibujar un solo búfer, aunque esto era bastante común hace treinta años. (Dios, me siento viejo en este momento, esto es lo que estaba haciendo cuando comencé a desarrollar juegos)

Búfer doble

Esto es mucho, mucho más simple que cualquiera de las estrategias anteriores.

En un sistema de doble búfer, tenemos suficiente memoria para almacenar dos imágenes de pantalla diferentes, por lo que designamos una de ellas como el "búfer frontal" y el otro, el "búfer trasero". El "búfer frontal" es lo que se muestra actualmente, y el "búfer trasero" es donde estamos dibujando actualmente.

Después de que terminemos de dibujar una imagen de pantalla en el búfer posterior, esperamos hasta vsync, y luego intercambiamos los dos búferes. De esta manera, el búfer posterior se convierte en el búfer frontal, y viceversa, y todo el intercambio ocurrió mientras el monitor no dibujaba nada.

Triple Buffer

Un problema que a menudo se plantea con los enfoques de doble búfer es que después de que terminemos de dibujar en el búfer posterior, tenemos que quedarnos sentados esperando a vsync antes de poder intercambiar los búferes y continuar trabajando; ¡podríamos haber estado haciendo cálculos durante ese tiempo! Lo que es más, todo el tiempo que estamos esperando para cambiar entre los búferes, la imagen en ese búfer posterior se hace cada vez más vieja, lo que aumenta la latencia percibida del usuario.

En los sistemas de triple búfer, creamos tres búferes: un búfer frontal y dos búferes traseros. La idea es esta:

El monitor muestra el búfer frontal, y estamos dibujando en el búfer trasero # 1. Si terminamos de dibujar en el búfer posterior # 1 antes de que el monitor termine de dibujar el búfer frontal, entonces, en lugar de esperar vsync, comenzaremos inmediatamente a dibujar el siguiente cuadro en el búfer trasero # 2. Si terminamos y vsync aún no ha llegado, comenzamos a retroceder en el búfer de respaldo # 1, y así sucesivamente. La idea es que cuando eventualmente se produzca vsync, uno u otro de nuestros búferes de respaldo estarán completos, y que uno se puede cambiar por el búfer frontal.

El beneficio del buffering triple es que no perdemos el tiempo que pasamos esperando vsync en el enfoque de buffering doble, y la imagen intercambiada en el buffer frontal puede ser "más fresca" que la que había estado esperando vsync 8ms. La desventaja del triple búfer es que necesitamos memoria adicional para almacenar la imagen de pantalla adicional, y que nuestro uso de CPU / GPU será mayor (nuevamente, ya que no disminuimos la velocidad para esperar vsync).

Por lo general, los controladores modernos a menudo realizan triple buffering de forma transparente, detrás de escena. Usted escribe su código para hacer doble búfer, y el controlador le devolverá el control antes de tiempo, y solo manejará internamente el intercambio entre la cantidad de memorias intermedias que quiera usar, sin que su código lo sepa.

Los proveedores de GPU actualmente recomiendan que no implementes el triple búfer, el controlador lo hará por ti automáticamente.


77
Esta es una respuesta increíblemente detallada y explica por qué muchas cosas se hacen como están (como el espacio de coordenadas de la pantalla, etc.). También respondí a mi pregunta "¿por qué no cuádruples buffers? Quintuple?" No me di cuenta de que el intercambio de búfer ocurrió en segundo plano, lo que significa que dos búferes de respaldo son el máximo necesario. Votado
lunchmeat317

En realidad, existe un búfer cuádruple. Esto es doble buffer para la vista estereoscópica. swiftless.com/tutorials/opengl/smooth_rotation.html
Narek

@Narek No. Citando desde su enlace: "Realmente no se puede habilitar el almacenamiento intermedio cuádruple real en entornos de gráficos de computadora ya que no hay un punto real". Sugerir que hacer doble búfer en dos vistas diferentes simultáneamente sería "búfer cuádruple" es simplemente un juego de palabras divertido; No es algo real.
Trevor Powell

@TrevorPowell Agregando una parte que olvidó incluir: "Bueno, típicamente el buffering cuádruple se refiere al doble buffering en un entorno estereoscópico. Por ejemplo: tiene dos pantallas, típicamente para propósitos 3D y cada ojo tiene doble buffer". Ahora el contexto podría ser más claro.
Narek

@TrevorPowell Sin embargo, su punto es totalmente claro. No tiene sentido tener más de 3 buffers para un buffer de renderizado.
Narek
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.