Qual é o conteúdo do buffer * após * uma chamada para glSwapBuffers ()?

8

( SDL_GL_SwapBuffers()em particular)

Quando você desenha uma cena e chama buffers de troca, é rotina glClear()a cena antes de desenhar qualquer coisa; se você não limpar, qual é o conteúdo do buffer? Isso é definido por alguma especificação ou varia de acordo com o driver?

Vai
fonte
Esta é uma pergunta muito interessante.
Notabene 12/01

Respostas:

13

Os detalhes de como trocar o buffer frontal e traseiro variam de plataforma para plataforma e, portanto, a resposta depende da plataforma.

De acordo com a documentação de referência GLX glXSwapBuffers :

O conteúdo do buffer de fundo fica indefinido após uma troca. Observe que isso se aplica aos buffers de pixel e às janelas.

No entanto, existe a extensão GLX_EXT_buffer_age :

O objetivo desta extensão é expor informações suficientes aos aplicativos sobre como o driver gerencia o conjunto de buffers frontal e traseiro associados a uma determinada superfície para permitir que os aplicativos reutilizem o conteúdo de quadros antigos e minimizar o quanto deve ser redesenhado para o próximo quadro.

Mas o Win32 SwapBuffers apenas diz:

Se o formato de pixel atual da janela referenciada por este contexto de dispositivo incluir um buffer de fundo, a função trocará os buffers frontal e traseiro ... Se o formato de pixel atual da janela mencionada pelo contexto de dispositivo não incluir um buffer de fundo, isso chamada não tem efeito e o conteúdo do buffer de fundo é indefinido quando a função retorna.

E CGLFlushDrawable, para gráficos do OS X Core diz:

Se o atributo de armazenamento de backup estiver definido como falso, os buffers poderão ser trocados em vez de copiados. Geralmente, esse é o caso no modo de tela cheia. Se o receptor não for um contexto com buffer duplo, esta chamada não fará nada.

Finalmente, na função de troca de buffer padrão do OpenGL ES, eglSwapBuffers :

O buffer de cores da superfície é deixado indefinido após a chamada eglSwapBuffers.

Então, o que tudo isso significa?

  • Para ser verdadeiramente multiplataforma, você não pode assumir nada sobre o buffer traseiro após uma troca. Seu conteúdo é indefinido, e você provavelmente deve glClear ou corrigi-lo antes de usá-lo.
  • Se você estiver usando Linux, poderá verificar a extensão da idade do buffer. Como um sistema pode ter um buffer triplo, talvez seja necessário rastrear vários quadros com danos e lidar com isso.
  • Se você estiver usando o OS X, poderá ser copiado e poderá obter uma troca. Portanto, você pode assumir que o conteúdo do backbuffer não é lixo, mas não controla se é o quadro que você acabou de enviar ou o quadro anterior.
  • Se você está direcionando apenas o Win32 e tem certeza de que possui um buffer de fundo, presumivelmente, pode presumir que seu conteúdo agora é o que estava no buffer frontal. (Embora essa seja uma suposição por omissão, e não explicitamente declarada; eu não ficaria surpreso se não funcionar em muitas / quaisquer configurações.)

Dadas as restrições do GLX e CGL e o desejo de minimizar as alterações entre o OpenGL e o OpenGL ES, você também pode simplesmente assumir que o conteúdo é lixo.

Sunny Sachanandani
fonte
1

Pelo que li o único comportamento é indefinido. Então, eu diria que não há garantia sobre qual será o conteúdo do buffer. Sem mencionar que algumas bibliotecas realmente envolvem uma chamada clara na chamada de buffers de troca.

David Yenglin
fonte
-1 por falta de fornecimento; A documentação do OpenGL é abundante e facilmente vinculada.
+1 porque, bem, ele realmente respondeu e a resposta estava correta. Fontes definitivamente ajudam, mas não são de forma alguma necessárias!
o0 '.
@ Lo'oris: Exceto, bem, ele não está correto. Ele está correto em algumas plataformas, mas não em todas, como minha resposta explica.
@ Joe: A única resposta correta, independentemente do "ambiente", é essa, como explica sua resposta. A codificação sabendo que isso quebrará "em algum lugar" estaria errada em primeiro lugar.
o0 '.
11
@ Lo'oris: Todo o código, especialmente o código de renderização, provavelmente quebrará em algum lugar . Uma boa resposta não diz apenas isso, mas explica onde está esse lugar.
0

O comportamento é indefinido; portanto, se você quiser preencher a tela inteira de qualquer maneira, considere deixar a coisa clara .. exceto em alguns ambientes (pelo menos em certas arquiteturas de ladrilhos) que realmente prejudicam o desempenho. A tela cheia limpa no início da renderização é uma operação tão comum que eu ficaria surpreso se não fosse bem otimizado em todas as plataformas de destino.

O motivo pelo qual NÃO É DEFINIDO é que, para muitas arquiteturas, tornar o estado do conteúdo definido seria uma sobrecarga extra, independentemente de como você definiria o padrão.

Quanto ao que você encontrará lá, posso adivinhar com base na experiência;

Em arquiteturas com buffer duplo (ou multi), como a maioria dos hardwares de vídeo para PCs de mesa, você provavelmente encontrará os "outros" dados do buffer. Isso não é garantido, pois não está na especificação, se alguma otimização estranha se beneficiar disso, eles coletarão os dados.

Em arquiteturas lado a lado, você pode encontrar os mesmos dados que o último quadro, alguns dados estranhamente distorcidos com base no tamanho do bloco ou praticamente qualquer outra coisa.

Então você tem algumas arquiteturas excêntricas (como o NDS) que podem fornecer praticamente qualquer coisa, já que sua definição de buffer não é exatamente o que você esperaria.

Jari Komppa
fonte
Uau, votos negativos. Estou falando sério sobre o que escrevi - especialmente se você estiver escrevendo para hardware móvel, inclua isso claramente lá.
Jari Komppa
Votei mal porque sua resposta é quase idêntica à de David, ainda não tem referências e, como a de David, não está correta nem toda a história.
Está bem. A única referência que posso dar, no entanto, é a minha própria experiência. Terei mais cuidado.
Jari Komppa
Fiz uma votação negativa porque essa resposta era estritamente pior que as outras duas (que eu votei ambas): não acrescentou nada e foi muito menos clara.
o0 '.