Que problema o buffer duplo ou triplo resolve nos jogos modernos?


31

Quero verificar se meu entendimento das causas do uso de buffer duplo (ou triplo) está correto:

Um monitor com atualização de 60Hz é exibido 60 vezes por segundo. Se o monitor atualizar a exibição do monitor, ele atualizará pixel por pixel e linha por linha. O monitor solicita os valores de cor para os pixels da memória de vídeo.

Se eu rodar agora um jogo, esse jogo está constantemente manipulando essa memória de vídeo.

Se este jogo não usar uma estratégia de buffer (buffer duplo, etc.), o seguinte problema pode ocorrer:

O monitor agora está atualizando seu monitor. Nesse momento, o monitor já havia atualizado a primeira metade do monitor. Ao mesmo tempo, o jogo manipulou a memória de vídeo com novos dados. Agora, o monitor acessa, na segunda metade do monitor, esses novos dados manipulados da memória de vídeo. Os problemas podem estar rasgando ou tremendo.

Meu entendimento dos casos de uso da estratégia de buffer está correto? Existem outras razões?

Respostas:


62

Fundamentalmente, um objetivo central na renderização é que cada quadro exibido no monitor apresente uma imagem única e coerente. Existem várias estratégias diferentes que são, ou foram, usadas para conseguir isso.

A seguir, menciono "vsync". Vsync é o momento em que o monitor começa a desenhar uma nova imagem na tela; é o ponto em que o "vblank" começa em uma tela CRT tradicional, onde a linha de varredura momentaneamente para de desenhar e volta para a parte superior do monitor. Este momento é muito importante para muitas das abordagens para enquadrar a coerência.

"Rasgar" é o que chamamos quando uma tela é renderizada a partir de duas imagens diferentes, em um único quadro. Se, por exemplo, desenhei duas imagens de tela que devem ser exibidas uma após a outra, mas o monitor exibiu a metade superior do quadro um e a metade inferior do quadro dois, que está "rasgando". Isso acontece devido à alteração dos dados que o monitor está lendo enquanto o monitor está desenhando, em vez de durante o vblank. (Nos programas modernos, isso normalmente acontece porque o usuário desabilitou a espera do vsync nas configurações de driver)

Zero-Buffer

No hardware mais antigo, geralmente não havia memória suficiente para armazenar uma imagem em tela cheia e, em vez de desenhar uma imagem em tela, era necessário especificar cores para cada linha de digitalização individualmente, enquanto o monitor estava desenhando essa linha. No Atari 2600, por exemplo, você tinha apenas 76 ciclos de instruções da máquina para especificar qual cor entrava em cada pixel da linha de varredura, antes que a televisão começasse a desenhar essa linha de varredura. E então você tinha 76 ciclos de instruções para fornecer o conteúdo para a próxima linha de verificação e assim por diante.

Buffer único

Ao desenhar em um contexto de "buffer único", você está desenhando diretamente na VRAM que está sendo lida pelo monitor. Nesta abordagem, você "corre na linha de verificação". A ideia geral é que, quando a linha de digitalização começar a desenhar o conteúdo do quadro anterior na parte superior da tela, você desenhe o VRAM por trás dele. Portanto, enquanto a linha de digitalização desenha a imagem da tela para o último quadro, você está desenhando o próximo quadro atrás da linha de digitalização.

Em geral, você está tentando terminar de desenhar a imagem do próximo quadro antes da linha de varredura "dobrar" você, contornando os pixels que você está desenhando e também para nunca ficar à frente da linha de varredura, ou então da sua nova o quadro pode ser inserido no que deveria ter sido o quadro anterior.

Por esse motivo, a renderização de buffer único normalmente funcionava desenhando linhas de digitalização, de cima para baixo e da esquerda para a direita. Se você desenhasse em outra ordem, era provável que a linha de varredura aparecesse novamente e localizasse partes da "próxima" imagem que você ainda não desenhou.

Observe que, em sistemas operacionais modernos, você normalmente nunca tem a oportunidade de desenhar um buffer único, embora isso fosse bastante comum trinta anos atrás. (caramba, eu me sinto velho agora - é isso que eu estava fazendo quando comecei no desenvolvimento de jogos)

Double-Buffer

Isso é muito, muito mais simples do que qualquer uma das estratégias que vieram antes.

Em um sistema de buffer duplo, temos memória suficiente para armazenar duas imagens de tela diferentes e, portanto, designamos uma delas como "buffer frontal" e a outra, "buffer de fundo". O "buffer frontal" é o que está sendo exibido no momento, e o "buffer traseiro" é o local onde estamos desenhando.

Depois de terminar de desenhar uma imagem de tela no buffer traseiro, aguardamos até vsync e trocamos os dois buffers. Dessa forma, o buffer traseiro se torna o buffer frontal e vice-versa, e toda a troca ocorreu enquanto o monitor não estava desenhando nada.

Triple-Buffer

Um problema frequentemente levantado com abordagens de buffer duplo é que, depois que terminamos de desenhar o buffer de fundo, precisamos ficar esperando o vsync antes de trocar os buffers e continuar trabalhando; nós poderíamos ter feito cálculos durante esse tempo! Além disso, todo o tempo que esperamos para trocar entre os buffers, a imagem nesse buffer traseiro está ficando cada vez mais antiga, aumentando assim a latência percebida do usuário.

Nos sistemas de buffer triplo, criamos para nós três buffers - um buffer frontal e dois buffers traseiros. A ideia é esta:

O monitor está exibindo o buffer frontal e estamos usando o buffer traseiro nº 1. Se terminarmos de desenhar o buffer traseiro nº 1 antes que o monitor termine de desenhar o buffer frontal, em vez de esperar pelo vsync, começaremos imediatamente a desenhar o próximo quadro no buffer traseiro nº 2. Se terminarmos e o vsync ainda não tiver chegado, começamos a voltar ao buffer número 1 e assim por diante. A idéia é que, quando o vsync finalmente acontecer, um ou outro de nossos buffers traseiros estará completo e esse poderá ser trocado pelo buffer frontal.

O benefício do buffer triplo é que não perdemos o tempo que gastamos esperando o vsync na abordagem de buffer duplo, e a imagem trocada no buffer frontal pode ser "mais atualizada" do que a que estava esperando pelo vsync por 8ms. O lado negativo do buffer triplo é que precisamos de memória extra para armazenar a imagem de tela extra e que o uso de CPU / GPU será maior (novamente, pois não diminuímos o tempo para esperar pelo vsync).

Normalmente, os drivers modernos costumam executar buffer triplo de forma transparente, nos bastidores. Você escreve seu código para fazer buffer duplo, e o driver realmente retorna o controle para você mais cedo e apenas manipula internamente a troca entre o número de buffers que deseja usar, sem que seu código esteja ciente disso.

Atualmente, os fornecedores de GPU recomendam que você não implemente o buffer triplo - o driver fará isso automaticamente.


7
Esta é uma resposta incrivelmente detalhada e explica por que muitas coisas são feitas do jeito que são (como o espaço de coordenadas da tela, etc.). Também respondeu à minha pergunta "por que não quadruplicar buffers? Quíntuplo?" Não percebi que a troca de buffer acontecia em segundo plano, o que significa que dois buffers de volta são o máximo necessário. Votado.
precisa saber é o seguinte

Na verdade, existe um buffer quad. Este é um buffer duplo para visualização estereoscópica. swiftless.com/tutorials/opengl/smooth_rotation.html
Narek

@Narek Não. Citando seu link: "Você não pode realmente ativar o buffer quad real em ambientes de computação gráfica, pois não há sentido real". Sugerir que fazer buffer duplo em duas visões diferentes simultaneamente seria "quad buffering" é apenas divertido jogo de palavras; não é algo real.
Trevor Powell

@TrevorPowell Adicionando parte que você esqueceu de incluir: "Bem, normalmente o buffer quádruplo refere-se ao buffer duplo em um ambiente estereoscópico. Por exemplo: você tem dois monitores, geralmente para fins 3D e cada olho é buffer duplo." Agora o contexto pode estar mais claro.
Narek

@TrevorPowell Seu argumento é totalmente claro. Não faz sentido ter mais de 3 buffers para um buffer de renderização.
Narek
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.